Commit | Line | Data |
---|---|---|
a79f248b DD |
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 | ||
15 | #undef extable_ent_size | |
16 | #undef compare_extable | |
17 | #undef do_func | |
18 | #undef Elf_Addr | |
19 | #undef Elf_Ehdr | |
20 | #undef Elf_Shdr | |
21 | #undef Elf_Rel | |
22 | #undef Elf_Rela | |
23 | #undef Elf_Sym | |
24 | #undef ELF_R_SYM | |
25 | #undef Elf_r_sym | |
26 | #undef ELF_R_INFO | |
27 | #undef Elf_r_info | |
28 | #undef ELF_ST_BIND | |
29 | #undef ELF_ST_TYPE | |
30 | #undef fn_ELF_R_SYM | |
31 | #undef fn_ELF_R_INFO | |
32 | #undef uint_t | |
33 | #undef _w | |
34 | ||
35 | #ifdef SORTEXTABLE_64 | |
36 | # define extable_ent_size 16 | |
37 | # define compare_extable compare_extable_64 | |
38 | # define do_func do64 | |
39 | # define Elf_Addr Elf64_Addr | |
40 | # define Elf_Ehdr Elf64_Ehdr | |
41 | # define Elf_Shdr Elf64_Shdr | |
42 | # define Elf_Rel Elf64_Rel | |
43 | # define Elf_Rela Elf64_Rela | |
44 | # define Elf_Sym Elf64_Sym | |
45 | # define ELF_R_SYM ELF64_R_SYM | |
46 | # define Elf_r_sym Elf64_r_sym | |
47 | # define ELF_R_INFO ELF64_R_INFO | |
48 | # define Elf_r_info Elf64_r_info | |
49 | # define ELF_ST_BIND ELF64_ST_BIND | |
50 | # define ELF_ST_TYPE ELF64_ST_TYPE | |
51 | # define fn_ELF_R_SYM fn_ELF64_R_SYM | |
52 | # define fn_ELF_R_INFO fn_ELF64_R_INFO | |
53 | # define uint_t uint64_t | |
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 _w w | |
75 | #endif | |
76 | ||
77 | static int compare_extable(const void *a, const void *b) | |
78 | { | |
79 | const uint_t *aa = a; | |
80 | const uint_t *bb = b; | |
81 | ||
82 | if (_w(*aa) < _w(*bb)) | |
83 | return -1; | |
84 | if (_w(*aa) > _w(*bb)) | |
85 | return 1; | |
86 | return 0; | |
87 | } | |
88 | ||
89 | static void | |
90 | do_func(Elf_Ehdr *const ehdr, char const *const fname) | |
91 | { | |
92 | Elf_Shdr *shdr; | |
93 | Elf_Shdr *shstrtab_sec; | |
94 | Elf_Shdr *strtab_sec = NULL; | |
95 | Elf_Shdr *symtab_sec = NULL; | |
96 | Elf_Shdr *extab_sec = NULL; | |
97 | Elf_Sym *sym; | |
98 | Elf_Sym *sort_needed_sym; | |
99 | Elf_Shdr *sort_needed_sec; | |
100 | uint32_t *sort_done_location; | |
101 | const char *secstrtab; | |
102 | const char *strtab; | |
103 | int i; | |
104 | int idx; | |
105 | ||
106 | shdr = (Elf_Shdr *)((void *)ehdr + _w(ehdr->e_shoff)); | |
107 | shstrtab_sec = shdr + w2(ehdr->e_shstrndx); | |
108 | secstrtab = (const char *)ehdr + _w(shstrtab_sec->sh_offset); | |
109 | for (i = 0; i < w2(ehdr->e_shnum); i++) { | |
110 | idx = w(shdr[i].sh_name); | |
111 | if (strcmp(secstrtab + idx, "__ex_table") == 0) | |
112 | extab_sec = shdr + i; | |
113 | if (strcmp(secstrtab + idx, ".symtab") == 0) | |
114 | symtab_sec = shdr + i; | |
115 | if (strcmp(secstrtab + idx, ".strtab") == 0) | |
116 | strtab_sec = shdr + i; | |
117 | } | |
118 | if (strtab_sec == NULL) { | |
119 | fprintf(stderr, "no .strtab in file: %s\n", fname); | |
120 | fail_file(); | |
121 | } | |
122 | if (symtab_sec == NULL) { | |
123 | fprintf(stderr, "no .symtab in file: %s\n", fname); | |
124 | fail_file(); | |
125 | } | |
126 | if (extab_sec == NULL) { | |
127 | fprintf(stderr, "no __ex_table in file: %s\n", fname); | |
128 | fail_file(); | |
129 | } | |
130 | strtab = (const char *)ehdr + _w(strtab_sec->sh_offset); | |
131 | ||
132 | /* Sort the table in place */ | |
133 | qsort((void *)ehdr + _w(extab_sec->sh_offset), | |
134 | (_w(extab_sec->sh_size) / extable_ent_size), | |
135 | extable_ent_size, compare_extable); | |
136 | ||
137 | /* find main_extable_sort_needed */ | |
138 | sort_needed_sym = NULL; | |
139 | for (i = 0; i < _w(symtab_sec->sh_size) / sizeof(Elf_Sym); i++) { | |
140 | sym = (void *)ehdr + _w(symtab_sec->sh_offset); | |
141 | sym += i; | |
142 | if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) | |
143 | continue; | |
144 | idx = w(sym->st_name); | |
145 | if (strcmp(strtab + idx, "main_extable_sort_needed") == 0) { | |
146 | sort_needed_sym = sym; | |
147 | break; | |
148 | } | |
149 | } | |
150 | if (sort_needed_sym == NULL) { | |
151 | fprintf(stderr, | |
152 | "no main_extable_sort_needed symbol in file: %s\n", | |
153 | fname); | |
154 | fail_file(); | |
155 | } | |
156 | sort_needed_sec = &shdr[w2(sort_needed_sym->st_shndx)]; | |
157 | sort_done_location = (void *)ehdr + | |
158 | _w(sort_needed_sec->sh_offset) + | |
159 | _w(sort_needed_sym->st_value) - | |
160 | _w(sort_needed_sec->sh_addr); | |
161 | ||
162 | printf("sort done marker at %lx\n", | |
163 | (unsigned long) (_w(sort_needed_sec->sh_offset) + | |
164 | _w(sort_needed_sym->st_value) - | |
165 | _w(sort_needed_sec->sh_addr))); | |
166 | /* We sorted it, clear the flag. */ | |
167 | *sort_done_location = 0; | |
168 | } |