From: Richard Sandiford Date: Mon, 27 Mar 2006 11:30:54 +0000 (+0000) Subject: * elfxx-mips.c (mips_got_entry): Add more commentary. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ead49a57e845c028e794fdeb6f3b2492e70b918e;p=binutils-gdb.git * 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. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 08eb42dc996..47d19f729d3 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2006-03-27 Richard Sandiford + + * 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 * 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 c9862d4bd57..4e27a53fda8 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 4be03b845aa..7684e380cf9 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2006-03-27 Richard Sandiford + + * 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 * 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 add2060acd6..645b7e0e503 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 00000000000..6d586869bfa --- /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 00000000000..8b9c87f86e2 --- /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 00000000000..b3d0584c881 --- /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 00000000000..500e7b17072 --- /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 00000000000..d1e6d646e7c --- /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 00000000000..0744b078f88 --- /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 00000000000..84120c04522 --- /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 00000000000..f6809b5280c --- /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 00000000000..02a0d35b73e --- /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 00000000000..d6deb002d62 --- /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