1 /*
   2  * Copyright (c) 2003, 2010, 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                                                 ELF_SHDR *shbuf,
 166                                                 struct elf_section *scn_cache)
 167 {
 168   ELF_SHDR* cursct = NULL;
 169   char *strtab;
 170   int cnt;
 171 
 172   if (scn_cache[ehdr->e_shstrndx].c_data == NULL) {
 173     if ((scn_cache[ehdr->e_shstrndx].c_data
 174          = read_section_data(fd, ehdr, cursct)) == NULL) {
 175       return NULL;
 176     }
 177   }
 178 
 179   strtab = scn_cache[ehdr->e_shstrndx].c_data;
 180 
 181   for (cursct = shbuf, cnt = 0;
 182        cnt < ehdr->e_shnum;
 183        cnt++, cursct++) {
 184     if (strcmp(cursct->sh_name + strtab, name) == 0) {
 185       scn_cache[cnt].c_data = read_section_data(fd, ehdr, cursct);
 186       return &scn_cache[cnt];
 187     }
 188   }
 189 
 190   return NULL;
 191 }
 192 
 193 /* Look for a ".gnu_debuglink" section.  If one exists, try to open a
 194    suitable debuginfo file.  */
 195 static int open_file_from_debug_link(const char *name,
 196                                      int fd,
 197                                      ELF_EHDR *ehdr,
 198                                      ELF_SHDR *shbuf,
 199                                      struct elf_section *scn_cache)
 200 {
 201   int debug_fd;
 202   struct elf_section *debug_link = find_section_by_name(".gnu_debuglink", fd, ehdr,
 203                                                         shbuf, scn_cache);
 204   if (debug_link == NULL)
 205     return -1;
 206   char *debug_filename = debug_link->c_data;
 207   int offset = (strlen(debug_filename) + 4) >> 2;
 208   static unsigned int crc;
 209   crc = ((unsigned int*)debug_link->c_data)[offset];
 210   char *debug_pathname = malloc(strlen(debug_filename)
 211                                 + strlen(name)
 212                                 + strlen(".debug/")
 213                                 + strlen(debug_file_directory)
 214                                 + 2);
 215   strcpy(debug_pathname, name);
 216   char *last_slash = strrchr(debug_pathname, '/');
 217   if (last_slash == NULL)
 218     return -1;
 219 
 220   /* Look in the same directory as the object.  */
 221   strcpy(last_slash+1, debug_filename);
 222 
 223   debug_fd = open_debug_file(debug_pathname, crc);
 224   if (debug_fd >= 0) {
 225     free(debug_pathname);
 226     return debug_fd;
 227   }
 228 
 229   /* Look in a subdirectory named ".debug".  */
 230   strcpy(last_slash+1, ".debug/");
 231   strcat(last_slash, debug_filename);
 232 
 233   debug_fd = open_debug_file(debug_pathname, crc);
 234   if (debug_fd >= 0) {
 235     free(debug_pathname);
 236     return debug_fd;
 237   }
 238 
 239   /* Look in /usr/lib/debug + the full pathname.  */
 240   strcpy(debug_pathname, debug_file_directory);
 241   strcat(debug_pathname, name);
 242   last_slash = strrchr(debug_pathname, '/');
 243   strcpy(last_slash+1, debug_filename);
 244 
 245   debug_fd = open_debug_file(debug_pathname, crc);
 246   if (debug_fd >= 0) {
 247     free(debug_pathname);
 248     return debug_fd;
 249   }
 250 
 251   free(debug_pathname);
 252   return -1;
 253 }
 254 
 255 static struct symtab* build_symtab_internal(int fd, const char *filename, bool try_debuginfo);
 256 
 257 /* Look for a ".gnu_debuglink" section.  If one exists, try to open a
 258    suitable debuginfo file and read a symbol table from it.  */
 259 static struct symtab *build_symtab_from_debug_link(const char *name,
 260                                      int fd,
 261                                      ELF_EHDR *ehdr,
 262                                      ELF_SHDR *shbuf,
 263                                      struct elf_section *scn_cache)
 264 {
 265   fd = open_file_from_debug_link(name, fd, ehdr, shbuf, scn_cache);
 266 
 267   if (fd >= 0) {
 268     struct symtab *symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false);
 269     close(fd);
 270     return symtab;
 271   }
 272 
 273   return NULL;
 274 }
 275 
 276 // Given a build_id, find the associated debuginfo file
 277 static char *
 278 build_id_to_debug_filename (size_t size, unsigned char *data)
 279 {
 280   char *filename, *s;
 281 
 282   filename = malloc(strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1
 283                     + 2 * size + (sizeof ".debug" - 1) + 1);
 284   s = filename + sprintf (filename, "%s/.build-id/", debug_file_directory);
 285   if (size > 0)
 286     {
 287       size--;
 288       s += sprintf (s, "%02x", *data++);
 289     }
 290   if (size > 0)
 291     *s++ = '/';
 292   while (size-- > 0)
 293     s += sprintf (s, "%02x", *data++);
 294   strcpy (s, ".debug");
 295 
 296   return filename;
 297 }
 298 
 299 // Read a build ID note.  Try to open any associated debuginfo file
 300 // and return its symtab
 301 static struct symtab* build_symtab_from_build_id(Elf64_Nhdr *note)
 302 {
 303   int fd;
 304   struct symtab *symtab = NULL;
 305 
 306   unsigned char *bytes
 307     = (unsigned char*)(note+1) + note->n_namesz;
 308   char *filename
 309     = (build_id_to_debug_filename (note->n_descsz, bytes));
 310 
 311   fd = pathmap_open(filename);
 312   if (fd >= 0) {
 313     symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false);
 314     close(fd);
 315   }
 316   free(filename);
 317 
 318   return symtab;
 319 }
 320 
 321 // read symbol table from given fd.  If try_debuginfo) is true, also
 322 // try to open an associated debuginfo file
 323 static struct symtab* build_symtab_internal(int fd, const char *filename, bool try_debuginfo) {
 324   ELF_EHDR ehdr;
 325   char *names = NULL;
 326   struct symtab* symtab = NULL;
 327 
 328   // Reading of elf header
 329   struct elf_section *scn_cache = NULL;
 330   int cnt = 0;
 331   ELF_SHDR* shbuf = NULL;
 332   ELF_SHDR* cursct = NULL;
 333   ELF_PHDR* phbuf = NULL;
 334   ELF_PHDR* phdr = NULL;
 335   int sym_section = SHT_DYNSYM;
 336 
 337   uintptr_t baseaddr = (uintptr_t)-1;
 338 
 339   lseek(fd, (off_t)0L, SEEK_SET);
 340   if (! read_elf_header(fd, &ehdr)) {
 341     // not an elf
 342     return NULL;
 343   }
 344 
 345   // read ELF header
 346   if ((shbuf = read_section_header_table(fd, &ehdr)) == NULL) {
 347     goto quit;
 348   }
 349 
 350   baseaddr = find_base_address(fd, &ehdr);
 351 
 352   scn_cache = (struct elf_section *)
 353               calloc(ehdr.e_shnum * sizeof(struct elf_section), 1);
 354   if (scn_cache == NULL) {
 355     goto quit;
 356   }
 357 
 358   for (cursct = shbuf, cnt = 0; cnt < ehdr.e_shnum; cnt++) {
 359     scn_cache[cnt].c_shdr = cursct;
 360     if (cursct->sh_type == SHT_SYMTAB || cursct->sh_type == SHT_STRTAB
 361         || cursct->sh_type == SHT_NOTE || cursct->sh_type == SHT_DYNSYM) {
 362       if ( (scn_cache[cnt].c_data = read_section_data(fd, &ehdr, cursct)) == NULL) {
 363          goto quit;
 364       }
 365     }
 366     if (cursct->sh_type == SHT_SYMTAB) {
 367       // Full symbol table available so use that
 368       sym_section = cursct->sh_type;
 369     }
 370     cursct++;
 371   }
 372 
 373   for (cnt = 1; cnt < ehdr.e_shnum; cnt++) {
 374     ELF_SHDR *shdr = scn_cache[cnt].c_shdr;
 375 
 376     if (shdr->sh_type == sym_section) {
 377       ELF_SYM  *syms;
 378       int j, n, rslt;
 379       size_t size;
 380 
 381       // FIXME: there could be multiple data buffers associated with the
 382       // same ELF section. Here we can handle only one buffer. See man page
 383       // for elf_getdata on Solaris.
 384 
 385       // guarantee(symtab == NULL, "multiple symtab");
 386       symtab = (struct symtab*)calloc(1, sizeof(struct symtab));
 387       if (symtab == NULL) {
 388          goto quit;
 389       }
 390       // the symbol table
 391       syms = (ELF_SYM *)scn_cache[cnt].c_data;
 392 
 393       // number of symbols
 394       n = shdr->sh_size / shdr->sh_entsize;
 395 
 396       // create hash table, we use hcreate_r, hsearch_r and hdestroy_r to
 397       // manipulate the hash table.
 398       symtab->hash_table = (struct hsearch_data*) calloc(1, sizeof(struct hsearch_data));
 399       rslt = hcreate_r(n, symtab->hash_table);
 400       // guarantee(rslt, "unexpected failure: hcreate_r");
 401 
 402       // shdr->sh_link points to the section that contains the actual strings
 403       // for symbol names. the st_name field in ELF_SYM is just the
 404       // string table index. we make a copy of the string table so the
 405       // strings will not be destroyed by elf_end.
 406       size = scn_cache[shdr->sh_link].c_shdr->sh_size;
 407       symtab->strs = (char *)malloc(size);
 408       memcpy(symtab->strs, scn_cache[shdr->sh_link].c_data, size);
 409 
 410       // allocate memory for storing symbol offset and size;
 411       symtab->num_symbols = n;
 412       symtab->symbols = (struct elf_symbol *)calloc(n , sizeof(struct elf_symbol));
 413 
 414       // copy symbols info our symtab and enter them info the hash table
 415       for (j = 0; j < n; j++, syms++) {
 416         ENTRY item, *ret;
 417         char *sym_name = symtab->strs + syms->st_name;
 418 
 419         // skip non-object and non-function symbols
 420         int st_type = ELF_ST_TYPE(syms->st_info);
 421         if ( st_type != STT_FUNC && st_type != STT_OBJECT)
 422            continue;
 423         // skip empty strings and undefined symbols
 424         if (*sym_name == '\0' || syms->st_shndx == SHN_UNDEF) continue;
 425 
 426         symtab->symbols[j].name   = sym_name;
 427         symtab->symbols[j].offset = syms->st_value - baseaddr;
 428         symtab->symbols[j].size   = syms->st_size;
 429 
 430         item.key = sym_name;
 431         item.data = (void *)&(symtab->symbols[j]);
 432 
 433         hsearch_r(item, ENTER, &ret, symtab->hash_table);
 434       }
 435     }
 436   }
 437 
 438   // Look for a separate debuginfo file.
 439   if (try_debuginfo) {
 440 
 441     // We prefer a debug symtab to an object's own symtab, so look in
 442     // the debuginfo file.  We stash a copy of the old symtab in case
 443     // there is no debuginfo.
 444     struct symtab* prev_symtab = symtab;
 445     symtab = NULL;
 446 
 447 #ifdef NT_GNU_BUILD_ID
 448     // First we look for a Build ID
 449     for (cursct = shbuf, cnt = 0;
 450          symtab == NULL && cnt < ehdr.e_shnum;
 451          cnt++) {
 452       if (cursct->sh_type == SHT_NOTE) {
 453         Elf64_Nhdr *note = (Elf64_Nhdr *)scn_cache[cnt].c_data;
 454         if (note->n_type == NT_GNU_BUILD_ID) {
 455           symtab = build_symtab_from_build_id(note);
 456         }
 457       }
 458       cursct++;
 459     }
 460 #endif
 461 
 462     // Then, if that doesn't work, the debug link
 463     if (symtab == NULL) {
 464       symtab = build_symtab_from_debug_link(filename, fd, &ehdr, shbuf,
 465                                             scn_cache);
 466     }
 467 
 468     // If we still haven't found a symtab, use the object's own symtab.
 469     if (symtab != NULL) {
 470       if (prev_symtab != NULL)
 471         destroy_symtab(prev_symtab);
 472     } else {
 473       symtab = prev_symtab;
 474     }
 475   }
 476 
 477 quit:
 478   if (shbuf) free(shbuf);
 479   if (phbuf) free(phbuf);
 480   if (scn_cache) {
 481     for (cnt = 0; cnt < ehdr.e_shnum; cnt++) {
 482       if (scn_cache[cnt].c_data != NULL) {
 483         free(scn_cache[cnt].c_data);
 484       }
 485     }
 486     free(scn_cache);
 487   }
 488   return symtab;
 489 }
 490 
 491 struct symtab* build_symtab(int fd, const char *filename) {
 492   return build_symtab_internal(fd, filename, /* try_debuginfo */ true);
 493 }
 494 
 495 
 496 void destroy_symtab(struct symtab* symtab) {
 497   if (!symtab) return;
 498   if (symtab->strs) free(symtab->strs);
 499   if (symtab->symbols) free(symtab->symbols);
 500   if (symtab->hash_table) {
 501      hdestroy_r(symtab->hash_table);
 502      free(symtab->hash_table);
 503   }
 504   free(symtab);
 505 }
 506 
 507 uintptr_t search_symbol(struct symtab* symtab, uintptr_t base,
 508                       const char *sym_name, int *sym_size) {
 509   ENTRY item;
 510   ENTRY* ret = NULL;
 511 
 512   // library does not have symbol table
 513   if (!symtab || !symtab->hash_table)
 514      return (uintptr_t)NULL;
 515 
 516   item.key = (char*) strdup(sym_name);
 517   hsearch_r(item, FIND, &ret, symtab->hash_table);
 518   if (ret) {
 519     struct elf_symbol * sym = (struct elf_symbol *)(ret->data);
 520     uintptr_t rslt = (uintptr_t) ((char*)base + sym->offset);
 521     if (sym_size) *sym_size = sym->size;
 522     free(item.key);
 523     return rslt;
 524   }
 525 
 526 quit:
 527   free(item.key);
 528   return (uintptr_t) NULL;
 529 }
 530 
 531 const char* nearest_symbol(struct symtab* symtab, uintptr_t offset,
 532                            uintptr_t* poffset) {
 533   int n = 0;
 534   if (!symtab) return NULL;
 535   for (; n < symtab->num_symbols; n++) {
 536      struct elf_symbol* sym = &(symtab->symbols[n]);
 537      if (sym->name != NULL &&
 538          offset >= sym->offset && offset < sym->offset + sym->size) {
 539         if (poffset) *poffset = (offset - sym->offset);
 540         return sym->name;
 541      }
 542   }
 543   return NULL;
 544 }