Пример #1
0
static void bfd_section_setup(bfd_section_t *Section) {
	bfd *Bfd = Section->Bfd;
	bfd_info_t *BfdInfo = Section->BfdInfo;
	asection *Sect = Section->Sect;
	Section->Size = bfd_get_section_size(Sect);
	bfd_malloc_and_get_section(Bfd, Sect, &Section->Code);
	arelent **Relocs = (arelent **)malloc(bfd_get_reloc_upper_bound(Bfd, Sect));
	Section->NoOfRelocs = bfd_canonicalize_reloc(Bfd, Sect, Relocs, BfdInfo->Symbols);
	Section->Relocs = (relocation_t *)malloc(sizeof(relocation_t) * Section->NoOfRelocs);
	for (int I = Section->NoOfRelocs - 1; I >= 0; --I) {
		relocation_t *Relocation = Section->Relocs + I;
		asymbol *Sym = *(Relocs[I]->sym_ptr_ptr);
		reloc_howto_type *Type = Relocs[I]->howto;
		Relocation->Position = Relocs[I]->address;
		Relocation->Size = bfd_get_reloc_size(Type);
		Relocation->Flags = Type->pc_relative ? RELOC_REL : RELOC_ABS;
		uint32_t *Target = (uint32_t *)(Section->Code + Relocs[I]->address);
		if (Type->pc_relative) {
#ifdef WINDOWS
			*(long *)(Section->Code + Relocs[I]->address) -= Relocs[I]->address + 4;// why oh why is this here???
#else
            *(long *)(Section->Code + Relocs[I]->address) -= Relocs[I]->address;// + 4 on windows platforms ???;
#endif
		};
		if (Sym->section == bfd_und_section_ptr) {
			symbol_t *Symbol;
			do {
				Symbol = (symbol_t *)stringtable_get(BfdInfo->LocalTable, Sym->name);
				if (Symbol) break;
				Symbol = (symbol_t *)stringtable_get(GlobalTable, Sym->name);
				if (Symbol) break;
				Symbol = (symbol_t *)stringtable_get(WeakTable, Sym->name);
				if (Symbol) break;
#ifdef WINDOWS
                char *WindowsSizeHint = strrchr(Sym->name, '@');
                if (WindowsSizeHint) {
                    *WindowsSizeHint = 0;
                    Symbol = (symbol_t *)stringtable_get(BfdInfo->LocalTable, Sym->name);
                    if (Symbol) break;
                    Symbol = (symbol_t *)stringtable_get(GlobalTable, Sym->name);
                    if (Symbol) break;
                    Symbol = (symbol_t *)stringtable_get(WeakTable, Sym->name);
                    if (Symbol) break;
                }
#endif
				printf("%s: unresolved symbol %s.\n", Bfd->filename, Sym->name);
				exit(1);
			} while (0);
			section_t *Section2 = Symbol->Section;
			section_relocate(Section2, Relocation, Target);
			if (Type->partial_inplace) *Target += (uint32_t)Symbol->Offset;
		} else if (Sym->section->userdata) {
			section_t *Section2 = (section_t *)Sym->section->userdata;
			section_relocate(Section2, Relocation, Target);
			if (Type->partial_inplace) *Target += (uint32_t)Sym->value;
		};
	};
};
Пример #2
0
void reloc_file(unsigned char* file_o, bfd* abfd, asymbol** syms)
{
    asection* sect;
    arelent **loc;
    int size;
    int i;

    /* relocat onl executable codes */
    //  sect = bfd_get_section_by_name(abfd, ".text");

    sect = abfd->sections;
    while (sect)
    {
        size = bfd_get_reloc_upper_bound(abfd, sect);
        assert(size >= 0);

        loc = (arelent**)malloc(size);
        size = bfd_canonicalize_reloc(abfd, sect, loc, syms);
        assert(size >= 0);

        for (i = 0; i < size ;i++) 
        {
            arelent *rel = loc[i];
            int *p = (int*)(file_o + abfd->origin + sect->filepos + rel->address);

            asymbol * sym = *rel->sym_ptr_ptr;
            const char *name = sym->name;

            /* relocate section */
            if ((sym->flags & BSF_SECTION_SYM) != 0) {
                printf("relocate section %s\n", name);
                asection *s = bfd_get_section_by_name(abfd, name);
                *p += (int)file_o + abfd->origin + s->filepos + rel->addend; 
            } else {
                /* relocate functions */
                int index = search_symbol_index(name);
                if (-1 == index) {
                    printf("relocate function %s\n", name);
                    *p += (int)dlsym(RTLD_DEFAULT, name);
                    if (rel->howto->pc_relative) *p -=(int)p;
                } else {
                    printf("relocate function (exp) %s\n", name);
                    *p += (int)g_asymbolname[index].func;
                    if (rel->howto->pc_relative) *p -=(int)p;
                }
            }
        }
        free(loc);
        sect = sect->next;
    }
}
Пример #3
0
static void
do_sections_p1 (struct coff_ofile *head)
{
  asection *section;
  int idx;
  struct coff_section *all = (struct coff_section *) (xcalloc (abfd->section_count + 1,
					     sizeof (struct coff_section)));
  head->nsections = abfd->section_count + 1;
  head->sections = all;

  for (idx = 0, section = abfd->sections; section; section = section->next, idx++)
    {
      long relsize;
      int i = section->target_index;
      arelent **relpp;
      long relcount;

      relsize = bfd_get_reloc_upper_bound (abfd, section);
      if (relsize < 0)
	bfd_fatal (bfd_get_filename (abfd));
      if (relsize == 0)
	continue;
      relpp = (arelent **) xmalloc (relsize);
      relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms);
      if (relcount < 0)
	bfd_fatal (bfd_get_filename (abfd));

      head->sections[i].name = (char *) (section->name);
      head->sections[i].code = section->flags & SEC_CODE;
      head->sections[i].data = section->flags & SEC_DATA;
      if (strcmp (section->name, ".bss") == 0)
	head->sections[i].data = 1;
      head->sections[i].address = section->lma;
      head->sections[i].size = bfd_get_section_size (section);
      head->sections[i].number = idx;
      head->sections[i].nrelocs = section->reloc_count;
      head->sections[i].relocs =
	(struct coff_reloc *) (xcalloc (section->reloc_count,
					sizeof (struct coff_reloc)));
      head->sections[i].bfd_section = section;
    }
  head->sections[0].name = "ABSOLUTE";
  head->sections[0].code = 0;
  head->sections[0].data = 0;
  head->sections[0].address = 0;
  head->sections[0].size = 0;
  head->sections[0].number = 0;
}
Пример #4
0
bfd_byte *
bfd_coff_reloc16_get_relocated_section_contents
  (bfd *in_abfd,
   struct bfd_link_info *link_info,
   struct bfd_link_order *link_order,
   bfd_byte *data,
   bfd_boolean relocatable,
   asymbol **symbols)
{
  /* Get enough memory to hold the stuff.  */
  bfd *input_bfd = link_order->u.indirect.section->owner;
  asection *input_section = link_order->u.indirect.section;
  long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
  arelent **reloc_vector;
  long reloc_count;
  bfd_size_type sz;

  if (reloc_size < 0)
    return NULL;

  /* If producing relocatable output, don't bother to relax.  */
  if (relocatable)
    return bfd_generic_get_relocated_section_contents (in_abfd, link_info,
						       link_order,
						       data, relocatable,
						       symbols);

  /* Read in the section.  */
  sz = input_section->rawsize ? input_section->rawsize : input_section->size;
  if (!bfd_get_section_contents (input_bfd, input_section, data, 0, sz))
    return NULL;

  reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
  if (!reloc_vector && reloc_size != 0)
    return NULL;

  reloc_count = bfd_canonicalize_reloc (input_bfd,
					input_section,
					reloc_vector,
					symbols);
  if (reloc_count < 0)
    {
      free (reloc_vector);
      return NULL;
    }

  if (reloc_count > 0)
    {
      arelent **parent = reloc_vector;
      arelent *reloc;
      unsigned int dst_address = 0;
      unsigned int src_address = 0;
      unsigned int run;
      unsigned int idx;

      /* Find how long a run we can do.  */
      while (dst_address < link_order->size)
	{
	  reloc = *parent;
	  if (reloc)
	    {
	      /* Note that the relaxing didn't tie up the addresses in the
		 relocation, so we use the original address to work out the
		 run of non-relocated data.  */
	      run = reloc->address - src_address;
	      parent++;
	    }
	  else
	    {
	      run = link_order->size - dst_address;
	    }

	  /* Copy the bytes.  */
	  for (idx = 0; idx < run; idx++)
	    data[dst_address++] = data[src_address++];

	  /* Now do the relocation.  */
	  if (reloc)
	    {
	      bfd_coff_reloc16_extra_cases (input_bfd, link_info, link_order,
					    reloc, data, &src_address,
					    &dst_address);
	    }
	}
    }
  free ((char *) reloc_vector);
  return data;
}
Пример #5
0
bfd_boolean
bfd_coff_reloc16_relax_section (bfd *abfd,
				asection *input_section,
				struct bfd_link_info *link_info,
				bfd_boolean *again)
{
  /* Get enough memory to hold the stuff.  */
  bfd *input_bfd = input_section->owner;
  unsigned *shrinks;
  unsigned shrink = 0;
  long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
  arelent **reloc_vector = NULL;
  long reloc_count;

  if (bfd_link_relocatable (link_info))
    (*link_info->callbacks->einfo)
      (_("%P%F: --relax and -r may not be used together\n"));

  /* We only do global relaxation once.  It is not safe to do it multiple
     times (see discussion of the "shrinks" array below).  */
  *again = FALSE;

  if (reloc_size < 0)
    return FALSE;

  reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
  if (!reloc_vector && reloc_size > 0)
    return FALSE;

  /* Get the relocs and think about them.  */
  reloc_count =
    bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector,
			    _bfd_generic_link_get_symbols (input_bfd));
  if (reloc_count < 0)
    {
      free (reloc_vector);
      return FALSE;
    }

  /* The reloc16.c and related relaxing code is very simple, the price
     for that simplicity is we can only call this function once for
     each section.

     So, to get the best results within that limitation, we do multiple
     relaxing passes over each section here.  That involves keeping track
     of the "shrink" at each reloc in the section.  This allows us to
     accurately determine the relative location of two relocs within
     this section.

     In theory, if we kept the "shrinks" array for each section for the
     entire link, we could use the generic relaxing code in the linker
     and get better results, particularly for jsr->bsr and 24->16 bit
     memory reference relaxations.  */

  if (reloc_count > 0)
    {
      int another_pass = 0;
      bfd_size_type amt;

      /* Allocate and initialize the shrinks array for this section.
	 The last element is used as an accumulator of shrinks.  */
      amt = reloc_count + 1;
      amt *= sizeof (unsigned);
      shrinks = (unsigned *) bfd_zmalloc (amt);

      /* Loop until nothing changes in this section.  */
      do
	{
	  arelent **parent;
	  unsigned int i;
	  long j;

	  another_pass = 0;

	  for (i = 0, parent = reloc_vector; *parent; parent++, i++)
	    {
	      /* Let the target/machine dependent code examine each reloc
		 in this section and attempt to shrink it.  */
	      shrink = bfd_coff_reloc16_estimate (abfd, input_section, *parent,
						  shrinks[i], link_info);

	      /* If it shrunk, note it in the shrinks array and set up for
		 another pass.  */
	      if (shrink != shrinks[i])
		{
		  another_pass = 1;
		  for (j = i + 1; j <= reloc_count; j++)
		    shrinks[j] += shrink - shrinks[i];
		}
	    }
	}
      while (another_pass);

      shrink = shrinks[reloc_count];
      free ((char *) shrinks);
    }

  input_section->rawsize = input_section->size;
  input_section->size -= shrink;
  free ((char *) reloc_vector);
  return TRUE;
}
/* just reloc parts - data comes later */
static void copy_section_relocs_edit (bfd *ibfd, sec_ptr isection, void *obfdarg)
{
    bfd *obfd = obfdarg;
    arelent **relpp;
    long relcount;
    sec_ptr osection;
    bfd_size_type size;
    long relsize;
    flagword flags;


    flags = bfd_get_section_flags (ibfd, isection);
    if ((flags & SEC_GROUP) != 0)
	return;

    osection = isection->output_section;
    size = bfd_get_section_size (isection);

    if (size == 0 || osection == 0)
	return;

    relsize = bfd_get_reloc_upper_bound (ibfd, isection);

    if (relsize <= 0)
    {
	/* not good */
	bfd_perror("attempting to do relocs");
	return;
    }

    relpp = malloc (relsize);

    relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);

    /* copy each reloc, possibly removing or changing it on the fly */
    arelent **temp_relpp;
    long temp_relcount = 0;
    long i;
    int msg_cnt = 0;
    struct change_reloc_struct *change_ptr;
    struct add_reloc_struct *new_reloc;
    asymbol **osympp;

    /* count new relocs to allocate space in reloc list */
    int reloc_add_cnt;
    reloc_add_cnt = 0;
    for (new_reloc = additional_relocs; new_reloc != NULL; new_reloc = new_reloc->next) {
	reloc_add_cnt++;
    }

    osympp = bfd_get_outsymbols(obfd);

    /* note: cannot run mprobe on osympp b/c the copy contents will sometimes realloc it from internal BFD storage */

    temp_relpp = malloc (relsize + reloc_add_cnt * sizeof(arelent *));
    for (i = 0; i < relcount; i++) {

	if (is_delete_reloc(bfd_asymbol_name(*relpp[i]->sym_ptr_ptr), delete_relocs)) {
	    continue;
	}
	else if ((change_ptr = find_change_reloc(bfd_asymbol_name(*relpp[i]->sym_ptr_ptr), change_relocs)) != NULL) {
	    int sym_idx;
	    sym_idx = find_symbol(osympp, change_ptr->new_symbol_name);
	    if (sym_idx < 0) {
		fprintf(stderr, "internal error: could not find new symbol %s in output symbol table\n", change_ptr->new_symbol_name);
		exit(1);
	    }
	    relpp[i]->sym_ptr_ptr = &(osympp[sym_idx]);
	}
	temp_relpp [temp_relcount++] = relpp [i];
    }

    /* now the additional relocs from the command line */
    if (strcmp(bfd_get_section_name(ibfd, isection), ".text") == 0) {
	add_reloc_struct *add_reloc;
	for (add_reloc = additional_relocs; add_reloc != NULL; add_reloc = add_reloc->next) {
	    arelent *new_reloc;
	    int symbol_idx;

	    new_reloc = malloc(sizeof(*new_reloc));
	    if ((symbol_idx = find_symbol(osympp, add_reloc->symbol_name)) < 0) {
		fprintf(stderr, "could not find symbol %s to perform a relocation! possible internal error\n", add_reloc->symbol_name);
		continue;
	    }
	    new_reloc->sym_ptr_ptr = &osympp[symbol_idx];
	    new_reloc->address = add_reloc->loc;
	    new_reloc->addend = 0;   /* never seemed to be used in my cursory investigation */
	    new_reloc->howto = bfd_reloc_type_lookup(ibfd, BFD_RELOC_32_PCREL);
	    if (new_reloc->howto == NULL) {
		fprintf(stderr, "could not get howto back from bfd subsystem\n");
		exit(1);
	    }

	    temp_relpp[temp_relcount++] = new_reloc;
	}
    }
    temp_relpp[temp_relcount] = NULL;

    relcount = temp_relcount;
    free (relpp);
    relpp = temp_relpp;

    bfd_set_reloc (obfd, osection, relcount == 0 ? NULL : relpp, relcount);
    if (relcount == 0)
	free (relpp);

    mcheck_check_all();

}