agent/src/os/bsd/symtab.c
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File hotspot-8003348 Sdiff agent/src/os/bsd

agent/src/os/bsd/symtab.c

Print this page
8003348: SA can not read core file on OS X
   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 <search.h>
  27 #include <stdlib.h>
  28 #include <string.h>
  29 #include <db.h>
  30 #include <fcntl.h>


  31 #include "symtab.h"

  32 #include "salibelf.h"

  33 
  34 
  35 // ----------------------------------------------------
  36 // functions for symbol lookups
  37 // ----------------------------------------------------
  38 
  39 struct elf_section {
  40   ELF_SHDR   *c_shdr;
  41   void       *c_data;
  42 };

  43 
  44 struct elf_symbol {
  45   char *name;
  46   uintptr_t offset;
  47   uintptr_t size;
  48 };
  49 
  50 typedef struct symtab {
  51   char *strs;
  52   size_t num_symbols;
  53   struct elf_symbol *symbols;
  54   DB* hash_table;

  55 } symtab_t;
  56 
































  57 // read symbol table from given fd.
  58 struct symtab* build_symtab(int fd) {























































































































  59   ELF_EHDR ehdr;
  60   struct symtab* symtab = NULL;
  61 
  62   // Reading of elf header
  63   struct elf_section *scn_cache = NULL;
  64   int cnt = 0;
  65   ELF_SHDR* shbuf = NULL;
  66   ELF_SHDR* cursct = NULL;
  67   ELF_PHDR* phbuf = NULL;
  68   int symtab_found = 0;
  69   int dynsym_found = 0;
  70   uint32_t symsection = SHT_SYMTAB;
  71 
  72   uintptr_t baseaddr = (uintptr_t)-1;
  73 
  74   lseek(fd, (off_t)0L, SEEK_SET);
  75   if (! read_elf_header(fd, &ehdr)) {
  76     // not an elf
  77     return NULL;
  78   }


 159 
 160       // copy symbols info our symtab and enter them info the hash table
 161       for (j = 0; j < n; j++, syms++) {
 162         DBT key, value;
 163         char *sym_name = symtab->strs + syms->st_name;
 164 
 165         // skip non-object and non-function symbols
 166         int st_type = ELF_ST_TYPE(syms->st_info);
 167         if ( st_type != STT_FUNC && st_type != STT_OBJECT)
 168            continue;
 169         // skip empty strings and undefined symbols
 170         if (*sym_name == '\0' || syms->st_shndx == SHN_UNDEF) continue;
 171 
 172         symtab->symbols[j].name   = sym_name;
 173         symtab->symbols[j].offset = syms->st_value - baseaddr;
 174         symtab->symbols[j].size   = syms->st_size;
 175 
 176         key.data = sym_name;
 177         key.size = strlen(sym_name) + 1;
 178         value.data = &(symtab->symbols[j]);
 179         value.size = sizeof(void *);
 180         (*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0);
 181       }
 182     }
 183   }
 184   goto quit;
 185 
 186 bad:
 187   destroy_symtab(symtab);
 188   symtab = NULL;
 189 
 190 quit:
 191   if (shbuf) free(shbuf);
 192   if (phbuf) free(phbuf);
 193   if (scn_cache) {
 194     for (cnt = 0; cnt < ehdr.e_shnum; cnt++) {
 195       if (scn_cache[cnt].c_data != NULL) {
 196         free(scn_cache[cnt].c_data);
 197       }
 198     }
 199     free(scn_cache);
 200   }
 201   return symtab;
 202 }
 203 
 204 void destroy_symtab(struct symtab* symtab) {


 205   if (!symtab) return;
 206   if (symtab->strs) free(symtab->strs);
 207   if (symtab->symbols) free(symtab->symbols);
 208   if (symtab->hash_table) {
 209     (*symtab->hash_table->close)(symtab->hash_table);
 210   }
 211   free(symtab);
 212 }
 213 
 214 uintptr_t search_symbol(struct symtab* symtab, uintptr_t base,
 215                       const char *sym_name, int *sym_size) {
 216   DBT key, value;
 217   int ret;
 218 
 219   // library does not have symbol table
 220   if (!symtab || !symtab->hash_table)
 221      return 0;

 222 
 223   key.data = (char*)(uintptr_t)sym_name;
 224   key.size = strlen(sym_name) + 1;
 225   ret = (*symtab->hash_table->get)(symtab->hash_table, &key, &value, 0);
 226   if (ret == 0) {
 227     struct elf_symbol *sym = value.data;
 228     uintptr_t rslt = (uintptr_t) ((char*)base + sym->offset);
 229     if (sym_size) *sym_size = sym->size;
 230     return rslt;
 231   }
 232 
 233   return 0;
 234 }
 235 
 236 const char* nearest_symbol(struct symtab* symtab, uintptr_t offset,
 237                            uintptr_t* poffset) {
 238   int n = 0;
 239   if (!symtab) return NULL;
 240   for (; n < symtab->num_symbols; n++) {
 241     struct elf_symbol* sym = &(symtab->symbols[n]);
 242     if (sym->name != NULL &&
 243       offset >= sym->offset && offset < sym->offset + sym->size) {
 244       if (poffset) *poffset = (offset - sym->offset);
 245       return sym->name;
 246     }
 247   }
 248   return NULL;
 249 }
   1 /*
   2  * Copyright (c) 2003, 2013, 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 <search.h>
  27 #include <stdlib.h>
  28 #include <string.h>
  29 #include <db.h>
  30 #include <fcntl.h>
  31 
  32 #include "libproc_impl.h"
  33 #include "symtab.h"
  34 #ifndef __APPLE__
  35 #include "salibelf.h"
  36 #endif // __APPLE__
  37 
  38 
  39 // ----------------------------------------------------
  40 // functions for symbol lookups
  41 // ----------------------------------------------------
  42 
  43 typedef struct symtab_symbol {
  44   char *name;                // name like __ZThread_...
  45   uintptr_t offset;          // to loaded address 
  46   uintptr_t size;            // size strlen
  47 } symtab_symbol;
  48 






  49 typedef struct symtab {
  50   char *strs;                // all symbols "__symbol1__'\0'__symbol2__...."
  51   size_t num_symbols;        

  52   DB* hash_table;
  53   symtab_symbol* symbols;
  54 } symtab_t;
  55 
  56 #ifdef __APPLE__
  57 
  58 void build_search_table(symtab_t *symtab) {
  59   int i;
  60   for (i = 0; i < symtab->num_symbols; i++) {
  61     DBT key, value; 
  62     key.data = symtab->symbols[i].name;
  63     key.size = strlen(key.data) + 1;
  64     value.data = &(symtab->symbols[i]);
  65     value.size = sizeof(symtab_symbol);
  66     (*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0);
  67 
  68     // check result
  69     if (is_debug()) {
  70       DBT rkey, rvalue;
  71       char* tmp = (char *)malloc(strlen(symtab->symbols[i].name) + 1);
  72       strcpy(tmp, symtab->symbols[i].name);
  73       rkey.data = tmp;
  74       rkey.size = strlen(tmp) + 1;
  75       (*symtab->hash_table->get)(symtab->hash_table, &rkey, &rvalue, 0);
  76       // we may get a copy back so compare contents
  77       symtab_symbol *res = (symtab_symbol *)rvalue.data;
  78       if (strcmp(res->name, symtab->symbols[i].name)  ||
  79           res->offset != symtab->symbols[i].offset    ||
  80           res->size != symtab->symbols[i].size) {
  81         print_debug("error to get hash_table value!\n");
  82       }
  83       free(tmp);
  84     }
  85   }
  86 }
  87 
  88 // read symbol table from given fd.
  89 struct symtab* build_symtab(int fd) {
  90   symtab_t* symtab = NULL;
  91   int i;
  92   mach_header_64 header;
  93   off_t image_start;
  94 
  95   if (!get_arch_off(fd, CPU_TYPE_X86_64, &image_start)) {
  96     print_debug("failed in get fat header\n");
  97     return NULL;
  98   }
  99   lseek(fd, image_start, SEEK_SET);
 100   if (read(fd, (void *)&header, sizeof(mach_header_64)) != sizeof(mach_header_64)) {
 101     print_debug("reading header failed!\n");
 102     return NULL;
 103   }
 104   // header
 105   if (header.magic != MH_MAGIC_64) {
 106     print_debug("not a valid .dylib file\n");
 107     return NULL;
 108   }
 109 
 110   load_command lcmd;
 111   symtab_command symtabcmd;
 112   nlist_64 lentry;
 113 
 114   bool lcsymtab_exist = false;
 115 
 116   long filepos = ltell(fd);
 117   for (i = 0; i < header.ncmds; i++) {
 118     lseek(fd, filepos, SEEK_SET);
 119     if (read(fd, (void *)&lcmd, sizeof(load_command)) != sizeof(load_command)) {
 120       print_debug("read load_command failed for file\n");
 121       return NULL;
 122     }
 123     filepos += lcmd.cmdsize;  // next command position
 124     if (lcmd.cmd == LC_SYMTAB) {
 125       lseek(fd, -sizeof(load_command), SEEK_CUR);
 126       lcsymtab_exist = true;
 127       break;
 128     }
 129   }
 130   if (!lcsymtab_exist) {
 131     print_debug("No symtab command found!\n");
 132     return NULL;
 133   }
 134   if (read(fd, (void *)&symtabcmd, sizeof(symtab_command)) != sizeof(symtab_command)) {
 135     print_debug("read symtab_command failed for file");
 136     return NULL;
 137   }
 138   symtab = (symtab_t *)malloc(sizeof(symtab_t));
 139   if (symtab == NULL) {
 140     print_debug("out of memory: allocating symtab\n");
 141     return NULL;
 142   }
 143 
 144   // create hash table, we use berkeley db to
 145   // manipulate the hash table.
 146   symtab->hash_table = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL);
 147   if (symtab->hash_table == NULL)
 148     goto quit;
 149 
 150   symtab->num_symbols = symtabcmd.nsyms;
 151   symtab->symbols = (symtab_symbol *)malloc(sizeof(symtab_symbol) * symtab->num_symbols);
 152   symtab->strs    = (char *)malloc(sizeof(char) * symtabcmd.strsize);
 153   if (symtab->symbols == NULL || symtab->strs == NULL) {
 154      print_debug("out of memory: allocating symtab.symbol or symtab.strs\n");
 155      goto quit;
 156   }
 157   lseek(fd, image_start + symtabcmd.symoff, SEEK_SET);
 158   for (i = 0; i < symtab->num_symbols; i++) {
 159     if (read(fd, (void *)&lentry, sizeof(nlist_64)) != sizeof(nlist_64)) {
 160       print_debug("read nlist_64 failed at %i\n", i);
 161       goto quit;
 162     }
 163     symtab->symbols[i].offset = lentry.n_value;
 164     symtab->symbols[i].size  = lentry.n_un.n_strx;        // index
 165   }
 166 
 167   // string table
 168   lseek(fd, image_start + symtabcmd.stroff, SEEK_SET);
 169   int size = read(fd, (void *)(symtab->strs), symtabcmd.strsize * sizeof(char));
 170   if (size != symtabcmd.strsize * sizeof(char)) {
 171      print_debug("reading string table failed\n");
 172      goto quit;
 173   }
 174  
 175   for (i = 0; i < symtab->num_symbols; i++) {
 176     symtab->symbols[i].name = symtab->strs + symtab->symbols[i].size;
 177     if (i > 0) {
 178       // fix size
 179       symtab->symbols[i - 1].size = symtab->symbols[i].size - symtab->symbols[i - 1].size;
 180       print_debug("%s size = %d\n", symtab->symbols[i - 1].name, symtab->symbols[i - 1].size);
 181 
 182     }
 183 
 184     if (i == symtab->num_symbols - 1) {
 185       // last index
 186       symtab->symbols[i].size = 
 187             symtabcmd.strsize - symtab->symbols[i].size;
 188       print_debug("%s size = %d\n", symtab->symbols[i].name, symtab->symbols[i].size);
 189     }
 190   }
 191 
 192   // build a hashtable for fast query
 193   build_search_table(symtab);
 194   return symtab;
 195 quit:
 196   if (symtab) destroy_symtab(symtab);
 197   return NULL;
 198 }
 199 
 200 #else // __APPLE__
 201 
 202 struct elf_section {
 203   ELF_SHDR   *c_shdr;
 204   void       *c_data;
 205 };
 206 
 207 // read symbol table from given fd.
 208 struct symtab* build_symtab(int fd) {
 209   ELF_EHDR ehdr;
 210   struct symtab* symtab = NULL;
 211 
 212   // Reading of elf header
 213   struct elf_section *scn_cache = NULL;
 214   int cnt = 0;
 215   ELF_SHDR* shbuf = NULL;
 216   ELF_SHDR* cursct = NULL;
 217   ELF_PHDR* phbuf = NULL;
 218   int symtab_found = 0;
 219   int dynsym_found = 0;
 220   uint32_t symsection = SHT_SYMTAB;
 221 
 222   uintptr_t baseaddr = (uintptr_t)-1;
 223 
 224   lseek(fd, (off_t)0L, SEEK_SET);
 225   if (! read_elf_header(fd, &ehdr)) {
 226     // not an elf
 227     return NULL;
 228   }


 309 
 310       // copy symbols info our symtab and enter them info the hash table
 311       for (j = 0; j < n; j++, syms++) {
 312         DBT key, value;
 313         char *sym_name = symtab->strs + syms->st_name;
 314 
 315         // skip non-object and non-function symbols
 316         int st_type = ELF_ST_TYPE(syms->st_info);
 317         if ( st_type != STT_FUNC && st_type != STT_OBJECT)
 318            continue;
 319         // skip empty strings and undefined symbols
 320         if (*sym_name == '\0' || syms->st_shndx == SHN_UNDEF) continue;
 321 
 322         symtab->symbols[j].name   = sym_name;
 323         symtab->symbols[j].offset = syms->st_value - baseaddr;
 324         symtab->symbols[j].size   = syms->st_size;
 325 
 326         key.data = sym_name;
 327         key.size = strlen(sym_name) + 1;
 328         value.data = &(symtab->symbols[j]);
 329         value.size = sizeof(symtab_symbol);
 330         (*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0);
 331       }
 332     }
 333   }
 334   goto quit;
 335 
 336 bad:
 337   destroy_symtab(symtab);
 338   symtab = NULL;
 339 
 340 quit:
 341   if (shbuf) free(shbuf);
 342   if (phbuf) free(phbuf);
 343   if (scn_cache) {
 344     for (cnt = 0; cnt < ehdr.e_shnum; cnt++) {
 345       if (scn_cache[cnt].c_data != NULL) {
 346         free(scn_cache[cnt].c_data);
 347       }
 348     }
 349     free(scn_cache);
 350   }
 351   return symtab;
 352 }
 353 
 354 #endif // __APPLE__
 355 
 356 void destroy_symtab(symtab_t* symtab) {
 357   if (!symtab) return;
 358   free(symtab->strs);
 359   free(symtab->symbols);



 360   free(symtab);
 361 }
 362 
 363 uintptr_t search_symbol(struct symtab* symtab, uintptr_t base, const char *sym_name, int *sym_size) {

 364   DBT key, value;
 365   int ret;
 366 
 367   // library does not have symbol table
 368   if (!symtab || !symtab->hash_table) {
 369      return 0;
 370   }
 371 
 372   key.data = (char*)(uintptr_t)sym_name;
 373   key.size = strlen(sym_name) + 1;
 374   ret = (*symtab->hash_table->get)(symtab->hash_table, &key, &value, 0);
 375   if (ret == 0) {
 376     symtab_symbol *sym = value.data;
 377     uintptr_t rslt = (uintptr_t) ((char*)base + sym->offset);
 378     if (sym_size) *sym_size = sym->size;
 379     return rslt;
 380   }
 381 
 382   return 0;
 383 }
 384 
 385 const char* nearest_symbol(struct symtab* symtab, uintptr_t offset,
 386                            uintptr_t* poffset) {
 387   int n = 0;
 388   if (!symtab) return NULL;
 389   for (; n < symtab->num_symbols; n++) {
 390     symtab_symbol* sym = &(symtab->symbols[n]);
 391     if (sym->name != NULL &&
 392       offset >= sym->offset && offset < sym->offset + sym->size) {
 393       if (poffset) *poffset = (offset - sym->offset);
 394       return sym->name;
 395     }
 396   }
 397   return NULL;
 398 }
agent/src/os/bsd/symtab.c
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File