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