* elflink.h (elf_bfd_final_link)
@ 2001-05-28 2:09 amodra
2001-05-29 4:58 ` amodra
0 siblings, 1 reply; 3+ messages in thread
From: amodra @ 2001-05-28 2:09 UTC (permalink / raw)
To: binutils; +Cc: parisc-linux, rhirst
Does anyone know why elf_link_output_extsym is only called for a
shared link on symbols forced local? Is it just a case of bit-rot
in that at one stage it was only symbol versioning with shared libs
that could force symbols local?
Not calling elf_link_output_extsym has the effect that the back-end
finish_dynamic_symbol routine isn't called, which means various hacks
are needed like the following:
bfd/ChangeLog
* elf32-hppa.c (elf32_hppa_relocate_section): Set up .plt entries
for symbols forced local that need plabels.
(elf32_hppa_adjust_dynamic_symbol): Don't allocate space in
.plt.rela for local syms if non-shared.
(hppa_build_one_stub): Mask lsb of plt.offset.
(elf32_hppa_finish_dynamic_symbol): Abort if lsb of plt.offset set.
(clobber_millicode_symbols): Correct comment.
(elf32_hppa_relocate_section): Likewise.
(elf32_hppa_finish_dynamic_symbol): Likewise.
--
Alan Modra
Index: bfd/elf32-hppa.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-hppa.c,v
retrieving revision 1.34
diff -u -p -r1.34 elf32-hppa.c
--- elf32-hppa.c 2001/05/25 03:46:49 1.34
+++ elf32-hppa.c 2001/05/28 08:31:36
@@ -831,6 +831,7 @@ hppa_build_one_stub (gen_entry, in_arg)
bfd_byte *loc;
bfd_vma sym_value;
bfd_vma insn;
+ bfd_vma off;
int val;
int size;
@@ -938,9 +939,12 @@ hppa_build_one_stub (gen_entry, in_arg)
case hppa_stub_import:
case hppa_stub_import_shared:
- if (stub_entry->h->elf.plt.offset >= (bfd_vma) -2)
+ off = stub_entry->h->elf.plt.offset;
+ if (off >= (bfd_vma) -2)
abort ();
- sym_value = (stub_entry->h->elf.plt.offset
+
+ off &= ~ (bfd_vma) 1;
+ sym_value = (off
+ hplink->splt->output_offset
+ hplink->splt->output_section->vma
- elf_gp (hplink->splt->output_section->owner));
@@ -1014,10 +1018,10 @@ hppa_build_one_stub (gen_entry, in_arg)
<__gp>. */
bfd_put_32 (hplink->splt->owner, value,
- hplink->splt->contents + eh->elf.plt.offset);
+ hplink->splt->contents + off);
value = elf_gp (hplink->splt->output_section->owner);
bfd_put_32 (hplink->splt->owner, value,
- hplink->splt->contents + eh->elf.plt.offset + 4);
+ hplink->splt->contents + off + 4);
}
break;
@@ -1957,11 +1961,14 @@ elf32_hppa_adjust_dynamic_symbol (info,
return false;
}
- /* We also need to make an entry in the .rela.plt section. */
- s = hplink->srelplt;
- s->_raw_size += sizeof (Elf32_External_Rela);
+ if (h->dynindx != -1 || info->shared)
+ {
+ /* We also need to make an entry in the .rela.plt section. */
+ s = hplink->srelplt;
+ s->_raw_size += sizeof (Elf32_External_Rela);
- hplink->need_plt_stub = 1;
+ hplink->need_plt_stub = 1;
+ }
}
return true;
}
@@ -2149,8 +2156,8 @@ clobber_millicode_symbols (h, info)
struct elf_link_hash_entry *h;
struct bfd_link_info *info;
{
- /* Note! We only want to remove these from the dynamic symbol
- table. Therefore we do not set ELF_LINK_FORCED_LOCAL. */
+ /* We only want to remove these from the dynamic symbol table.
+ Therefore we do not leave ELF_LINK_FORCED_LOCAL set. */
if (h->type == STT_PARISC_MILLI)
{
unsigned short oldflags = h->elf_link_hash_flags;
@@ -3684,10 +3691,10 @@ elf32_hppa_relocate_section (output_bfd,
if (info->shared)
{
- /* Output a dynamic *ABS* relocation for this
- GOT entry. In this case it is relative to
- the base of the object because the symbol
- index is zero. */
+ /* Output a dynamic relocation for this GOT
+ entry. In this case it is relative to the
+ base of the object because the symbol index
+ is zero. */
Elf_Internal_Rela outrel;
asection *srelgot = hplink->srelgot;
@@ -3735,6 +3742,25 @@ elf32_hppa_relocate_section (output_bfd,
if (h != NULL)
{
off = h->elf.plt.offset;
+ if (!info->shared
+ && (h->elf.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
+ {
+ /* In a non-shared link, adjust_dynamic_symbols
+ isn't called for symbols forced local. We
+ need to write out the plt entry here. */
+ if ((off & 1) != 0)
+ off &= ~1;
+ else
+ {
+ bfd_put_32 (output_bfd,
+ relocation,
+ hplink->splt->contents + off);
+ bfd_put_32 (output_bfd,
+ elf_gp (hplink->splt->output_section->owner),
+ hplink->splt->contents + off + 4);
+ h->elf.plt.offset |= 1;
+ }
+ }
}
else
{
@@ -3780,7 +3806,7 @@ elf32_hppa_relocate_section (output_bfd,
}
}
- if (off >= (bfd_vma) -2)
+ if (off >= (bfd_vma) -2 || (off & 1) != 0)
abort ();
/* PLABELs contain function pointers. Relocation is to
@@ -4015,6 +4041,9 @@ elf32_hppa_finish_dynamic_symbol (output
{
bfd_vma value;
+ if (h->plt.offset & 1)
+ abort ();
+
/* This symbol has an entry in the procedure linkage table. Set
it up.
@@ -4045,8 +4074,8 @@ elf32_hppa_finish_dynamic_symbol (output
{
/* To support lazy linking, the function pointer is
initialised to point to a special stub stored at the
- end of the .plt. This is only done for plt entries
- with a non-*ABS* dynamic relocation. */
+ end of the .plt. This is not done for plt entries
+ with a base-relative dynamic relocation. */
value = (hplink->splt->output_offset
+ hplink->splt->output_section->vma
+ hplink->splt->_raw_size
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: elflink.h (elf_bfd_final_link)
2001-05-28 2:09 elflink.h (elf_bfd_final_link) amodra
@ 2001-05-29 4:58 ` amodra
2001-06-04 21:38 ` tweak elf32_hppa .got allocation Alan Modra
0 siblings, 1 reply; 3+ messages in thread
From: amodra @ 2001-05-29 4:58 UTC (permalink / raw)
To: binutils
On Mon, May 28, 2001 at 06:46:53PM +0930, Alan Modra wrote:
>
> Not calling elf_link_output_extsym has the effect that the back-end
> finish_dynamic_symbol routine isn't called, which means various hacks
> are needed
And here's another set of hacks. This time the problem is that the
back-end adjust_dynamic_symbol isn't called for all dynamic symbols,
just those needing .plt entries. That means any finagling of .got
entries, in particular for symbols with non-default visibility,
cannot be done by adjust_dynamic_symbol. So there's no easy way to
reclaim space from .rela.got when we find a reloc is no longer needed.
I found the easiest thing was to dispense with elf_gc_common_final_link
and allocate all .got space in size_dynamic_sections.
bfd/ChangeLog
* elf32-hppa.c (elf32_hppa_check_relocs): Don't NEED_PLT for
millicode. Don't allocate .got and .rela.got space here..
(elf32_hppa_gc_sweep_hook): ..and no need to deallocate here..
(elf32_hppa_adjust_dynamic_symbol): ..and don't allocate .plt and
.rela.plt here..
(allocate_plt_and_got): ..instead do it all here. New function.
(elf32_hppa_size_dynamic_sections): Allocate local .got space and
call allocate_plt_and_got. No need to zap .got if not dynamic.
(elf32_hppa_final_link): Call regular bfd_final_link instead of
gc_common_final_link.
(WILL_CALL_FINISH_DYNAMIC_SYMBOL): Define.
(elf32_hppa_relocate_section): Use it here.
(elf32_hppa_finish_dynamic_symbol): Remove superfluous test of
dynamic_sections_created.
I'll apply this to the mainline in a day or two.
--
Alan Modra
Index: bfd/elf32-hppa.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-hppa.c,v
retrieving revision 1.35
diff -u -p -r1.35 elf32-hppa.c
--- elf32-hppa.c 2001/05/28 10:12:04 1.35
+++ elf32-hppa.c 2001/05/29 10:05:13
@@ -366,6 +366,9 @@ static boolean elf32_hppa_adjust_dynamic
static boolean hppa_handle_PIC_calls
PARAMS ((struct elf_link_hash_entry *, PTR));
+static boolean allocate_plt_and_got
+ PARAMS ((struct elf_link_hash_entry *, PTR));
+
#if ((! LONG_BRANCH_PIC_IN_SHLIB && LONG_BRANCH_VIA_PLT) \
|| RELATIVE_DYNAMIC_RELOCS)
static boolean hppa_discard_copies
@@ -1333,6 +1336,8 @@ elf32_hppa_check_relocs (abfd, info, sec
where a symbol is forced local by versioning, or due
to symbolic linking, and we lose the .plt entry. */
need_entry = NEED_PLT | NEED_STUBREL;
+ if (h->elf.type == STT_PARISC_MILLI)
+ need_entry = NEED_STUBREL;
}
break;
@@ -1431,9 +1436,6 @@ elf32_hppa_check_relocs (abfd, info, sec
&h->elf))
return false;
}
-
- hplink->sgot->_raw_size += GOT_ENTRY_SIZE;
- hplink->srelgot->_raw_size += sizeof (Elf32_External_Rela);
}
else
h->elf.got.refcount += 1;
@@ -1458,20 +1460,7 @@ elf32_hppa_check_relocs (abfd, info, sec
memset (local_got_refcounts, -1, size);
}
if (local_got_refcounts[r_symndx] == -1)
- {
- local_got_refcounts[r_symndx] = 1;
-
- hplink->sgot->_raw_size += GOT_ENTRY_SIZE;
- if (info->shared)
- {
- /* If we are generating a shared object, we need to
- output a reloc so that the dynamic linker can
- adjust this GOT entry (because the address
- the shared library is loaded at is not fixed). */
- hplink->srelgot->_raw_size +=
- sizeof (Elf32_External_Rela);
- }
- }
+ local_got_refcounts[r_symndx] = 1;
else
local_got_refcounts[r_symndx] += 1;
}
@@ -1773,8 +1762,6 @@ elf32_hppa_gc_sweep_hook (abfd, info, se
struct elf_link_hash_entry *h;
struct elf32_hppa_link_hash_table *hplink;
bfd *dynobj;
- asection *sgot;
- asection *srelgot;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
@@ -1787,9 +1774,6 @@ elf32_hppa_gc_sweep_hook (abfd, info, se
if (dynobj == NULL)
return true;
- sgot = hplink->sgot;
- srelgot = hplink->srelgot;
-
relend = relocs + sec->reloc_count;
for (rel = relocs; rel < relend; rel++)
switch ((unsigned int) ELF32_R_TYPE (rel->r_info))
@@ -1802,27 +1786,12 @@ elf32_hppa_gc_sweep_hook (abfd, info, se
{
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
if (h->got.refcount > 0)
- {
- h->got.refcount -= 1;
- if (h->got.refcount == 0)
- {
- sgot->_raw_size -= GOT_ENTRY_SIZE;
- srelgot->_raw_size -= sizeof (Elf32_External_Rela);
- }
- }
+ h->got.refcount -= 1;
}
else if (local_got_refcounts != NULL)
{
if (local_got_refcounts[r_symndx] > 0)
- {
- local_got_refcounts[r_symndx] -= 1;
- if (local_got_refcounts[r_symndx] == 0)
- {
- sgot->_raw_size -= GOT_ENTRY_SIZE;
- if (info->shared)
- srelgot->_raw_size -= sizeof (Elf32_External_Rela);
- }
- }
+ local_got_refcounts[r_symndx] -= 1;
}
break;
@@ -1880,6 +1849,17 @@ elf32_hppa_hide_symbol (info, h)
}
}
+/* This is the condition under which elf32_hppa_finish_dynamic_symbol
+ will be called from elflink.h. If elflink.h doesn't call our
+ finish_dynamic_symbol routine, we'll need to do something about
+ initializing any .plt and .got entries in elf32_hppa_relocate_section. */
+#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \
+ ((DYN) \
+ && ((INFO)->shared \
+ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
+ && ((H)->dynindx != -1 \
+ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
+
/* Adjust a symbol defined by a dynamic object and referenced by a
regular object. The current definition is in some section of the
dynamic object, but we're not including those sections. We have to
@@ -1938,19 +1918,6 @@ elf32_hppa_adjust_dynamic_symbol (info,
}
}
- /* Make an entry in the .plt section. */
- s = hplink->splt;
- h->plt.offset = s->_raw_size;
- if (PLABEL_PLT_ENTRY_SIZE != PLT_ENTRY_SIZE
- && ((struct elf32_hppa_link_hash_entry *) h)->plabel
- && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
- {
- /* Add some extra space for the dynamic linker to use. */
- s->_raw_size += PLABEL_PLT_ENTRY_SIZE;
- }
- else
- s->_raw_size += PLT_ENTRY_SIZE;
-
if (! ((struct elf32_hppa_link_hash_entry *) h)->pic_call)
{
/* Make sure this symbol is output as a dynamic symbol. */
@@ -1960,16 +1927,8 @@ elf32_hppa_adjust_dynamic_symbol (info,
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
return false;
}
-
- if (h->dynindx != -1 || info->shared)
- {
- /* We also need to make an entry in the .rela.plt section. */
- s = hplink->srelplt;
- s->_raw_size += sizeof (Elf32_External_Rela);
-
- hplink->need_plt_stub = 1;
- }
}
+
return true;
}
@@ -2094,6 +2053,66 @@ hppa_handle_PIC_calls (h, inf)
return true;
}
+/* Allocate space in .plt, .got and associated reloc sections for
+ global syms. */
+static boolean
+allocate_plt_and_got (h, inf)
+ struct elf_link_hash_entry *h;
+ PTR inf;
+{
+ struct bfd_link_info *info;
+ struct elf32_hppa_link_hash_table *hplink;
+ asection *s;
+
+ info = (struct bfd_link_info *) inf;
+ hplink = hppa_link_hash_table (info);
+ if (hplink->root.dynamic_sections_created
+ && h->plt.refcount > 0)
+ {
+ /* Make an entry in the .plt section. */
+ s = hplink->splt;
+ h->plt.offset = s->_raw_size;
+ if (PLABEL_PLT_ENTRY_SIZE != PLT_ENTRY_SIZE
+ && ((struct elf32_hppa_link_hash_entry *) h)->plabel
+ && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+ {
+ /* Add some extra space for the dynamic linker to use. */
+ s->_raw_size += PLABEL_PLT_ENTRY_SIZE;
+ }
+ else
+ s->_raw_size += PLT_ENTRY_SIZE;
+
+ if (! ((struct elf32_hppa_link_hash_entry *) h)->pic_call
+ && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
+ {
+ /* We also need to make an entry in the .rela.plt section. */
+ hplink->srelplt->_raw_size += sizeof (Elf32_External_Rela);
+ hplink->need_plt_stub = 1;
+ }
+ }
+ else
+ {
+ h->plt.offset = (bfd_vma) -1;
+ h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+ }
+
+ if (h->got.refcount > 0)
+ {
+ boolean dyn;
+
+ s = hplink->sgot;
+ h->got.offset = s->_raw_size;
+ s->_raw_size += GOT_ENTRY_SIZE;
+ dyn = hplink->root.dynamic_sections_created;
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
+ hplink->srelgot->_raw_size += sizeof (Elf32_External_Rela);
+ }
+ else
+ h->got.offset = (bfd_vma) -1;
+
+ return true;
+}
+
#if ((! LONG_BRANCH_PIC_IN_SHLIB && LONG_BRANCH_VIA_PLT) \
|| RELATIVE_DYNAMIC_RELOCS)
/* This function is called via elf_link_hash_traverse to discard space
@@ -2206,32 +2225,54 @@ elf32_hppa_size_dynamic_sections (output
clobber_millicode_symbols,
info);
- /* Set up .plt offsets for local plabels. */
+ /* Set up .got and .plt offsets for local syms. */
for (i = info->input_bfds; i; i = i->link_next)
{
+ bfd_signed_vma *local_got;
+ bfd_signed_vma *end_local_got;
bfd_signed_vma *local_plt;
bfd_signed_vma *end_local_plt;
bfd_size_type locsymcount;
Elf_Internal_Shdr *symtab_hdr;
+ asection *srel;
+
+ if (bfd_get_flavour (i) != bfd_target_elf_flavour)
+ continue;
- local_plt = elf_local_got_refcounts (i);
- if (!local_plt)
+ local_got = elf_local_got_refcounts (i);
+ if (!local_got)
continue;
symtab_hdr = &elf_tdata (i)->symtab_hdr;
locsymcount = symtab_hdr->sh_info;
- local_plt += locsymcount;
- end_local_plt = local_plt + locsymcount;
+ end_local_got = local_got + locsymcount;
+ s = hplink->sgot;
+ srel = hplink->srelgot;
+ for (; local_got < end_local_got; ++local_got)
+ {
+ if (*local_got > 0)
+ {
+ *local_got = s->_raw_size;
+ s->_raw_size += GOT_ENTRY_SIZE;
+ if (info->shared)
+ srel->_raw_size += sizeof (Elf32_External_Rela);
+ }
+ else
+ *local_got = (bfd_vma) -1;
+ }
+ local_plt = end_local_got;
+ end_local_plt = local_plt + locsymcount;
+ s = hplink->splt;
+ srel = hplink->srelplt;
for (; local_plt < end_local_plt; ++local_plt)
{
if (*local_plt > 0)
{
- s = hplink->splt;
*local_plt = s->_raw_size;
s->_raw_size += PLT_ENTRY_SIZE;
if (info->shared)
- hplink->srelplt->_raw_size += sizeof (Elf32_External_Rela);
+ srel->_raw_size += sizeof (Elf32_External_Rela);
}
else
*local_plt = (bfd_vma) -1;
@@ -2247,15 +2288,13 @@ elf32_hppa_size_dynamic_sections (output
elf_link_hash_traverse (&hplink->root,
hppa_handle_PIC_calls,
info);
-
- /* We may have created entries in the .rela.got section.
- However, if we are not creating the dynamic sections, we will
- not actually use these entries. Reset the size of .rela.got,
- which will cause it to get stripped from the output file
- below. */
- hplink->srelgot->_raw_size = 0;
}
+ /* Allocate global sym .plt and .got entries. */
+ elf_link_hash_traverse (&hplink->root,
+ allocate_plt_and_got,
+ info);
+
#if ((! LONG_BRANCH_PIC_IN_SHLIB && LONG_BRANCH_VIA_PLT) \
|| RELATIVE_DYNAMIC_RELOCS)
/* If this is a -Bsymbolic shared link, then we need to discard all
@@ -3164,9 +3203,8 @@ elf32_hppa_final_link (abfd, info)
{
asection *s;
- /* Invoke the regular ELF garbage collecting linker to do all the
- work. */
- if (!_bfd_elf32_gc_common_final_link (abfd, info))
+ /* Invoke the regular ELF linker to do all the work. */
+ if (!bfd_elf32_bfd_final_link (abfd, info))
return false;
/* If we're producing a final executable, sort the contents of the
@@ -3635,16 +3673,14 @@ elf32_hppa_relocate_section (output_bfd,
if (h != NULL)
{
bfd_vma off;
+ boolean dyn;
off = h->elf.got.offset;
if (off == (bfd_vma) -1)
abort ();
- if (! hplink->root.dynamic_sections_created
- || (info->shared
- && (info->symbolic || h->elf.dynindx == -1)
- && (h->elf.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) != 0))
+ dyn = hplink->root.dynamic_sections_created;
+ if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, &h->elf))
{
/* This is actually a static link, or it is a
-Bsymbolic link and the symbol is defined
@@ -3742,8 +3778,7 @@ elf32_hppa_relocate_section (output_bfd,
if (h != NULL)
{
off = h->elf.plt.offset;
- if (!info->shared
- && (h->elf.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
+ if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, &h->elf))
{
/* In a non-shared link, adjust_dynamic_symbols
isn't called for symbols forced local. We
@@ -4133,15 +4168,14 @@ elf32_hppa_finish_dynamic_symbol (output
+ hplink->sgot->output_offset
+ hplink->sgot->output_section->vma);
- /* If this is a static link, or it is a -Bsymbolic link and the
- symbol is defined locally or was forced to be local because
- of a version file, we just want to emit a RELATIVE reloc.
- The entry in the global offset table will already have been
- initialized in the relocate_section function. */
- if (! hplink->root.dynamic_sections_created
- || (info->shared
- && (info->symbolic || h->dynindx == -1)
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+ /* If this is a -Bsymbolic link and the symbol is defined
+ locally or was forced to be local because of a version file,
+ we just want to emit a RELATIVE reloc. The entry in the
+ global offset table will already have been initialized in the
+ relocate_section function. */
+ if (info->shared
+ && (info->symbolic || h->dynindx == -1)
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
{
rel.r_info = ELF32_R_INFO (0, R_PARISC_DIR32);
rel.r_addend = (h->root.u.def.value
^ permalink raw reply [flat|nested] 3+ messages in thread
* tweak elf32_hppa .got allocation.
2001-05-29 4:58 ` amodra
@ 2001-06-04 21:38 ` Alan Modra
0 siblings, 0 replies; 3+ messages in thread
From: Alan Modra @ 2001-06-04 21:38 UTC (permalink / raw)
To: binutils
Um, we allocated too much space when indirect syms were involved.
bfd/ChangeLog
* elf32_hppa.c (allocate_plt_and_got): Skip indirect and warning syms.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2001-06-04 21:38 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-05-28 2:09 elflink.h (elf_bfd_final_link) amodra
2001-05-29 4:58 ` amodra
2001-06-04 21:38 ` tweak elf32_hppa .got allocation Alan Modra
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).