* elfxx-mips.c (mips_got_entry): Add more commentary.

(mips_elf_local_got_index): Use the hash table entry to record
	the GOT index of forced-local symbols.
	(mips_elf_initialize_tls_index): Rearrange code.  Store the index
	in either the hash table entry or the mips_got_entry, not both.
	Add more commentary.
	(mips_elf_multi_got): Make sure the g->next is nonnull when calling
	mips_elf_initialize_tls_index.

	* ld-mips-elf/tls-hidden3a.s, ld-mips-elf/tls-hidden3b.s,
	* ld-mips-elf/tls-hidden3.d, ld-mips-elf/tls-hidden3.got,
	* ld-mips-elf/tls-hidden3.ld, ld-mips-elf/tls-hidden3.r,
	* ld-mips-elf/tls-hidden4a.s, ld-mips-elf/tls-hidden4b.s,
	* ld-mips-elf/tls-hidden4.got, ld-mips-elf/tls-hidden4.r: New tests.
	* ld-mips-elf/mips-elf.exp: Run them.
This commit is contained in:
Richard Sandiford 2006-03-27 11:30:54 +00:00
parent 5cc40a5834
commit ead49a57e8
14 changed files with 318 additions and 34 deletions

View File

@ -1,3 +1,14 @@
2006-03-27 Richard Sandiford <richard@codesourcery.com>
* elfxx-mips.c (mips_got_entry): Add more commentary.
(mips_elf_local_got_index): Use the hash table entry to record
the GOT index of forced-local symbols.
(mips_elf_initialize_tls_index): Rearrange code. Store the index
in either the hash table entry or the mips_got_entry, not both.
Add more commentary.
(mips_elf_multi_got): Make sure the g->next is nonnull when calling
mips_elf_initialize_tls_index.
2006-03-25 Bernd Schmidt <bernd.schmidt@analog.com>
* elf32-bfin.c (bfd_const_reloc, bfd_oper_reloc, bfin_push_reloc,

View File

@ -44,8 +44,39 @@
#include "hashtab.h"
/* This structure is used to hold .got entries while estimating got
sizes. */
/* This structure is used to hold information about one GOT entry.
There are three types of entry:
(1) absolute addresses
(abfd == NULL)
(2) SYMBOL + OFFSET addresses, where SYMBOL is local to an input bfd
(abfd != NULL, symndx >= 0)
(3) global and forced-local symbols
(abfd != NULL, symndx == -1)
Type (3) entries are treated differently for different types of GOT.
In the "master" GOT -- i.e. the one that describes every GOT
reference needed in the link -- the mips_got_entry is keyed on both
the symbol and the input bfd that references it. If it turns out
that we need multiple GOTs, we can then use this information to
create separate GOTs for each input bfd.
However, we want each of these separate GOTs to have at most one
entry for a given symbol, so their type (3) entries are keyed only
on the symbol. The input bfd given by the "abfd" field is somewhat
arbitrary in this case.
This means that when there are multiple GOTs, each GOT has a unique
mips_got_entry for every symbol within it. We can therefore use the
mips_got_entry fields (tls_type and gotidx) to track the symbol's
GOT index.
However, if it turns out that we need only a single GOT, we continue
to use the master GOT to describe it. There may therefore be several
mips_got_entries for the same symbol, each with a different input bfd.
We want to make sure that each symbol gets a unique GOT entry, so when
there's a single GOT, we use the symbol's hash entry, not the
mips_got_entry fields, to track a symbol's GOT index. */
struct mips_got_entry
{
/* The input bfd in which the symbol is defined. */
@ -2371,8 +2402,16 @@ mips_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
return MINUS_ONE;
if (TLS_RELOC_P (r_type))
return mips_tls_got_index (abfd, entry->gotidx, &entry->tls_type, r_type,
info, h, value);
{
if (entry->symndx == -1 && g->next == NULL)
/* A type (3) entry in the single-GOT case. We use the symbol's
hash table entry to track the index. */
return mips_tls_got_index (abfd, h->tls_got_offset, &h->tls_type,
r_type, info, h, value);
else
return mips_tls_got_index (abfd, entry->gotidx, &entry->tls_type,
r_type, info, h, value);
}
else
return entry->gotidx;
}
@ -3118,55 +3157,54 @@ mips_elf_merge_gots (void **bfd2got_, void *p)
return 1;
}
/* Set the TLS GOT index for the GOT entry in ENTRYP. */
/* Set the TLS GOT index for the GOT entry in ENTRYP. ENTRYP's NEXT field
is null iff there is just a single GOT. */
static int
mips_elf_initialize_tls_index (void **entryp, void *p)
{
struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
struct mips_got_info *g = p;
bfd_vma next_index;
/* We're only interested in TLS symbols. */
if (entry->tls_type == 0)
return 1;
if (entry->symndx == -1)
next_index = MIPS_ELF_GOT_SIZE (entry->abfd) * (long) g->tls_assigned_gotno;
if (entry->symndx == -1 && g->next == NULL)
{
/* There may be multiple mips_got_entry structs for a global variable
if there is just one GOT. Just do this once. */
if (g->next == NULL)
/* A type (3) got entry in the single-GOT case. We use the symbol's
hash table entry to track its index. */
if (entry->d.h->tls_type & GOT_TLS_OFFSET_DONE)
return 1;
entry->d.h->tls_type |= GOT_TLS_OFFSET_DONE;
entry->d.h->tls_got_offset = next_index;
}
else
{
if (entry->tls_type & GOT_TLS_LDM)
{
if (entry->d.h->tls_type & GOT_TLS_OFFSET_DONE)
/* There are separate mips_got_entry objects for each input bfd
that requires an LDM entry. Make sure that all LDM entries in
a GOT resolve to the same index. */
if (g->tls_ldm_offset != MINUS_TWO && g->tls_ldm_offset != MINUS_ONE)
{
entry->gotidx = entry->d.h->tls_got_offset;
entry->gotidx = g->tls_ldm_offset;
return 1;
}
entry->d.h->tls_type |= GOT_TLS_OFFSET_DONE;
}
}
else if (entry->tls_type & GOT_TLS_LDM)
{
/* Similarly, there may be multiple structs for the LDM entry. */
if (g->tls_ldm_offset != MINUS_TWO && g->tls_ldm_offset != MINUS_ONE)
{
entry->gotidx = g->tls_ldm_offset;
return 1;
g->tls_ldm_offset = next_index;
}
entry->gotidx = next_index;
}
/* Initialize the GOT offset. */
entry->gotidx = MIPS_ELF_GOT_SIZE (entry->abfd) * (long) g->tls_assigned_gotno;
if (g->next == NULL && entry->symndx == -1)
entry->d.h->tls_got_offset = entry->gotidx;
/* Account for the entries we've just allocated. */
if (entry->tls_type & (GOT_TLS_GD | GOT_TLS_LDM))
g->tls_assigned_gotno += 2;
if (entry->tls_type & GOT_TLS_IE)
g->tls_assigned_gotno += 1;
if (entry->tls_type & GOT_TLS_LDM)
g->tls_ldm_offset = entry->gotidx;
return 1;
}
@ -3492,16 +3530,19 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
g->local_gotno += assign + pages;
assign = g->local_gotno + g->global_gotno + g->tls_gotno;
/* Take g out of the direct list, and push it onto the reversed
list that gg points to. g->next is guaranteed to be nonnull after
this operation, as required by mips_elf_initialize_tls_index. */
gn = g->next;
g->next = gg->next;
gg->next = g;
/* Set up any TLS entries. We always place the TLS entries after
all non-TLS entries. */
g->tls_assigned_gotno = g->local_gotno + g->global_gotno;
htab_traverse (g->got_entries, mips_elf_initialize_tls_index, g);
/* Take g out of the direct list, and push it onto the reversed
list that gg points to. */
gn = g->next;
g->next = gg->next;
gg->next = g;
/* Move onto the next GOT. It will be a secondary GOT if nonull. */
g = gn;
/* Mark global symbols in every non-primary GOT as ineligible for

View File

@ -1,3 +1,12 @@
2006-03-27 Richard Sandiford <richard@codesourcery.com>
* ld-mips-elf/tls-hidden3a.s, ld-mips-elf/tls-hidden3b.s,
* ld-mips-elf/tls-hidden3.d, ld-mips-elf/tls-hidden3.got,
* ld-mips-elf/tls-hidden3.ld, ld-mips-elf/tls-hidden3.r,
* ld-mips-elf/tls-hidden4a.s, ld-mips-elf/tls-hidden4b.s,
* ld-mips-elf/tls-hidden4.got, ld-mips-elf/tls-hidden4.r: New tests.
* ld-mips-elf/mips-elf.exp: Run them.
2006-03-25 Richard Sandiford <richard@codesourcery.com>
* ld-m68k/merge-error-1a.s, ld-m68k/merge-error-1b.s,

View File

@ -199,6 +199,17 @@ set mips_tls_tests {
"-EB -march=mips1 -32 -KPIC" {tls-hidden2a.s tls-hidden2b.s}
{{objdump -drj.text tls-hidden2.d} {objdump -sj.got tls-hidden2-got.d}}
"tls-hidden2.so"}
{"Shared library with TLS and hidden symbols (3)"
"-shared -melf32btsmip -T tls-hidden3.ld"
"-EB -march=mips2 -32 -KPIC" {tls-hidden3a.s tls-hidden3b.s}
{{objdump -dj.text tls-hidden3.d} {objdump -sj.got tls-hidden3.got}
{readelf --relocs tls-hidden3.r}}
"tls-hidden3.so"}
{"Shared library with TLS and hidden symbols (4)"
"-shared -melf32btsmip -T tls-hidden3.ld"
"-EB -march=mips2 -32 -KPIC" {tls-hidden4a.s tls-hidden4b.s}
{{objdump -sj.got tls-hidden4.got} {readelf --relocs tls-hidden4.r}}
"tls-hidden4.so"}
}
if {[istarget mips*-*-linux*]} {

View File

@ -0,0 +1,24 @@
.*: file format .*
Disassembly of section \.text:
#
# The TLS entries are ordered as follows:
#
# foo0 (-0x7ff0 + 0x20)
# foo2 (-0x7ff0 + 0x24)
# foo3 (-0x7ff0 + 0x28)
# foo1 (-0x7ff0 + 0x2c)
#
# Any order would be acceptable, but it must match the .got dump.
#
00080c00 <\.text>:
80c00: 8f848030 lw a0,-32720\(gp\)
80c04: 8f84803c lw a0,-32708\(gp\)
80c08: 8f848034 lw a0,-32716\(gp\)
80c0c: 8f848038 lw a0,-32712\(gp\)
80c10: 8f848030 lw a0,-32720\(gp\)
80c14: 8f84803c lw a0,-32708\(gp\)
80c18: 8f848034 lw a0,-32716\(gp\)
80c1c: 8f848038 lw a0,-32712\(gp\)

View File

@ -0,0 +1,24 @@
.*: file format .*
#
# The GOT layout is:
#
# - 2 reserved entries
# - 5 local page entries
# - 1 global entry for "undef"
# - 4 TLS entries
#
# The order of the TLS entries is:
#
# foo0 (offset 0x20)
# foo2 (offset 0x24)
# foo3 (offset 0x28)
# foo1 (offset 0x2c)
#
# Any order would be acceptable, but it must match the .d dump.
#
Contents of section \.got:
90000 00000000 80000000 00000000 00000000 .*
90010 00000000 00000000 00000000 00000000 .*
90020 0000abc0 0000abc8 0000abcc 0000abc4 .*

View File

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

View File

@ -0,0 +1,13 @@
Relocation section '\.rel\.dyn' at offset .* contains 6 entries:
Offset Info Type Sym\.Value Sym\. Name
00000000 00000000 R_MIPS_NONE
#
# The order of the next four entries doesn't matter. The important thing
# is that there is exactly one entry per GOT TLS slot.
#
00090020 0000002f R_MIPS_TLS_TPREL3
0009002c 0000002f R_MIPS_TLS_TPREL3
00090024 0000002f R_MIPS_TLS_TPREL3
00090028 0000002f R_MIPS_TLS_TPREL3
00090030 .*03 R_MIPS_REL32 00000000 undef

View File

@ -0,0 +1,10 @@
.macro load
lw $4,%gottprel(foo\@)($gp)
.endm
.rept 4
load
.endr
.section .tdata,"awT",@progbits
.fill 0xabc0

View File

@ -0,0 +1,18 @@
.macro load
.text
lw $4,%gottprel(foo\@)($gp)
.global foo\@
.type foo\@,@object
.size foo\@,4
.section .tdata,"awT",@progbits
foo\@:
.word \@
.endm
.rept 4
load
.endr
.data
.word undef

View File

@ -0,0 +1,28 @@
.*: file format .*
Contents of section \.got:
#
# The order of the TLS entries in this GOT is:
#
# foo2
# foo3
# foo0
# foo1
#
# The order and address don't matter; the important thing is that the
# addresses match the relocs in the .r dump and that there is a separate
# entry for each symbol.
#
#...
1c4080 0000abc8 0000abcc 0000abc0 0000abc4 .*
#
# Likewise, but the order of the entries in this GOT is:
#
# foo3
# foo2
# foo0
# foo1
#...
1d00c0 00000000 00000000 00000000 0000abcc .*
1d00d0 0000abc8 0000abc0 0000abc4 .*

View File

@ -0,0 +1,19 @@
Relocation section '\.rel\.dyn' at offset .* contains .* entries:
Offset Info Type Sym\.Value Sym\. Name
00000000 00000000 R_MIPS_NONE
#
# The order and addresses of the next eight entries don't matter. The
# important thing is that there is exactly one entry per GOT TLS slot
# and that the addresses match those in the .got dump.
#
001d00d4 0000002f R_MIPS_TLS_TPREL3
001d00d8 0000002f R_MIPS_TLS_TPREL3
001d00d0 0000002f R_MIPS_TLS_TPREL3
001d00cc 0000002f R_MIPS_TLS_TPREL3
001c4088 0000002f R_MIPS_TLS_TPREL3
001c408c 0000002f R_MIPS_TLS_TPREL3
001c4080 0000002f R_MIPS_TLS_TPREL3
001c4084 0000002f R_MIPS_TLS_TPREL3
.* R_MIPS_REL32 .*
#pass

View File

@ -0,0 +1,18 @@
.macro load
lw $4,%gottprel(foo\@)($gp)
.endm
.rept 4
load
.endr
.macro load2
lw $4,%got(undefa\@)($gp)
.endm
.rept 0x3000
load2
.endr
.section .tdata,"awT",@progbits
.fill 0xabc0

View File

@ -0,0 +1,27 @@
.macro load
.text
lw $4,%gottprel(foo\@)($gp)
.global foo\@
.type foo\@,@object
.size foo\@,4
.section .tdata,"awT",@progbits
foo\@:
.word \@
.endm
.rept 4
load
.endr
.text
.macro load2
lw $4,%got(undefb\@)($gp)
.endm
.rept 0x3000
load2
.endr
.data
.word undef