sortextable.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*
  2. * sortextable.h
  3. *
  4. * Copyright 2011 - 2012 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 _r
  33. #undef _w
  34. #ifdef SORTEXTABLE_64
  35. # define extable_ent_size 16
  36. # define compare_extable compare_extable_64
  37. # define do_func do64
  38. # define Elf_Addr Elf64_Addr
  39. # define Elf_Ehdr Elf64_Ehdr
  40. # define Elf_Shdr Elf64_Shdr
  41. # define Elf_Rel Elf64_Rel
  42. # define Elf_Rela Elf64_Rela
  43. # define Elf_Sym Elf64_Sym
  44. # define ELF_R_SYM ELF64_R_SYM
  45. # define Elf_r_sym Elf64_r_sym
  46. # define ELF_R_INFO ELF64_R_INFO
  47. # define Elf_r_info Elf64_r_info
  48. # define ELF_ST_BIND ELF64_ST_BIND
  49. # define ELF_ST_TYPE ELF64_ST_TYPE
  50. # define fn_ELF_R_SYM fn_ELF64_R_SYM
  51. # define fn_ELF_R_INFO fn_ELF64_R_INFO
  52. # define uint_t uint64_t
  53. # define _r r8
  54. # define _w w8
  55. #else
  56. # define extable_ent_size 8
  57. # define compare_extable compare_extable_32
  58. # define do_func do32
  59. # define Elf_Addr Elf32_Addr
  60. # define Elf_Ehdr Elf32_Ehdr
  61. # define Elf_Shdr Elf32_Shdr
  62. # define Elf_Rel Elf32_Rel
  63. # define Elf_Rela Elf32_Rela
  64. # define Elf_Sym Elf32_Sym
  65. # define ELF_R_SYM ELF32_R_SYM
  66. # define Elf_r_sym Elf32_r_sym
  67. # define ELF_R_INFO ELF32_R_INFO
  68. # define Elf_r_info Elf32_r_info
  69. # define ELF_ST_BIND ELF32_ST_BIND
  70. # define ELF_ST_TYPE ELF32_ST_TYPE
  71. # define fn_ELF_R_SYM fn_ELF32_R_SYM
  72. # define fn_ELF_R_INFO fn_ELF32_R_INFO
  73. # define uint_t uint32_t
  74. # define _r r
  75. # define _w w
  76. #endif
  77. static int compare_extable(const void *a, const void *b)
  78. {
  79. Elf_Addr av = _r(a);
  80. Elf_Addr bv = _r(b);
  81. if (av < bv)
  82. return -1;
  83. if (av > bv)
  84. return 1;
  85. return 0;
  86. }
  87. static void
  88. do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
  89. {
  90. Elf_Shdr *shdr;
  91. Elf_Shdr *shstrtab_sec;
  92. Elf_Shdr *strtab_sec = NULL;
  93. Elf_Shdr *symtab_sec = NULL;
  94. Elf_Shdr *extab_sec = NULL;
  95. Elf_Sym *sym;
  96. const Elf_Sym *symtab;
  97. Elf32_Word *symtab_shndx_start = NULL;
  98. Elf_Sym *sort_needed_sym;
  99. Elf_Shdr *sort_needed_sec;
  100. Elf_Rel *relocs = NULL;
  101. int relocs_size = 0;
  102. uint32_t *sort_done_location;
  103. const char *secstrtab;
  104. const char *strtab;
  105. char *extab_image;
  106. int extab_index = 0;
  107. int i;
  108. int idx;
  109. unsigned int num_sections;
  110. unsigned int secindex_strings;
  111. shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->e_shoff));
  112. num_sections = r2(&ehdr->e_shnum);
  113. if (num_sections == SHN_UNDEF)
  114. num_sections = _r(&shdr[0].sh_size);
  115. secindex_strings = r2(&ehdr->e_shstrndx);
  116. if (secindex_strings == SHN_XINDEX)
  117. secindex_strings = r(&shdr[0].sh_link);
  118. shstrtab_sec = shdr + secindex_strings;
  119. secstrtab = (const char *)ehdr + _r(&shstrtab_sec->sh_offset);
  120. for (i = 0; i < num_sections; i++) {
  121. idx = r(&shdr[i].sh_name);
  122. if (strcmp(secstrtab + idx, "__ex_table") == 0) {
  123. extab_sec = shdr + i;
  124. extab_index = i;
  125. }
  126. if ((r(&shdr[i].sh_type) == SHT_REL ||
  127. r(&shdr[i].sh_type) == SHT_RELA) &&
  128. r(&shdr[i].sh_info) == extab_index) {
  129. relocs = (void *)ehdr + _r(&shdr[i].sh_offset);
  130. relocs_size = _r(&shdr[i].sh_size);
  131. }
  132. if (strcmp(secstrtab + idx, ".symtab") == 0)
  133. symtab_sec = shdr + i;
  134. if (strcmp(secstrtab + idx, ".strtab") == 0)
  135. strtab_sec = shdr + i;
  136. if (r(&shdr[i].sh_type) == SHT_SYMTAB_SHNDX)
  137. symtab_shndx_start = (Elf32_Word *)(
  138. (const char *)ehdr + _r(&shdr[i].sh_offset));
  139. }
  140. if (strtab_sec == NULL) {
  141. fprintf(stderr, "no .strtab in file: %s\n", fname);
  142. fail_file();
  143. }
  144. if (symtab_sec == NULL) {
  145. fprintf(stderr, "no .symtab in file: %s\n", fname);
  146. fail_file();
  147. }
  148. symtab = (const Elf_Sym *)((const char *)ehdr +
  149. _r(&symtab_sec->sh_offset));
  150. if (extab_sec == NULL) {
  151. fprintf(stderr, "no __ex_table in file: %s\n", fname);
  152. fail_file();
  153. }
  154. strtab = (const char *)ehdr + _r(&strtab_sec->sh_offset);
  155. extab_image = (void *)ehdr + _r(&extab_sec->sh_offset);
  156. if (custom_sort) {
  157. custom_sort(extab_image, _r(&extab_sec->sh_size));
  158. } else {
  159. int num_entries = _r(&extab_sec->sh_size) / extable_ent_size;
  160. qsort(extab_image, num_entries,
  161. extable_ent_size, compare_extable);
  162. }
  163. /* If there were relocations, we no longer need them. */
  164. if (relocs)
  165. memset(relocs, 0, relocs_size);
  166. /* find main_extable_sort_needed */
  167. sort_needed_sym = NULL;
  168. for (i = 0; i < _r(&symtab_sec->sh_size) / sizeof(Elf_Sym); i++) {
  169. sym = (void *)ehdr + _r(&symtab_sec->sh_offset);
  170. sym += i;
  171. if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
  172. continue;
  173. idx = r(&sym->st_name);
  174. if (strcmp(strtab + idx, "main_extable_sort_needed") == 0) {
  175. sort_needed_sym = sym;
  176. break;
  177. }
  178. }
  179. if (sort_needed_sym == NULL) {
  180. fprintf(stderr,
  181. "no main_extable_sort_needed symbol in file: %s\n",
  182. fname);
  183. fail_file();
  184. }
  185. sort_needed_sec = &shdr[get_secindex(r2(&sym->st_shndx),
  186. sort_needed_sym - symtab,
  187. symtab_shndx_start)];
  188. sort_done_location = (void *)ehdr +
  189. _r(&sort_needed_sec->sh_offset) +
  190. _r(&sort_needed_sym->st_value) -
  191. _r(&sort_needed_sec->sh_addr);
  192. #if 0
  193. printf("sort done marker at %lx\n",
  194. (unsigned long)((char *)sort_done_location - (char *)ehdr));
  195. #endif
  196. /* We sorted it, clear the flag. */
  197. w(0, sort_done_location);
  198. }