Exemple #1
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* 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;
}