.plt stub for lazy linking, --stub-group-size=N ld switch,

import stub fix, extra DIR14F reloc to fix abort in tc_gen_reloc
This commit is contained in:
Alan Modra 2000-09-27 17:30:19 +00:00
parent 5506e1a5d8
commit 47d89dba5e
10 changed files with 300 additions and 86 deletions

View file

@ -1,3 +1,40 @@
2000-09-27 Alan Modra <alan@linuxcare.com.au>
* elf32-hppa.c (plt_stub): New.
(PLT_STUB_ENTRY): Define.
(elf32_hppa_link_hash_table): Change multi_subspace to packed
boolean. Add need_plt_stub, has_12bit_branch and has_17bit_branch.
(elf32_hppa_link_hash_table_create): Init to suit.
(elf32_hppa_check_relocs): Set has_12bit_branch and
has_17bit_branch as appropriate.
(elf32_hppa_adjust_dynamic_symbol): Set need_plt_stub for
non-local functions.
(elf32_hppa_size_dynamic_sections): Correct setting of reltext.
Add space for plt_stub as needed.
(elf32_hppa_finish_dynamic_symbol): Point .plt entries for global
functions at plt_stub.
(elf32_hppa_finish_dynamic_sections): Write plt_stub.
(elf32_hppa_create_dynamic_sections): Leave .plt executable.
* elf32-hppa.h (elf32_hppa_size_stubs): Add group_size param.
* elf32-hppa.c (elf32_hppa_size_stubs): Likewise. Use it instead
of fixed size, and if negative, disable handling of input sections
before stub section. Set up default stub group size depending
on detected branch relocs.
(hppa_build_one_stub): Use lrsel and rrsel for import stubs to
ensure different offsets from sym_value aren't rounded to
different 2k blocks. Use lrsel and rrsel for other stubs too for
consistency rather than necessity.
(elf32_hppa_check_relocs): Handle R_PARISC_DIR14F.
(final_link_relocate): Likewise.
(elf32_hppa_relocate_section): Likewise.
* elf-hppa.h (elf_hppa_howto_table): Add R_PARISC_DIR14F reloc.
(_bfd_elf_hppa_gen_reloc_type): Generate them.
(elf_hppa_final_link_relocate): Handle them.
(elf_hppa_relocate_insn): Likewise.
(_bfd_elf_hppa_gen_reloc_type): Add missing e_ldsel and e_rdsel cases.
2000-09-26 Hans-Peter Nilsson <hp@axis.com>
* elfcode.h (elf_object_p): Preserve and clear abfd section

View file

@ -118,8 +118,8 @@ static reloc_howto_type elf_hppa_howto_table[ELF_HOWTO_TABLE_SIZE] =
bfd_elf_generic_reloc, "R_PARISC_UNIMPLEMENTED", false, 0, 0, false },
{ R_PARISC_DIR14R, 0, 0, 14, false, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_DIR14R", false, 0, 0, false },
{ R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_UNIMPLEMENTED", false, 0, 0, false },
{ R_PARISC_DIR14F, 0, 0, 14, false, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_DIR14F", false, 0, 0, false },
/* 8 */
{ R_PARISC_PCREL12F, 0, 0, 12, true, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_PARISC_PCREL12F", false, 0, 0, false },
@ -657,8 +657,12 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym)
case 14:
switch (field)
{
case e_fsel:
final_type = R_PARISC_DIR14F;
break;
case e_rsel:
case e_rrsel:
case e_rdsel:
final_type = R_PARISC_DIR14R;
break;
case e_rtsel:
@ -686,6 +690,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym)
break;
case e_rsel:
case e_rrsel:
case e_rdsel:
final_type = R_PARISC_DIR17R;
break;
default:
@ -698,6 +703,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym)
{
case e_lsel:
case e_lrsel:
case e_ldsel:
case e_nlsel:
case e_nlrsel:
final_type = R_PARISC_DIR21L;
@ -763,6 +769,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym)
{
case e_rsel:
case e_rrsel:
case e_rdsel:
/* R_PARISC_DLTREL14R for elf64, R_PARISC_DPREL14R for elf32 */
final_type = base_type + OFFSET_14R_FROM_21L;
break;
@ -780,6 +787,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym)
{
case e_lsel:
case e_lrsel:
case e_ldsel:
case e_nlsel:
case e_nlrsel:
/* R_PARISC_DLTREL21L for elf64, R_PARISC_DPREL21L for elf32 */
@ -817,6 +825,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym)
{
case e_rsel:
case e_rrsel:
case e_rdsel:
final_type = R_PARISC_PCREL14R;
break;
case e_fsel:
@ -832,6 +841,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym)
{
case e_rsel:
case e_rrsel:
case e_rdsel:
final_type = R_PARISC_PCREL17R;
break;
case e_fsel:
@ -847,6 +857,7 @@ _bfd_elf_hppa_gen_reloc_type (abfd, base_type, format, field, ignore, sym)
{
case e_lsel:
case e_lrsel:
case e_ldsel:
case e_nlsel:
case e_nlrsel:
final_type = R_PARISC_PCREL21L;
@ -1712,6 +1723,7 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
case R_PARISC_DIR17R:
case R_PARISC_DIR17F:
case R_PARISC_DIR14R:
case R_PARISC_DIR14F:
case R_PARISC_DIR14WR:
case R_PARISC_DIR14DR:
case R_PARISC_DIR16F:
@ -1728,7 +1740,8 @@ elf_hppa_final_link_relocate (rel, input_bfd, output_bfd,
else if (r_type == R_PARISC_DIR17F
|| r_type == R_PARISC_DIR16F
|| r_type == R_PARISC_DIR16WF
|| r_type == R_PARISC_DIR16DF)
|| r_type == R_PARISC_DIR16DF
|| r_type == R_PARISC_DIR14F)
value = hppa_field_adjust (value, addend, e_fsel);
else
value = hppa_field_adjust (value, addend, e_rrsel);
@ -2055,6 +2068,7 @@ elf_hppa_relocate_insn (insn, sym_value, r_type)
case R_PARISC_PLTOFF14F:
case R_PARISC_PLTOFF16F:
case R_PARISC_DIR14R:
case R_PARISC_DIR14F:
case R_PARISC_DIR16F:
case R_PARISC_LTOFF16F:
return (insn & ~ 0x3fff) | low_sign_unext (sym_value, 14);

View file

@ -120,6 +120,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define GOT_ENTRY_SIZE 4
#define ELF_DYNAMIC_INTERPRETER "/lib/ld.so.1"
static const bfd_byte plt_stub[] =
{
0x0e, 0x80, 0x10, 0x96, /* 1: ldw 0(%r20),%r22 */
0xea, 0xc0, 0xc0, 0x00, /* bv %r0(%r22) */
0x0e, 0x88, 0x10, 0x95, /* ldw 4(%r20),%r21 */
#define PLT_STUB_ENTRY (3*4)
0xea, 0x9f, 0x1f, 0xdd, /* b,l 1b,%r20 */
0xd6, 0x80, 0x1c, 0x1e, /* depi 0,31,2,%r20 */
0x00, 0xc0, 0xff, 0xee, /* 9: .word fixup_func */
0xde, 0xad, 0xbe, 0xef /* .word fixup_ltp */
};
/* Section name for stubs is the associated section name plus this
string. */
#define STUB_SUFFIX ".stub"
@ -240,9 +252,6 @@ struct elf32_hppa_link_hash_table {
/* Linker stub bfd. */
bfd *stub_bfd;
/* Whether we support multiple sub-spaces for shared libs. */
boolean multi_subspace;
/* Linker call-backs. */
asection * (*add_stub_section) PARAMS ((const char *, asection *));
void (*layout_sections_again) PARAMS ((void));
@ -268,6 +277,17 @@ struct elf32_hppa_link_hash_table {
asection *srelplt;
asection *sdynbss;
asection *srelbss;
/* Whether we support multiple sub-spaces for shared libs. */
unsigned int multi_subspace:1;
/* Flags set when PCREL12F and PCREL17F branches detected. Used to
select suitable defaults for the stub group size. */
unsigned int has_12bit_branch:1;
unsigned int has_17bit_branch:1;
/* Set if we need a .plt stub to support lazy dynamic linking. */
unsigned int need_plt_stub:1;
};
@ -498,7 +518,6 @@ elf32_hppa_link_hash_table_create (abfd)
return NULL;
ret->stub_bfd = NULL;
ret->multi_subspace = 0;
ret->add_stub_section = NULL;
ret->layout_sections_again = NULL;
ret->stub_group = NULL;
@ -508,6 +527,10 @@ elf32_hppa_link_hash_table_create (abfd)
ret->srelplt = NULL;
ret->sdynbss = NULL;
ret->srelbss = NULL;
ret->multi_subspace = 0;
ret->has_12bit_branch = 0;
ret->has_17bit_branch = 0;
ret->need_plt_stub = 0;
return &ret->root.root;
}
@ -896,11 +919,11 @@ hppa_build_one_stub (gen_entry, in_arg)
+ stub_sec->output_section->vma);
bfd_put_32 (stub_bfd, (bfd_vma) BL_R1, loc);
val = hppa_field_adjust (sym_value, (bfd_signed_vma) -8, e_lsel);
val = hppa_field_adjust (sym_value, (bfd_signed_vma) -8, e_lrsel);
insn = hppa_rebuild_insn ((int) ADDIL_R1, val, 21);
bfd_put_32 (stub_bfd, insn, loc + 4);
val = hppa_field_adjust (sym_value, (bfd_signed_vma) -8, e_rsel) >> 2;
val = hppa_field_adjust (sym_value, (bfd_signed_vma) -8, e_rrsel) >> 2;
insn = hppa_rebuild_insn ((int) BE_SR4_R1, val, 17);
bfd_put_32 (stub_bfd, insn, loc + 8);
size = 12;
@ -918,17 +941,22 @@ hppa_build_one_stub (gen_entry, in_arg)
if (stub_entry->stub_type == hppa_stub_import_shared)
insn = ADDIL_R19;
#endif
val = hppa_field_adjust (sym_value, (bfd_signed_vma) 0, e_lsel),
val = hppa_field_adjust (sym_value, (bfd_signed_vma) 0, e_lrsel),
insn = hppa_rebuild_insn ((int) insn, val, 21);
bfd_put_32 (stub_bfd, insn, loc);
val = hppa_field_adjust (sym_value, (bfd_signed_vma) 0, e_rsel);
/* It is critical to use lrsel/rrsel here because we are using
two different offsets (+0 and +4) from sym_value. If we use
lsel/rsel then with unfortunate sym_values we will round
sym_value+4 up to the next 2k block leading to a mis-match
between the lsel and rsel value. */
val = hppa_field_adjust (sym_value, (bfd_signed_vma) 0, e_rrsel);
insn = hppa_rebuild_insn ((int) LDW_R1_R21, val, 14);
bfd_put_32 (stub_bfd, insn, loc + 4);
if (hplink->multi_subspace)
{
val = hppa_field_adjust (sym_value, (bfd_signed_vma) 4, e_rsel);
val = hppa_field_adjust (sym_value, (bfd_signed_vma) 4, e_rrsel);
insn = hppa_rebuild_insn ((int) LDW_R1_DLT, val, 14);
bfd_put_32 (stub_bfd, insn, loc + 8);
@ -942,7 +970,7 @@ hppa_build_one_stub (gen_entry, in_arg)
else
{
bfd_put_32 (stub_bfd, (bfd_vma) BV_R0_R21, loc + 8);
val = hppa_field_adjust (sym_value, (bfd_signed_vma) 4, e_rsel);
val = hppa_field_adjust (sym_value, (bfd_signed_vma) 4, e_rrsel);
insn = hppa_rebuild_insn ((int) LDW_R1_DLT, val, 14);
bfd_put_32 (stub_bfd, insn, loc + 12);
@ -1146,8 +1174,6 @@ elf32_hppa_create_dynamic_sections (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
{
flagword flags;
asection *s;
struct elf32_hppa_link_hash_table *hplink;
/* Don't try to create the .plt and .got twice. */
@ -1159,14 +1185,7 @@ elf32_hppa_create_dynamic_sections (abfd, info)
if (! _bfd_elf_create_dynamic_sections (abfd, info))
return false;
/* Our .plt just contains pointers. I suppose we should be using
.plt.got but .plt.got doesn't make too much sense without a .plt
section. Set the flags to say the .plt isn't executable. */
s = bfd_get_section_by_name (abfd, ".plt");
flags = bfd_get_section_flags (abfd, s);
if (! bfd_set_section_flags (abfd, s, flags & ~SEC_CODE))
return false;
hplink->splt = s;
hplink->splt = bfd_get_section_by_name (abfd, ".plt");
hplink->srelplt = bfd_get_section_by_name (abfd, ".rela.plt");
hplink->sgot = bfd_get_section_by_name (abfd, ".got");
@ -1278,11 +1297,15 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
break;
case R_PARISC_PCREL12F:
hplink->has_12bit_branch = 1;
/* Fall thru. */
case R_PARISC_PCREL17C:
case R_PARISC_PCREL17F:
hplink->has_17bit_branch = 1;
/* Fall thru. */
case R_PARISC_PCREL22F:
/* Handle calls, and function pointers as they might need to
go through the .plt, and might require long branch stubs. */
/* Function calls might need to go through the .plt, and
might require long branch stubs. */
if (h == NULL)
{
/* We know local syms won't need a .plt entry, and if
@ -1329,7 +1352,8 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
case R_PARISC_DIR17F: /* Used for external branches. */
case R_PARISC_DIR17R:
case R_PARISC_DIR14R: /* Used for load/store from absolute locn. */
case R_PARISC_DIR14F: /* Used for load/store from absolute locn. */
case R_PARISC_DIR14R:
case R_PARISC_DIR21L: /* As above, and for ext branches too. */
#if 1
/* Help debug shared library creation. Any of the above
@ -1932,6 +1956,8 @@ elf32_hppa_adjust_dynamic_symbol (info, h)
/* 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;
}
@ -2295,28 +2321,22 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
if (s->_raw_size != 0)
{
asection *target;
const char *outname;
/* Remember whether there are any reloc sections other
than .rela.plt. */
if (strcmp (name+5, ".plt") != 0)
{
const char *outname;
relocs = true;
relocs = true;
/* If this relocation section applies to a read only
section, then we probably need a DT_TEXTREL
entry. The entries in the .rela.plt section
really apply to the .got section, which we
created ourselves and so know is not readonly. */
outname = bfd_get_section_name (output_bfd,
s->output_section);
target = bfd_get_section_by_name (output_bfd, outname + 5);
if (target != NULL
&& (target->flags & SEC_READONLY) != 0
&& (target->flags & SEC_ALLOC) != 0)
reltext = true;
}
/* If this relocation section applies to a read only
section, then we probably need a DT_TEXTREL entry. */
outname = bfd_get_section_name (output_bfd,
s->output_section);
target = bfd_get_section_by_name (output_bfd, outname + 5);
if (target != NULL
&& (target->flags & SEC_READONLY) != 0
&& (target->flags & SEC_ALLOC) != 0)
reltext = true;
/* We use the reloc_count field as a counter if we need
to copy relocs into the output file. */
@ -2324,7 +2344,22 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
}
}
else if (strcmp (name, ".plt") == 0)
;
{
if (hplink->need_plt_stub)
{
/* Make space for the plt stub at the end of the .plt
section. We want this stub right at the end, up
against the .got section. */
int gotalign = bfd_section_alignment (dynobj, hplink->sgot);
int pltalign = bfd_section_alignment (dynobj, s);
bfd_size_type mask;
if (gotalign > pltalign)
bfd_set_section_alignment (dynobj, s, gotalign);
mask = ((bfd_size_type) 1 << gotalign) - 1;
s->_raw_size = (s->_raw_size + sizeof (plt_stub) + mask) & ~mask;
}
}
else if (strcmp (name, ".got") == 0)
;
else
@ -2413,12 +2448,13 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
instruction. */
boolean
elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace,
elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size,
add_stub_section, layout_sections_again)
bfd *output_bfd;
bfd *stub_bfd;
struct bfd_link_info *info;
boolean multi_subspace;
bfd_signed_vma group_size;
asection * (*add_stub_section) PARAMS ((const char *, asection *));
void (*layout_sections_again) PARAMS ((void));
{
@ -2429,6 +2465,8 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace,
unsigned int bfd_indx, bfd_count;
int top_id, top_index;
struct elf32_hppa_link_hash_table *hplink;
bfd_size_type stub_group_size;
boolean stubs_always_before_branch;
boolean stub_changed = 0;
boolean ret = 0;
@ -2439,6 +2477,20 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace,
hplink->multi_subspace = multi_subspace;
hplink->add_stub_section = add_stub_section;
hplink->layout_sections_again = layout_sections_again;
stubs_always_before_branch = group_size < 0;
if (group_size < 0)
stub_group_size = -group_size;
else
stub_group_size = group_size;
if (stub_group_size == 1)
{
/* Default values. */
stub_group_size = 8000000;
if (hplink->has_17bit_branch || hplink->multi_subspace)
stub_group_size = 250000;
if (hplink->has_12bit_branch)
stub_group_size = 7812;
}
/* Count the number of input BFDs and find the top input section id. */
for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0;
@ -2490,7 +2542,7 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace,
section != NULL;
section = section->next)
{
if ((section->flags & SEC_CODE) != 0 && section->index <= top_index)
if ((section->flags & SEC_CODE) != 0)
input_list[section->index] = NULL;
}
@ -2546,7 +2598,7 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace,
total = tail->_raw_size;
while ((prev = PREV_SEC (curr)) != NULL
&& ((total += curr->output_offset - prev->output_offset)
< 250000))
< stub_group_size))
curr = prev;
/* OK, the size from the start of CURR to the end is less
@ -2570,14 +2622,17 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace,
/* But wait, there's more! Input sections up to 250000
bytes before the stub section can be handled by it too. */
total = 0;
while (prev != NULL
&& ((total += tail->output_offset - prev->output_offset)
< 250000))
if (!stubs_always_before_branch)
{
tail = prev;
prev = PREV_SEC (tail);
hplink->stub_group[tail->id].link_sec = curr;
total = 0;
while (prev != NULL
&& ((total += tail->output_offset - prev->output_offset)
< stub_group_size))
{
tail = prev;
prev = PREV_SEC (tail);
hplink->stub_group[tail->id].link_sec = curr;
}
}
tail = prev;
}
@ -3256,6 +3311,7 @@ final_link_relocate (input_section, contents, rel, value, hplink, sym_sec, h)
switch (r_type)
{
case R_PARISC_DIR32:
case R_PARISC_DIR14F:
case R_PARISC_DIR17F:
case R_PARISC_PCREL17C:
case R_PARISC_PCREL14F:
@ -3688,6 +3744,7 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
case R_PARISC_DIR17F:
case R_PARISC_DIR17R:
case R_PARISC_DIR14F:
case R_PARISC_DIR14R:
case R_PARISC_DIR21L:
case R_PARISC_DPREL14F:
@ -3871,7 +3928,6 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
if (h->plt.offset != (bfd_vma) -1)
{
bfd_vma value;
Elf_Internal_Rela rel;
/* This symbol has an entry in the procedure linkage table. Set
it up.
@ -3879,15 +3935,7 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
The format of a plt entry is
<funcaddr>
<__gp>
<used by ld.so>
The last field is present only for plt entries that are used
by global plabels. */
/* We do not actually care about the value in the PLT entry if
we are creating a shared library and the symbol is still
undefined; We create a dynamic relocation to fill in the
correct value. */
*/
value = 0;
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
@ -3898,22 +3946,10 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
+ h->root.u.def.section->output_section->vma);
}
bfd_put_32 (hplink->splt->owner,
value,
hplink->splt->contents + h->plt.offset);
bfd_put_32 (hplink->splt->owner,
elf_gp (hplink->splt->output_section->owner),
hplink->splt->contents + h->plt.offset + 4);
if (PLABEL_PLT_ENTRY_SIZE != PLT_ENTRY_SIZE
&& ((struct elf32_hppa_link_hash_entry *) h)->plabel
&& h->dynindx != -1)
{
memset (hplink->splt->contents + h->plt.offset + 8,
0, PLABEL_PLT_ENTRY_SIZE - PLT_ENTRY_SIZE);
}
if (! ((struct elf32_hppa_link_hash_entry *) h)->pic_call)
{
Elf_Internal_Rela rel;
/* Create a dynamic IPLT relocation for this entry. */
rel.r_offset = (h->plt.offset
+ hplink->splt->output_offset
@ -3921,6 +3957,15 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
if (! ((struct elf32_hppa_link_hash_entry *) h)->plt_abs
&& h->dynindx != -1)
{
/* 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. */
value = (hplink->splt->output_offset
+ hplink->splt->output_section->vma
+ hplink->splt->_raw_size
- sizeof (plt_stub)
+ PLT_STUB_ENTRY);
rel.r_info = ELF32_R_INFO (h->dynindx, R_PARISC_IPLT);
rel.r_addend = 0;
}
@ -3940,6 +3985,20 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
hplink->srelplt->reloc_count++;
}
bfd_put_32 (hplink->splt->owner,
value,
hplink->splt->contents + h->plt.offset);
bfd_put_32 (hplink->splt->owner,
elf_gp (hplink->splt->output_section->owner),
hplink->splt->contents + h->plt.offset + 4);
if (PLABEL_PLT_ENTRY_SIZE != PLT_ENTRY_SIZE
&& ((struct elf32_hppa_link_hash_entry *) h)->plabel
&& h->dynindx != -1)
{
memset (hplink->splt->contents + h->plt.offset + 8,
0, PLABEL_PLT_ENTRY_SIZE - PLT_ENTRY_SIZE);
}
if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
{
/* Mark the symbol as undefined, rather than as defined in
@ -4122,17 +4181,38 @@ elf32_hppa_finish_dynamic_sections (output_bfd, info)
hplink->sgot->contents);
/* The second entry is reserved for use by the dynamic linker. */
bfd_put_32 (output_bfd, (bfd_vma) 0, hplink->sgot->contents + 4);
memset (hplink->sgot->contents + GOT_ENTRY_SIZE, 0, GOT_ENTRY_SIZE);
/* Set .got entry size. */
elf_section_data (hplink->sgot->output_section)
->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
}
/* Set plt entry size. */
if (hplink->splt->_raw_size != 0)
elf_section_data (hplink->splt->output_section)
->this_hdr.sh_entsize = PLT_ENTRY_SIZE;
{
/* Set plt entry size. */
elf_section_data (hplink->splt->output_section)
->this_hdr.sh_entsize = PLT_ENTRY_SIZE;
if (hplink->need_plt_stub)
{
/* Set up the .plt stub. */
memcpy (hplink->splt->contents
+ hplink->splt->_raw_size - sizeof (plt_stub),
plt_stub, sizeof (plt_stub));
if ((hplink->splt->output_offset
+ hplink->splt->output_section->vma
+ hplink->splt->_raw_size)
!= (hplink->sgot->output_offset
+ hplink->sgot->output_section->vma))
{
(*_bfd_error_handler)
(_(".got section not immediately after .plt section"));
return false;
}
}
}
return true;
}

View file

@ -37,7 +37,7 @@
#include "elf/hppa.h"
boolean elf32_hppa_size_stubs
PARAMS ((bfd *, bfd *, struct bfd_link_info *, boolean,
PARAMS ((bfd *, bfd *, struct bfd_link_info *, boolean, bfd_signed_vma,
asection * (*) PARAMS ((const char *, asection *)),
void (*) PARAMS ((void))));

View file

@ -6,6 +6,8 @@
(hppa_fix_adjustable): Undo 2000-09-23 change.
(hppa_force_relocation): Likewise. Add fx_addsy assertion.
Correct distance calculation.
(tc_gen_reloc): Print the file name and line number if we can't
handle a fixup.
From John David Anglin <dave@hiauly1.hia.nrc.ca>
* config/tc-hppa.c (nonzero_dibits): Define.

View file

@ -1,3 +1,7 @@
2000-09-27 Alan Modra <alan@linuxcare.com.au>
* hppa.h (R_PARISC_DIR14F): Add.
2000-09-14 Alexandre Oliva <aoliva@redhat.com>
* sh.h (R_SH_GOT32, R_SH_PLT32, R_SH_COPY, R_SH_GLOB_DAT,

View file

@ -121,6 +121,9 @@ RELOC_NUMBER (R_PARISC_DIR17F, 4)
RELOC_NUMBER (R_PARISC_DIR14R, 6)
/* load/store (1) RR(symbol, addend) */
RELOC_NUMBER (R_PARISC_DIR14F, 7)
/* load/store (1) symbol, addend */
/* PC-relative relocation types
Typically used for calls.
Note PCREL17C and PCREL17F differ only in overflow handling.

View file

@ -1,3 +1,15 @@
2000-09-28 Alan Modra <alan@linuxcare.com.au>
* ld.texinfo (HPPA ELF32): New section.
* emultempl/hppaelf.em (group_size): New.
(hppaelf_finish): Pass group_size to elf32_hppa_size_stubs.
(PARSE_AND_LIST_PROLOGUE): Add OPTION_STUBGROUP_SIZE.
(PARSE_AND_LIST_LONGOPTS): Add --stub-group-size. Duplicate
options to prevent abbreviations matching.
(PARSE_AND_LIST_OPTIONS): Describe the above. Reformat.
(PARSE_AND_LIST_ARGS_CASES): Handle it.
2000-09-21 Michael Sokolov <msokolov@ivan.Harhan.ORG>
* emultempl/m68kelf.em: Conditionalise the embedded relocs feature

View file

@ -44,6 +44,10 @@ static lang_input_statement_type *stub_file;
stubs. */
static int multi_subspace = 0;
/* Maximum size of a group of input sections that can be handled by
one stub section. A value of +/-1 indicates the bfd back-end
should use a suitable default size. */
static bfd_signed_vma group_size = 1;
/* This is called before the input files are opened. We create a new
fake input file to hold the stub sections. */
@ -292,6 +296,7 @@ hppaelf_finish ()
stub_file->the_bfd,
&link_info,
multi_subspace,
group_size,
&hppaelf_add_stub_section,
&hppaelf_layaout_sections_again))
{
@ -349,16 +354,31 @@ EOF
#
PARSE_AND_LIST_PROLOGUE='
#define OPTION_MULTI_SUBSPACE 301
#define OPTION_STUBGROUP_SIZE (OPTION_MULTI_SUBSPACE + 1)
'
# The options are repeated below so that no abbreviations are allowed.
# Otherwise -s matches stub-group-size
PARSE_AND_LIST_LONGOPTS='
{ "multi-subspace", no_argument, NULL, OPTION_MULTI_SUBSPACE},
{ "multi-subspace", no_argument, NULL, OPTION_MULTI_SUBSPACE },
{ "multi-subspace", no_argument, NULL, OPTION_MULTI_SUBSPACE },
{ "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
{ "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE },
'
PARSE_AND_LIST_OPTIONS='
fprintf (file, _("\
--multi-subspace Generate import and export stubs to support\n\
multiple sub-space shared libraries\n"
--multi-subspace Generate import and export stubs to support\n\
multiple sub-space shared libraries\n"
));
fprintf (file, _("\
--stub-group-size=N Maximum size of a group of input sections that can be\n\
handled by one stub section. A negative value\n\
locates all stubs before their branches (with a\n\
group size of -N), while a positive value allows\n\
two groups of input sections, one before, and one\n\
after each stub section. Values of +/-1 indicate\n\
the linker should choose suitable defaults."
));
'
@ -366,6 +386,15 @@ PARSE_AND_LIST_ARGS_CASES='
case OPTION_MULTI_SUBSPACE:
multi_subspace = 1;
break;
case OPTION_STUBGROUP_SIZE:
{
const char *end;
group_size = bfd_scan_vma (optarg, &end, 0);
if (*end)
einfo (_("%P%F: invalid number `%s'\''\n"), optarg);
}
break;
'
# Put these extra hppaelf routines in ld_${EMULATION_NAME}_emulation

View file

@ -3904,6 +3904,7 @@ functionality are not listed.
* H8/300:: @code{ld} and the H8/300
* i960:: @code{ld} and the Intel 960 family
* ARM:: @code{ld} and the ARM family
* HPPA ELF32:: @code{ld} and HPPA 32-bit ELF
@ifset TICOFF
* TI COFF:: @code{ld} and TI COFF
@end ifset
@ -4047,6 +4048,38 @@ But it also sets the bottom bit of the address, so that it can be
branched to using a BX instruction, and the program will start
executing in Thumb mode straight away.
@node HPPA ELF32
@section @code{ld} and HPPA 32-bit ELF support
@cindex HPPA multiple sub-space stubs
@kindex --multi-subspace
When generating a shared library, @code{ld} will by default generate
import stubs suitable for use with a single sub-space application.
The @samp{--multi-subspace} switch causes @code{ld} to generate export
stubs, and different (larger) import stubs suitable for use with
multiple sub-spaces.
@cindex HPPA stub grouping
@kindex --stub-group-size=@var{N}
Long branch stubs and import/export stubs are placed by @code{ld} in
stub sections located between groups of input sections.
@samp{--stub-group-size} specifies the maximum size of a group of input
sections handled by one stub section. Since branch offsets are signed,
a stub section may serve two groups of input sections, one group before
the stub section, and one group after it. However, when using
conditional branches that require stubs, it may be better (for branch
prediction) that stub sections only serve one group of input sections.
A negative value for @samp{N} chooses this scheme, ensuring that
branches to stubs always use a negative offset. Two special values of
@samp{N} are recognized, @samp{1} and @samp{-1}. These both instruct
@code{ld} to automatically size input section groups for the branch types
detected, with the same behaviour regarding stub placement as other
positive or negative values of @samp{N} respectively.
Note that @samp{--stub-group-size} does not split input sections. A
single input section larger than the group size specified will of course
create a larger group (of one section). If input sections are too
large, it may not be possible for a branch to reach its stub.
@ifset TICOFF
@node TI COFF
@section @code{ld}'s support for various TI COFF versions