* elfxx-mips.c (mips_elf_link_hash_table): Add function_stub_size.
	(STUB_ORI): New macro.
	(STUB_LI16U): Fix formatting.
	(MIPS_FUNCTION_STUB_SIZE): Delete.
	(MIPS_FUNCTION_STUB_MAX_SIZE): Likewise.
	(MIPS_FUNCTION_STUB_NORMAL_SIZE): New macro.
	(MIPS_FUNCTION_STUB_BIG_SIZE): Likewise.
	(_bfd_mips_elf_adjust_dynamic_symbol): Use htab->function_stub_size
	instead of MIPS_FUNCTION_STUB_SIZE.
	(count_section_dynsyms): New function, split out from
	_bfd_mips_elf_final_link.
	(_bfd_mips_elf_always_size_sections): Get a worst-case estimate
	of the number of dynamic symbols needed and use it to set up
	function_stub_size.  Use function_stub_size rather than
	MIPS_FUNCTION_STUB_SIZE to determine the size of the stub section.
	Use 16-byte stubs for 0x10000 dynamic symbols.
	(_bfd_mips_elf_size_dynamic_sections): Use htab->function_stub_size
	instead of MIPS_FUNCTION_STUB_SIZE.  Fix formatting.
	(_bfd_mips_elf_finish_dynamic_symbol): Likewise.  Change the
	size of the stub buffer from MIPS_FUNCTION_STUB_MAX_SIZE to
	MIPS_FUNCTION_STUB_BIG_SIZE.  Tweak the check for unhandled dynindxes.
	Use MIPS_FUNCTION_STUB_BIG_SIZE rather than a hard-coded 20.
	Use STUB_ORI rather than STUB_LI16U for big stubs.
	(_bfd_mips_elf_link_hash_table_create): Initialize function_stub_size.
	(_bfd_mips_elf_final_link): Use count_section_dynsyms.

ld/testsuite/
	* ld-mips-elf/stub-dynsym-1.s,
	* ld-mips-elf/stub-dynsym-1.ld,
	* ld-mips-elf/stub-dynsym-1-7fff.d,
	* ld-mips-elf/stub-dynsym-1-8000.d,
	* ld-mips-elf/stub-dynsym-1-fff0.d,
	* ld-mips-elf/stub-dynsym-1-10000.d,
	* ld-mips-elf/stub-dynsym-1-2fe80.d: New test.
	* ld-mips-elf/mips-elf.exp: Run it.
This commit is contained in:
Richard Sandiford 2006-06-11 08:33:27 +00:00
parent dbed2504e9
commit 5108fc1bc9
11 changed files with 252 additions and 39 deletions

View File

@ -1,3 +1,32 @@
2006-06-11 Richard Sandiford <richard@codesourcery.com>
Thiemo Seufer <ths@mips.com>
* elfxx-mips.c (mips_elf_link_hash_table): Add function_stub_size.
(STUB_ORI): New macro.
(STUB_LI16U): Fix formatting.
(MIPS_FUNCTION_STUB_SIZE): Delete.
(MIPS_FUNCTION_STUB_MAX_SIZE): Likewise.
(MIPS_FUNCTION_STUB_NORMAL_SIZE): New macro.
(MIPS_FUNCTION_STUB_BIG_SIZE): Likewise.
(_bfd_mips_elf_adjust_dynamic_symbol): Use htab->function_stub_size
instead of MIPS_FUNCTION_STUB_SIZE.
(count_section_dynsyms): New function, split out from
_bfd_mips_elf_final_link.
(_bfd_mips_elf_always_size_sections): Get a worst-case estimate
of the number of dynamic symbols needed and use it to set up
function_stub_size. Use function_stub_size rather than
MIPS_FUNCTION_STUB_SIZE to determine the size of the stub section.
Use 16-byte stubs for 0x10000 dynamic symbols.
(_bfd_mips_elf_size_dynamic_sections): Use htab->function_stub_size
instead of MIPS_FUNCTION_STUB_SIZE. Fix formatting.
(_bfd_mips_elf_finish_dynamic_symbol): Likewise. Change the
size of the stub buffer from MIPS_FUNCTION_STUB_MAX_SIZE to
MIPS_FUNCTION_STUB_BIG_SIZE. Tweak the check for unhandled dynindxes.
Use MIPS_FUNCTION_STUB_BIG_SIZE rather than a hard-coded 20.
Use STUB_ORI rather than STUB_LI16U for big stubs.
(_bfd_mips_elf_link_hash_table_create): Initialize function_stub_size.
(_bfd_mips_elf_final_link): Use count_section_dynsyms.
2006-06-09 David Ung <davidu@mips.com>
* bfd/elfxx-mips.c (mips_elf_calculate_relocation): Fix mode for stub

View File

@ -335,6 +335,8 @@ struct mips_elf_link_hash_table
bfd_vma plt_header_size;
/* The size of a PLT entry in bytes (VxWorks only). */
bfd_vma plt_entry_size;
/* The size of a function stub entry in bytes. */
bfd_vma function_stub_size;
};
#define TLS_RELOC_P(r_type) \
@ -633,16 +635,15 @@ static bfd *reldyn_sorting_bfd;
: 0x03e07821)) /* addu t7,ra */
#define STUB_LUI(VAL) (0x3c180000 + (VAL)) /* lui t8,VAL */
#define STUB_JALR 0x0320f809 /* jalr t9,ra */
#define STUB_LI16U(VAL) (0x34180000 + (VAL)) /* ori t8,zero,VAL unsigned*/
#define STUB_ORI(VAL) (0x37180000 + (VAL)) /* ori t8,t8,VAL */
#define STUB_LI16U(VAL) (0x34180000 + (VAL)) /* ori t8,zero,VAL unsigned */
#define STUB_LI16S(abfd, VAL) \
((ABI_64_P (abfd) \
? (0x64180000 + (VAL)) /* daddiu t8,zero,VAL sign extended */ \
: (0x24180000 + (VAL)))) /* addiu t8,zero,VAL sign extended */
#define MIPS_FUNCTION_STUB_SIZE(INFO) \
(elf_hash_table (INFO)->dynsymcount > 65536 ? 20 : 16)
#define MIPS_FUNCTION_STUB_MAX_SIZE 20
#define MIPS_FUNCTION_STUB_NORMAL_SIZE 16
#define MIPS_FUNCTION_STUB_BIG_SIZE 20
/* The name of the dynamic interpreter. This is put in the .interp
section. */
@ -6832,7 +6833,9 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
bfd *dynobj;
struct mips_elf_link_hash_entry *hmips;
asection *s;
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
dynobj = elf_hash_table (info)->dynobj;
/* Make sure we know what is going on here. */
@ -6885,7 +6888,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
h->plt.offset = s->size;
/* Make room for this stub code. */
s->size += MIPS_FUNCTION_STUB_SIZE (info);
s->size += htab->function_stub_size;
/* The last half word of the stub will be filled with the index
of this symbol in .dynsym section. */
@ -7073,6 +7076,32 @@ _bfd_mips_vxworks_adjust_dynamic_symbol (struct bfd_link_info *info,
return TRUE;
}
/* Return the number of dynamic section symbols required by OUTPUT_BFD.
The number might be exact or a worst-case estimate, depending on how
much information is available to elf_backend_omit_section_dynsym at
the current linking stage. */
static bfd_size_type
count_section_dynsyms (bfd *output_bfd, struct bfd_link_info *info)
{
bfd_size_type count;
count = 0;
if (info->shared || elf_hash_table (info)->is_relocatable_executable)
{
asection *p;
const struct elf_backend_data *bed;
bed = get_elf_backend_data (output_bfd);
for (p = output_bfd->sections; p ; p = p->next)
if ((p->flags & SEC_EXCLUDE) == 0
&& (p->flags & SEC_ALLOC) != 0
&& !(*bed->elf_backend_omit_section_dynsym) (output_bfd, info, p))
++count;
}
return count;
}
/* This function is called after all the input files have been read,
and the input sections have been assigned to output sections. We
check for any mips16 stub sections that we can discard. */
@ -7089,6 +7118,7 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd,
int i;
bfd_size_type loadable_size = 0;
bfd_size_type local_gotno;
bfd_size_type dynsymcount;
bfd *sub;
struct mips_elf_count_tls_arg count_tls_arg;
struct mips_elf_link_hash_table *htab;
@ -7147,10 +7177,22 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd,
relocations, then GLOBAL_GOTSYM will be NULL. */
i = 0;
/* Get a worst-case estimate of the number of dynamic symbols needed.
At this point, dynsymcount does not account for section symbols
and count_section_dynsyms may overestimate the number that will
be needed. */
dynsymcount = (elf_hash_table (info)->dynsymcount
+ count_section_dynsyms (output_bfd, info));
/* Determine the size of one stub entry. */
htab->function_stub_size = (dynsymcount > 0x10000
? MIPS_FUNCTION_STUB_BIG_SIZE
: MIPS_FUNCTION_STUB_NORMAL_SIZE);
/* In the worst case, we'll get one stub per dynamic symbol, plus
one to account for the dummy entry at the end required by IRIX
rld. */
loadable_size += MIPS_FUNCTION_STUB_SIZE (info) * (i + 1);
loadable_size += htab->function_stub_size * (i + 1);
if (htab->is_vxworks)
/* There's no need to allocate page entries for VxWorks; R_MIPS_GOT16
@ -7367,14 +7409,14 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
else if (strcmp (name, MIPS_ELF_STUB_SECTION_NAME (output_bfd)) == 0)
{
/* IRIX rld assumes that the function stub isn't at the end
of .text section. So put a dummy. XXX */
s->size += MIPS_FUNCTION_STUB_SIZE (info);
of .text section. So put a dummy. XXX */
s->size += htab->function_stub_size;
}
else if (! info->shared
&& ! mips_elf_hash_table (info)->use_rld_obj_head
&& strncmp (name, ".rld_map", 8) == 0)
{
/* We add a room for __rld_map. It will be filled in by the
/* We add a room for __rld_map. It will be filled in by the
rtld to contain a pointer to the _r_debug structure. */
s->size += 4;
}
@ -8006,13 +8048,15 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
struct mips_got_info *g, *gg;
const char *name;
int idx;
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
dynobj = elf_hash_table (info)->dynobj;
if (h->plt.offset != MINUS_ONE)
{
asection *s;
bfd_byte stub[MIPS_FUNCTION_STUB_MAX_SIZE];
bfd_byte stub[MIPS_FUNCTION_STUB_BIG_SIZE];
/* This symbol has a stub. Set it up. */
@ -8022,13 +8066,13 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
MIPS_ELF_STUB_SECTION_NAME (dynobj));
BFD_ASSERT (s != NULL);
BFD_ASSERT ((MIPS_FUNCTION_STUB_SIZE (info) == 20)
|| (h->dynindx <= 65536));
BFD_ASSERT ((htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
|| (h->dynindx <= 0xffff));
/* Values up to 2^31 - 1 are allowed. Larger values would cause
sign extension at runtime in the stub, resulting in a
negative index value. */
if (h->dynindx & 0x80000000)
sign extension at runtime in the stub, resulting in a negative
index value. */
if (h->dynindx & ~0x7fffffff)
return FALSE;
/* Fill the stub. */
@ -8037,9 +8081,9 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
idx += 4;
bfd_put_32 (output_bfd, STUB_MOVE (output_bfd), stub + idx);
idx += 4;
if (MIPS_FUNCTION_STUB_SIZE (info) == 20)
if (htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
{
bfd_put_32 (output_bfd, STUB_LUI ((h->dynindx >> 16 ) & 0xffff),
bfd_put_32 (output_bfd, STUB_LUI ((h->dynindx >> 16) & 0x7fff),
stub + idx);
idx += 4;
}
@ -8048,15 +8092,16 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
/* If a large stub is not required and sign extension is not a
problem, then use legacy code in the stub. */
if ((MIPS_FUNCTION_STUB_SIZE (info) == 20) || (h->dynindx & 0xffff8000))
if (htab->function_stub_size == MIPS_FUNCTION_STUB_BIG_SIZE)
bfd_put_32 (output_bfd, STUB_ORI (h->dynindx & 0xffff), stub + idx);
else if (h->dynindx & ~0x7fff)
bfd_put_32 (output_bfd, STUB_LI16U (h->dynindx & 0xffff), stub + idx);
else
bfd_put_32 (output_bfd,
STUB_LI16S (output_bfd, h->dynindx & 0xffff), stub + idx);
bfd_put_32 (output_bfd, STUB_LI16S (output_bfd, h->dynindx),
stub + idx);
BFD_ASSERT (h->plt.offset <= s->size);
memcpy (s->contents + h->plt.offset,
stub, MIPS_FUNCTION_STUB_SIZE (info));
memcpy (s->contents + h->plt.offset, stub, htab->function_stub_size);
/* Mark the symbol as undefined. plt.offset != -1 occurs
only for the referenced symbol. */
@ -8859,10 +8904,10 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
{
file_ptr dummy_offset;
BFD_ASSERT (s->size >= MIPS_FUNCTION_STUB_SIZE (info));
dummy_offset = s->size - MIPS_FUNCTION_STUB_SIZE (info);
BFD_ASSERT (s->size >= htab->function_stub_size);
dummy_offset = s->size - htab->function_stub_size;
memset (s->contents + dummy_offset, 0,
MIPS_FUNCTION_STUB_SIZE (info));
htab->function_stub_size);
}
}
}
@ -9974,6 +10019,7 @@ _bfd_mips_elf_link_hash_table_create (bfd *abfd)
ret->splt = NULL;
ret->plt_header_size = 0;
ret->plt_entry_size = 0;
ret->function_stub_size = 0;
return &ret->root.root;
}
@ -10049,18 +10095,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
we count the sections after (possibly) removing the .options
section above. */
dynsecsymcount = 0;
if (info->shared)
{
asection * p;
for (p = abfd->sections; p ; p = p->next)
if ((p->flags & SEC_EXCLUDE) == 0
&& (p->flags & SEC_ALLOC) != 0
&& !(*bed->elf_backend_omit_section_dynsym) (abfd, info, p))
++ dynsecsymcount;
}
dynsecsymcount = count_section_dynsyms (abfd, info);
if (! mips_elf_sort_hash_table (info, dynsecsymcount + 1))
return FALSE;

View File

@ -1,3 +1,14 @@
2006-06-11 Richard Sandiford <richard@codesourcery.com>
* ld-mips-elf/stub-dynsym-1.s,
* ld-mips-elf/stub-dynsym-1.ld,
* ld-mips-elf/stub-dynsym-1-7fff.d,
* ld-mips-elf/stub-dynsym-1-8000.d,
* ld-mips-elf/stub-dynsym-1-fff0.d,
* ld-mips-elf/stub-dynsym-1-10000.d,
* ld-mips-elf/stub-dynsym-1-2fe80.d: New test.
* ld-mips-elf/mips-elf.exp: Run it.
2006-06-06 Alan Modra <amodra@bigpond.net.au>
* ld-elfvers/vers.exp (objdump_versionstuff): Allow versions in

View File

@ -137,6 +137,33 @@ if $has_newabi {
run_dump_test "emit-relocs-1"
}
if {[istarget mips*-*-linux*]} {
# The number of symbols that are always included in the symbol table
# for these tests. The 5 are:
#
# the null symbol entry
# the .MIPS.stubs section symbol
# the .text section symbol
# _gp
# _GLOBAL_OFFSET_TABLE_
set base_syms 5
foreach dynsym { 7fff 8000 fff0 10000 2fe80 } {
run_ld_link_tests \
[list [list \
"Stub for dynsym 0x$dynsym" \
"-shared -melf32btsmip -T stub-dynsym-1.ld" \
[concat \
"-EB -march=mips1 -32 -KPIC" \
"--defsym base_syms=$base_syms" \
"--defsym dynsym=0x$dynsym"] \
[list "stub-dynsym-1.s"] \
[list [list \
"objdump" "-dz" \
"stub-dynsym-1-$dynsym.d"]] \
"stub-dynsym-1-$dynsym"]]
}
}
# For tests which may involve multiple files, use run_ld_link_tests.
# List contains test-items with 3 items followed by 2 lists:

View File

@ -0,0 +1,18 @@
.*: file format elf32-tradbigmips
Disassembly of section \.MIPS\.stubs:
.* <\.MIPS.stubs>:
.*: 8f998010 lw t9,-32752\(gp\)
.*: 03e07821 move t7,ra
.*: 3c180001 lui t8,0x1
.*: 0320f809 jalr t9
.*: 37180000 ori t8,t8,0x0
.*: 00000000 nop
.*: 00000000 nop
.*: 00000000 nop
.*: 00000000 nop
.*: 00000000 nop
Disassembly of section .text:
#pass

View File

@ -0,0 +1,18 @@
.*: file format elf32-tradbigmips
Disassembly of section \.MIPS\.stubs:
.* <\.MIPS.stubs>:
.*: 8f998010 lw t9,-32752\(gp\)
.*: 03e07821 move t7,ra
.*: 3c180002 lui t8,0x2
.*: 0320f809 jalr t9
.*: 3718fe80 ori t8,t8,0xfe80
.*: 00000000 nop
.*: 00000000 nop
.*: 00000000 nop
.*: 00000000 nop
.*: 00000000 nop
Disassembly of section .text:
#pass

View File

@ -0,0 +1,16 @@
.*: file format elf32-tradbigmips
Disassembly of section \.MIPS\.stubs:
.* <\.MIPS.stubs>:
.*: 8f998010 lw t9,-32752\(gp\)
.*: 03e07821 move t7,ra
.*: 0320f809 jalr t9
.*: 24187fff li t8,32767
.*: 00000000 nop
.*: 00000000 nop
.*: 00000000 nop
.*: 00000000 nop
Disassembly of section .text:
#pass

View File

@ -0,0 +1,16 @@
.*: file format elf32-tradbigmips
Disassembly of section \.MIPS\.stubs:
.* <\.MIPS.stubs>:
.*: 8f998010 lw t9,-32752\(gp\)
.*: 03e07821 move t7,ra
.*: 0320f809 jalr t9
.*: 34188000 li t8,0x8000
.*: 00000000 nop
.*: 00000000 nop
.*: 00000000 nop
.*: 00000000 nop
Disassembly of section .text:
#pass

View File

@ -0,0 +1,16 @@
.*: file format elf32-tradbigmips
Disassembly of section \.MIPS\.stubs:
.* <\.MIPS.stubs>:
.*: 8f998010 lw t9,-32752\(gp\)
.*: 03e07821 move t7,ra
.*: 0320f809 jalr t9
.*: 3418fff0 li t8,0xfff0
.*: 00000000 nop
.*: 00000000 nop
.*: 00000000 nop
.*: 00000000 nop
Disassembly of section .text:
#pass

View File

@ -0,0 +1,17 @@
SECTIONS
{
. = 0x80000;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.rel.dyn : { *(.rel.dyn) }
.MIPS.stubs : { *(.MIPS.stubs) }
.text : { *(.text) }
. = ALIGN (0x10000);
_gp = . + 0x7ff0;
.got : { *(.got) }
/DISCARD/ : { *(.reginfo) }
}

View File

@ -0,0 +1,10 @@
.macro decl
.global exported\@
.equ exported\@,\@
.endm
.rept dynsym - base_syms
decl
.endr
lw $25,%call16(foo)($gp)