1/*
2 * Copyright (c) 2003, 2014, 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
38struct elf_section {
39  ELF_SHDR   *c_shdr;
40  void       *c_data;
41};
42
43struct elf_symbol {
44  char *name;
45  uintptr_t offset;
46  uintptr_t size;
47};
48
49typedef 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.
61static 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. */
65unsigned 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.  */
133static int
134open_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.  */
162static 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.  */
194static 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  strcpy(debug_pathname, name);
214  char *last_slash = strrchr(debug_pathname, '/');
215  if (last_slash == NULL) {
216    free(debug_pathname);
217    return -1;
218  }
219
220  /* Look in the same directory as the object.  */
221  strcpy(last_slash+1, debug_filename);
222  debug_fd = open_debug_file(debug_pathname, crc);
223  if (debug_fd >= 0) {
224    free(debug_pathname);
225    return debug_fd;
226  }
227
228  /* Look in a subdirectory named ".debug".  */
229  strcpy(last_slash+1, ".debug/");
230  strcat(last_slash, debug_filename);
231
232  debug_fd = open_debug_file(debug_pathname, crc);
233  if (debug_fd >= 0) {
234    free(debug_pathname);
235    return debug_fd;
236  }
237
238  /* Look in /usr/lib/debug + the full pathname.  */
239  strcpy(debug_pathname, debug_file_directory);
240  strcat(debug_pathname, name);
241  last_slash = strrchr(debug_pathname, '/');
242  strcpy(last_slash+1, debug_filename);
243
244  debug_fd = open_debug_file(debug_pathname, crc);
245  if (debug_fd >= 0) {
246    free(debug_pathname);
247    return debug_fd;
248  }
249
250  free(debug_pathname);
251  return -1;
252}
253
254static struct symtab* build_symtab_internal(int fd, const char *filename, bool try_debuginfo);
255
256/* Look for a ".gnu_debuglink" section.  If one exists, try to open a
257   suitable debuginfo file and read a symbol table from it.  */
258static struct symtab *build_symtab_from_debug_link(const char *name,
259                                     int fd,
260                                     ELF_EHDR *ehdr,
261                                     struct elf_section *scn_cache)
262{
263  fd = open_file_from_debug_link(name, fd, ehdr, scn_cache);
264
265  if (fd >= 0) {
266    struct symtab *symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false);
267    close(fd);
268    return symtab;
269  }
270
271  return NULL;
272}
273
274// Given a build_id, find the associated debuginfo file
275static char *
276build_id_to_debug_filename (size_t size, unsigned char *data)
277{
278  char *filename, *s;
279
280  filename = malloc(strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1
281                    + 2 * size + (sizeof ".debug" - 1) + 1);
282  s = filename + sprintf (filename, "%s/.build-id/", debug_file_directory);
283  if (size > 0)
284    {
285      size--;
286      s += sprintf (s, "%02x", *data++);
287    }
288  if (size > 0)
289    *s++ = '/';
290  while (size-- > 0)
291    s += sprintf (s, "%02x", *data++);
292  strcpy (s, ".debug");
293
294  return filename;
295}
296
297// Read a build ID note.  Try to open any associated debuginfo file
298// and return its symtab
299static struct symtab* build_symtab_from_build_id(Elf64_Nhdr *note)
300{
301  int fd;
302  struct symtab *symtab = NULL;
303
304  unsigned char *bytes
305    = (unsigned char*)(note+1) + note->n_namesz;
306  char *filename
307    = (build_id_to_debug_filename (note->n_descsz, bytes));
308
309  fd = pathmap_open(filename);
310  if (fd >= 0) {
311    symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false);
312    close(fd);
313  }
314  free(filename);
315
316  return symtab;
317}
318
319// read symbol table from given fd.  If try_debuginfo) is true, also
320// try to open an associated debuginfo file
321static struct symtab* build_symtab_internal(int fd, const char *filename, bool try_debuginfo) {
322  ELF_EHDR ehdr;
323  char *names = NULL;
324  struct symtab* symtab = NULL;
325
326  // Reading of elf header
327  struct elf_section *scn_cache = NULL;
328#if defined(ppc64) && !defined(ABI_ELFv2)
329  // Only big endian ppc64 (i.e. ABI_ELFv1) has 'official procedure descriptors' in ELF files
330  // see: http://refspecs.linuxfoundation.org/LSB_3.1.1/LSB-Core-PPC64/LSB-Core-PPC64/specialsections.html
331  struct elf_section *opd_sect = NULL;
332  ELF_SHDR *opd = NULL;
333#endif
334  int cnt = 0;
335  ELF_SHDR* shbuf = NULL;
336  ELF_SHDR* cursct = NULL;
337  ELF_PHDR* phbuf = NULL;
338  ELF_PHDR* phdr = NULL;
339  int sym_section = SHT_DYNSYM;
340
341  uintptr_t baseaddr = (uintptr_t)-1;
342
343  lseek(fd, (off_t)0L, SEEK_SET);
344  if (! read_elf_header(fd, &ehdr)) {
345    // not an elf
346    return NULL;
347  }
348
349  // read ELF header
350  if ((shbuf = read_section_header_table(fd, &ehdr)) == NULL) {
351    goto quit;
352  }
353
354  baseaddr = find_base_address(fd, &ehdr);
355
356  scn_cache = (struct elf_section *)
357              calloc(ehdr.e_shnum * sizeof(struct elf_section), 1);
358  if (scn_cache == NULL) {
359    goto quit;
360  }
361
362  for (cursct = shbuf, cnt = 0; cnt < ehdr.e_shnum; cnt++) {
363    scn_cache[cnt].c_shdr = cursct;
364    if (cursct->sh_type == SHT_SYMTAB || cursct->sh_type == SHT_STRTAB
365        || cursct->sh_type == SHT_NOTE || cursct->sh_type == SHT_DYNSYM) {
366      if ( (scn_cache[cnt].c_data = read_section_data(fd, &ehdr, cursct)) == NULL) {
367         goto quit;
368      }
369    }
370    if (cursct->sh_type == SHT_SYMTAB) {
371      // Full symbol table available so use that
372      sym_section = cursct->sh_type;
373    }
374    cursct++;
375  }
376
377#if defined(ppc64) && !defined(ABI_ELFv2)
378  opd_sect = find_section_by_name(".opd", fd, &ehdr, scn_cache);
379  if (opd_sect != NULL && opd_sect->c_data != NULL && opd_sect->c_shdr != NULL) {
380    // plausibility check
381    opd = opd_sect->c_shdr;
382  }
383#endif
384
385  for (cnt = 1; cnt < ehdr.e_shnum; cnt++) {
386    ELF_SHDR *shdr = scn_cache[cnt].c_shdr;
387
388    if (shdr->sh_type == sym_section) {
389      ELF_SYM  *syms;
390      int rslt;
391      size_t size, n, j, htab_sz;
392
393      // FIXME: there could be multiple data buffers associated with the
394      // same ELF section. Here we can handle only one buffer. See man page
395      // for elf_getdata on Solaris.
396
397      // guarantee(symtab == NULL, "multiple symtab");
398      symtab = (struct symtab*)calloc(1, sizeof(struct symtab));
399      if (symtab == NULL) {
400         goto quit;
401      }
402      // the symbol table
403      syms = (ELF_SYM *)scn_cache[cnt].c_data;
404
405      // number of symbols
406      n = shdr->sh_size / shdr->sh_entsize;
407
408      // create hash table, we use hcreate_r, hsearch_r and hdestroy_r to
409      // manipulate the hash table.
410
411      // NOTES section in the man page of hcreate_r says
412      // "Hash table implementations are usually more efficient when
413      // the table contains enough free space to minimize collisions.
414      // Typically, this means that nel should be at least 25% larger
415      // than the maximum number of elements that the caller expects
416      // to store in the table."
417      htab_sz = n*1.25;
418
419      symtab->hash_table = (struct hsearch_data*) calloc(1, sizeof(struct hsearch_data));
420      rslt = hcreate_r(n, symtab->hash_table);
421      // guarantee(rslt, "unexpected failure: hcreate_r");
422
423      // shdr->sh_link points to the section that contains the actual strings
424      // for symbol names. the st_name field in ELF_SYM is just the
425      // string table index. we make a copy of the string table so the
426      // strings will not be destroyed by elf_end.
427      size = scn_cache[shdr->sh_link].c_shdr->sh_size;
428      symtab->strs = (char *)malloc(size);
429      memcpy(symtab->strs, scn_cache[shdr->sh_link].c_data, size);
430
431      // allocate memory for storing symbol offset and size;
432      symtab->num_symbols = n;
433      symtab->symbols = (struct elf_symbol *)calloc(n , sizeof(struct elf_symbol));
434
435      // copy symbols info our symtab and enter them info the hash table
436      for (j = 0; j < n; j++, syms++) {
437        ENTRY item, *ret;
438        uintptr_t sym_value;
439        char *sym_name = symtab->strs + syms->st_name;
440
441        // skip non-object and non-function symbols
442        int st_type = ELF_ST_TYPE(syms->st_info);
443        if ( st_type != STT_FUNC && st_type != STT_OBJECT)
444           continue;
445        // skip empty strings and undefined symbols
446        if (*sym_name == '\0' || syms->st_shndx == SHN_UNDEF) continue;
447
448        symtab->symbols[j].name   = sym_name;
449        symtab->symbols[j].size   = syms->st_size;
450        sym_value = syms->st_value;
451
452#if defined(ppc64) && !defined(ABI_ELFv2)
453        // see hotspot/src/share/vm/utilities/elfFuncDescTable.hpp for a detailed description
454        // of why we have to go this extra way via the '.opd' section on big endian ppc64
455        if (opd != NULL && *sym_name != '.' &&
456            (opd->sh_addr <= sym_value && sym_value <= opd->sh_addr + opd->sh_size)) {
457          sym_value = ((ELF_ADDR*)opd_sect->c_data)[(sym_value - opd->sh_addr) / sizeof(ELF_ADDR*)];
458        }
459#endif
460
461        symtab->symbols[j].offset = sym_value - baseaddr;
462        item.key = sym_name;
463        item.data = (void *)&(symtab->symbols[j]);
464        hsearch_r(item, ENTER, &ret, symtab->hash_table);
465      }
466    }
467  }
468
469#if defined(ppc64) && !defined(ABI_ELFv2)
470  // On Linux/PPC64 the debuginfo files contain an empty function descriptor
471  // section (i.e. '.opd' section) which makes the resolution of symbols
472  // with the above algorithm impossible (we would need the have both, the
473  // .opd section from the library and the symbol table from the debuginfo
474  // file which doesn't match with the current workflow.)
475  goto quit;
476#endif
477
478  // Look for a separate debuginfo file.
479  if (try_debuginfo) {
480    // We prefer a debug symtab to an object's own symtab, so look in
481    // the debuginfo file.  We stash a copy of the old symtab in case
482    // there is no debuginfo.
483    struct symtab* prev_symtab = symtab;
484    symtab = NULL;
485
486#ifdef NT_GNU_BUILD_ID
487    // First we look for a Build ID
488    for (cursct = shbuf, cnt = 0;
489         symtab == NULL && cnt < ehdr.e_shnum;
490         cnt++) {
491      if (cursct->sh_type == SHT_NOTE) {
492        Elf64_Nhdr *note = (Elf64_Nhdr *)scn_cache[cnt].c_data;
493        if (note->n_type == NT_GNU_BUILD_ID) {
494          symtab = build_symtab_from_build_id(note);
495        }
496      }
497      cursct++;
498    }
499#endif
500
501    // Then, if that doesn't work, the debug link
502    if (symtab == NULL) {
503      symtab = build_symtab_from_debug_link(filename, fd, &ehdr,
504                                            scn_cache);
505    }
506
507    // If we still haven't found a symtab, use the object's own symtab.
508    if (symtab != NULL) {
509      if (prev_symtab != NULL)
510        destroy_symtab(prev_symtab);
511    } else {
512      symtab = prev_symtab;
513    }
514  }
515
516quit:
517  if (shbuf) free(shbuf);
518  if (phbuf) free(phbuf);
519  if (scn_cache) {
520    for (cnt = 0; cnt < ehdr.e_shnum; cnt++) {
521      if (scn_cache[cnt].c_data != NULL) {
522        free(scn_cache[cnt].c_data);
523      }
524    }
525    free(scn_cache);
526  }
527  return symtab;
528}
529
530struct symtab* build_symtab(int fd, const char *filename) {
531  return build_symtab_internal(fd, filename, /* try_debuginfo */ true);
532}
533
534
535void destroy_symtab(struct symtab* symtab) {
536  if (!symtab) return;
537  if (symtab->strs) free(symtab->strs);
538  if (symtab->symbols) free(symtab->symbols);
539  if (symtab->hash_table) {
540     hdestroy_r(symtab->hash_table);
541     free(symtab->hash_table);
542  }
543  free(symtab);
544}
545
546uintptr_t search_symbol(struct symtab* symtab, uintptr_t base,
547                      const char *sym_name, int *sym_size) {
548  ENTRY item;
549  ENTRY* ret = NULL;
550
551  // library does not have symbol table
552  if (!symtab || !symtab->hash_table)
553     return (uintptr_t)NULL;
554
555  item.key = (char*) strdup(sym_name);
556  item.data = NULL;
557  hsearch_r(item, FIND, &ret, symtab->hash_table);
558  if (ret) {
559    struct elf_symbol * sym = (struct elf_symbol *)(ret->data);
560    uintptr_t rslt = (uintptr_t) ((char*)base + sym->offset);
561    if (sym_size) *sym_size = sym->size;
562    free(item.key);
563    return rslt;
564  }
565
566quit:
567  free(item.key);
568  return (uintptr_t) NULL;
569}
570
571const char* nearest_symbol(struct symtab* symtab, uintptr_t offset,
572                           uintptr_t* poffset) {
573  int n = 0;
574  if (!symtab) return NULL;
575  for (; n < symtab->num_symbols; n++) {
576     struct elf_symbol* sym = &(symtab->symbols[n]);
577     if (sym->name != NULL &&
578         offset >= sym->offset && offset < sym->offset + sym->size) {
579        if (poffset) *poffset = (offset - sym->offset);
580        return sym->name;
581     }
582  }
583  return NULL;
584}
585