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* 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; }
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; }
static int epk_open_exe() { long EPIK_start = (long) &EPIK_Comp_start; bfd * BfdImage = 0; int nr_all_syms; int i; size_t size; asymbol **syms; static char exe[64]; int pid; #ifdef GNU_DEMANGLE if (getenv("EPK_DEMANGLE_STYLE")) { epk_demangle_style = epk_str2int(getenv("EPK_DEMANGLE_STYLE")); if (epk_demangle_style < 0) elg_cntl_msg("Demangling disabled"); else elg_cntl_msg("Set demangle style to %d", epk_demangle_style); } #endif /* Initialize BFD */ bfd_init(); pid = getpid(); sprintf(exe, "/proc/%d/exe", pid); BfdImage = bfd_openr(exe, 0 ); if ( ! BfdImage ) { sprintf(exe, "/proc/%d/object/a.out", pid); BfdImage = bfd_openr(exe, 0 ); if ( ! BfdImage ) { elg_error_msg("Cannot get executable image."); } } /* Check image format */ if ( ! bfd_check_format(BfdImage, bfd_object) ) { elg_error_msg("ERROR: BFD format failure."); } /* Get & check size of symbol table */ size = bfd_get_symtab_upper_bound(BfdImage); if ( size < 1 ) { return 0; } /* Read canonicalized symbols */ syms = malloc(size); nr_all_syms = bfd_canonicalize_symtab(BfdImage, syms); elg_cntl_msg("Got %d symbols in image.", nr_all_syms); if ( nr_all_syms < 1 ) { return 0; } epk_filter_add("EPIK_*"); /* required for EPIK_Tracer */ epk_filter_gen(); /* initialise filter from file (if defined) */ if (EPIK_start > (long) &EPIK_Gen_start) EPIK_start = (long) &EPIK_Gen_start; elg_cntl_msg("EPIK_start=%p", EPIK_start); for (i=0; i<nr_all_syms; ++i) { char* dem_name = 0; long addr; const char* filename; const char* funcname; unsigned int lno; if ( syms[i]->flags & BSF_FUNCTION ) { /* ignore system functions */ if ( strncmp(syms[i]->name, "bfd_", 4) == 0 || strstr(syms[i]->name, "@@") != NULL ) continue; /* get filename and linenumber from debug info */ /* needs -g */ filename = NULL; lno = -1; bfd_find_nearest_line(BfdImage, bfd_get_section(syms[i]), syms, syms[i]->value, &filename, &funcname, &lno); /* calculate function address */ addr = syms[i]->section->vma + syms[i]->value; /* XXXX probably remove this (for smg2000) */ /* ignore functions outside of program itself */ if (addr >= EPIK_start) continue; #ifdef GNU_DEMANGLE /* use demangled name if possible */ if (epk_demangle_style >= 0) dem_name = cplus_demangle(syms[i]->name, epk_demangle_style); #endif /* filtered functions are not included in hashtable */ nfuncs++; if( dem_name ) { if (epk_filter_check(dem_name)) epk_hash_put(addr, dem_name, filename, lno); else nblack++; } else if (epk_filter_check(syms[i]->name)) { char *n = strdup(syms[i]->name); epk_hash_put(addr, n, filename, lno); } else nblack++; } } free(syms); bfd_close(BfdImage); elg_cntl_msg("Found %d functions (%d filtered)", nfuncs, nblack); return 1; }