* 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:
parent
5cc40a5834
commit
ead49a57e8
|
@ -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,
|
||||
|
|
109
bfd/elfxx-mips.c
109
bfd/elfxx-mips.c
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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*]} {
|
||||
|
|
|
@ -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\)
|
|
@ -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 .*
|
|
@ -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: *; };
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,10 @@
|
|||
.macro load
|
||||
lw $4,%gottprel(foo\@)($gp)
|
||||
.endm
|
||||
|
||||
.rept 4
|
||||
load
|
||||
.endr
|
||||
|
||||
.section .tdata,"awT",@progbits
|
||||
.fill 0xabc0
|
|
@ -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
|
|
@ -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 .*
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue