diff --git a/bfd/amigaoslink.c b/bfd/amigaoslink.c index 92c46ec..c9dde7c 100644 --- a/bfd/amigaoslink.c +++ b/bfd/amigaoslink.c @@ -96,6 +96,8 @@ int amiga_attribute = 0; /* This one is used to indicate base-relative linking */ int amiga_base_relative = 0; +static int amiga_base_relative32 = 0; + /* This one is used to indicate -resident linking */ int amiga_resident = 0; @@ -147,7 +149,7 @@ get_relocated_section_contents (abfd, link_info, link_order, data, bfd_reloc_status_type (*reloc_func)(bfd *, arelent *, PTR, sec_ptr, bfd *, char **); - DPRINT(5,("Entering get_rel_sec_cont\n")); + DPRINT(5,("\n----\nEntering get_rel_sec_cont\n")); if (reloc_size < 0) goto error_return; @@ -191,7 +193,7 @@ get_relocated_section_contents (abfd, link_info, link_order, data, { arelent **parent; - DPRINT(5,("reloc_count=%ld\n",reloc_count)); + DPRINT(5,("doing relocs section=%s at %p, output=%s reloc_count=%ld\n", input_section->name, reloc_vector, input_section->output_section->name, reloc_count)); for (parent = reloc_vector; *parent != (arelent *) NULL; parent++) @@ -199,8 +201,10 @@ get_relocated_section_contents (abfd, link_info, link_order, data, char *error_message = (char *) NULL; bfd_reloc_status_type r; - DPRINT(5,("Applying a reloc\nparent=%lx, reloc_vector=%lx, " - "*parent=%lx\n",parent,reloc_vector,*parent)); + DPRINT(5,("apply reloc: %s in %s type=%d\n", + (*((*parent)->sym_ptr_ptr))->name, + (*((*parent)->sym_ptr_ptr))->section->name, + (*parent)->howto->type)); r=(*reloc_func) (input_bfd, *parent, (PTR) data, @@ -276,8 +280,9 @@ my_add_to (r, data, add, flags) bfd_reloc_status_type ret=bfd_reloc_ok; bfd_byte *p=((bfd_byte *)data)+r->address; int val; + asymbol *sym=*(r->sym_ptr_ptr); - DPRINT(5,("Entering add_value\n")); + DPRINT(5,("Entering add_value for %s with add: %x\n", sym->name, add)); switch (r->howto->size) { @@ -390,7 +395,7 @@ amiga_perform_reloc (abfd, r, data, sec, obfd, error_message) bfd_boolean copy; int relocation,flags; - DPRINT(5,("Entering APR\nflavour is %d (amiga_flavour=%d, aout_flavour=%d)\n", + DPRINT(5,("\nEntering APR\nflavour is %d (amiga_flavour=%d, aout_flavour=%d)\n", bfd_get_flavour (sec->owner), bfd_target_amiga_flavour, bfd_target_aout_flavour)); @@ -409,9 +414,9 @@ amiga_perform_reloc (abfd, r, data, sec, obfd, error_message) sym=*(r->sym_ptr_ptr); - /* FIXME: XXX */ - if (0 && sym->udata.p) - sym = ((struct generic_link_hash_entry *) sym->udata.p)->sym; +// ?? /* FIXME: XXX */ +// if (0 && sym->udata.p) +// sym = ((struct generic_link_hash_entry *) sym->udata.p)->sym; target_section=sym->section; @@ -423,7 +428,14 @@ amiga_perform_reloc (abfd, r, data, sec, obfd, error_message) relocation=0; flags=RELOC_SIGNED; copy=FALSE; ret=bfd_reloc_ok; - DPRINT(5,("%s: size=%u\n",r->howto->name,bfd_get_reloc_size(r->howto))); + DPRINT(5,("amigaRELOC: %s: size=%u\n",r->howto->name,bfd_get_reloc_size(r->howto))); + DPRINT(10,("target=%s, target->out=%s(%lx), sec->out=%s(%lx), symbol=%s\n", + target_section->name, + target_section->output_section->name, + target_section->output_section, + sec->output_section->name, + sec->output_section, + sym->name)); switch (r->howto->type) { case H_ABS32: @@ -441,6 +453,8 @@ amiga_perform_reloc (abfd, r, data, sec, obfd, error_message) relocation=0; copy=TRUE; } + if (amiga_base_relative32 && 0 == strcmp("___a4_init", sym->name)) + relocation -= (AMIGA_DATA(target_section->output_section->owner))->a4init; break; case H_PC8: /* pcrel */ @@ -468,6 +482,7 @@ amiga_perform_reloc (abfd, r, data, sec, obfd, error_message) case H_SD8: /* baserel */ case H_SD16: case H_SD32: + amiga_base_relative32 |= r->howto->type == H_SD32; /* Relocs are always relative to the symbol ___a4_init */ /* Relocs to .bss section are converted to a reloc to .data section, since .bss section contains only COMMON sections...... and should @@ -489,12 +504,13 @@ amiga_perform_reloc (abfd, r, data, sec, obfd, error_message) else { amiga_update_target_section (target_section); - - relocation = sym->value + target_section->output_offset - - (AMIGA_DATA(target_section->output_section->owner))->a4init - + r->addend; + relocation = sym->value + target_section->output_offset + r->addend; flags|=ADDEND_UNSIGNED; } + + if (amiga_base_relative && r->howto->type != H_SD32) + relocation -= (AMIGA_DATA(target_section->output_section->owner))->a4init; + break; default: @@ -509,7 +525,7 @@ amiga_perform_reloc (abfd, r, data, sec, obfd, error_message) if (copy) /* Copy reloc to output section */ { - DPRINT(5,("Copying reloc\n")); + DPRINT(5,("Copying reloc to %s:%s at %d\n", sec->output_section->name, sym->name, r->address)); target_section=sec->output_section; r->address+=sec->output_offset; target_section->orelocation[target_section->reloc_count++]=r; @@ -564,7 +580,7 @@ aout_perform_reloc (abfd, r, data, sec, obfd, error_message) bfd_boolean copy; int relocation,flags; - DPRINT(5,("Entering aout_perf_reloc\n")); + DPRINT(5,("\nEntering aout_perf_reloc\n")); /* If obfd==NULL: Apply the reloc, if possible. */ /* Else: Modify it and return */ @@ -579,6 +595,7 @@ aout_perform_reloc (abfd, r, data, sec, obfd, error_message) /* Try to apply the reloc */ sym=*(r->sym_ptr_ptr); + target_section=sym->section; if (bfd_is_und_section(target_section)) /* Error */ @@ -593,7 +610,13 @@ aout_perform_reloc (abfd, r, data, sec, obfd, error_message) relocation=0; flags=RELOC_SIGNED; copy=FALSE; ret=bfd_reloc_ok; - DPRINT(10,("RELOC: %s, %d: size=%u\n",r->howto->name,r->howto->type,bfd_get_reloc_size(r->howto))); + DPRINT(10,("aoutRELOC: %s, %d: size=%u\n",r->howto->name,r->howto->type,bfd_get_reloc_size(r->howto))); + DPRINT(10,("target->out=%s(%lx), sec->out=%s(%lx), symbol=%s\n", + target_section->output_section->name, + target_section->output_section, + sec->output_section->name, + sec->output_section, + sym->name)); switch (r->howto->type) { case H_ABS8: /* 8/16 bit reloc, pc relative or absolute */ @@ -612,27 +635,24 @@ aout_perform_reloc (abfd, r, data, sec, obfd, error_message) // SBF: the if statement has been fixed, but the linker does no longer work. // if ((target_section->output_section->flags&SEC_DATA)!=0) // I replaced it with the old (obvious bogus) statement - // TODO: a better fix - if (target_section->output_section->flags & (SEC_DATA != 0)) + // TODO: a better fix? + //if (target_section->output_section->flags & (SEC_DATA != 0)) + if (amiga_base_relative) goto baserel; /* Dirty, but no code duplication.. */ bfd_msg ("pc relative relocation out-of-range in section %s. " "Relocation was to symbol %s",sec->name,sym->name); - DPRINT(10,("Section %s, target %s: Reloc out-of-range...not same " - "section, aout_perf\nsec->out=%s, target->out=%s, " - "offset=%lx\n",sec->name,target_section->name, - sec->output_section->name, - target_section->output_section->name,r->address)); ret=bfd_reloc_outofrange; } else { /* Same section, this is a pc relative hunk... */ DPRINT(5,("Reloc to same section...\n")); - relocation=-(r->address+sec->output_offset); + relocation=-(long)(r->address+sec->output_offset); } break; case H_ABS32: /* 32 bit reloc, pc relative or absolute */ + DPRINT(5, ("32 bit reloc, pc relative or absolute: %s=%d, target_sec_offset=%d, add=%d\n", sym->name, sym->value, target_section->output_offset, r->addend)); if (bfd_is_abs_section(target_section)) /* Ref to absolute hunk */ relocation=sym->value; else if (bfd_is_com_section(target_section)) /* ref to common */ @@ -643,16 +663,29 @@ aout_perform_reloc (abfd, r, data, sec, obfd, error_message) else { if (amiga_base_relative) - aout_update_target_section (target_section); + { + aout_update_target_section (target_section); + } relocation=0; copy=TRUE; + copy=!amiga_base_relative32; + } + if (amiga_base_relative32) + { + relocation = sym->value + target_section->output_offset; + flags|=ADDEND_UNSIGNED; + copy = sec->name == target_section->name; // .text->.text or .data->.data + + if (copy) + { + relocation = 0; + } + else if(0 == strcmp("___a4_init", sym->name)) + { + relocation = - (long)(AMIGA_DATA(target_section->output_section->owner))->a4init; + copy=TRUE; + } } - DPRINT(10,("target->out=%s(%lx), sec->out=%s(%lx), symbol=%s\n", - target_section->output_section->name, - target_section->output_section, - sec->output_section->name, - sec->output_section, - sym->name)); break; case H_PC8: /* pcrel */ @@ -663,12 +696,6 @@ aout_perform_reloc (abfd, r, data, sec, obfd, error_message) relocation=sym->value; else if (sec->output_section!=target_section->output_section) /* Error */ { - DPRINT(10,("target->out=%s(%lx), sec->out=%s(%lx), symbol=%s\n", - target_section->output_section->name, - target_section->output_section, - sec->output_section->name, - sec->output_section, - sym->name)); DPRINT(5,("pc relative, but out-of-range\n")); ret=bfd_reloc_outofrange; } @@ -681,6 +708,7 @@ aout_perform_reloc (abfd, r, data, sec, obfd, error_message) case H_SD16: /* baserel */ case H_SD32: + amiga_base_relative32 |= r->howto->type == H_SD32; baserel: DPRINT(10,("baserel: %s\n", sym->name)); /* We use the symbol ___a4_init as base */ @@ -708,8 +736,7 @@ aout_perform_reloc (abfd, r, data, sec, obfd, error_message) { aout_update_target_section (target_section); - relocation = sym->value + target_section->output_offset - - (AMIGA_DATA(target_section->output_section->owner))->a4init; + relocation = sym->value + target_section->output_offset; /* if the symbol is in .bss, subtract the offset that gas has put into the opcode */ if (target_section->index == 2) @@ -721,6 +748,10 @@ aout_perform_reloc (abfd, r, data, sec, obfd, error_message) r->address)); flags|=ADDEND_UNSIGNED; } + + if (amiga_base_relative && r->howto->type != H_SD32 && r->howto->type != H_ABS32) + relocation -= (AMIGA_DATA(target_section->output_section->owner))->a4init; + DPRINT(10,("target->out=%s(%lx), sec->out=%s(%lx), symbol=%s\n", target_section->output_section->name, target_section->output_section, @@ -741,7 +772,7 @@ aout_perform_reloc (abfd, r, data, sec, obfd, error_message) if (copy) /* Copy reloc to output section */ { - DPRINT(5,("Copying reloc\n")); + DPRINT(5,("Copying reloc to %s:%s at %d\n", sec->output_section->name, sym->name, r->address)); target_section=sec->output_section; r->address+=sec->output_offset; target_section->orelocation[target_section->reloc_count++]=r;