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

agent/src/os/bsd/symtab.c

Print this page
8003348: SA can not read core file on OS X

*** 1,7 **** /* ! * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. --- 1,7 ---- /* ! * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 26,63 **** #include <search.h> #include <stdlib.h> #include <string.h> #include <db.h> #include <fcntl.h> #include "symtab.h" #include "salibelf.h" // ---------------------------------------------------- // functions for symbol lookups // ---------------------------------------------------- ! struct elf_section { ! ELF_SHDR *c_shdr; ! void *c_data; ! }; - struct elf_symbol { - char *name; - uintptr_t offset; - uintptr_t size; - }; - typedef struct symtab { ! char *strs; size_t num_symbols; - struct elf_symbol *symbols; DB* hash_table; } symtab_t; // read symbol table from given fd. struct symtab* build_symtab(int fd) { ELF_EHDR ehdr; struct symtab* symtab = NULL; // Reading of elf header struct elf_section *scn_cache = NULL; --- 26,213 ---- #include <search.h> #include <stdlib.h> #include <string.h> #include <db.h> #include <fcntl.h> + + #include "libproc_impl.h" #include "symtab.h" + #ifndef __APPLE__ #include "salibelf.h" + #endif // __APPLE__ // ---------------------------------------------------- // functions for symbol lookups // ---------------------------------------------------- ! typedef struct symtab_symbol { ! char *name; // name like __ZThread_... ! uintptr_t offset; // to loaded address ! uintptr_t size; // size strlen ! } symtab_symbol; typedef struct symtab { ! char *strs; // all symbols "__symbol1__'\0'__symbol2__...." size_t num_symbols; DB* hash_table; + symtab_symbol* symbols; } symtab_t; + #ifdef __APPLE__ + + void build_search_table(symtab_t *symtab) { + int i; + for (i = 0; i < symtab->num_symbols; i++) { + DBT key, value; + key.data = symtab->symbols[i].name; + key.size = strlen(key.data) + 1; + value.data = &(symtab->symbols[i]); + value.size = sizeof(symtab_symbol); + (*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0); + + // check result + if (is_debug()) { + DBT rkey, rvalue; + char* tmp = (char *)malloc(strlen(symtab->symbols[i].name) + 1); + strcpy(tmp, symtab->symbols[i].name); + rkey.data = tmp; + rkey.size = strlen(tmp) + 1; + (*symtab->hash_table->get)(symtab->hash_table, &rkey, &rvalue, 0); + // we may get a copy back so compare contents + symtab_symbol *res = (symtab_symbol *)rvalue.data; + if (strcmp(res->name, symtab->symbols[i].name) || + res->offset != symtab->symbols[i].offset || + res->size != symtab->symbols[i].size) { + print_debug("error to get hash_table value!\n"); + } + free(tmp); + } + } + } + // read symbol table from given fd. struct symtab* build_symtab(int fd) { + symtab_t* symtab = NULL; + int i; + mach_header_64 header; + off_t image_start; + + if (!get_arch_off(fd, CPU_TYPE_X86_64, &image_start)) { + print_debug("failed in get fat header\n"); + return NULL; + } + lseek(fd, image_start, SEEK_SET); + if (read(fd, (void *)&header, sizeof(mach_header_64)) != sizeof(mach_header_64)) { + print_debug("reading header failed!\n"); + return NULL; + } + // header + if (header.magic != MH_MAGIC_64) { + print_debug("not a valid .dylib file\n"); + return NULL; + } + + load_command lcmd; + symtab_command symtabcmd; + nlist_64 lentry; + + bool lcsymtab_exist = false; + + long filepos = ltell(fd); + for (i = 0; i < header.ncmds; i++) { + lseek(fd, filepos, SEEK_SET); + if (read(fd, (void *)&lcmd, sizeof(load_command)) != sizeof(load_command)) { + print_debug("read load_command failed for file\n"); + return NULL; + } + filepos += lcmd.cmdsize; // next command position + if (lcmd.cmd == LC_SYMTAB) { + lseek(fd, -sizeof(load_command), SEEK_CUR); + lcsymtab_exist = true; + break; + } + } + if (!lcsymtab_exist) { + print_debug("No symtab command found!\n"); + return NULL; + } + if (read(fd, (void *)&symtabcmd, sizeof(symtab_command)) != sizeof(symtab_command)) { + print_debug("read symtab_command failed for file"); + return NULL; + } + symtab = (symtab_t *)malloc(sizeof(symtab_t)); + if (symtab == NULL) { + print_debug("out of memory: allocating symtab\n"); + return NULL; + } + + // create hash table, we use berkeley db to + // manipulate the hash table. + symtab->hash_table = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL); + if (symtab->hash_table == NULL) + goto quit; + + symtab->num_symbols = symtabcmd.nsyms; + symtab->symbols = (symtab_symbol *)malloc(sizeof(symtab_symbol) * symtab->num_symbols); + symtab->strs = (char *)malloc(sizeof(char) * symtabcmd.strsize); + if (symtab->symbols == NULL || symtab->strs == NULL) { + print_debug("out of memory: allocating symtab.symbol or symtab.strs\n"); + goto quit; + } + lseek(fd, image_start + symtabcmd.symoff, SEEK_SET); + for (i = 0; i < symtab->num_symbols; i++) { + if (read(fd, (void *)&lentry, sizeof(nlist_64)) != sizeof(nlist_64)) { + print_debug("read nlist_64 failed at %i\n", i); + goto quit; + } + symtab->symbols[i].offset = lentry.n_value; + symtab->symbols[i].size = lentry.n_un.n_strx; // index + } + + // string table + lseek(fd, image_start + symtabcmd.stroff, SEEK_SET); + int size = read(fd, (void *)(symtab->strs), symtabcmd.strsize * sizeof(char)); + if (size != symtabcmd.strsize * sizeof(char)) { + print_debug("reading string table failed\n"); + goto quit; + } + + for (i = 0; i < symtab->num_symbols; i++) { + symtab->symbols[i].name = symtab->strs + symtab->symbols[i].size; + if (i > 0) { + // fix size + symtab->symbols[i - 1].size = symtab->symbols[i].size - symtab->symbols[i - 1].size; + print_debug("%s size = %d\n", symtab->symbols[i - 1].name, symtab->symbols[i - 1].size); + + } + + if (i == symtab->num_symbols - 1) { + // last index + symtab->symbols[i].size = + symtabcmd.strsize - symtab->symbols[i].size; + print_debug("%s size = %d\n", symtab->symbols[i].name, symtab->symbols[i].size); + } + } + + // build a hashtable for fast query + build_search_table(symtab); + return symtab; + quit: + if (symtab) destroy_symtab(symtab); + return NULL; + } + + #else // __APPLE__ + + struct elf_section { + ELF_SHDR *c_shdr; + void *c_data; + }; + + // read symbol table from given fd. + struct symtab* build_symtab(int fd) { ELF_EHDR ehdr; struct symtab* symtab = NULL; // Reading of elf header struct elf_section *scn_cache = NULL;
*** 174,184 **** symtab->symbols[j].size = syms->st_size; key.data = sym_name; key.size = strlen(sym_name) + 1; value.data = &(symtab->symbols[j]); ! value.size = sizeof(void *); (*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0); } } } goto quit; --- 324,334 ---- symtab->symbols[j].size = syms->st_size; key.data = sym_name; key.size = strlen(sym_name) + 1; value.data = &(symtab->symbols[j]); ! value.size = sizeof(symtab_symbol); (*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0); } } } goto quit;
*** 199,232 **** free(scn_cache); } return symtab; } ! void destroy_symtab(struct symtab* symtab) { if (!symtab) return; ! if (symtab->strs) free(symtab->strs); ! if (symtab->symbols) free(symtab->symbols); ! if (symtab->hash_table) { ! (*symtab->hash_table->close)(symtab->hash_table); ! } free(symtab); } ! uintptr_t search_symbol(struct symtab* symtab, uintptr_t base, ! const char *sym_name, int *sym_size) { DBT key, value; int ret; // library does not have symbol table ! if (!symtab || !symtab->hash_table) return 0; key.data = (char*)(uintptr_t)sym_name; key.size = strlen(sym_name) + 1; ret = (*symtab->hash_table->get)(symtab->hash_table, &key, &value, 0); if (ret == 0) { ! struct elf_symbol *sym = value.data; uintptr_t rslt = (uintptr_t) ((char*)base + sym->offset); if (sym_size) *sym_size = sym->size; return rslt; } --- 349,381 ---- free(scn_cache); } return symtab; } ! #endif // __APPLE__ ! ! void destroy_symtab(symtab_t* symtab) { if (!symtab) return; ! free(symtab->strs); ! free(symtab->symbols); free(symtab); } ! uintptr_t search_symbol(struct symtab* symtab, uintptr_t base, const char *sym_name, int *sym_size) { DBT key, value; int ret; // library does not have symbol table ! if (!symtab || !symtab->hash_table) { return 0; + } key.data = (char*)(uintptr_t)sym_name; key.size = strlen(sym_name) + 1; ret = (*symtab->hash_table->get)(symtab->hash_table, &key, &value, 0); if (ret == 0) { ! symtab_symbol *sym = value.data; uintptr_t rslt = (uintptr_t) ((char*)base + sym->offset); if (sym_size) *sym_size = sym->size; return rslt; }
*** 236,246 **** const char* nearest_symbol(struct symtab* symtab, uintptr_t offset, uintptr_t* poffset) { int n = 0; if (!symtab) return NULL; for (; n < symtab->num_symbols; n++) { ! struct elf_symbol* sym = &(symtab->symbols[n]); if (sym->name != NULL && offset >= sym->offset && offset < sym->offset + sym->size) { if (poffset) *poffset = (offset - sym->offset); return sym->name; } --- 385,395 ---- const char* nearest_symbol(struct symtab* symtab, uintptr_t offset, uintptr_t* poffset) { int n = 0; if (!symtab) return NULL; for (; n < symtab->num_symbols; n++) { ! symtab_symbol* sym = &(symtab->symbols[n]); if (sym->name != NULL && offset >= sym->offset && offset < sym->offset + sym->size) { if (poffset) *poffset = (offset - sym->offset); return sym->name; }
agent/src/os/bsd/symtab.c
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File