sortextable.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. * sortextable.h
  3. *
  4. * Copyright 2011 Cavium, Inc.
  5. *
  6. * Some of this code was taken out of recordmcount.h written by:
  7. *
  8. * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
  9. * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
  10. *
  11. *
  12. * Licensed under the GNU General Public License, version 2 (GPLv2).
  13. */
  14. #undef extable_ent_size
  15. #undef compare_extable
  16. #undef do_func
  17. #undef Elf_Addr
  18. #undef Elf_Ehdr
  19. #undef Elf_Shdr
  20. #undef Elf_Rel
  21. #undef Elf_Rela
  22. #undef Elf_Sym
  23. #undef ELF_R_SYM
  24. #undef Elf_r_sym
  25. #undef ELF_R_INFO
  26. #undef Elf_r_info
  27. #undef ELF_ST_BIND
  28. #undef ELF_ST_TYPE
  29. #undef fn_ELF_R_SYM
  30. #undef fn_ELF_R_INFO
  31. #undef uint_t
  32. #undef _w
  33. #ifdef SORTEXTABLE_64
  34. # define extable_ent_size 16
  35. # define compare_extable compare_extable_64
  36. # define do_func do64
  37. # define Elf_Addr Elf64_Addr
  38. # define Elf_Ehdr Elf64_Ehdr
  39. # define Elf_Shdr Elf64_Shdr
  40. # define Elf_Rel Elf64_Rel
  41. # define Elf_Rela Elf64_Rela
  42. # define Elf_Sym Elf64_Sym
  43. # define ELF_R_SYM ELF64_R_SYM
  44. # define Elf_r_sym Elf64_r_sym
  45. # define ELF_R_INFO ELF64_R_INFO
  46. # define Elf_r_info Elf64_r_info
  47. # define ELF_ST_BIND ELF64_ST_BIND
  48. # define ELF_ST_TYPE ELF64_ST_TYPE
  49. # define fn_ELF_R_SYM fn_ELF64_R_SYM
  50. # define fn_ELF_R_INFO fn_ELF64_R_INFO
  51. # define uint_t uint64_t
  52. # define _w w8
  53. #else
  54. # define extable_ent_size 8
  55. # define compare_extable compare_extable_32
  56. # define do_func do32
  57. # define Elf_Addr Elf32_Addr
  58. # define Elf_Ehdr Elf32_Ehdr
  59. # define Elf_Shdr Elf32_Shdr
  60. # define Elf_Rel Elf32_Rel
  61. # define Elf_Rela Elf32_Rela
  62. # define Elf_Sym Elf32_Sym
  63. # define ELF_R_SYM ELF32_R_SYM
  64. # define Elf_r_sym Elf32_r_sym
  65. # define ELF_R_INFO ELF32_R_INFO
  66. # define Elf_r_info Elf32_r_info
  67. # define ELF_ST_BIND ELF32_ST_BIND
  68. # define ELF_ST_TYPE ELF32_ST_TYPE
  69. # define fn_ELF_R_SYM fn_ELF32_R_SYM
  70. # define fn_ELF_R_INFO fn_ELF32_R_INFO
  71. # define uint_t uint32_t
  72. # define _w w
  73. #endif
  74. static int compare_extable(const void *a, const void *b)
  75. {
  76. const uint_t *aa = a;
  77. const uint_t *bb = b;
  78. if (_w(*aa) < _w(*bb))
  79. return -1;
  80. if (_w(*aa) > _w(*bb))
  81. return 1;
  82. return 0;
  83. }
  84. static void
  85. do_func(Elf_Ehdr *const ehdr, char const *const fname)
  86. {
  87. Elf_Shdr *shdr;
  88. Elf_Shdr *shstrtab_sec;
  89. Elf_Shdr *strtab_sec = NULL;
  90. Elf_Shdr *symtab_sec = NULL;
  91. Elf_Shdr *extab_sec = NULL;
  92. Elf_Sym *sym;
  93. Elf_Sym *sort_needed_sym;
  94. Elf_Shdr *sort_needed_sec;
  95. uint32_t *sort_done_location;
  96. const char *secstrtab;
  97. const char *strtab;
  98. int i;
  99. int idx;
  100. shdr = (Elf_Shdr *)((void *)ehdr + _w(ehdr->e_shoff));
  101. shstrtab_sec = shdr + w2(ehdr->e_shstrndx);
  102. secstrtab = (const char *)ehdr + _w(shstrtab_sec->sh_offset);
  103. for (i = 0; i < w2(ehdr->e_shnum); i++) {
  104. idx = w(shdr[i].sh_name);
  105. if (strcmp(secstrtab + idx, "__ex_table") == 0)
  106. extab_sec = shdr + i;
  107. if (strcmp(secstrtab + idx, ".symtab") == 0)
  108. symtab_sec = shdr + i;
  109. if (strcmp(secstrtab + idx, ".strtab") == 0)
  110. strtab_sec = shdr + i;
  111. }
  112. if (strtab_sec == NULL) {
  113. fprintf(stderr, "no .strtab in file: %s\n", fname);
  114. fail_file();
  115. }
  116. if (symtab_sec == NULL) {
  117. fprintf(stderr, "no .symtab in file: %s\n", fname);
  118. fail_file();
  119. }
  120. if (extab_sec == NULL) {
  121. fprintf(stderr, "no __ex_table in file: %s\n", fname);
  122. fail_file();
  123. }
  124. strtab = (const char *)ehdr + _w(strtab_sec->sh_offset);
  125. /* Sort the table in place */
  126. qsort((void *)ehdr + _w(extab_sec->sh_offset),
  127. (_w(extab_sec->sh_size) / extable_ent_size),
  128. extable_ent_size, compare_extable);
  129. /* find main_extable_sort_needed */
  130. sort_needed_sym = NULL;
  131. for (i = 0; i < _w(symtab_sec->sh_size) / sizeof(Elf_Sym); i++) {
  132. sym = (void *)ehdr + _w(symtab_sec->sh_offset);
  133. sym += i;
  134. if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
  135. continue;
  136. idx = w(sym->st_name);
  137. if (strcmp(strtab + idx, "main_extable_sort_needed") == 0) {
  138. sort_needed_sym = sym;
  139. break;
  140. }
  141. }
  142. if (sort_needed_sym == NULL) {
  143. fprintf(stderr,
  144. "no main_extable_sort_needed symbol in file: %s\n",
  145. fname);
  146. fail_file();
  147. }
  148. sort_needed_sec = &shdr[w2(sort_needed_sym->st_shndx)];
  149. sort_done_location = (void *)ehdr +
  150. _w(sort_needed_sec->sh_offset) +
  151. _w(sort_needed_sym->st_value) -
  152. _w(sort_needed_sec->sh_addr);
  153. printf("sort done marker at %lx\n",
  154. (unsigned long) (_w(sort_needed_sec->sh_offset) +
  155. _w(sort_needed_sym->st_value) -
  156. _w(sort_needed_sec->sh_addr)));
  157. /* We sorted it, clear the flag. */
  158. *sort_done_location = 0;
  159. }