static int compare_symbols (const PTR ap, const PTR bp) { const asymbol *a = *(const asymbol **) ap; const asymbol *b = *(const asymbol **) bp; if (bfd_asymbol_value (a) > bfd_asymbol_value (b)) return 1; else if (bfd_asymbol_value (a) < bfd_asymbol_value (b)) return -1; return 0; }
/* Based on objdump source */ static int disasm_compare_symbols(const void *ap, const void *bp) { const asymbol *a = *(const asymbol **)ap; const asymbol *b = *(const asymbol **)bp; if (bfd_asymbol_value(a) > bfd_asymbol_value(b)) return (1); if (bfd_asymbol_value(a) < bfd_asymbol_value(b)) return (-1); return (0); }
/* Get the memory bank parameters by looking at the global symbols defined by the linker. */ static int sim_get_bank_parameters (SIM_DESC sd, bfd* abfd) { sim_cpu *cpu; long symsize; long symbol_count, i; unsigned size; asymbol** asymbols; asymbol** current; cpu = STATE_CPU (sd, 0); symsize = bfd_get_symtab_upper_bound (abfd); if (symsize < 0) { sim_io_eprintf (sd, "Cannot read symbols of program"); return 0; } asymbols = (asymbol **) xmalloc (symsize); symbol_count = bfd_canonicalize_symtab (abfd, asymbols); if (symbol_count < 0) { sim_io_eprintf (sd, "Cannot read symbols of program"); return 0; } size = 0; for (i = 0, current = asymbols; i < symbol_count; i++, current++) { const char* name = bfd_asymbol_name (*current); if (strcmp (name, BFD_M68HC11_BANK_START_NAME) == 0) { cpu->bank_start = bfd_asymbol_value (*current); } else if (strcmp (name, BFD_M68HC11_BANK_SIZE_NAME) == 0) { size = bfd_asymbol_value (*current); } else if (strcmp (name, BFD_M68HC11_BANK_VIRTUAL_NAME) == 0) { cpu->bank_virtual = bfd_asymbol_value (*current); } } free (asymbols); cpu->bank_end = cpu->bank_start + size; cpu->bank_shift = 0; for (; size > 1; size >>= 1) cpu->bank_shift++; return 0; }
bfd_vma getSymbolPaddedSize(bfd* abfd, asymbol* sym, asymbol* next) { bfd_section* sec = bfd_get_section(sym); // If next symbol is from the same section, size is considered to be the address difference // Otherwise, symbol is assumed to occupy the rest of the section // Exception to the rule is when symbol VMA is not in the section (this can happen for TLS symbols) // Then just fall back to the ELF-specified size return (next && sec == bfd_get_section(next) && next->value < sec->size) ? bfd_asymbol_value(next) - bfd_asymbol_value(sym) : sym->value < sec->size ? sec->size - sym->value : getSymbolSize(abfd, sym); }
void dump_symbols(const char *filename){ bfd *abfd; asymbol *store; char *p; void *minisyms; int symnum,i; size_t size; int dyn=0; int ret; abfd=bfd_openr(filename,NULL); assert(abfd); ret=bfd_check_format(abfd,bfd_object); assert(ret); if(!(bfd_get_file_flags(abfd)&& HAS_SYMS)){ bfd_close(abfd); return; } store = bfd_make_empty_symbol(abfd); symnum = bfd_read_minisymbols(abfd,dyn,&minisyms,&size); assert(symnum>=0); p=(char *)minisyms; for(i=0;i<symnum;i++){ asymbol *sym = bfd_minisymbol_to_symbol(abfd,dyn,p,store); const char *name = bfd_asymbol_name(sym); int value = bfd_asymbol_value(sym); printf("%08x %s\n",value,name); p+=size; } free(store); free(minisyms); bfd_close(abfd); }
static int objdump_symbol_at_address (bfd_vma vma, struct disassemble_info * info) { asymbol * sym; //sym = find_symbol_for_address (vma, info, NULL); return (sym != NULL && (bfd_asymbol_value (sym) == vma)); }
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; }
/** * 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; }
/* search symbol */ int get_symbol_pos(const char* symbol_name, bfd* abfd, asymbol** syms, int symnum, char* file_o) { int i; int symbol_pos = 0; for (i = 0; i < symnum; i++) { asymbol *sym = syms[i]; const char *name = bfd_asymbol_name(sym); if (NULL == name || 0 == strlen(name) || '.' == name[0]) continue; if (0 == strcmp(name, symbol_name)) { LOG("[INFO] %s\n", name); int value = bfd_asymbol_value(sym); symbol_pos = (int)file_o + abfd->origin + sym->section->filepos + value; LOG("Found %s :0x%08X (absolute)\n", name, symbol_pos); break; } } return symbol_pos; }
long locate_dv_func(void) { asymbol **symbol_table; bfd *b = bfd_openr(oracle, NULL); if (b == NULL) { perror("bfd_openr"); exit(-1); } bfd_check_format(b, bfd_object); long storage_needed = bfd_get_symtab_upper_bound(b); if(storage_needed < 0) { fprintf(stderr, "wtf?!\n"); exit(-1); } if((symbol_table = (asymbol**)malloc(storage_needed)) == 0) { perror("malloc"); exit(-1); } int num_symbols; if((num_symbols = bfd_canonicalize_symtab(b, symbol_table)) <= 0) { fprintf(stderr, "no symbols info\n"); exit(-1); } int i; for(i = 0; i < num_symbols; i++) { char *symname = bfd_asymbol_name(symbol_table[i]); void *symaddr = bfd_asymbol_value(symbol_table[i]); /* don't even ask why this funciton, for real hardcore: gdb -p <oraclePIDs> */ if(!strcmp(symname, "kzvtins")) { fprintf(stderr, "[%d] symbol \"kzvtins\" at 0x%lx\n", getpid(), (long) symaddr); return (long) symaddr; } } return 0; }
void create_symbol_function_pos(char* file_o, bfd* abfd, asymbol** syms, int symnum) { int i; for (i = 0; i < symnum; i++) { asymbol *sym = syms[i]; const char *name = bfd_asymbol_name(sym); int value = bfd_asymbol_value(sym); symbol_info info; if (NULL == name || 0 == strlen(name) || '.' == name[0]) continue; LOG("[INFO] %s\n", name); bfd_get_symbol_info(abfd, sym, &info); /* 定義されたシンボルのみを探す */ if (!bfd_is_undefined_symclass(info.type)) { if (name[0] != '_') { int symbol_pos = 0; symbol_pos = abfd->origin + sym->section->filepos + value; LOG("Found %s :0x%08X (relative), ", name, symbol_pos); symbol_pos += (int)file_o; LOG("Found %s :0x%08X (absolute)\n", name, symbol_pos); add_symbol(name, symbol_pos); } } } }
SymbolTable::SymbolTable(string path) { //Open the file as binary file descriptor: bfd* descr = bfd_openr(path.c_str(), NULL); if (!descr) { throw runtime_error("Failed to open binary file descriptor."); } //Check the format of the file: if (!bfd_check_format(descr, bfd_object)) { bfd_close(descr); throw runtime_error("Failed to verify binary format."); } //Get the size of the symbol table: long symbolTableSize = bfd_get_symtab_upper_bound(descr); if (symbolTableSize <= 0) { bfd_close(descr); if (symbolTableSize < 0) { throw runtime_error("Failed to read the upper bound of the symbol table."); } else { return; } } //Alloc space for the table: asymbol** symbolTable = (asymbol**)malloc(symbolTableSize); if (!symbolTable) { bfd_close(descr); throw runtime_error("Failed to allocate space for the symbol table."); } //Get the number of symbols by canonicalizing the table: long symbolTableCount = bfd_canonicalize_symtab(descr, symbolTable); if (symbolTableCount < 0) { bfd_close(descr); free(symbolTable); throw runtime_error("Failed to read the number of symbols in the symbol table."); } //Iterate: for (int i = 0; i < symbolTableCount; i++) { //Is there a name? if (!symbolTable[i]->name) { continue; } //Get the symbol data: Symbol* newSymbol = new Symbol(string(bfd_asymbol_name(symbolTable[i])), (pword)bfd_asymbol_value(symbolTable[i])); //Check: if (!newSymbol) { throw runtime_error("Failed to allocate space for a symbol."); } this->table[newSymbol->getName()] = newSymbol; } //Close the file descriptor and free the table: bfd_close(descr); free(symbolTable); }
// -------------------------------------------------------------------------- void* ctkBinaryFileDescriptorPrivate::resolve(const char * symbol) { if (!this->BFD) { return 0; } void *addr = 0; // Get the symbol table long storageNeeded = bfd_get_symtab_upper_bound(this->BFD); asymbol ** symbolTable = (asymbol **) malloc(storageNeeded); long numberOfSymbols = bfd_canonicalize_symtab(this->BFD, symbolTable); // Run through the symbol table, looking for the requested symbol for (int i = 0; i < numberOfSymbols; i++) { if (strcmp(symbol, symbolTable[i]->name) == 0) { // Found the symbol, get the section pointer asection *p = bfd_get_section(symbolTable[i]); // Do we have this section already? MemorySectionContainer::iterator sit; for (sit = this->Sections.begin(); sit != this->Sections.end(); ++sit) { if ((*sit).first == p) { break; } } PTR mem; if (sit == this->Sections.end()) { // Get the contents of the section bfd_size_type sz = bfd_get_section_size (p); mem = malloc (sz); if (bfd_get_section_contents(this->BFD, p, mem, (file_ptr) 0,sz)) { this->Sections.push_back( MemorySectionType(p, mem) ); } else { // Error reading section free(mem); break; } } else { // pull the start of the section block from the cache mem = const_cast<void*>((*sit).second); } // determine the address of this section addr = (char *)mem + (bfd_asymbol_value(symbolTable[i]) - bfd_asymbol_base(symbolTable[i])); break; } } // cleanup. just delete the outer vector for the symbol table free(symbolTable); return addr; }
void sim_disasm_one (void) { static int last_sym = -1; static const char * prev_filename = ""; static int prev_lineno = 0; const char * filename; const char * functionname; unsigned int lineno; int sym, bestaddr; int min, max, i; int save_trace = trace; int mypc = get_reg (pc); if (! sim_get_current_source_location (& filename, & functionname, & lineno)) return; trace = 0; if (filename && functionname && lineno) { if (lineno != prev_lineno || strcmp (prev_filename, filename)) { char * the_line = load_file_and_line (filename, lineno); const char * slash = strrchr (filename, '/'); if (!slash) slash = filename; else slash++; printf ("========================================" "=====================================\n"); printf ("\033[37;41m %s:%d: \033[33;40m %s\033[K\033[0m\n", slash, lineno, the_line); } prev_lineno = lineno; prev_filename = filename; } min = -1; max = symcount; while (min < max - 1) { bfd_vma sa; sym = (min + max) / 2; sa = bfd_asymbol_value (symtab[sym]); /*printf("checking %4d %08x %s\n", sym, sa, bfd_asymbol_name (symtab[sym])); */ if (sa > mypc) max = sym; else if (sa < mypc) min = sym; else { min = sym; break; } } if (min != -1 && min != last_sym) { bestaddr = bfd_asymbol_value (symtab[min]); printf ("\033[43;30m%s", bfd_asymbol_name (symtab[min])); if (bestaddr != mypc) printf ("+%d", mypc - bestaddr); printf (":\t\t\t\033[0m\n"); last_sym = min; #if 0 if (trace == 1) if (strcmp (bfd_asymbol_name (symtab[min]), "abort") == 0 || strcmp (bfd_asymbol_name (symtab[min]), "exit") == 0) trace = 0; #endif } opbuf[0] = 0; #ifdef CYCLE_ACCURATE printf ("\033[33m %04u %06x: ", (int)(regs.cycle_count % 10000), mypc); #else printf ("\033[33m %06x: ", mypc); #endif max = print_insn_rx (mypc, & info); for (i = 0; i < max; i++) { if (rx_big_endian) printf ("%02x", mem_get_qi ((mypc + i) ^ 3)); else printf ("%02x", mem_get_qi (mypc + i)); } do { printf (" "); i ++; } while (i < 6); printf ("%-16s ", opbuf); printf ("\033[0m\n"); trace = save_trace; }
bfd_reloc_status_type pmbfd_perform_relocation(bfd *abfd, pmbfd_arelent *r, asymbol *psym, asection *input_section) { Elf32_Word pc; int64_t val, msk; int32_t oval,nval; int16_t sval; int8_t bval; int64_t llim,ulim; Elf32_Rela *rela = &r->rela32; uint8_t type = ELF32_R_TYPE(rela->r_info); struct sparc_rel_desc *dsc; if ( R_SPARC_NONE == type ) { /* No-op; BFD uses a zero dst_mask... */ return bfd_reloc_ok; } /* use R_SPARC_NONE as a dummy for 'unsupported' */ dsc = type >= sizeof(sparc_rels) ? &sparc_rels[R_SPARC_NONE] : &sparc_rels[type]; if ( 0 == dsc->nbytes ) { ERRPR("pmbfd_perform_relocation_sparc(): unsupported relocation type : %"PRIu8"\n", type); return bfd_reloc_notsupported; } if ( bfd_is_und_section(bfd_get_section(psym)) ) return bfd_reloc_undefined; pc = bfd_get_section_vma(abfd, input_section) + rela->r_offset; if ( ! dsc->unaligned && (pc & (dsc->nbytes - 1)) ) { ERRPR("pmbfd_perform_relocation_sparc(): location to relocate (0x%08"PRIx32") not properly aligned\n", pc); return bfd_reloc_other; } val = (int64_t)bfd_asymbol_value(psym) + (int64_t)rela->r_addend; if ( dsc->pc_relative ) val -= (int64_t)pc; val >>= dsc->shift; /* works also if the left shift is 32 */ msk = (1LL << dsc->width); msk--; switch ( dsc->sparc_rel_check ) { default: case sparc_rel_check_none: ulim = ~(1LL<<63); llim = ~ulim; break; case sparc_rel_check_unsg: ulim = msk; llim = 0; break; case sparc_rel_check_bits: ulim = msk; llim = ~ulim; break; case sparc_rel_check_sign: ulim = msk>>1; llim = ~ulim; break; } #if (DEBUG & DEBUG_RELOC) fprintf(stderr,"Relocating val: 0x%08"PRIx64", ulim: 0x%08"PRIx64", pc: 0x%08"PRIx32", sym: 0x%08lx\n", val, ulim, pc, bfd_asymbol_value(psym)); #endif if ( val < llim || val > ulim ) { return bfd_reloc_overflow; } if ( 1 == dsc->nbytes ) { memcpy(&bval, (void*)pc, sizeof(bval)); oval = bval; } else if ( 2 == dsc->nbytes ) { memcpy(&sval, (void*)pc, sizeof(sval)); oval = sval; } else { memcpy(&oval, (void*)pc, sizeof(oval)); } nval = ( oval & ~msk ) | (val & msk); /* patch back */ if ( 1 == dsc->nbytes ) { bval = nval; memcpy((void*)pc, &bval, sizeof(bval)); } else if ( 2 == dsc->nbytes ) { sval = nval; memcpy((void*)pc, &sval, sizeof(sval)); } else { memcpy((void*)pc, &nval, sizeof(nval)); } return bfd_reloc_ok; }
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; }
map<address_t, asm_function_t *> identify_functions(const map<address_t, section_t *> sections, bfd *abfd) { map<address_t, asm_function_t *> funcs; //set<asm_function_t *> funcs; long storage_needed; asymbol **symtbl; long symcount, sorted_symcount; /* We could identify function boundries in stripped binaries by looking for the function prologue. TBD. */ if(!(bfd_get_file_flags(abfd) & HAS_SYMS)){ return get_stripped_binary_functions( abfd); //fatal("identify_functions", //"No support for stripped binaries (yet)"); } //assert(bfd_get_flavour(abfd) == bfd_target_elf_flavour); /* instead of handling only elf format binary, allow other types with a warning -- pongsin */ if (bfd_get_flavour(abfd) != bfd_target_elf_flavour) cerr << "Warning! The binary is not in ELF format. " << "Other formats haven't been thoroughly tested." << endl; storage_needed = bfd_get_symtab_upper_bound(abfd); if(storage_needed <= 0){ fatal("identify_functions", "symbol table damaged"); } symtbl = (asymbol **) xmalloc(storage_needed); symcount = bfd_canonicalize_symtab(abfd, symtbl); if(symcount <= 0) fatal("initialize_symtable", "symbol table damaged"); sorted_symcount = remove_useless_symbols(symtbl, symcount); qsort(symtbl, sorted_symcount, sizeof(asymbol *), compare_symbols); long i, place; asymbol *sym, *nextsym; for(i = 0; i < sorted_symcount; i++){ sym = symtbl[i]; /* if(sym->name != NULL){ printf("name: %s %u F:%x\n", sym->name, sym->flags & BSF_FUNCTION, sym->flags); } */ if(sym->flags & BSF_FUNCTION){ asm_function_t *f = new asm_function_t; f->start_addr = sym->section->vma + sym->value; f->name = sym->name; // memcpy(&(s->symbol), sym, sizeof(asymbol)); place = i; // FIXME: this still doesn't do the right thing for _init on ARM // also, this doesn't work for the last symbol while(place < sorted_symcount && (bfd_asymbol_value(sym) >= bfd_asymbol_value(symtbl[place])) ) place++; nextsym = symtbl[place]; // FIXME: We could approximate end_addr better, eg, by looking at where // the section ends. /* end addrress is approximation. the last valid address may be before this value */ f->end_addr = nextsym->value + nextsym->section->vma; //bfd_symbol_info(sym, &(s->info)); // end_addr so far is really the start_addr of the next function // subtract one if possible. if(f->end_addr != f->start_addr) f->end_addr--; if(funcs.find(f->start_addr) != funcs.end()){ asm_function_t *old = funcs[f->start_addr]; // Replace old functions with the new one if the new // one is bigger. if( (f->end_addr - f->start_addr) > (old->end_addr - old->start_addr)){ funcs[f->start_addr] = f; } } else { funcs[f->start_addr] = f; } } } free(symtbl); return funcs; }
void msp430_trace_one (int mypc) { static int last_sym = -1; static const char * prev_filename = ""; static int prev_lineno = 0; const char * filename; const char * functionname; unsigned int lineno; int sym, bestaddr; int min, max, i; if (! msp430_get_current_source_location (mypc, & filename, & functionname, & lineno)) return; if (filename && functionname && lineno) { if (lineno != prev_lineno || strcmp (prev_filename, filename)) { char * the_line = load_file_and_line (filename, lineno); const char * slash = strrchr (filename, '/'); if (!slash) slash = filename; else slash ++; fprintf (stderr, "========================================" "=====================================\n"); fprintf (stderr, "\033[37;41m %s:%d: \033[33;40m %s\033[K\033[0m\n", slash, lineno, the_line); } prev_lineno = lineno; prev_filename = filename; } min = -1; max = symcount; while (min < max - 1) { bfd_vma sa; sym = (min + max) / 2; sa = bfd_asymbol_value (symtab[sym]); /*printf ("checking %4d %08x %s\n", sym, sa, bfd_asymbol_name (symtab[sym])); */ if (sa > mypc) max = sym; else if (sa < mypc) min = sym; else { min = sym; break; } } if (min != -1 && min != last_sym) { bestaddr = bfd_asymbol_value (symtab[min]); fprintf (stderr, "\033[43;30m%s", bfd_asymbol_name (symtab[min])); if (bestaddr != mypc) fprintf (stderr, "+%d", mypc - bestaddr); fprintf (stderr, ":\t\t\t\033[0m\n"); last_sym = min; #if 0 if (trace == 1) if (strcmp (bfd_asymbol_name (symtab[min]), "abort") == 0 || strcmp (bfd_asymbol_name (symtab[min]), "exit") == 0) trace = 0; #endif } }
void sim_disasm_one (void) { static int initted = 0; static asymbol **symtab = 0; static int symcount = 0; static int last_sym = -1; static struct disassemble_info info; int storage, sym, bestaddr; int min, max, i; static asection *code_section = 0; static bfd_vma code_base = 0; asection *s; int save_trace = trace; static const char *prev_filename = ""; static int prev_lineno = 0; const char *filename; const char *functionname; unsigned int lineno; int mypc = get_reg (pc); if (current_bfd == 0) return; trace = 0; if (!initted) { initted = 1; memset (&info, 0, sizeof (info)); INIT_DISASSEMBLE_INFO (info, stdout, op_printf); info.read_memory_func = sim_dis_read; info.arch = bfd_get_arch (current_bfd); info.mach = bfd_get_mach (current_bfd); if (info.mach == 0) { info.arch = bfd_arch_m32c; info.mach = default_machine; } disassemble_init_for_target (&info); storage = bfd_get_symtab_upper_bound (current_bfd); if (storage > 0) { symtab = (asymbol **) malloc (storage); symcount = bfd_canonicalize_symtab (current_bfd, symtab); symcount = remove_useless_symbols (symtab, symcount); qsort (symtab, symcount, sizeof (asymbol *), compare_symbols); } for (s = current_bfd->sections; s; s = s->next) { if (s->flags & SEC_CODE || code_section == 0) { code_section = s; code_base = bfd_section_lma (current_bfd, s); break; } } } filename = functionname = 0; lineno = 0; if (bfd_find_nearest_line (current_bfd, code_section, symtab, mypc - code_base, &filename, &functionname, &lineno)) { if (filename && functionname && lineno) { if (lineno != prev_lineno || strcmp (prev_filename, filename)) { char *the_line = load_file_and_line (filename, lineno); const char *slash = strrchr (filename, '/'); if (!slash) slash = filename; else slash++; printf ("========================================" "=====================================\n"); printf ("\033[37;41m %s:%d: \033[33;40m %s\033[K\033[0m\n", slash, lineno, the_line); } prev_lineno = lineno; prev_filename = filename; } } { min = -1; max = symcount; while (min < max - 1) { bfd_vma sa; sym = (min + max) / 2; sa = bfd_asymbol_value (symtab[sym]); /*printf("checking %4d %08x %s\n", sym, sa, bfd_asymbol_name (symtab[sym])); */ if (sa > mypc) max = sym; else if (sa < mypc) min = sym; else { min = sym; break; } } if (min != -1 && min != last_sym) { bestaddr = bfd_asymbol_value (symtab[min]); printf ("\033[43;30m%s", bfd_asymbol_name (symtab[min])); if (bestaddr != mypc) printf ("+%d", mypc - bestaddr); printf (":\t\t\t\033[0m\n"); last_sym = min; #if 0 if (trace == 1) if (strcmp (bfd_asymbol_name (symtab[min]), "abort") == 0 || strcmp (bfd_asymbol_name (symtab[min]), "exit") == 0) trace = 0; #endif } } opbuf[0] = 0; printf ("\033[33m%06x: ", mypc); max = print_insn_m32c (mypc, &info); for (i = 0; i < max; i++) printf ("%02x", mem_get_qi (mypc + i)); for (; i < 6; i++) printf (" "); printf ("%-16s ", opbuf); printf ("\033[0m\n"); trace = save_trace; }
/* ripped off from objdump.c, line 469 */ int compare_symbols(const void *ap, const void *bp) { const asymbol *a = * (const asymbol **) ap; const asymbol *b = * (const asymbol **) bp; const char *an; const char *bn; size_t anl; size_t bnl; bfd_boolean af; bfd_boolean bf; flagword aflags; flagword bflags; if (bfd_asymbol_value (a) > bfd_asymbol_value (b)) return 1; else if (bfd_asymbol_value (a) < bfd_asymbol_value (b)) return -1; if (a->section > b->section) return 1; else if (a->section < b->section) return -1; an = bfd_asymbol_name (a); bn = bfd_asymbol_name (b); anl = strlen (an); bnl = strlen (bn); /* The symbols gnu_compiled and gcc2_compiled convey no real information, so put them after other symbols with the same value. */ af = (strstr (an, "gnu_compiled") != NULL || strstr (an, "gcc2_compiled") != NULL); bf = (strstr (bn, "gnu_compiled") != NULL || strstr (bn, "gcc2_compiled") != NULL); if (af && ! bf) return 1; if (! af && bf) return -1; /* We use a heuristic for the file name, to try to sort it after more useful symbols. It may not work on non Unix systems, but it doesn't really matter; the only difference is precisely which symbol names get printed. */ #define file_symbol(s, sn, snl) \ (((s)->flags & BSF_FILE) != 0 \ || ((sn)[(snl) - 2] == '.' \ && ((sn)[(snl) - 1] == 'o' \ || (sn)[(snl) - 1] == 'a'))) af = file_symbol (a, an, anl); bf = file_symbol (b, bn, bnl); if (af && ! bf) return 1; if (! af && bf) return -1; aflags = a->flags; bflags = b->flags; if ((aflags & BSF_DEBUGGING) != (bflags & BSF_DEBUGGING)) { if ((aflags & BSF_DEBUGGING) != 0) return 1; else return -1; } if ((aflags & BSF_FUNCTION) != (bflags & BSF_FUNCTION)) { if ((aflags & BSF_FUNCTION) != 0) return -1; else return 1; } if ((aflags & BSF_LOCAL) != (bflags & BSF_LOCAL)) { if ((aflags & BSF_LOCAL) != 0) return 1; else return -1; } if ((aflags & BSF_GLOBAL) != (bflags & BSF_GLOBAL)) { if ((aflags & BSF_GLOBAL) != 0) return -1; else return 1; } /* Symbols that start with '.' might be section names, so sort them after symbols that don't start with '.'. */ if (an[0] == '.' && bn[0] != '.') return 1; if (an[0] != '.' && bn[0] == '.') return -1; /* Finally, if we can't distinguish them in any other way, try to get consistent results by sorting the symbols by name. */ return strcmp (an, bn); }
bool show_exe_function(void *addr, struct string *str) { bool ret; const char *function_name; bfd_vma symbol_offset; bfd_vma symbol_start; const char *filename; asection *sections; unsigned int line; asymbol **symbols; asymbol *symbol; int nr_symbols; bfd *abfd; int size; symbols = NULL; bfd_init(); abfd = bfd_openr("/proc/self/exe", NULL); if (!abfd) goto failed; if (!bfd_check_format(abfd, bfd_object)) goto failed; size = bfd_get_symtab_upper_bound(abfd); if (!size) goto failed; symbols = malloc(size); if (!symbols) goto failed; nr_symbols = bfd_canonicalize_symtab(abfd, symbols); sections = bfd_get_section_by_name(abfd, ".debug_info"); if (!sections) goto failed; if (!bfd_find_nearest_line (abfd, sections, symbols, (unsigned long) addr, &filename, &function_name, &line)) goto failed; if (!function_name) goto failed; symbol = lookup_symbol(symbols, nr_symbols, function_name); if (!symbol) goto failed; symbol_start = bfd_asymbol_value(symbol); symbol_offset = (unsigned long) addr - symbol_start; str_append(str, "%s+%llx (%s:%i)\n", function_name, (long long) symbol_offset, filename, line); ret = true; out: free(symbols); if (abfd) bfd_close(abfd); return ret; failed: /* * If above steps failed then try to obtain the symbol description with * backtrace_symbols(). */ ret = show_backtrace_function(addr, str); goto out; }
char *symbol_lookup(struct kvm *kvm, unsigned long addr, char *sym, size_t size) { const char *filename; bfd_vma sym_offset; bfd_vma sym_start; asection *section; unsigned int line; const char *func; long symtab_size; asymbol *symbol; asymbol **syms; int nr_syms, ret; ret = -ENOENT; if (!abfd) goto not_found; if (!bfd_check_format(abfd, bfd_object)) goto not_found; symtab_size = bfd_get_symtab_upper_bound(abfd); if (!symtab_size) goto not_found; ret = -ENOMEM; syms = malloc(symtab_size); if (!syms) goto not_found; nr_syms = bfd_canonicalize_symtab(abfd, syms); ret = -ENOENT; section = bfd_get_section_by_name(abfd, ".debug_aranges"); if (!section) goto not_found; if (!bfd_find_nearest_line(abfd, section, NULL, addr, &filename, &func, &line)) goto not_found; if (!func) goto not_found; symbol = lookup(syms, nr_syms, func); if (IS_ERR(symbol)) goto not_found; sym_start = bfd_asymbol_value(symbol); sym_offset = addr - sym_start; snprintf(sym, size, "%s+%llx (%s:%i)", func, (long long) sym_offset, filename, line); sym[size - 1] = '\0'; free(syms); return sym; not_found: return ERR_PTR(ret); }
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); }
static void disasm_print_address(bfd_vma addr, struct disassemble_info *info) { char *name; char *file; int line; char buffer[address_buffer_length]; sprintf(buffer, address_buffer_format, (long long)addr); (*info->fprintf_func)(info->stream, "0x%s", buffer); # define _jit disasm_jit # undef jit_pointer_p # define jit_pointer_p(u) \ ((u) >= _jit->code.ptr && (u) < _jit->pc.uc) if (jit_pointer_p((jit_uint8_t *)(jit_word_t)addr)) { if (jit_get_note((jit_uint8_t *)(jit_word_t)addr, &name, &file, &line)) (*info->fprintf_func)(info->stream, " %s:%s:%d", name ? name : "", file ? file : "", line); } # undef jit_pointer_p # undef _jit else if (disasm_num_symbols) { long low; long high; long offset; asymbol *symbol; low = 0; high = disasm_num_symbols; do { offset = (low + high) >> 1; symbol = disasm_symbols[offset]; if (bfd_asymbol_value(symbol) > addr) high = offset - 1; else if (bfd_asymbol_value(symbol) < addr) low = offset + 1; else break; } while (low < high); if (offset >= 0 && offset < disasm_num_symbols) { if (bfd_asymbol_value(symbol) < addr) { while (++offset < disasm_num_symbols) { symbol = disasm_symbols[offset]; if (bfd_asymbol_value(symbol) >= addr) break; } } else if (bfd_asymbol_value(symbol) > addr) { while (offset--) { if (bfd_asymbol_value(disasm_symbols[offset]) < addr) break; symbol = disasm_symbols[offset]; } } if (bfd_asymbol_value(symbol) == addr) (*info->fprintf_func)(info->stream, " # %s", symbol->name); } } }
static debug_type parse_coff_struct_type (bfd *abfd, struct coff_symbols *symbols, struct coff_types *types, int ntype, union internal_auxent *pauxent, void *dhandle) { long symend; int alloc; debug_field *fields; int count; bfd_boolean done; symend = pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l; alloc = 10; fields = (debug_field *) xmalloc (alloc * sizeof *fields); count = 0; done = FALSE; while (! done && symbols->coff_symno < symend && symbols->symno < symbols->symcount) { asymbol *sym; long this_coff_symno; struct internal_syment syment; union internal_auxent auxent; union internal_auxent *psubaux; bfd_vma bitpos = 0, bitsize = 0; sym = symbols->syms[symbols->symno]; if (! bfd_coff_get_syment (abfd, sym, &syment)) { non_fatal (_("bfd_coff_get_syment failed: %s"), bfd_errmsg (bfd_get_error ())); return DEBUG_TYPE_NULL; } this_coff_symno = symbols->coff_symno; ++symbols->symno; symbols->coff_symno += 1 + syment.n_numaux; if (syment.n_numaux == 0) psubaux = NULL; else { if (! bfd_coff_get_auxent (abfd, sym, 0, &auxent)) { non_fatal (_("bfd_coff_get_auxent failed: %s"), bfd_errmsg (bfd_get_error ())); return DEBUG_TYPE_NULL; } psubaux = &auxent; } switch (syment.n_sclass) { case C_MOS: case C_MOU: bitpos = 8 * bfd_asymbol_value (sym); bitsize = 0; break; case C_FIELD: bitpos = bfd_asymbol_value (sym); bitsize = auxent.x_sym.x_misc.x_lnsz.x_size; break; case C_EOS: done = TRUE; break; } if (! done) { debug_type ftype; debug_field f; ftype = parse_coff_type (abfd, symbols, types, this_coff_symno, syment.n_type, psubaux, TRUE, dhandle); f = debug_make_field (dhandle, bfd_asymbol_name (sym), ftype, bitpos, bitsize, DEBUG_VISIBILITY_PUBLIC); if (f == DEBUG_FIELD_NULL) return DEBUG_TYPE_NULL; if (count + 1 >= alloc) { alloc += 10; fields = ((debug_field *) xrealloc (fields, alloc * sizeof *fields)); } fields[count] = f; ++count; } } fields[count] = DEBUG_FIELD_NULL; return debug_make_struct_type (dhandle, ntype == T_STRUCT, pauxent->x_sym.x_misc.x_lnsz.x_size, fields); }
static void macho_add_oso_symfile (oso_el *oso, const gdb_bfd_ref_ptr &abfd, const char *name, struct objfile *main_objfile, symfile_add_flags symfile_flags) { int storage; int i; asymbol **symbol_table; asymbol **symp; struct bfd_hash_table table; int nbr_sections; /* Per section flag to mark which section have been rebased. */ unsigned char *sections_rebased; if (mach_o_debug_level > 0) printf_unfiltered (_("Loading debugging symbols from oso: %s\n"), oso->name); if (!bfd_check_format (abfd.get (), bfd_object)) { warning (_("`%s': can't read symbols: %s."), oso->name, bfd_errmsg (bfd_get_error ())); return; } if (abfd->my_archive == NULL && oso->mtime != bfd_get_mtime (abfd.get ())) { warning (_("`%s': file time stamp mismatch."), oso->name); return; } if (!bfd_hash_table_init_n (&table, macho_sym_hash_newfunc, sizeof (struct macho_sym_hash_entry), oso->nbr_syms)) { warning (_("`%s': can't create hash table"), oso->name); return; } bfd_set_cacheable (abfd.get (), 1); /* Read symbols table. */ storage = bfd_get_symtab_upper_bound (abfd.get ()); symbol_table = (asymbol **) xmalloc (storage); bfd_canonicalize_symtab (abfd.get (), symbol_table); /* Init section flags. */ nbr_sections = bfd_count_sections (abfd.get ()); sections_rebased = (unsigned char *) alloca (nbr_sections); for (i = 0; i < nbr_sections; i++) sections_rebased[i] = 0; /* Put symbols for the OSO file in the hash table. */ for (symp = oso->oso_sym; symp != oso->end_sym; symp++) { const asymbol *sym = *symp; bfd_mach_o_asymbol *mach_o_sym = (bfd_mach_o_asymbol *)sym; switch (mach_o_sym->n_type) { case N_ENSYM: case N_BNSYM: case N_GSYM: sym = NULL; break; case N_FUN: if (sym->name == NULL || sym->name[0] == 0) sym = NULL; break; case N_STSYM: break; default: sym = NULL; break; } if (sym != NULL) { struct macho_sym_hash_entry *ent; ent = (struct macho_sym_hash_entry *) bfd_hash_lookup (&table, sym->name, TRUE, FALSE); if (ent->sym != NULL) complaint (_("Duplicated symbol %s in symbol table"), sym->name); else { if (mach_o_debug_level > 4) { struct gdbarch *arch = get_objfile_arch (main_objfile); printf_unfiltered (_("Adding symbol %s (addr: %s)\n"), sym->name, paddress (arch, sym->value)); } ent->sym = sym; } } } /* Relocate symbols of the OSO. */ for (i = 0; symbol_table[i]; i++) { asymbol *sym = symbol_table[i]; bfd_mach_o_asymbol *mach_o_sym = (bfd_mach_o_asymbol *)sym; if (mach_o_sym->n_type & BFD_MACH_O_N_STAB) continue; if ((mach_o_sym->n_type & BFD_MACH_O_N_TYPE) == BFD_MACH_O_N_UNDF && sym->value != 0) { /* For common symbol use the min symtab and modify the OSO symbol table. */ CORE_ADDR res; res = macho_resolve_oso_sym_with_minsym (main_objfile, sym); if (res != 0) { sym->section = bfd_com_section_ptr; sym->value = res; } } else if ((mach_o_sym->n_type & BFD_MACH_O_N_TYPE) == BFD_MACH_O_N_SECT) { /* Normal symbol. */ asection *sec = sym->section; bfd_mach_o_section *msec; unsigned int sec_type; /* Skip buggy ones. */ if (sec == NULL || sections_rebased[sec->index] != 0) continue; /* Only consider regular, non-debugging sections. */ msec = bfd_mach_o_get_mach_o_section (sec); sec_type = msec->flags & BFD_MACH_O_SECTION_TYPE_MASK; if ((sec_type == BFD_MACH_O_S_REGULAR || sec_type == BFD_MACH_O_S_ZEROFILL) && (msec->flags & BFD_MACH_O_S_ATTR_DEBUG) == 0) { CORE_ADDR addr = 0; if ((mach_o_sym->n_type & BFD_MACH_O_N_EXT) != 0) { /* Use the min symtab for global symbols. */ addr = macho_resolve_oso_sym_with_minsym (main_objfile, sym); } else { struct macho_sym_hash_entry *ent; ent = (struct macho_sym_hash_entry *) bfd_hash_lookup (&table, sym->name, FALSE, FALSE); if (ent != NULL) addr = bfd_asymbol_value (ent->sym); } /* Adjust the section. */ if (addr != 0) { CORE_ADDR res = addr - sym->value; if (mach_o_debug_level > 3) { struct gdbarch *arch = get_objfile_arch (main_objfile); printf_unfiltered (_("resolve sect %s with %s (set to %s)\n"), sec->name, sym->name, paddress (arch, res)); } bfd_set_section_vma (abfd.get (), sec, res); sections_rebased[sec->index] = 1; } } else { /* Mark the section as never rebased. */ sections_rebased[sec->index] = 2; } } } bfd_hash_table_free (&table); /* We need to clear SYMFILE_MAINLINE to avoid interractive question from symfile.c:symbol_file_add_with_addrs_or_offsets. */ symbol_file_add_from_bfd (abfd.get (), name, symfile_flags & ~(SYMFILE_MAINLINE | SYMFILE_VERBOSE), NULL, main_objfile->flags & (OBJF_REORDERED | OBJF_SHARED | OBJF_READNOW | OBJF_USERLOADED), main_objfile); }