1 /* 2 * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include <unistd.h> 26 #include <sys/procfs.h> 27 #include <search.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include "symtab.h" 31 #include "salibelf.h" 32 33 34 // ---------------------------------------------------- 35 // functions for symbol lookups 36 // ---------------------------------------------------- 37 38 struct elf_section { 39 ELF_SHDR *c_shdr; 40 void *c_data; 41 }; 42 43 struct elf_symbol { 44 char *name; 45 uintptr_t offset; 46 uintptr_t size; 47 }; 48 49 typedef struct symtab { 50 char *strs; 51 size_t num_symbols; 52 struct elf_symbol *symbols; 53 struct hsearch_data *hash_table; 54 } symtab_t; 55 56 57 // Directory that contains global debuginfo files. In theory it 58 // should be possible to change this, but in a Java environment there 59 // is no obvious place to put a user interface to do it. Maybe this 60 // could be set with an environment variable. 61 static const char debug_file_directory[] = "/usr/lib/debug"; 62 63 /* The CRC used in gnu_debuglink, retrieved from 64 http://sourceware.org/gdb/current/onlinedocs/gdb/Separate-Debug-Files.html#Separate-Debug-Files. */ 65 unsigned int gnu_debuglink_crc32 (unsigned int crc, 66 unsigned char *buf, size_t len) 67 { 68 static const unsigned int crc32_table[256] = 69 { 70 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 71 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 72 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 73 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 74 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 75 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 76 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 77 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 78 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 79 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 80 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 81 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 82 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 83 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 84 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 85 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 86 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 87 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 88 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 89 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 90 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 91 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 92 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 93 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 94 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 95 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 96 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 97 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 98 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 99 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 100 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 101 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 102 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 103 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 104 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 105 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 106 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 107 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 108 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 109 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 110 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 111 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 112 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 113 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 114 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 115 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 116 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 117 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 118 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 119 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 120 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 121 0x2d02ef8d 122 }; 123 unsigned char *end; 124 125 crc = ~crc & 0xffffffff; 126 for (end = buf + len; buf < end; ++buf) 127 crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); 128 return ~crc & 0xffffffff; 129 } 130 131 /* Open a debuginfo file and check its CRC. If it exists and the CRC 132 matches return its fd. */ 133 static int 134 open_debug_file (const char *pathname, unsigned int crc) 135 { 136 unsigned int file_crc = 0; 137 unsigned char buffer[8 * 1024]; 138 139 int fd = pathmap_open(pathname); 140 141 if (fd < 0) 142 return -1; 143 144 lseek(fd, 0, SEEK_SET); 145 146 for (;;) { 147 int len = read(fd, buffer, sizeof buffer); 148 if (len <= 0) 149 break; 150 file_crc = gnu_debuglink_crc32(file_crc, buffer, len); 151 } 152 153 if (crc == file_crc) 154 return fd; 155 else { 156 close(fd); 157 return -1; 158 } 159 } 160 161 /* Find an ELF section. */ 162 static struct elf_section *find_section_by_name(char *name, 163 int fd, 164 ELF_EHDR *ehdr, 165 struct elf_section *scn_cache) 166 { 167 char *strtab; 168 int cnt; 169 int strtab_size; 170 171 // Section cache have to already contain data for e_shstrndx section. 172 // If it's not true - elf file is broken, so just bail out 173 if (scn_cache[ehdr->e_shstrndx].c_data == NULL) { 174 return NULL; 175 } 176 177 strtab = scn_cache[ehdr->e_shstrndx].c_data; 178 strtab_size = scn_cache[ehdr->e_shstrndx].c_shdr->sh_size; 179 180 for (cnt = 0; cnt < ehdr->e_shnum; ++cnt) { 181 if (scn_cache[cnt].c_shdr->sh_name < strtab_size) { 182 if (strcmp(scn_cache[cnt].c_shdr->sh_name + strtab, name) == 0) { 183 scn_cache[cnt].c_data = read_section_data(fd, ehdr, scn_cache[cnt].c_shdr); 184 return &scn_cache[cnt]; 185 } 186 } 187 } 188 189 return NULL; 190 } 191 192 /* Look for a ".gnu_debuglink" section. If one exists, try to open a 193 suitable debuginfo file. */ 194 static int open_file_from_debug_link(const char *name, 195 int fd, 196 ELF_EHDR *ehdr, 197 struct elf_section *scn_cache) 198 { 199 int debug_fd; 200 struct elf_section *debug_link = find_section_by_name(".gnu_debuglink", fd, ehdr, 201 scn_cache); 202 if (debug_link == NULL) 203 return -1; 204 char *debug_filename = debug_link->c_data; 205 int offset = (strlen(debug_filename) + 4) >> 2; 206 static unsigned int crc; 207 crc = ((unsigned int*)debug_link->c_data)[offset]; 208 char *debug_pathname = malloc(strlen(debug_filename) 209 + strlen(name) 210 + strlen(".debug/") 211 + strlen(debug_file_directory) 212 + 2); 213 if (debug_pathname == NULL) { 214 return -1; 215 } 216 strcpy(debug_pathname, name); 217 char *last_slash = strrchr(debug_pathname, '/'); 218 if (last_slash == NULL) { 219 free(debug_pathname); 220 return -1; 221 } 222 223 /* Look in the same directory as the object. */ 224 strcpy(last_slash+1, debug_filename); 225 debug_fd = open_debug_file(debug_pathname, crc); 226 if (debug_fd >= 0) { 227 free(debug_pathname); 228 return debug_fd; 229 } 230 231 /* Look in a subdirectory named ".debug". */ 232 strcpy(last_slash+1, ".debug/"); 233 strcat(last_slash, debug_filename); 234 235 debug_fd = open_debug_file(debug_pathname, crc); 236 if (debug_fd >= 0) { 237 free(debug_pathname); 238 return debug_fd; 239 } 240 241 /* Look in /usr/lib/debug + the full pathname. */ 242 strcpy(debug_pathname, debug_file_directory); 243 strcat(debug_pathname, name); 244 last_slash = strrchr(debug_pathname, '/'); 245 strcpy(last_slash+1, debug_filename); 246 247 debug_fd = open_debug_file(debug_pathname, crc); 248 if (debug_fd >= 0) { 249 free(debug_pathname); 250 return debug_fd; 251 } 252 253 free(debug_pathname); 254 return -1; 255 } 256 257 static struct symtab* build_symtab_internal(int fd, const char *filename, bool try_debuginfo); 258 259 /* Look for a ".gnu_debuglink" section. If one exists, try to open a 260 suitable debuginfo file and read a symbol table from it. */ 261 static struct symtab *build_symtab_from_debug_link(const char *name, 262 int fd, 263 ELF_EHDR *ehdr, 264 struct elf_section *scn_cache) 265 { 266 fd = open_file_from_debug_link(name, fd, ehdr, scn_cache); 267 268 if (fd >= 0) { 269 struct symtab *symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false); 270 close(fd); 271 return symtab; 272 } 273 274 return NULL; 275 } 276 277 // Given a build_id, find the associated debuginfo file 278 static char * 279 build_id_to_debug_filename (size_t size, unsigned char *data) 280 { 281 char *filename, *s; 282 283 filename = malloc(strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1 284 + 2 * size + (sizeof ".debug" - 1) + 1); 285 if (filename == NULL) { 286 return NULL; 287 } 288 s = filename + sprintf (filename, "%s/.build-id/", debug_file_directory); 289 if (size > 0) 290 { 291 size--; 292 s += sprintf (s, "%02x", *data++); 293 } 294 if (size > 0) 295 *s++ = '/'; 296 while (size-- > 0) 297 s += sprintf (s, "%02x", *data++); 298 strcpy (s, ".debug"); 299 300 return filename; 301 } 302 303 // Read a build ID note. Try to open any associated debuginfo file 304 // and return its symtab 305 static struct symtab* build_symtab_from_build_id(Elf64_Nhdr *note) 306 { 307 int fd; 308 struct symtab *symtab = NULL; 309 310 unsigned char *bytes 311 = (unsigned char*)(note+1) + note->n_namesz; 312 char *filename 313 = (build_id_to_debug_filename (note->n_descsz, bytes)); 314 if (filename == NULL) { 315 return NULL; 316 } 317 fd = pathmap_open(filename); 318 if (fd >= 0) { 319 symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false); 320 close(fd); 321 } 322 free(filename); 323 324 return symtab; 325 } 326 327 // read symbol table from given fd. If try_debuginfo) is true, also 328 // try to open an associated debuginfo file 329 static struct symtab* build_symtab_internal(int fd, const char *filename, bool try_debuginfo) { 330 ELF_EHDR ehdr; 331 char *names = NULL; 332 struct symtab* symtab = NULL; 333 334 // Reading of elf header 335 struct elf_section *scn_cache = NULL; 336 #if defined(ppc64) && !defined(ABI_ELFv2) 337 // Only big endian ppc64 (i.e. ABI_ELFv1) has 'official procedure descriptors' in ELF files 338 // see: http://refspecs.linuxfoundation.org/LSB_3.1.1/LSB-Core-PPC64/LSB-Core-PPC64/specialsections.html 339 struct elf_section *opd_sect = NULL; 340 ELF_SHDR *opd = NULL; 341 #endif 342 int cnt = 0; 343 ELF_SHDR* shbuf = NULL; 344 ELF_SHDR* cursct = NULL; 345 ELF_PHDR* phbuf = NULL; 346 ELF_PHDR* phdr = NULL; 347 int sym_section = SHT_DYNSYM; 348 349 uintptr_t baseaddr = (uintptr_t)-1; 350 351 lseek(fd, (off_t)0L, SEEK_SET); 352 if (! read_elf_header(fd, &ehdr)) { 353 // not an elf 354 return NULL; 355 } 356 357 // read ELF header 358 if ((shbuf = read_section_header_table(fd, &ehdr)) == NULL) { 359 goto quit; 360 } 361 362 baseaddr = find_base_address(fd, &ehdr); 363 364 scn_cache = (struct elf_section *) 365 calloc(ehdr.e_shnum * sizeof(struct elf_section), 1); 366 if (scn_cache == NULL) { 367 goto quit; 368 } 369 370 for (cursct = shbuf, cnt = 0; cnt < ehdr.e_shnum; cnt++) { 371 scn_cache[cnt].c_shdr = cursct; 372 if (cursct->sh_type == SHT_SYMTAB || cursct->sh_type == SHT_STRTAB 373 || cursct->sh_type == SHT_NOTE || cursct->sh_type == SHT_DYNSYM) { 374 if ( (scn_cache[cnt].c_data = read_section_data(fd, &ehdr, cursct)) == NULL) { 375 goto quit; 376 } 377 } 378 if (cursct->sh_type == SHT_SYMTAB) { 379 // Full symbol table available so use that 380 sym_section = cursct->sh_type; 381 } 382 cursct++; 383 } 384 385 #if defined(ppc64) && !defined(ABI_ELFv2) 386 opd_sect = find_section_by_name(".opd", fd, &ehdr, scn_cache); 387 if (opd_sect != NULL && opd_sect->c_data != NULL && opd_sect->c_shdr != NULL) { 388 // plausibility check 389 opd = opd_sect->c_shdr; 390 } 391 #endif 392 393 for (cnt = 1; cnt < ehdr.e_shnum; cnt++) { 394 ELF_SHDR *shdr = scn_cache[cnt].c_shdr; 395 396 if (shdr->sh_type == sym_section) { 397 ELF_SYM *syms; 398 int rslt; 399 size_t size, n, j, htab_sz; 400 401 // FIXME: there could be multiple data buffers associated with the 402 // same ELF section. Here we can handle only one buffer. See man page 403 // for elf_getdata on Solaris. 404 405 // guarantee(symtab == NULL, "multiple symtab"); 406 symtab = (struct symtab*)calloc(1, sizeof(struct symtab)); 407 if (symtab == NULL) { 408 goto quit; 409 } 410 // the symbol table 411 syms = (ELF_SYM *)scn_cache[cnt].c_data; 412 413 // number of symbols 414 n = shdr->sh_size / shdr->sh_entsize; 415 416 // create hash table, we use hcreate_r, hsearch_r and hdestroy_r to 417 // manipulate the hash table. 418 419 // NOTES section in the man page of hcreate_r says 420 // "Hash table implementations are usually more efficient when 421 // the table contains enough free space to minimize collisions. 422 // Typically, this means that nel should be at least 25% larger 423 // than the maximum number of elements that the caller expects 424 // to store in the table." 425 htab_sz = n*1.25; 426 427 symtab->hash_table = (struct hsearch_data*) calloc(1, sizeof(struct hsearch_data)); 428 if (symtab->hash_table == NULL) { 429 goto bad; 430 } 431 432 rslt = hcreate_r(n, symtab->hash_table); 433 // guarantee(rslt, "unexpected failure: hcreate_r"); 434 435 // shdr->sh_link points to the section that contains the actual strings 436 // for symbol names. the st_name field in ELF_SYM is just the 437 // string table index. we make a copy of the string table so the 438 // strings will not be destroyed by elf_end. 439 size = scn_cache[shdr->sh_link].c_shdr->sh_size; 440 symtab->strs = (char *)malloc(size); 441 if (symtab->strs == NULL) { 442 goto bad; 443 } 444 memcpy(symtab->strs, scn_cache[shdr->sh_link].c_data, size); 445 446 // allocate memory for storing symbol offset and size; 447 symtab->num_symbols = n; 448 symtab->symbols = (struct elf_symbol *)calloc(n , sizeof(struct elf_symbol)); 449 if (symtab->symbols == NULL) { 450 goto bad; 451 } 452 453 // copy symbols info our symtab and enter them info the hash table 454 for (j = 0; j < n; j++, syms++) { 455 ENTRY item, *ret; 456 uintptr_t sym_value; 457 char *sym_name = symtab->strs + syms->st_name; 458 459 // skip non-object and non-function symbols 460 int st_type = ELF_ST_TYPE(syms->st_info); 461 if ( st_type != STT_FUNC && st_type != STT_OBJECT) 462 continue; 463 // skip empty strings and undefined symbols 464 if (*sym_name == '\0' || syms->st_shndx == SHN_UNDEF) continue; 465 466 symtab->symbols[j].name = sym_name; 467 symtab->symbols[j].size = syms->st_size; 468 sym_value = syms->st_value; 469 470 #if defined(ppc64) && !defined(ABI_ELFv2) 471 // see hotspot/src/share/vm/utilities/elfFuncDescTable.hpp for a detailed description 472 // of why we have to go this extra way via the '.opd' section on big endian ppc64 473 if (opd != NULL && *sym_name != '.' && 474 (opd->sh_addr <= sym_value && sym_value <= opd->sh_addr + opd->sh_size)) { 475 sym_value = ((ELF_ADDR*)opd_sect->c_data)[(sym_value - opd->sh_addr) / sizeof(ELF_ADDR*)]; 476 } 477 #endif 478 479 symtab->symbols[j].offset = sym_value - baseaddr; 480 item.key = sym_name; 481 item.data = (void *)&(symtab->symbols[j]); 482 hsearch_r(item, ENTER, &ret, symtab->hash_table); 483 } 484 } 485 } 486 487 #if defined(ppc64) && !defined(ABI_ELFv2) 488 // On Linux/PPC64 the debuginfo files contain an empty function descriptor 489 // section (i.e. '.opd' section) which makes the resolution of symbols 490 // with the above algorithm impossible (we would need the have both, the 491 // .opd section from the library and the symbol table from the debuginfo 492 // file which doesn't match with the current workflow.) 493 goto quit; 494 #endif 495 496 // Look for a separate debuginfo file. 497 if (try_debuginfo) { 498 // We prefer a debug symtab to an object's own symtab, so look in 499 // the debuginfo file. We stash a copy of the old symtab in case 500 // there is no debuginfo. 501 struct symtab* prev_symtab = symtab; 502 symtab = NULL; 503 504 #ifdef NT_GNU_BUILD_ID 505 // First we look for a Build ID 506 for (cursct = shbuf, cnt = 0; 507 symtab == NULL && cnt < ehdr.e_shnum; 508 cnt++) { 509 if (cursct->sh_type == SHT_NOTE) { 510 Elf64_Nhdr *note = (Elf64_Nhdr *)scn_cache[cnt].c_data; 511 if (note->n_type == NT_GNU_BUILD_ID) { 512 symtab = build_symtab_from_build_id(note); 513 } 514 } 515 cursct++; 516 } 517 #endif 518 519 // Then, if that doesn't work, the debug link 520 if (symtab == NULL) { 521 symtab = build_symtab_from_debug_link(filename, fd, &ehdr, 522 scn_cache); 523 } 524 525 // If we still haven't found a symtab, use the object's own symtab. 526 if (symtab != NULL) { 527 if (prev_symtab != NULL) 528 destroy_symtab(prev_symtab); 529 } else { 530 symtab = prev_symtab; 531 } 532 } 533 goto quit; 534 535 bad: 536 destroy_symtab(symtab); 537 symtab = NULL; 538 539 quit: 540 if (shbuf) free(shbuf); 541 if (phbuf) free(phbuf); 542 if (scn_cache) { 543 for (cnt = 0; cnt < ehdr.e_shnum; cnt++) { 544 if (scn_cache[cnt].c_data != NULL) { 545 free(scn_cache[cnt].c_data); 546 } 547 } 548 free(scn_cache); 549 } 550 return symtab; 551 } 552 553 struct symtab* build_symtab(int fd, const char *filename) { 554 return build_symtab_internal(fd, filename, /* try_debuginfo */ true); 555 } 556 557 558 void destroy_symtab(struct symtab* symtab) { 559 if (!symtab) return; 560 if (symtab->strs) free(symtab->strs); 561 if (symtab->symbols) free(symtab->symbols); 562 if (symtab->hash_table) { 563 hdestroy_r(symtab->hash_table); 564 free(symtab->hash_table); 565 } 566 free(symtab); 567 } 568 569 uintptr_t search_symbol(struct symtab* symtab, uintptr_t base, 570 const char *sym_name, int *sym_size) { 571 ENTRY item; 572 ENTRY* ret = NULL; 573 574 // library does not have symbol table 575 if (!symtab || !symtab->hash_table) 576 return (uintptr_t)NULL; 577 578 item.key = (char*) strdup(sym_name); 579 item.data = NULL; 580 hsearch_r(item, FIND, &ret, symtab->hash_table); 581 if (ret) { 582 struct elf_symbol * sym = (struct elf_symbol *)(ret->data); 583 uintptr_t rslt = (uintptr_t) ((char*)base + sym->offset); 584 if (sym_size) *sym_size = sym->size; 585 free(item.key); 586 return rslt; 587 } 588 589 quit: 590 free(item.key); 591 return (uintptr_t) NULL; 592 } 593 594 const char* nearest_symbol(struct symtab* symtab, uintptr_t offset, 595 uintptr_t* poffset) { 596 int n = 0; 597 if (!symtab) return NULL; 598 for (; n < symtab->num_symbols; n++) { 599 struct elf_symbol* sym = &(symtab->symbols[n]); 600 if (sym->name != NULL && 601 offset >= sym->offset && offset < sym->offset + sym->size) { 602 if (poffset) *poffset = (offset - sym->offset); 603 return sym->name; 604 } 605 } 606 return NULL; 607 }