Blame view
scripts/sorttable.h
9.65 KB
4317cf95c treewide: Replace... |
1 |
/* SPDX-License-Identifier: GPL-2.0-only */ |
a79f248b9 scripts: Add sort... |
2 |
/* |
109167063 scripts/sorttable... |
3 |
* sorttable.h |
a79f248b9 scripts: Add sort... |
4 |
* |
57fa18994 scripts/sorttable... |
5 6 7 8 |
* Added ORC unwind tables sort support and other updates: * Copyright (C) 1999-2019 Alibaba Group Holding Limited. by: * Shile Zhang <shile.zhang@linux.alibaba.com> * |
d59a16836 scripts/sortextab... |
9 |
* Copyright 2011 - 2012 Cavium, Inc. |
a79f248b9 scripts: Add sort... |
10 |
* |
57fa18994 scripts/sorttable... |
11 12 13 |
* Some of code was taken out of arch/x86/kernel/unwind_orc.c, written by: * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com> * |
a79f248b9 scripts: Add sort... |
14 15 |
* Some of this code was taken out of recordmcount.h written by: * |
6402e1416 scripts/sortextab... |
16 |
* Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved. |
a79f248b9 scripts: Add sort... |
17 |
* Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc. |
a79f248b9 scripts: Add sort... |
18 19 20 21 |
*/ #undef extable_ent_size #undef compare_extable |
57cafdf2a scripts/sortextab... |
22 |
#undef do_sort |
a79f248b9 scripts: Add sort... |
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#undef Elf_Addr #undef Elf_Ehdr #undef Elf_Shdr #undef Elf_Rel #undef Elf_Rela #undef Elf_Sym #undef ELF_R_SYM #undef Elf_r_sym #undef ELF_R_INFO #undef Elf_r_info #undef ELF_ST_BIND #undef ELF_ST_TYPE #undef fn_ELF_R_SYM #undef fn_ELF_R_INFO #undef uint_t |
d59a16836 scripts/sortextab... |
38 |
#undef _r |
a79f248b9 scripts: Add sort... |
39 |
#undef _w |
109167063 scripts/sorttable... |
40 |
#ifdef SORTTABLE_64 |
a79f248b9 scripts: Add sort... |
41 42 |
# define extable_ent_size 16 # define compare_extable compare_extable_64 |
57cafdf2a scripts/sortextab... |
43 |
# define do_sort do_sort_64 |
a79f248b9 scripts: Add sort... |
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# define Elf_Addr Elf64_Addr # define Elf_Ehdr Elf64_Ehdr # define Elf_Shdr Elf64_Shdr # define Elf_Rel Elf64_Rel # define Elf_Rela Elf64_Rela # define Elf_Sym Elf64_Sym # define ELF_R_SYM ELF64_R_SYM # define Elf_r_sym Elf64_r_sym # define ELF_R_INFO ELF64_R_INFO # define Elf_r_info Elf64_r_info # define ELF_ST_BIND ELF64_ST_BIND # define ELF_ST_TYPE ELF64_ST_TYPE # define fn_ELF_R_SYM fn_ELF64_R_SYM # define fn_ELF_R_INFO fn_ELF64_R_INFO # define uint_t uint64_t |
d59a16836 scripts/sortextab... |
59 |
# define _r r8 |
a79f248b9 scripts: Add sort... |
60 61 62 63 |
# define _w w8 #else # define extable_ent_size 8 # define compare_extable compare_extable_32 |
57cafdf2a scripts/sortextab... |
64 |
# define do_sort do_sort_32 |
a79f248b9 scripts: Add sort... |
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# define Elf_Addr Elf32_Addr # define Elf_Ehdr Elf32_Ehdr # define Elf_Shdr Elf32_Shdr # define Elf_Rel Elf32_Rel # define Elf_Rela Elf32_Rela # define Elf_Sym Elf32_Sym # define ELF_R_SYM ELF32_R_SYM # define Elf_r_sym Elf32_r_sym # define ELF_R_INFO ELF32_R_INFO # define Elf_r_info Elf32_r_info # define ELF_ST_BIND ELF32_ST_BIND # define ELF_ST_TYPE ELF32_ST_TYPE # define fn_ELF_R_SYM fn_ELF32_R_SYM # define fn_ELF_R_INFO fn_ELF32_R_INFO # define uint_t uint32_t |
d59a16836 scripts/sortextab... |
80 |
# define _r r |
a79f248b9 scripts: Add sort... |
81 82 |
# define _w w #endif |
57fa18994 scripts/sorttable... |
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) /* ORC unwinder only support X86_64 */ #include <errno.h> #include <pthread.h> #include <asm/orc_types.h> #define ERRSTR_MAXSZ 256 char g_err[ERRSTR_MAXSZ]; int *g_orc_ip_table; struct orc_entry *g_orc_table; pthread_t orc_sort_thread; static inline unsigned long orc_ip(const int *ip) { return (unsigned long)ip + *ip; } static int orc_sort_cmp(const void *_a, const void *_b) { struct orc_entry *orc_a; const int *a = g_orc_ip_table + *(int *)_a; const int *b = g_orc_ip_table + *(int *)_b; unsigned long a_val = orc_ip(a); unsigned long b_val = orc_ip(b); if (a_val > b_val) return 1; if (a_val < b_val) return -1; /* * The "weak" section terminator entries need to always be on the left * to ensure the lookup code skips them in favor of real entries. * These terminator entries exist to handle any gaps created by * whitelisted .o files which didn't get objtool generation. */ orc_a = g_orc_table + (a - g_orc_ip_table); return orc_a->sp_reg == ORC_REG_UNDEFINED && !orc_a->end ? -1 : 1; } static void *sort_orctable(void *arg) { int i; int *idxs = NULL; int *tmp_orc_ip_table = NULL; struct orc_entry *tmp_orc_table = NULL; unsigned int *orc_ip_size = (unsigned int *)arg; unsigned int num_entries = *orc_ip_size / sizeof(int); unsigned int orc_size = num_entries * sizeof(struct orc_entry); idxs = (int *)malloc(*orc_ip_size); if (!idxs) { snprintf(g_err, ERRSTR_MAXSZ, "malloc idxs: %s", strerror(errno)); pthread_exit(g_err); } tmp_orc_ip_table = (int *)malloc(*orc_ip_size); if (!tmp_orc_ip_table) { snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_ip_table: %s", strerror(errno)); pthread_exit(g_err); } tmp_orc_table = (struct orc_entry *)malloc(orc_size); if (!tmp_orc_table) { snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_table: %s", strerror(errno)); pthread_exit(g_err); } /* initialize indices array, convert ip_table to absolute address */ for (i = 0; i < num_entries; i++) { idxs[i] = i; tmp_orc_ip_table[i] = g_orc_ip_table[i] + i * sizeof(int); } memcpy(tmp_orc_table, g_orc_table, orc_size); qsort(idxs, num_entries, sizeof(int), orc_sort_cmp); for (i = 0; i < num_entries; i++) { if (idxs[i] == i) continue; /* convert back to relative address */ g_orc_ip_table[i] = tmp_orc_ip_table[idxs[i]] - i * sizeof(int); g_orc_table[i] = tmp_orc_table[idxs[i]]; } free(idxs); free(tmp_orc_ip_table); free(tmp_orc_table); pthread_exit(NULL); } #endif |
a79f248b9 scripts: Add sort... |
180 181 |
static int compare_extable(const void *a, const void *b) { |
d59a16836 scripts/sortextab... |
182 183 |
Elf_Addr av = _r(a); Elf_Addr bv = _r(b); |
a79f248b9 scripts: Add sort... |
184 |
|
d59a16836 scripts/sortextab... |
185 |
if (av < bv) |
a79f248b9 scripts: Add sort... |
186 |
return -1; |
d59a16836 scripts/sortextab... |
187 |
if (av > bv) |
a79f248b9 scripts: Add sort... |
188 189 190 |
return 1; return 0; } |
57cafdf2a scripts/sortextab... |
191 |
static int do_sort(Elf_Ehdr *ehdr, |
6402e1416 scripts/sortextab... |
192 193 |
char const *const fname, table_sort_t custom_sort) |
a79f248b9 scripts: Add sort... |
194 |
{ |
57fa18994 scripts/sorttable... |
195 |
int rc = -1; |
57cafdf2a scripts/sortextab... |
196 |
Elf_Shdr *s, *shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->e_shoff)); |
a79f248b9 scripts: Add sort... |
197 198 199 200 |
Elf_Shdr *strtab_sec = NULL; Elf_Shdr *symtab_sec = NULL; Elf_Shdr *extab_sec = NULL; Elf_Sym *sym; |
59c36455d scripts/sortextab... |
201 |
const Elf_Sym *symtab; |
57cafdf2a scripts/sortextab... |
202 203 |
Elf32_Word *symtab_shndx = NULL; Elf_Sym *sort_needed_sym = NULL; |
a79f248b9 scripts: Add sort... |
204 |
Elf_Shdr *sort_needed_sec; |
d59a16836 scripts/sortextab... |
205 |
Elf_Rel *relocs = NULL; |
7cbc0ea79 scripts/sortextab... |
206 |
int relocs_size = 0; |
57cafdf2a scripts/sortextab... |
207 208 |
uint32_t *sort_needed_loc; const char *secstrings; |
a79f248b9 scripts: Add sort... |
209 |
const char *strtab; |
d59a16836 scripts/sortextab... |
210 211 |
char *extab_image; int extab_index = 0; |
a79f248b9 scripts: Add sort... |
212 213 |
int i; int idx; |
57cafdf2a scripts/sortextab... |
214 215 |
unsigned int shnum; unsigned int shstrndx; |
57fa18994 scripts/sorttable... |
216 217 218 219 220 |
#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) unsigned int orc_ip_size = 0; unsigned int orc_size = 0; unsigned int orc_num_entries = 0; #endif |
a79f248b9 scripts: Add sort... |
221 |
|
57cafdf2a scripts/sortextab... |
222 223 224 225 |
shstrndx = r2(&ehdr->e_shstrndx); if (shstrndx == SHN_XINDEX) shstrndx = r(&shdr[0].sh_link); secstrings = (const char *)ehdr + _r(&shdr[shstrndx].sh_offset); |
59c36455d scripts/sortextab... |
226 |
|
57cafdf2a scripts/sortextab... |
227 228 229 |
shnum = r2(&ehdr->e_shnum); if (shnum == SHN_UNDEF) shnum = _r(&shdr[0].sh_size); |
59c36455d scripts/sortextab... |
230 |
|
57cafdf2a scripts/sortextab... |
231 232 233 234 |
for (i = 0, s = shdr; s < shdr + shnum; i++, s++) { idx = r(&s->sh_name); if (!strcmp(secstrings + idx, "__ex_table")) { extab_sec = s; |
d59a16836 scripts/sortextab... |
235 236 |
extab_index = i; } |
57cafdf2a scripts/sortextab... |
237 238 239 240 241 242 243 244 245 246 |
if (!strcmp(secstrings + idx, ".symtab")) symtab_sec = s; if (!strcmp(secstrings + idx, ".strtab")) strtab_sec = s; if ((r(&s->sh_type) == SHT_REL || r(&s->sh_type) == SHT_RELA) && r(&s->sh_info) == extab_index) { relocs = (void *)ehdr + _r(&s->sh_offset); relocs_size = _r(&s->sh_size); |
d59a16836 scripts/sortextab... |
247 |
} |
57cafdf2a scripts/sortextab... |
248 249 250 |
if (r(&s->sh_type) == SHT_SYMTAB_SHNDX) symtab_shndx = (Elf32_Word *)((const char *)ehdr + _r(&s->sh_offset)); |
57fa18994 scripts/sorttable... |
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) /* locate the ORC unwind tables */ if (!strcmp(secstrings + idx, ".orc_unwind_ip")) { orc_ip_size = s->sh_size; g_orc_ip_table = (int *)((void *)ehdr + s->sh_offset); } if (!strcmp(secstrings + idx, ".orc_unwind")) { orc_size = s->sh_size; g_orc_table = (struct orc_entry *)((void *)ehdr + s->sh_offset); } #endif } /* for loop */ #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) if (!g_orc_ip_table || !g_orc_table) { fprintf(stderr, "incomplete ORC unwind tables in file: %s ", fname); goto out; } orc_num_entries = orc_ip_size / sizeof(int); if (orc_ip_size % sizeof(int) != 0 || orc_size % sizeof(struct orc_entry) != 0 || orc_num_entries != orc_size / sizeof(struct orc_entry)) { fprintf(stderr, "inconsistent ORC unwind table entries in file: %s ", fname); goto out; |
a79f248b9 scripts: Add sort... |
284 |
} |
57cafdf2a scripts/sortextab... |
285 |
|
57fa18994 scripts/sorttable... |
286 287 288 289 290 291 292 293 294 295 |
/* create thread to sort ORC unwind tables concurrently */ if (pthread_create(&orc_sort_thread, NULL, sort_orctable, &orc_ip_size)) { fprintf(stderr, "pthread_create orc_sort_thread failed '%s': %s ", strerror(errno), fname); goto out; } #endif |
57cafdf2a scripts/sortextab... |
296 297 298 |
if (!extab_sec) { fprintf(stderr, "no __ex_table in file: %s ", fname); |
57fa18994 scripts/sorttable... |
299 |
goto out; |
a79f248b9 scripts: Add sort... |
300 |
} |
57cafdf2a scripts/sortextab... |
301 |
|
6402e1416 scripts/sortextab... |
302 303 304 |
if (!symtab_sec) { fprintf(stderr, "no .symtab in file: %s ", fname); |
57fa18994 scripts/sorttable... |
305 |
goto out; |
a79f248b9 scripts: Add sort... |
306 |
} |
57cafdf2a scripts/sortextab... |
307 308 309 310 |
if (!strtab_sec) { fprintf(stderr, "no .strtab in file: %s ", fname); |
57fa18994 scripts/sorttable... |
311 |
goto out; |
a79f248b9 scripts: Add sort... |
312 |
} |
a79f248b9 scripts: Add sort... |
313 |
|
d59a16836 scripts/sortextab... |
314 |
extab_image = (void *)ehdr + _r(&extab_sec->sh_offset); |
57cafdf2a scripts/sortextab... |
315 316 317 |
strtab = (const char *)ehdr + _r(&strtab_sec->sh_offset); symtab = (const Elf_Sym *)((const char *)ehdr + _r(&symtab_sec->sh_offset)); |
d59a16836 scripts/sortextab... |
318 319 320 321 322 323 324 325 |
if (custom_sort) { custom_sort(extab_image, _r(&extab_sec->sh_size)); } else { int num_entries = _r(&extab_sec->sh_size) / extable_ent_size; qsort(extab_image, num_entries, extable_ent_size, compare_extable); } |
57cafdf2a scripts/sortextab... |
326 |
|
d59a16836 scripts/sortextab... |
327 328 329 |
/* If there were relocations, we no longer need them. */ if (relocs) memset(relocs, 0, relocs_size); |
a79f248b9 scripts: Add sort... |
330 |
|
57cafdf2a scripts/sortextab... |
331 332 333 334 |
/* find the flag main_extable_sort_needed */ for (sym = (void *)ehdr + _r(&symtab_sec->sh_offset); sym < sym + _r(&symtab_sec->sh_size) / sizeof(Elf_Sym); sym++) { |
a79f248b9 scripts: Add sort... |
335 336 |
if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) continue; |
57cafdf2a scripts/sortextab... |
337 338 |
if (!strcmp(strtab + r(&sym->st_name), "main_extable_sort_needed")) { |
a79f248b9 scripts: Add sort... |
339 340 341 342 |
sort_needed_sym = sym; break; } } |
57cafdf2a scripts/sortextab... |
343 |
|
6402e1416 scripts/sortextab... |
344 |
if (!sort_needed_sym) { |
a79f248b9 scripts: Add sort... |
345 |
fprintf(stderr, |
6402e1416 scripts/sortextab... |
346 347 |
"no main_extable_sort_needed symbol in file: %s ", |
a79f248b9 scripts: Add sort... |
348 |
fname); |
57fa18994 scripts/sorttable... |
349 |
goto out; |
a79f248b9 scripts: Add sort... |
350 |
} |
57cafdf2a scripts/sortextab... |
351 |
|
59c36455d scripts/sortextab... |
352 353 |
sort_needed_sec = &shdr[get_secindex(r2(&sym->st_shndx), sort_needed_sym - symtab, |
57cafdf2a scripts/sortextab... |
354 355 |
symtab_shndx)]; sort_needed_loc = (void *)ehdr + |
d59a16836 scripts/sortextab... |
356 357 358 |
_r(&sort_needed_sec->sh_offset) + _r(&sort_needed_sym->st_value) - _r(&sort_needed_sec->sh_addr); |
a79f248b9 scripts: Add sort... |
359 |
|
57cafdf2a scripts/sortextab... |
360 361 |
/* extable has been sorted, clear the flag */ w(0, sort_needed_loc); |
57fa18994 scripts/sorttable... |
362 |
rc = 0; |
57cafdf2a scripts/sortextab... |
363 |
|
57fa18994 scripts/sorttable... |
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
out: #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) if (orc_sort_thread) { void *retval = NULL; /* wait for ORC tables sort done */ rc = pthread_join(orc_sort_thread, &retval); if (rc) fprintf(stderr, "pthread_join failed '%s': %s ", strerror(errno), fname); else if (retval) { rc = -1; fprintf(stderr, "failed to sort ORC tables '%s': %s ", (char *)retval, fname); } } #endif return rc; |
a79f248b9 scripts: Add sort... |
385 |
} |