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