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