You should have received a copy of the GNU General Public License
along with this program; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* This file is based on a preliminary PowerPC ELF ABI. The
information may not match the final PowerPC ELF ABI. It includes
bfd_vma addend;
/* which linker section this is */
elf_linker_section_t *lsect;
- /* whether address was written yet */
- bfd_boolean written_address_p;
} elf_linker_section_pointers_t;
struct ppc_elf_obj_tdata
that the linker doesn't crater when trying to make more than
2 sections. */
-static struct bfd_elf_special_section const ppc_elf_special_sections[]=
+static struct bfd_elf_special_section const
+ ppc_special_sections_p[] =
+{
+ { ".plt", 4, 0, SHT_NOBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { NULL, 0, 0, 0, 0 }
+};
+
+static struct bfd_elf_special_section const
+ ppc_special_sections_s[] =
{
- { ".tags", 5, 0, SHT_ORDERED, SHF_ALLOC },
{ ".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ ".sbss", 5, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
{ ".sdata2", 7, -2, SHT_PROGBITS, SHF_ALLOC },
{ ".sbss2", 6, -2, SHT_PROGBITS, SHF_ALLOC },
+ { NULL, 0, 0, 0, 0 }
+};
+
+static struct bfd_elf_special_section const
+ ppc_special_sections_t[] =
+{
+ { ".tags", 5, 0, SHT_ORDERED, SHF_ALLOC },
+ { NULL, 0, 0, 0, 0 }
+};
+
+static struct bfd_elf_special_section const
+ ppc_special_sections_other[]=
+{
{ ".PPC.EMB.apuinfo", 16, 0, SHT_NOTE, 0 },
{ ".PPC.EMB.sdata0", 15, 0, SHT_PROGBITS, SHF_ALLOC },
{ ".PPC.EMB.sbss0", 14, 0, SHT_PROGBITS, SHF_ALLOC },
- { ".plt", 4, 0, SHT_NOBITS, SHF_ALLOC + SHF_EXECINSTR },
- { NULL, 0, 0, 0, 0 }
+ { NULL, 0, 0, 0, 0 }
+};
+
+static struct bfd_elf_special_section const *
+ ppc_elf_special_sections[27]=
+{
+ NULL, /* 'a' */
+ NULL, /* 'b' */
+ NULL, /* 'c' */
+ NULL, /* 'd' */
+ NULL, /* 'e' */
+ NULL, /* 'f' */
+ NULL, /* 'g' */
+ NULL, /* 'h' */
+ NULL, /* 'i' */
+ NULL, /* 'j' */
+ NULL, /* 'k' */
+ NULL, /* 'l' */
+ NULL, /* 'm' */
+ NULL, /* 'n' */
+ NULL, /* 'o' */
+ ppc_special_sections_p, /* 'p' */
+ NULL, /* 'q' */
+ NULL, /* 'r' */
+ ppc_special_sections_s, /* 's' */
+ ppc_special_sections_t, /* 's' */
+ NULL, /* 'u' */
+ NULL, /* 'v' */
+ NULL, /* 'w' */
+ NULL, /* 'x' */
+ NULL, /* 'y' */
+ NULL, /* 'z' */
+ ppc_special_sections_other, /* other */
};
\f
/* Very simple linked list structure for recording apuinfo values. */
bfd_vma offset;
} tlsld_got;
+ /* Size of reserved GOT entries. */
+ unsigned int got_header_size;
+ /* Non-zero if allocating the header left a gap. */
+ unsigned int got_gap;
+
/* Small local sym to section mapping cache. */
struct sym_sec_cache sym_sec;
};
if (!bfd_set_section_flags (abfd, s, flags))
return FALSE;
- htab->relgot = bfd_make_section (abfd, ".rela.got");
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED | SEC_READONLY);
+ htab->relgot = bfd_make_section_with_flags (abfd, ".rela.got", flags);
if (!htab->relgot
- || ! bfd_set_section_flags (abfd, htab->relgot,
- (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY | SEC_LINKER_CREATED
- | SEC_READONLY))
|| ! bfd_set_section_alignment (abfd, htab->relgot, 2))
return FALSE;
| SEC_LINKER_CREATED);
htab->dynbss = bfd_get_section_by_name (abfd, ".dynbss");
- htab->dynsbss = s = bfd_make_section (abfd, ".dynsbss");
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, SEC_ALLOC | SEC_LINKER_CREATED))
+ s = bfd_make_section_with_flags (abfd, ".dynsbss",
+ SEC_ALLOC | SEC_LINKER_CREATED);
+ htab->dynsbss = s;
+ if (s == NULL)
return FALSE;
if (! info->shared)
{
htab->relbss = bfd_get_section_by_name (abfd, ".rela.bss");
- htab->relsbss = s = bfd_make_section (abfd, ".rela.sbss");
+ s = bfd_make_section_with_flags (abfd, ".rela.sbss",
+ flags | SEC_READONLY);
+ htab->relsbss = s;
if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
|| ! bfd_set_section_alignment (abfd, s, 2))
return FALSE;
}
if (s == NULL)
abort ();
- flags = SEC_ALLOC | SEC_CODE | SEC_IN_MEMORY | SEC_LINKER_CREATED;
+ flags = SEC_ALLOC | SEC_CODE | SEC_LINKER_CREATED;
return bfd_set_section_flags (abfd, s, flags);
}
if (!htab->elf.dynobj)
htab->elf.dynobj = abfd;
- htab->sbss = bfd_make_section_anyway (htab->elf.dynobj, ".sbss");
- if (htab->sbss == NULL
- || ! bfd_set_section_flags (htab->elf.dynobj, htab->sbss, flags))
+ htab->sbss = bfd_make_section_anyway_with_flags (htab->elf.dynobj,
+ ".sbss",
+ flags);
+ if (htab->sbss == NULL)
return FALSE;
}
if (!htab->elf.dynobj)
htab->elf.dynobj = abfd;
- /* See if the section already exists. */
- s = bfd_get_section_by_name (htab->elf.dynobj, lsect->name);
- if (s == NULL || (s->flags & flags) != flags)
- {
- s = bfd_make_section_anyway (htab->elf.dynobj, lsect->name);
- if (s == NULL
- || !bfd_set_section_flags (htab->elf.dynobj, s, flags))
- return FALSE;
- }
- lsect->section = s;
-
- if (bfd_get_section_alignment (htab->elf.dynobj, s) < 2
- && !bfd_set_section_alignment (htab->elf.dynobj, s, 2))
+ s = bfd_make_section_anyway_with_flags (htab->elf.dynobj,
+ lsect->name,
+ flags);
+ if (s == NULL
+ || !bfd_set_section_alignment (htab->elf.dynobj, s, 2))
return FALSE;
-
- s->size = align_power (s->size, 2);
-
-#ifdef DEBUG
- fprintf (stderr, "Creating section %s, current size = %ld\n",
- lsect->name, (long) s->size);
-#endif
+ lsect->section = s;
return TRUE;
}
static bfd_boolean
elf_create_pointer_linker_section (bfd *abfd,
- struct bfd_link_info *info,
elf_linker_section_t *lsect,
struct elf_link_hash_entry *h,
const Elf_Internal_Rela *rel)
return TRUE;
ptr_linker_section_ptr = &eh->linker_section_pointer;
- /* Make sure this symbol is output as a dynamic symbol. */
- if (h->dynindx == -1)
- {
- if (! bfd_elf_link_record_dynamic_symbol (info, h))
- return FALSE;
- }
}
else
{
linker_section_ptr->next = *ptr_linker_section_ptr;
linker_section_ptr->addend = rel->r_addend;
linker_section_ptr->lsect = lsect;
- linker_section_ptr->written_address_p = FALSE;
*ptr_linker_section_ptr = linker_section_ptr;
linker_section_ptr->offset = lsect->section->size;
if (info->relocatable)
return TRUE;
+ /* Don't do anything special with non-loaded, non-alloced sections.
+ In particular, any relocs in such sections should not affect GOT
+ and PLT reference counting (ie. we don't allow them to create GOT
+ or PLT entries), there's no possibility or desire to optimize TLS
+ relocs, and there's not much point in propagating relocs to shared
+ libs that the dynamic linker won't relocate. */
+ if ((sec->flags & SEC_ALLOC) == 0)
+ return TRUE;
+
#ifdef DEBUG
_bfd_error_handler ("ppc_elf_check_relocs called for section %A in %B",
sec, abfd);
/* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got.
This shows up in particular in an R_PPC_ADDR32 in the eabi
startup code. */
- if (h && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+ if (h != NULL
+ && htab->got == NULL
+ && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
{
- if (htab->got == NULL)
- {
- if (htab->elf.dynobj == NULL)
- htab->elf.dynobj = abfd;
- if (!ppc_elf_create_got (htab->elf.dynobj, info))
- return FALSE;
- }
+ if (htab->elf.dynobj == NULL)
+ htab->elf.dynobj = abfd;
+ if (!ppc_elf_create_got (htab->elf.dynobj, info))
+ return FALSE;
+ BFD_ASSERT (h == htab->elf.hgot);
}
r_type = ELF32_R_TYPE (rel->r_info);
&& !ppc_elf_create_linker_section (abfd, info, 0,
&htab->sdata[0]))
return FALSE;
- if (!elf_create_pointer_linker_section (abfd, info,
- &htab->sdata[0], h, rel))
+ if (!elf_create_pointer_linker_section (abfd, &htab->sdata[0],
+ h, rel))
return FALSE;
break;
&& !ppc_elf_create_linker_section (abfd, info, SEC_READONLY,
&htab->sdata[1]))
return FALSE;
- if (!elf_create_pointer_linker_section (abfd, info,
- &htab->sdata[1], h, rel))
+ if (!elf_create_pointer_linker_section (abfd, &htab->sdata[1],
+ h, rel))
return FALSE;
break;
case R_PPC_REL14_BRTAKEN:
case R_PPC_REL14_BRNTAKEN:
case R_PPC_REL32:
- if (h == NULL
- || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+ if (h == NULL || h == htab->elf.hgot)
break;
/* fall through */
|| !h->def_regular))))
|| (ELIMINATE_COPY_RELOCS
&& !info->shared
- && (sec->flags & SEC_ALLOC) != 0
&& h != NULL
&& (h->root.type == bfd_link_hash_defweak
|| !h->def_regular)))
{
flagword flags;
- sreloc = bfd_make_section (htab->elf.dynobj, name);
flags = (SEC_HAS_CONTENTS | SEC_READONLY
- | SEC_IN_MEMORY | SEC_LINKER_CREATED);
- if ((sec->flags & SEC_ALLOC) != 0)
- flags |= SEC_ALLOC | SEC_LOAD;
+ | SEC_IN_MEMORY | SEC_LINKER_CREATED
+ | SEC_ALLOC | SEC_LOAD);
+ sreloc = bfd_make_section_with_flags (htab->elf.dynobj,
+ name,
+ flags);
if (sreloc == NULL
- || ! bfd_set_section_flags (htab->elf.dynobj,
- sreloc, flags)
|| ! bfd_set_section_alignment (htab->elf.dynobj,
sreloc, 2))
return FALSE;
bfd_signed_vma *local_got_refcounts;
const Elf_Internal_Rela *rel, *relend;
+ if ((sec->flags & SEC_ALLOC) == 0)
+ return TRUE;
+
elf_section_data (sec)->local_dynrel = NULL;
htab = ppc_elf_hash_table (info);
case R_PPC_REL14_BRTAKEN:
case R_PPC_REL14_BRNTAKEN:
case R_PPC_REL32:
- if (h == NULL
- || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+ if (h == NULL || h == htab->elf.hgot)
break;
/* Fall thru */
return TRUE;
}
\f
+/* Allocate NEED contiguous space in .got, and return the offset.
+ Handles allocation of the got header when crossing 32k. */
+
+static bfd_vma
+allocate_got (struct ppc_elf_link_hash_table *htab, unsigned int need)
+{
+ bfd_vma where;
+ unsigned int max_before_header = 32764;
+
+ if (need <= htab->got_gap)
+ {
+ where = max_before_header - htab->got_gap;
+ htab->got_gap -= need;
+ }
+ else
+ {
+ if (htab->got->size + need > max_before_header
+ && htab->got->size <= max_before_header)
+ {
+ htab->got_gap = max_before_header - htab->got->size;
+ htab->got->size = max_before_header + htab->got_header_size;
+ }
+ where = htab->got->size;
+ htab->got->size += need;
+ }
+ return where;
+}
+
/* Allocate space in associated reloc sections for dynamic relocs. */
static bfd_boolean
else
{
bfd_boolean dyn;
- eh->elf.got.offset = htab->got->size;
+ unsigned int need = 0;
if ((eh->tls_mask & TLS_TLS) != 0)
{
if ((eh->tls_mask & TLS_LD) != 0)
- htab->got->size += 8;
+ need += 8;
if ((eh->tls_mask & TLS_GD) != 0)
- htab->got->size += 8;
+ need += 8;
if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0)
- htab->got->size += 4;
+ need += 4;
if ((eh->tls_mask & TLS_DTPREL) != 0)
- htab->got->size += 4;
+ need += 4;
}
else
- htab->got->size += 4;
+ need += 4;
+ eh->elf.got.offset = allocate_got (htab, need);
dyn = htab->elf.dynamic_sections_created;
if ((info->shared
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, &eh->elf))
&& (ELF_ST_VISIBILITY (eh->elf.other) == STV_DEFAULT
|| eh->elf.root.type != bfd_link_hash_undefweak))
{
- /* All the entries we allocated need relocs. */
- htab->relgot->size
- += ((htab->got->size - eh->elf.got.offset) / 4
- * sizeof (Elf32_External_Rela));
- /* Except LD only needs one. */
+ /* All the entries we allocated need relocs.
+ Except LD only needs one. */
if ((eh->tls_mask & TLS_LD) != 0)
- htab->relgot->size -= sizeof (Elf32_External_Rela);
+ need -= 4;
+ htab->relgot->size += need * (sizeof (Elf32_External_Rela) / 4);
}
}
}
}
}
- if (htab->tlsld_got.refcount > 0)
- {
- htab->tlsld_got.offset = htab->got->size;
- htab->got->size += 8;
- if (info->shared)
- htab->relgot->size += sizeof (Elf32_External_Rela);
- }
- else
- htab->tlsld_got.offset = (bfd_vma) -1;
+ htab->got_header_size = 16;
/* Set up .got offsets for local syms, and space for local dynamic
relocs. */
char *lgot_masks;
bfd_size_type locsymcount;
Elf_Internal_Shdr *symtab_hdr;
- asection *srel;
if (!is_ppc_elf_target (ibfd->xvec))
continue;
locsymcount = symtab_hdr->sh_info;
end_local_got = local_got + locsymcount;
lgot_masks = (char *) end_local_got;
- s = htab->got;
- srel = htab->relgot;
for (; local_got < end_local_got; ++local_got, ++lgot_masks)
if (*local_got > 0)
{
{
/* If just an LD reloc, we'll just use
htab->tlsld_got.offset. */
- if (htab->tlsld_got.offset == (bfd_vma) -1)
- {
- htab->tlsld_got.offset = s->size;
- s->size += 8;
- if (info->shared)
- srel->size += sizeof (Elf32_External_Rela);
- }
+ htab->tlsld_got.refcount += 1;
*local_got = (bfd_vma) -1;
}
else
{
- *local_got = s->size;
+ unsigned int need = 0;
if ((*lgot_masks & TLS_TLS) != 0)
{
if ((*lgot_masks & TLS_GD) != 0)
- s->size += 8;
+ need += 8;
if ((*lgot_masks & (TLS_TPREL | TLS_TPRELGD)) != 0)
- s->size += 4;
+ need += 4;
if ((*lgot_masks & TLS_DTPREL) != 0)
- s->size += 4;
+ need += 4;
}
else
- s->size += 4;
+ need += 4;
+ *local_got = allocate_got (htab, need);
if (info->shared)
- srel->size += ((s->size - *local_got) / 4
- * sizeof (Elf32_External_Rela));
+ htab->relgot->size += (need
+ * (sizeof (Elf32_External_Rela) / 4));
}
}
else
*local_got = (bfd_vma) -1;
}
+ if (htab->tlsld_got.refcount > 0)
+ {
+ htab->tlsld_got.offset = allocate_got (htab, 8);
+ if (info->shared)
+ htab->relgot->size += sizeof (Elf32_External_Rela);
+ }
+ else
+ htab->tlsld_got.offset = (bfd_vma) -1;
+
/* Allocate space for global sym dynamic relocs. */
elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
+ if (htab->got != NULL)
+ {
+ unsigned int g_o_t = 32768;
+
+ /* If we haven't allocated the header, do so now. */
+ if (htab->got->size <= 32768)
+ {
+ g_o_t = htab->got->size;
+ htab->got->size += htab->got_header_size;
+ }
+ g_o_t += 4;
+
+ htab->elf.hgot->root.u.def.value = g_o_t;
+ }
+
/* We've now determined the sizes of the various dynamic sections.
Allocate memory for them. */
relocs = FALSE;
if (s->size == 0)
{
- _bfd_strip_section_from_output (info, s);
+ s->flags |= SEC_EXCLUDE;
continue;
}
*again = FALSE;
- /* Nothing to do if there are no relocations. */
- if ((isec->flags & SEC_RELOC) == 0 || isec->reloc_count == 0)
+ /* Nothing to do if there are no relocations, and no need to do
+ anything with non-alloc sections. */
+ if ((isec->flags & SEC_ALLOC) == 0
+ || (isec->flags & SEC_RELOC) == 0
+ || isec->reloc_count == 0)
return TRUE;
trampoff = (isec->size + 3) & (bfd_vma) -4;
return FALSE;
}
\f
-/* Set SYM_NAME to VAL if the symbol exists and is undefined. */
-
-static void
-set_linker_sym (struct ppc_elf_link_hash_table *htab,
- const char *sym_name,
- bfd_vma val)
-{
- struct elf_link_hash_entry *h;
- h = elf_link_hash_lookup (&htab->elf, sym_name, FALSE, FALSE, FALSE);
- if (h != NULL && h->root.type == bfd_link_hash_undefined)
- {
- h->root.type = bfd_link_hash_defined;
- h->root.u.def.section = bfd_abs_section_ptr;
- h->root.u.def.value = val;
- h->def_regular = 1;
- h->type = STT_OBJECT;
- h->other = STV_HIDDEN;
- }
-}
-
/* Set _SDA_BASE_, _SDA2_BASE, and sbss start and end syms. They are
set here rather than via PROVIDE in the default linker script,
because using PROVIDE inside an output section statement results in
val = s->vma + 32768;
lsect->sym_val = val;
- set_linker_sym (htab, lsect->sym_name, val);
+ _bfd_elf_provide_symbol (info, lsect->sym_name, val);
}
s = bfd_get_section_by_name (obfd, ".sbss");
val = 0;
if (s != NULL)
val = s->vma;
- set_linker_sym (htab, "__sbss_start", val);
- set_linker_sym (htab, "___sbss_start", val);
+ _bfd_elf_provide_symbol (info, "__sbss_start", val);
+ _bfd_elf_provide_symbol (info, "___sbss_start", val);
if (s != NULL)
val += s->size;
- set_linker_sym (htab, "__sbss_end", val);
- set_linker_sym (htab, "___sbss_end", val);
+ _bfd_elf_provide_symbol (info, "__sbss_end", val);
+ _bfd_elf_provide_symbol (info, "___sbss_end", val);
return TRUE;
}
\f
-#define bfd_put_ptr(BFD, VAL, ADDR) bfd_put_32 (BFD, VAL, ADDR)
-
/* Fill in the address for a pointer generated in a linker section. */
static bfd_vma
-elf_finish_pointer_linker_section (bfd *output_bfd,
- bfd *input_bfd,
- struct bfd_link_info *info,
+elf_finish_pointer_linker_section (bfd *input_bfd,
elf_linker_section_t *lsect,
struct elf_link_hash_entry *h,
bfd_vma relocation,
struct ppc_elf_link_hash_entry *eh;
eh = (struct ppc_elf_link_hash_entry *) h;
- linker_section_ptr
- = elf_find_pointer_linker_section (eh->linker_section_pointer,
- rel->r_addend,
- lsect);
-
- BFD_ASSERT (linker_section_ptr != NULL);
-
- if (! elf_hash_table (info)->dynamic_sections_created
- || (info->shared
- && info->symbolic
- && h->def_regular))
- {
- /* This is actually a static link, or it is a
- -Bsymbolic link and the symbol is defined
- locally. We must initialize this entry in the
- global section.
-
- When doing a dynamic link, we create a .rela.<xxx>
- relocation entry to initialize the value. This
- is done in the finish_dynamic_symbol routine. */
- if (!linker_section_ptr->written_address_p)
- {
- linker_section_ptr->written_address_p = TRUE;
- bfd_put_ptr (output_bfd,
- relocation + linker_section_ptr->addend,
- (lsect->section->contents
- + linker_section_ptr->offset));
- }
- }
+ BFD_ASSERT (eh->elf.def_regular);
+ linker_section_ptr = eh->linker_section_pointer;
}
else
{
/* Handle local symbol. */
unsigned long r_symndx = ELF32_R_SYM (rel->r_info);
+
BFD_ASSERT (elf_local_ptr_offsets (input_bfd) != NULL);
- BFD_ASSERT (elf_local_ptr_offsets (input_bfd)[r_symndx] != NULL);
- linker_section_ptr = (elf_find_pointer_linker_section
- (elf_local_ptr_offsets (input_bfd)[r_symndx],
- rel->r_addend,
- lsect));
+ linker_section_ptr = elf_local_ptr_offsets (input_bfd)[r_symndx];
+ }
- BFD_ASSERT (linker_section_ptr != NULL);
+ linker_section_ptr = elf_find_pointer_linker_section (linker_section_ptr,
+ rel->r_addend,
+ lsect);
+ BFD_ASSERT (linker_section_ptr != NULL);
- /* Write out pointer if it hasn't been rewritten out before. */
- if (!linker_section_ptr->written_address_p)
- {
- linker_section_ptr->written_address_p = TRUE;
- bfd_put_ptr (output_bfd, relocation + linker_section_ptr->addend,
- lsect->section->contents + linker_section_ptr->offset);
- }
+ /* Offset will always be a multiple of four, so use the bottom bit
+ as a "written" flag. */
+ if ((linker_section_ptr->offset & 1) == 0)
+ {
+ bfd_put_32 (lsect->section->owner,
+ relocation + linker_section_ptr->addend,
+ lsect->section->contents + linker_section_ptr->offset);
+ linker_section_ptr->offset += 1;
}
relocation = (lsect->section->output_offset
- + linker_section_ptr->offset
+ + linker_section_ptr->offset - 1
- 0x8000);
#ifdef DEBUG
{
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
- sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym);
+ sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec);
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
}
}
}
- relocation = htab->got->output_offset + off - 4;
+ relocation = htab->got->output_offset + off;
+ relocation -= htab->elf.hgot->root.u.def.value;
/* Addends on got relocations don't make much sense.
x+off@got is actually x@got+off, and since the got is
/* If these relocations are not to a named symbol, they can be
handled right here, no need to bother the dynamic linker. */
if (SYMBOL_REFERENCES_LOCAL (info, h)
- || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+ || h == htab->elf.hgot)
break;
/* fall through */
break;
/* Fall thru. */
+ if ((input_section->flags & SEC_ALLOC) == 0)
+ break;
+ /* Fall thru. */
+
if ((info->shared
&& (h == NULL
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| !SYMBOL_CALLS_LOCAL (info, h)))
|| (ELIMINATE_COPY_RELOCS
&& !info->shared
- && (input_section->flags & SEC_ALLOC) != 0
&& h != NULL
&& h->dynindx != -1
&& !h->non_got_ref
case R_PPC_EMB_SDAI16:
BFD_ASSERT (htab->sdata[0].section != NULL);
relocation
- = elf_finish_pointer_linker_section (output_bfd, input_bfd, info,
- &htab->sdata[0], h,
- relocation, rel);
+ = elf_finish_pointer_linker_section (input_bfd, &htab->sdata[0],
+ h, relocation, rel);
break;
/* Indirect .sdata2 relocation. */
case R_PPC_EMB_SDA2I16:
BFD_ASSERT (htab->sdata[1].section != NULL);
relocation
- = elf_finish_pointer_linker_section (output_bfd, input_bfd, info,
- &htab->sdata[1], h,
- relocation, rel);
+ = elf_finish_pointer_linker_section (input_bfd, &htab->sdata[1],
+ h, relocation, rel);
break;
/* Handle the TOC16 reloc. We want to use the offset within the .got
if (r != bfd_reloc_ok)
{
- if (sym_name == NULL)
- sym_name = "(null)";
if (r == bfd_reloc_overflow)
{
if (warned)
#endif
/* Mark some specially defined symbols as absolute. */
- if (strcmp (h->root.root.string, "_DYNAMIC") == 0
- || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
+ if (h == htab->elf.hgot
+ || strcmp (h->root.root.string, "_DYNAMIC") == 0
|| strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
sym->st_shndx = SHN_ABS;
/* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4 so that a function can
easily find the address of the _GLOBAL_OFFSET_TABLE_. */
- if (htab->got)
+ if (htab->got != NULL)
{
- unsigned char *contents = htab->got->contents;
- bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, contents);
+ unsigned char *p = htab->got->contents;
+ bfd_vma val;
- if (sdyn == NULL)
- bfd_put_32 (output_bfd, 0, contents + 4);
- else
- bfd_put_32 (output_bfd,
- sdyn->output_section->vma + sdyn->output_offset,
- contents + 4);
+ p += elf_hash_table (info)->hgot->root.u.def.value;
+ bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, p - 4);
+
+ val = 0;
+ if (sdyn != NULL)
+ val = sdyn->output_section->vma + sdyn->output_offset;
+ bfd_put_32 (output_bfd, val, p);
elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 4;
}
#endif
#define elf_backend_plt_not_loaded 1
-#define elf_backend_got_symbol_offset 4
#define elf_backend_can_gc_sections 1
#define elf_backend_can_refcount 1
-#define elf_backend_got_header_size 12
#define elf_backend_rela_normal 1
#define bfd_elf32_mkobject ppc_elf_mkobject