summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@nildram.co.uk>2006-03-27 11:30:54 +0000
committerRichard Sandiford <rsandifo@nildram.co.uk>2006-03-27 11:30:54 +0000
commit80c0b81ff793936b25d9001a82cd28a7d07fa950 (patch)
treeb3331d7f4d0f9c65f93acd27b391c4c1c0a9ffa3
parent542d707abcb145a1f510064bf910fa5c0df86c69 (diff)
downloadbinutils-redhat-80c0b81ff793936b25d9001a82cd28a7d07fa950.tar.gz
* 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.
-rw-r--r--bfd/ChangeLog11
-rw-r--r--bfd/elfxx-mips.c109
-rw-r--r--ld/testsuite/ChangeLog9
-rw-r--r--ld/testsuite/ld-mips-elf/mips-elf.exp11
-rw-r--r--ld/testsuite/ld-mips-elf/tls-hidden3.d24
-rw-r--r--ld/testsuite/ld-mips-elf/tls-hidden3.got24
-rw-r--r--ld/testsuite/ld-mips-elf/tls-hidden3.ld31
-rw-r--r--ld/testsuite/ld-mips-elf/tls-hidden3.r13
-rw-r--r--ld/testsuite/ld-mips-elf/tls-hidden3a.s10
-rw-r--r--ld/testsuite/ld-mips-elf/tls-hidden3b.s18
-rw-r--r--ld/testsuite/ld-mips-elf/tls-hidden4.got28
-rw-r--r--ld/testsuite/ld-mips-elf/tls-hidden4.r19
-rw-r--r--ld/testsuite/ld-mips-elf/tls-hidden4a.s18
-rw-r--r--ld/testsuite/ld-mips-elf/tls-hidden4b.s27
14 files changed, 318 insertions, 34 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 08eb42dc99..47d19f729d 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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,
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index c9862d4bd5..4e27a53fda 100644
--- a/bfd/elfxx-mips.c
+++ b/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
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 4be03b845a..7684e380cf 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -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,
diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp
index add2060acd..645b7e0e50 100644
--- a/ld/testsuite/ld-mips-elf/mips-elf.exp
+++ b/ld/testsuite/ld-mips-elf/mips-elf.exp
@@ -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*]} {
diff --git a/ld/testsuite/ld-mips-elf/tls-hidden3.d b/ld/testsuite/ld-mips-elf/tls-hidden3.d
new file mode 100644
index 0000000000..6d586869bf
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/tls-hidden3.d
@@ -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\)
diff --git a/ld/testsuite/ld-mips-elf/tls-hidden3.got b/ld/testsuite/ld-mips-elf/tls-hidden3.got
new file mode 100644
index 0000000000..8b9c87f86e
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/tls-hidden3.got
@@ -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 .*
diff --git a/ld/testsuite/ld-mips-elf/tls-hidden3.ld b/ld/testsuite/ld-mips-elf/tls-hidden3.ld
new file mode 100644
index 0000000000..b3d0584c88
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/tls-hidden3.ld
@@ -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: *; };
+}
diff --git a/ld/testsuite/ld-mips-elf/tls-hidden3.r b/ld/testsuite/ld-mips-elf/tls-hidden3.r
new file mode 100644
index 0000000000..500e7b1707
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/tls-hidden3.r
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/tls-hidden3a.s b/ld/testsuite/ld-mips-elf/tls-hidden3a.s
new file mode 100644
index 0000000000..d1e6d646e7
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/tls-hidden3a.s
@@ -0,0 +1,10 @@
+ .macro load
+ lw $4,%gottprel(foo\@)($gp)
+ .endm
+
+ .rept 4
+ load
+ .endr
+
+ .section .tdata,"awT",@progbits
+ .fill 0xabc0
diff --git a/ld/testsuite/ld-mips-elf/tls-hidden3b.s b/ld/testsuite/ld-mips-elf/tls-hidden3b.s
new file mode 100644
index 0000000000..0744b078f8
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/tls-hidden3b.s
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/tls-hidden4.got b/ld/testsuite/ld-mips-elf/tls-hidden4.got
new file mode 100644
index 0000000000..84120c0452
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/tls-hidden4.got
@@ -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 .*
diff --git a/ld/testsuite/ld-mips-elf/tls-hidden4.r b/ld/testsuite/ld-mips-elf/tls-hidden4.r
new file mode 100644
index 0000000000..f6809b5280
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/tls-hidden4.r
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/tls-hidden4a.s b/ld/testsuite/ld-mips-elf/tls-hidden4a.s
new file mode 100644
index 0000000000..02a0d35b73
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/tls-hidden4a.s
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/tls-hidden4b.s b/ld/testsuite/ld-mips-elf/tls-hidden4b.s
new file mode 100644
index 0000000000..d6deb002d6
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/tls-hidden4b.s
@@ -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