static CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname) { long storage_needed; asymbol *sym; asymbol **symbol_table; unsigned int number_of_symbols; unsigned int i; struct cleanup *back_to; CORE_ADDR symaddr = 0; storage_needed = bfd_get_symtab_upper_bound (abfd); if (storage_needed > 0) { symbol_table = (asymbol **) xmalloc (storage_needed); back_to = make_cleanup (xfree, symbol_table); number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); for (i = 0; i < number_of_symbols; i++) { sym = *symbol_table++; if (strcmp (sym->name, symname) == 0) { /* Bfd symbols are section relative. */ symaddr = sym->value + sym->section->vma; break; } } do_cleanups (back_to); } if (symaddr) return symaddr; /* Look for the symbol in the dynamic string table too. */ storage_needed = bfd_get_dynamic_symtab_upper_bound (abfd); if (storage_needed > 0) { symbol_table = (asymbol **) xmalloc (storage_needed); back_to = make_cleanup (xfree, symbol_table); number_of_symbols = bfd_canonicalize_dynamic_symtab (abfd, symbol_table); for (i = 0; i < number_of_symbols; i++) { sym = *symbol_table++; if (strcmp (sym->name, symname) == 0) { /* Bfd symbols are section relative. */ symaddr = sym->value + sym->section->vma; break; } } do_cleanups (back_to); } return symaddr; }
static int slurp_symtab(bfd *abfd, struct a2l_data *a2l) { long storage; long symcount; asymbol **syms; bfd_boolean dynamic = FALSE; if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0) return bfd_error(bfd_get_filename(abfd)); storage = bfd_get_symtab_upper_bound(abfd); if (storage == 0L) { storage = bfd_get_dynamic_symtab_upper_bound(abfd); dynamic = TRUE; } if (storage < 0L) return bfd_error(bfd_get_filename(abfd)); syms = malloc(storage); if (dynamic) symcount = bfd_canonicalize_dynamic_symtab(abfd, syms); else symcount = bfd_canonicalize_symtab(abfd, syms); if (symcount < 0) { free(syms); return bfd_error(bfd_get_filename(abfd)); } a2l->syms = syms; return 0; }
static int elf_read_symbols(elf_reader_t *reader, const char *path, elfread_src_t srcsec) { int i, nsymbols, nfiltered, iflt; size_t storage_needed; reader->__abfd = bfd_openr(path, NULL); if (!reader->__abfd) return -1; bfd_check_format(reader->__abfd, bfd_object); storage_needed = (srcsec == READSYMBOLS_TEXT) ? bfd_get_symtab_upper_bound(reader->__abfd) : bfd_get_dynamic_symtab_upper_bound(reader->__abfd); if (storage_needed <= 0) { return -1; } reader->__symbol_table = (asymbol**)malloc(storage_needed); if (!reader->__symbol_table) return -1; nsymbols = (srcsec == READSYMBOLS_TEXT) ? bfd_canonicalize_symtab(reader->__abfd, reader->__symbol_table) : bfd_canonicalize_dynamic_symtab(reader->__abfd, reader->__symbol_table); if (nsymbols < 0) return -1; nfiltered = 0; for (i = 0; i < nsymbols; i++) { if (reader->__symbol_table[i]->flags & (BSF_FUNCTION | BSF_GLOBAL)) nfiltered++; } reader->symbols = (elf_symbol_t *)malloc(nfiltered * sizeof(elf_symbol_t)); if (!reader->symbols) return -1; for (i = 0, iflt = 0; i < nsymbols && iflt < nfiltered; i++) { asymbol *is = reader->__symbol_table[i]; if (is->flags & (BSF_FUNCTION | BSF_GLOBAL)) { elf_symbol_t *os = reader->symbols + iflt++; os->symbol_name = (const char *)bfd_asymbol_name(is); os->symbol_value = bfd_asymbol_value(is); os->symbol_size = BFD_GET_SYMBOL_SIZE(is); os->symbol_class = (char)bfd_decode_symclass(is); } } assert(iflt == nfiltered); return iflt; }
std::vector<asymbol*> slurpDynamicSymtab(bfd* abfd) { long storage_needed = bfd_get_dynamic_symtab_upper_bound (abfd); if (storage_needed <= 0) return std::vector<asymbol*>(); std::vector<asymbol*> res(storage_needed); long symcount = bfd_canonicalize_dynamic_symtab (abfd, &res[0]); res.resize(symcount); return std::move(res); }
/** * Obtain the information of dynamic symbol (library call) */ dyn_functions_t *get_synthetic_symbols(const char *filename) { asymbol** syms = NULL; long symcount = 0; asymbol** dynsyms = NULL; long dynsymcount = 0; asymbol* synthsyms = NULL; long synthcount = 0; long storage; vector<dyn_function_t *> *ret = new vector<dyn_function_t *>(); asm_program_t *prog = new asm_program_t; bfd *abfd = initialize_bfd(filename); initialize_sections(abfd, prog); if (bfd_get_file_flags (abfd) & HAS_SYMS) { storage = bfd_get_symtab_upper_bound (abfd); assert (storage >= 0); if (storage > 0) syms = (asymbol**) xmalloc(storage); symcount = bfd_canonicalize_symtab (abfd, syms); assert (symcount >= 0); } storage = bfd_get_dynamic_symtab_upper_bound (abfd); if (storage > 0) { dynsyms = (asymbol**) xmalloc(storage); dynsymcount = bfd_canonicalize_dynamic_symtab (abfd, dynsyms); } synthcount = bfd_get_synthetic_symtab (abfd, symcount, syms, dynsymcount, dynsyms, &synthsyms); if (synthcount < 0) synthcount = 0; for (int i=0; i<synthcount; ++i) { dyn_function_t *temp = new dyn_function_t; temp->name = string(bfd_asymbol_name(&(synthsyms[i]))); temp->addr = bfd_asymbol_value(&(synthsyms[i])); ret->push_back(temp); } if (synthsyms) free(synthsyms); if (dynsyms) free(dynsyms); if (syms) free(syms); bfd_close(abfd); return ret; }
long _bfd_generic_read_minisymbols (bfd *abfd, bfd_boolean dynamic, void **minisymsp, unsigned int *sizep) { long storage; asymbol **syms = NULL; long symcount; if (dynamic) storage = bfd_get_dynamic_symtab_upper_bound (abfd); else storage = bfd_get_symtab_upper_bound (abfd); if (storage < 0) goto error_return; if (storage == 0) return 0; syms = (asymbol **) bfd_malloc (storage); if (syms == NULL) goto error_return; if (dynamic) symcount = bfd_canonicalize_dynamic_symtab (abfd, syms); else symcount = bfd_canonicalize_symtab (abfd, syms); if (symcount < 0) goto error_return; *minisymsp = syms; *sizep = sizeof (asymbol *); return symcount; error_return: bfd_set_error (bfd_error_no_symbols); if (syms != NULL) free (syms); return -1; }
static void read_syms(bfd *abfd) { long storage, symcount; bfd_boolean dynamic = FALSE; if (syms) return; if (!(bfd_get_file_flags(abfd) & HAS_SYMS)) { wpa_printf(MSG_INFO, "No symbols"); return; } storage = bfd_get_symtab_upper_bound(abfd); if (storage == 0) { storage = bfd_get_dynamic_symtab_upper_bound(abfd); dynamic = TRUE; } if (storage < 0) { wpa_printf(MSG_INFO, "Unknown symtab upper bound"); return; } syms = malloc(storage); if (syms == NULL) { wpa_printf(MSG_INFO, "Failed to allocate memory for symtab " "(%ld bytes)", storage); return; } if (dynamic) symcount = bfd_canonicalize_dynamic_symtab(abfd, syms); else symcount = bfd_canonicalize_symtab(abfd, syms); if (symcount < 0) { wpa_printf(MSG_INFO, "Failed to canonicalize %ssymtab", dynamic ? "dynamic " : ""); free(syms); syms = NULL; return; } }
int main(int argc, char *argv[]) { bfd *abfd; bfd_init(); abfd = bfd_openr(argv[1], NULL); if (abfd == NULL) { bfd_perror("bfd_openr"); exit(1); } if (! bfd_check_format(abfd, bfd_object)) { bfd_perror("bfd_check_format"); } printf("SYMBOL TABLE:\n"); { long storage_needed; asymbol **symbol_table; long number_of_symbols; long i; storage_needed = bfd_get_symtab_upper_bound (abfd); printf("storage_need=%d\n", storage_needed); if (storage_needed < 0) { bfd_perror("bfd_get_symtab_upper_bound"); exit(1); } if (storage_needed == 0) { printf("no symbols\n"); exit(0); } symbol_table = (asymbol **)malloc (storage_needed); number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); if (number_of_symbols < 0) { bfd_perror("bfd_canonicalize_symtab"); exit(1); } for (i = 0; i < number_of_symbols; i++) { asymbol *asym = symbol_table[i]; int symclass = bfd_decode_symclass(asym); symbol_info syminfo; bfd_symbol_info(asym, &syminfo); bfd_print_symbol_vandf(abfd, stdout, asym); printf(" 0x%x %s ", symclass, bfd_is_undefined_symclass(symclass) ? "?" : " "); printf(" %s ", bfd_asymbol_name(asym)); printf("%p ", bfd_asymbol_value(asym)); // printf(" %d ", syminfo.value); /* asymbol_value */ // printf(" %d ", syminfo.type); /* symclass */ // printf(" %s ", syminfo.name); /* asymbol_name */ printf(" %d ", syminfo.stab_type); printf(" %d ", syminfo.stab_other); printf(" %d ", syminfo.stab_desc); // printf(" %s ", syminfo.stab_name); printf("\n"); } } printf("DYNAMIC SYMBOL TABLE:\n"); { long storage_needed; asymbol **symbol_table; long number_of_symbols; long i; storage_needed = bfd_get_dynamic_symtab_upper_bound (abfd); printf("storage_need=%d\n", storage_needed); if (storage_needed < 0) { bfd_perror("bfd_get_symtab_upper_bound"); exit(1); } if (storage_needed == 0) { printf("no symbols\n"); exit(0); } symbol_table = (asymbol **)malloc (storage_needed); number_of_symbols = bfd_canonicalize_dynamic_symtab (abfd, symbol_table); if (number_of_symbols < 0) { bfd_perror("bfd_canonicalize_symtab"); exit(1); } for (i = 0; i < number_of_symbols; i++) { asymbol *asym = symbol_table[i]; int symclass = bfd_decode_symclass(asym); symbol_info syminfo; bfd_symbol_info(asym, &syminfo); bfd_print_symbol_vandf(abfd, stdout, asym); printf(" 0x%x %s ", symclass, bfd_is_undefined_symclass(symclass) ? "?" : " "); printf(" %s ", bfd_asymbol_name(asym)); printf("%p ", bfd_asymbol_value(asym)); // printf(" %d ", syminfo.value); /* asymbol_value */ // printf(" %d ", syminfo.type); /* symclass */ // printf(" %s ", syminfo.name); /* asymbol_name */ printf(" %d ", syminfo.stab_type); printf(" %d ", syminfo.stab_other); printf(" %d ", syminfo.stab_desc); // printf(" %s ", syminfo.stab_name); printf("\n"); } } exit(0); }
vine_symbols_t * get_symbols_of_file(const char *filename) { asymbol** syms = NULL; long symcount = 0; long sorted_symcount = 0; asymbol** dynsyms = NULL; long dynsymcount = 0; asymbol* synthsyms = NULL; long synthcount = 0; long storage; vector<vine_symbol_t *> *ret = new vector<vine_symbol_t *>(); // asm_program_t *prog = new asm_program_t; // printf("initializing bfd\n\n"); bfd *abfd = initialize_bfd(filename); // printf("done\n\n"); // printf("initializing sections...\n\n"); // initialize_sections(abfd, prog); // printf("done\n\n"); asymbol *sym; if (bfd_get_file_flags (abfd) & HAS_SYMS) { storage = bfd_get_symtab_upper_bound (abfd); assert (storage >= 0); if (storage > 0) syms = (asymbol**) xmalloc(storage); symcount = bfd_canonicalize_symtab (abfd, syms); assert (symcount >= 0); sorted_symcount = remove_useless_symbols(syms, symcount); qsort(syms, sorted_symcount, sizeof(asymbol *), compare_symbols); for(int i= 0; i < sorted_symcount; i++){ vine_symbol_t *temp = new vine_symbol_t; temp->name = string(bfd_asymbol_name((syms[i]))); temp->addr = bfd_asymbol_value((syms[i])); sym = syms[i]; temp->is_function = (sym->flags & BSF_FUNCTION) != 0; temp->is_dynamic = 0; ret->push_back(temp); } } storage = bfd_get_dynamic_symtab_upper_bound (abfd); if (storage > 0) { dynsyms = (asymbol**) xmalloc(storage); dynsymcount = bfd_canonicalize_dynamic_symtab (abfd, dynsyms); } synthcount = bfd_get_synthetic_symtab (abfd, symcount, syms, dynsymcount, dynsyms, &synthsyms); if (synthcount < 0) synthcount = 0; for (int i=0; i<synthcount; i++) { vine_symbol_t *temp = new vine_symbol_t; temp->name = string(bfd_asymbol_name(&(synthsyms[i]))); temp->addr = bfd_asymbol_value(&(synthsyms[i])); temp->is_function = (synthsyms[i].flags & BSF_FUNCTION) != 0; temp->is_dynamic = 1; ret->push_back(temp); } if (synthsyms) free(synthsyms); if (dynsyms) free(dynsyms); if (syms) free(syms); bfd_close(abfd); return ret; }
int main(int argc, char ** argv) { bfd *fd; asection *sec; file_ptr offset; long st_size; asymbol ** symbol_table; long sym_count, i; if (argc != 2) { fprintf(stderr, "Usage: objinfo_helper <dynamic library>\n"); return 2; } fd = bfd_openr(argv[1], "default"); if (!fd) { fprintf(stderr, "Error opening file %s\n", argv[1]); return 2; } if (! bfd_check_format (fd, bfd_object)) { fprintf(stderr, "Error: wrong format\n"); bfd_close(fd); return 2; } sec = bfd_get_section_by_name(fd, ".data"); if (! sec) { fprintf(stderr, "Error: section .data not found\n"); bfd_close(fd); return 2; } offset = sec->filepos; st_size = bfd_get_dynamic_symtab_upper_bound (fd); if (st_size <= 0) { fprintf(stderr, "Error: size of section .data unknown\n"); bfd_close(fd); return 2; } symbol_table = malloc(st_size); if (! symbol_table) { fprintf(stderr, "Error: out of memory\n"); bfd_close(fd); return 2; } sym_count = bfd_canonicalize_dynamic_symtab (fd, symbol_table); for (i = 0; i < sym_count; i++) { if (strcmp(symbol_table[i]->name, "caml_plugin_header") == 0) { printf("%ld\n", (long) (offset + symbol_table[i]->value)); bfd_close(fd); return 0; } } fprintf(stderr, "Error: missing symbol caml_plugin_header\n"); bfd_close(fd); return 2; }
void mini_dump_get_debug_info_about_address(MiniDump *self, guint64 address, gchar *module_name, const gchar **source_file_name, const gchar **function_name,guint *line_number) { gchar *filename = g_build_filename(self->bin_dir,module_name, NULL); bfd *abfd = bfd_openr(filename,NULL); asection *section; long storage; long symcount; bfd_boolean dynamic = FALSE; asymbol **syms; if (abfd == NULL) return; if (!bfd_check_format (abfd, bfd_object)) { bfd_close(abfd); return; } if ((bfd_get_file_flags (abfd) & HAS_SYMS) == 0) { bfd_close(abfd); return; } storage = bfd_get_symtab_upper_bound (abfd); if (storage == 0) { storage = bfd_get_dynamic_symtab_upper_bound (abfd); dynamic = TRUE; } if (storage < 0) { bfd_close(abfd); return; } syms = (asymbol **) g_malloc0(storage); if (dynamic) symcount = bfd_canonicalize_dynamic_symtab (abfd, syms); else symcount = bfd_canonicalize_symtab (abfd, syms); if (symcount < 0) { bfd_close(abfd); g_free(syms); return; } section = abfd->sections; long i = 0; gchar *temp = g_strdup_printf("%s_symbols",filename); FILE *sym_file = fopen(temp,"wb"); for (i = 0; i < symcount; i++) { fprintf(sym_file,"%s\t%08X\t%08X\t%p\n",syms[i]->name,syms[i]->value,syms[i]->flags,syms[i]->udata.p); } g_free(temp); fclose(sym_file); while(section) { bfd_vma vma; bfd_vma pc = address; bfd_size_type size; if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0) { goto next_iteration; } vma = bfd_get_section_vma (abfd, section); if (pc < vma) { goto next_iteration; } size = bfd_get_section_size (section); if (pc >= vma + size) { goto next_iteration; } if (bfd_find_nearest_line (abfd, section, syms, pc - vma, source_file_name, function_name, line_number)) { break; } next_iteration: section = section->next; } }
void resolve(const address_type& addr, const char * binfile, const char ** source_file_name, const char ** func_name, unsigned int * line_number) { if (!binfile || !*binfile) { return; } *source_file_name = nullptr; *line_number = 0; *func_name = nullptr; boost::mutex::scoped_lock lock(_lib_mutex); _init(); if (!_init_called) { return; } sym_map_type::iterator itBfd = _syms.find(binfile); if (itBfd == _syms.end()) { sym_tab_type fbfd; fbfd.base = _compute_maps_base(binfile); //FIXME: char *find_separate_debug_file (bfd *abfd); fbfd.abfd.reset(bfd_openr(binfile, 0), bfd_close_wrapper()); if (!fbfd.abfd) { return; } #ifdef BFD_DECOMPRESS // Old libbfd? fbfd.abfd->flags |= BFD_DECOMPRESS; #endif // Required bfd_check_format(fbfd.abfd.get(), bfd_object); fbfd.text = bfd_get_section_by_name(fbfd.abfd.get(), ".text"); fbfd.storage_needed = bfd_get_symtab_upper_bound(fbfd.abfd.get()); if (0 == fbfd.storage_needed) { fbfd.dynamic = true; fbfd.storage_needed = bfd_get_dynamic_symtab_upper_bound(fbfd.abfd.get()); } fbfd.syms.reset(static_cast<asymbol**>(::malloc(fbfd.storage_needed)), free_wrapper<asymbol*>()); if (fbfd.dynamic) { fbfd.cSymbols = bfd_canonicalize_dynamic_symtab(fbfd.abfd.get(), fbfd.syms.get()); } else { fbfd.cSymbols = bfd_canonicalize_symtab(fbfd.abfd.get(), fbfd.syms.get()); } BOOST_ASSERT(fbfd.cSymbols >= 0); _syms[binfile] = fbfd; itBfd = _syms.find(binfile); } if (itBfd != _syms.end()) { const sym_tab_type &stab = itBfd->second; bfd_vma vma = bfd_get_section_vma(stab.abfd.get(), stab.text); long offset = ((long)addr) - stab.base - vma; //stab.text->vma; if (offset > 0) { if ( !bfd_find_nearest_line(stab.abfd.get(), stab.text, stab.syms.get(), offset, source_file_name, func_name, line_number) ) { //std::cerr << "libbfd: could not find " << std::hex << addr; *source_file_name = nullptr; *line_number = 0; *func_name = nullptr; } //trace it } } }
static void elf_symtab_read (struct objfile *objfile, int dynamic) { long storage_needed; asymbol *sym; asymbol **symbol_table; long number_of_symbols; long i; int index; struct cleanup *back_to; CORE_ADDR symaddr; CORE_ADDR offset; enum minimal_symbol_type ms_type; /* If sectinfo is nonNULL, it contains section info that should end up filed in the objfile. */ struct stab_section_info *sectinfo = NULL; /* If filesym is nonzero, it points to a file symbol, but we haven't seen any section info for it yet. */ asymbol *filesym = 0; #ifdef SOFUN_ADDRESS_MAYBE_MISSING /* Name of filesym, as saved on the symbol_obstack. */ char *filesymname = obsavestring ("", 0, &objfile->symbol_obstack); #endif struct dbx_symfile_info *dbx = objfile->sym_stab_info; unsigned long size; int stripped = (bfd_get_symcount (objfile->obfd) == 0); if (dynamic) { storage_needed = bfd_get_dynamic_symtab_upper_bound (objfile->obfd); /* Nothing to be done if there is no dynamic symtab. */ if (storage_needed < 0) return; } else { storage_needed = bfd_get_symtab_upper_bound (objfile->obfd); if (storage_needed < 0) error ("Can't read symbols from %s: %s", bfd_get_filename (objfile->obfd), bfd_errmsg (bfd_get_error ())); } if (storage_needed > 0) { symbol_table = (asymbol **) xmalloc (storage_needed); back_to = make_cleanup (xfree, symbol_table); if (dynamic) number_of_symbols = bfd_canonicalize_dynamic_symtab (objfile->obfd, symbol_table); else number_of_symbols = bfd_canonicalize_symtab (objfile->obfd, symbol_table); if (number_of_symbols < 0) error ("Can't read symbols from %s: %s", bfd_get_filename (objfile->obfd), bfd_errmsg (bfd_get_error ())); for (i = 0; i < number_of_symbols; i++) { sym = symbol_table[i]; if (sym->name == NULL || *sym->name == '\0') { /* Skip names that don't exist (shouldn't happen), or names that are null strings (may happen). */ continue; } offset = ANOFFSET (objfile->section_offsets, sym->section->index); if (dynamic && sym->section == &bfd_und_section && (sym->flags & BSF_FUNCTION)) { struct minimal_symbol *msym; /* Symbol is a reference to a function defined in a shared library. If its value is non zero then it is usually the address of the corresponding entry in the procedure linkage table, plus the desired section offset. If its value is zero then the dynamic linker has to resolve the symbol. We are unable to find any meaningful address for this symbol in the executable file, so we skip it. */ symaddr = sym->value; if (symaddr == 0) continue; symaddr += offset; msym = record_minimal_symbol_and_info ((char *) sym->name, symaddr, mst_solib_trampoline, NULL, sym->section, objfile); #ifdef SOFUN_ADDRESS_MAYBE_MISSING if (msym != NULL) msym->filename = filesymname; #endif continue; } /* If it is a nonstripped executable, do not enter dynamic symbols, as the dynamic symbol table is usually a subset of the main symbol table. */ if (dynamic && !stripped) continue; if (sym->flags & BSF_FILE) { /* STT_FILE debugging symbol that helps stabs-in-elf debugging. Chain any old one onto the objfile; remember new sym. */ if (sectinfo != NULL) { sectinfo->next = dbx->stab_section_info; dbx->stab_section_info = sectinfo; sectinfo = NULL; } filesym = sym; #ifdef SOFUN_ADDRESS_MAYBE_MISSING filesymname = obsavestring ((char *) filesym->name, strlen (filesym->name), &objfile->symbol_obstack); #endif } else if (sym->flags & (BSF_GLOBAL | BSF_LOCAL | BSF_WEAK)) { struct minimal_symbol *msym; /* Select global/local/weak symbols. Note that bfd puts abs symbols in their own section, so all symbols we are interested in will have a section. */ /* Bfd symbols are section relative. */ symaddr = sym->value + sym->section->vma; /* Relocate all non-absolute symbols by the section offset. */ if (sym->section != &bfd_abs_section) { symaddr += offset; } /* For non-absolute symbols, use the type of the section they are relative to, to intuit text/data. Bfd provides no way of figuring this out for absolute symbols. */ if (sym->section == &bfd_abs_section) { /* This is a hack to get the minimal symbol type right for Irix 5, which has absolute addresses with special section indices for dynamic symbols. */ unsigned short shndx = ((elf_symbol_type *) sym)->internal_elf_sym.st_shndx; switch (shndx) { case SHN_MIPS_TEXT: ms_type = mst_text; break; case SHN_MIPS_DATA: ms_type = mst_data; break; case SHN_MIPS_ACOMMON: ms_type = mst_bss; break; default: ms_type = mst_abs; } /* If it is an Irix dynamic symbol, skip section name symbols, relocate all others by section offset. */ if (ms_type != mst_abs) { if (sym->name[0] == '.') continue; symaddr += offset; } } else if (sym->section->flags & SEC_CODE) { if (sym->flags & BSF_GLOBAL) { ms_type = mst_text; } else if ((sym->name[0] == '.' && sym->name[1] == 'L') || ((sym->flags & BSF_LOCAL) && sym->name[0] == '$' && sym->name[1] == 'L')) /* Looks like a compiler-generated label. Skip it. The assembler should be skipping these (to keep executables small), but apparently with gcc on the (OBSOLETE) delta m88k SVR4, it loses. So to have us check too should be harmless (but I encourage people to fix this in the assembler instead of adding checks here). */ continue; else { ms_type = mst_file_text; } } else if (sym->section->flags & SEC_ALLOC) { if (sym->flags & (BSF_GLOBAL | BSF_WEAK)) { if (sym->section->flags & SEC_LOAD) { ms_type = mst_data; } else { ms_type = mst_bss; } } else if (sym->flags & BSF_LOCAL) { /* Named Local variable in a Data section. Check its name for stabs-in-elf. The STREQ macro checks the first character inline, so we only actually do a strcmp function call on names that start with 'B' or 'D' */ index = SECT_OFF_MAX; if (STREQ ("Bbss.bss", sym->name)) { index = SECT_OFF_BSS (objfile); } else if (STREQ ("Ddata.data", sym->name)) { index = SECT_OFF_DATA (objfile); } else if (STREQ ("Drodata.rodata", sym->name)) { index = SECT_OFF_RODATA (objfile); } if (index != SECT_OFF_MAX) { /* Found a special local symbol. Allocate a sectinfo, if needed, and fill it in. */ if (sectinfo == NULL) { sectinfo = (struct stab_section_info *) xmmalloc (objfile->md, sizeof (*sectinfo)); memset (sectinfo, 0, sizeof (*sectinfo)); if (filesym == NULL) { complain (§ion_info_complaint, sym->name); } else { sectinfo->filename = (char *) filesym->name; } } if (index != -1) { if (sectinfo->sections[index] != 0) { complain (§ion_info_dup_complaint, sectinfo->filename); } } else internal_error (__FILE__, __LINE__, "Section index uninitialized."); /* Bfd symbols are section relative. */ symaddr = sym->value + sym->section->vma; /* Relocate non-absolute symbols by the section offset. */ if (sym->section != &bfd_abs_section) { symaddr += offset; } if (index != -1) sectinfo->sections[index] = symaddr; else internal_error (__FILE__, __LINE__, "Section index uninitialized."); /* The special local symbols don't go in the minimal symbol table, so ignore this one. */ continue; } /* Not a special stabs-in-elf symbol, do regular symbol processing. */ if (sym->section->flags & SEC_LOAD) { ms_type = mst_file_data; } else { ms_type = mst_file_bss; } } else { ms_type = mst_unknown; } } else { /* FIXME: Solaris2 shared libraries include lots of odd "absolute" and "undefined" symbols, that play hob with actions like finding what function the PC is in. Ignore them if they aren't text, data, or bss. */ /* ms_type = mst_unknown; */ continue; /* Skip this symbol. */ } /* Pass symbol size field in via BFD. FIXME!!! */ size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size; msym = record_minimal_symbol_and_info ((char *) sym->name, symaddr, ms_type, (void *) size, sym->section, objfile); #ifdef SOFUN_ADDRESS_MAYBE_MISSING if (msym != NULL) msym->filename = filesymname; #endif ELF_MAKE_MSYMBOL_SPECIAL (sym, msym); } } do_cleanups (back_to); } }
struct ast_vector_string *__ast_bt_get_symbols(void **addresses, size_t num_frames) { struct ast_vector_string *return_strings; int stackfr; bfd *bfdobj; long allocsize; char msg[MSG_BUFF_LEN]; static pthread_mutex_t bfd_mutex = PTHREAD_MUTEX_INITIALIZER; return_strings = malloc(sizeof(struct ast_vector_string)); if (!return_strings) { return NULL; } if (AST_VECTOR_INIT(return_strings, num_frames)) { free(return_strings); return NULL; } for (stackfr = 0; stackfr < num_frames; stackfr++) { int symbolcount; struct bfd_data data = { .return_strings = return_strings, .msg = msg, .pc = (bfd_vma)(uintptr_t) addresses[stackfr], .found = 0, .dynamic = 0, }; msg[0] = '\0'; if (!dladdr((void *)(uintptr_t) data.pc, &data.dli)) { continue; } data.libname = strrchr(data.dli.dli_fname, '/'); if (!data.libname) { data.libname = data.dli.dli_fname; } else { data.libname++; } pthread_mutex_lock(&bfd_mutex); /* Using do while(0) here makes it easier to escape and clean up */ do { bfdobj = bfd_openr(data.dli.dli_fname, NULL); if (!bfdobj) { break; } /* bfd_check_format does more than check. It HAS to be called */ if (!bfd_check_format(bfdobj, bfd_object)) { break; } data.has_syms = !!(bfd_get_file_flags(bfdobj) & HAS_SYMS); data.dynamic = !!(bfd_get_file_flags(bfdobj) & DYNAMIC); if (!data.has_syms) { break; } allocsize = data.dynamic ? bfd_get_dynamic_symtab_upper_bound(bfdobj) : bfd_get_symtab_upper_bound(bfdobj); if (allocsize < 0) { break; } data.syms = malloc(allocsize); if (!data.syms) { break; } symbolcount = data.dynamic ? bfd_canonicalize_dynamic_symtab(bfdobj, data.syms) : bfd_canonicalize_symtab(bfdobj, data.syms); if (symbolcount < 0) { break; } bfd_map_over_sections(bfdobj, process_section, &data); } while(0); if (bfdobj) { bfd_close(bfdobj); free(data.syms); data.syms = NULL; } pthread_mutex_unlock(&bfd_mutex); /* Default output, if we cannot find the information within BFD */ if (!data.found) { snprintf(msg, sizeof(msg), "%s %s()", data.libname, S_OR(data.dli.dli_sname, "<unknown>")); AST_VECTOR_APPEND(return_strings, strdup(msg)); } } return return_strings; } #else struct ast_vector_string *__ast_bt_get_symbols(void **addresses, size_t num_frames) { char **strings; struct ast_vector_string *return_strings; int i; return_strings = malloc(sizeof(struct ast_vector_string)); if (!return_strings) { return NULL; } if (AST_VECTOR_INIT(return_strings, num_frames)) { free(return_strings); return NULL; } strings = backtrace_symbols(addresses, num_frames); if (strings) { for (i = 0; i < num_frames; i++) { AST_VECTOR_APPEND(return_strings, strdup(strings[i])); } free(strings); } return return_strings; }
/* * Implementation */ void jit_init_debug(const char *progname) { #if DISASSEMBLER bfd_init(); if (progname) disasm_bfd = bfd_openr(progname, NULL); if (disasm_bfd == NULL) { #if defined(__linux__) disasm_bfd = bfd_openr("/proc/self/exe", NULL); if (disasm_bfd == NULL) #endif return; } bfd_check_format(disasm_bfd, bfd_object); bfd_check_format(disasm_bfd, bfd_archive); disasm_print = disassembler(disasm_bfd); assert(disasm_print); INIT_DISASSEMBLE_INFO(disasm_info, disasm_stream, fprintf); # if defined(__i386__) || defined(__x86_64__) disasm_info.arch = bfd_arch_i386; # if defined(__x86_64__) # if __WORDSIZE == 32 disasm_info.mach = bfd_mach_x64_32; # else disasm_info.mach = bfd_mach_x86_64; # endif # else disasm_info.mach = bfd_mach_i386_i386; # endif # endif # if defined(__powerpc__) disasm_info.arch = bfd_arch_powerpc; disasm_info.mach = bfd_mach_ppc64; # if HAVE_DISASSEMBLE_INIT_FOR_TARGET disassemble_init_for_target(&disasm_info); # elif HAVE_DISASSEMBLE_INIT_POWERPC disassemble_init_powerpc(&disasm_info); # endif # if defined(__powerpc64__) disasm_info.disassembler_options = "64"; # endif # if HAVE_DISASSEMBLE_INIT_FOR_TARGET disassemble_init_for_target(&disasm_info); # elif HAVE_DISASSEMBLE_INIT_POWERPC disassemble_init_powerpc(&disasm_info); # endif # endif # if defined(__sparc__) disasm_info.endian = disasm_info.display_endian = BFD_ENDIAN_BIG; # endif # if defined(__s390__) || defined(__s390x__) disasm_info.arch = bfd_arch_s390; # if __WORDSIZE == 32 disasm_info.mach = bfd_mach_s390_31; # else disasm_info.mach = bfd_mach_s390_64; # endif disasm_info.endian = disasm_info.display_endian = BFD_ENDIAN_BIG; disasm_info.disassembler_options = "zarch"; # endif # if defined(__alpha__) disasm_info.arch = bfd_arch_alpha; disasm_info.mach = bfd_mach_alpha_ev6; # endif disasm_info.print_address_func = disasm_print_address; if (bfd_get_file_flags(disasm_bfd) & HAS_SYMS) { asymbol **in; asymbol **out; asymbol *symbol; long offset; long sym_count; long dyn_count; long sym_storage; long dyn_storage; if ((sym_storage = bfd_get_symtab_upper_bound(disasm_bfd)) >= 0) { if (bfd_get_file_flags(disasm_bfd) & DYNAMIC) { dyn_storage = bfd_get_dynamic_symtab_upper_bound(disasm_bfd); # if defined(__alpha__) /* XXX */ if (dyn_storage < 0) dyn_storage = 0; # else assert(dyn_storage >= 0); # endif } else dyn_storage = 0; jit_alloc((jit_pointer_t *)&disasm_symbols, (sym_storage + dyn_storage) * sizeof(asymbol *)); sym_count = bfd_canonicalize_symtab(disasm_bfd, disasm_symbols); assert(sym_count >= 0); if (dyn_storage) { dyn_count = bfd_canonicalize_dynamic_symtab(disasm_bfd, disasm_symbols + sym_count); assert(dyn_count >= 0); } else dyn_count = 0; disasm_num_symbols = sym_count + dyn_count; disasm_num_synthetic = bfd_get_synthetic_symtab(disasm_bfd, sym_count, disasm_symbols, dyn_count, disasm_symbols + sym_count, &disasm_synthetic); if (disasm_num_synthetic > 0) { jit_realloc((jit_pointer_t *)&disasm_symbols, (sym_storage + dyn_storage) * sizeof(asymbol *), (sym_storage + dyn_storage + disasm_num_synthetic) * sizeof(asymbol *)); for (offset = 0; offset < disasm_num_synthetic; offset++) disasm_symbols[disasm_num_symbols++] = disasm_synthetic + offset; } /* remove symbols not useful for disassemble */ in = out = disasm_symbols; for (offset = 0; offset < disasm_num_symbols; offset++) { symbol = *in++; if (symbol->name && symbol->name[0] != '\0' && !(symbol->flags & (BSF_DEBUGGING | BSF_SECTION_SYM)) && !bfd_is_und_section(symbol->section) && !bfd_is_com_section(symbol->section)) *out++ = symbol; } disasm_num_symbols = out - disasm_symbols; qsort(disasm_symbols, disasm_num_symbols, sizeof(asymbol *), disasm_compare_symbols); } } #endif }