536 changes: 347 additions & 189 deletions lld/ELF/SyntheticSections.cpp

Large diffs are not rendered by default.

161 changes: 126 additions & 35 deletions lld/ELF/SyntheticSections.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,12 +178,21 @@ class MipsGotSection final : public SyntheticSection {
bool updateAllocSize() override;
void finalizeContents() override;
bool empty() const override;
void addEntry(Symbol &Sym, int64_t Addend, RelExpr Expr);
bool addDynTlsEntry(Symbol &Sym);
bool addTlsIndex();
uint64_t getPageEntryOffset(const Symbol &B, int64_t Addend) const;
uint64_t getSymEntryOffset(const Symbol &B, int64_t Addend) const;
uint64_t getGlobalDynOffset(const Symbol &B) const;

// Join separate GOTs built for each input file to generate
// primary and optional multiple secondary GOTs.
template <class ELFT> void build();

void addEntry(InputFile &File, Symbol &Sym, int64_t Addend, RelExpr Expr);
void addDynTlsEntry(InputFile &File, Symbol &Sym);
void addTlsIndex(InputFile &File);

uint64_t getPageEntryOffset(const InputFile &F, const Symbol &S,
int64_t Addend) const;
uint64_t getSymEntryOffset(const InputFile &F, const Symbol &S,
int64_t Addend) const;
uint64_t getGlobalDynOffset(const InputFile &F, const Symbol &S) const;
uint64_t getTlsIndexOffset(const InputFile &F) const;

// Returns the symbol which corresponds to the first entry of the global part
// of GOT on MIPS platform. It is required to fill up MIPS-specific dynamic
Expand All @@ -195,13 +204,8 @@ class MipsGotSection final : public SyntheticSection {
// the number of reserved entries.
unsigned getLocalEntriesNum() const;

// Returns offset of TLS part of the MIPS GOT table. This part goes
// after 'local' and 'global' entries.
uint64_t getTlsOffset() const;

uint32_t getTlsIndexOff() const { return TlsIndexOff; }

uint64_t getGp() const;
// Return _gp value for primary GOT (nullptr) or particular input file.
uint64_t getGp(const InputFile *F = nullptr) const;

private:
// MIPS GOT consists of three parts: local, global and tls. Each part
Expand Down Expand Up @@ -240,32 +244,110 @@ class MipsGotSection final : public SyntheticSection {
// addressing, but MIPS ABI requires that these entries be present in GOT.
// TLS entries:
// Entries created by TLS relocations.
//
// If the sum of local, global and tls entries is less than 64K only single
// got is enough. Otherwise, multi-got is created. Series of primary and
// multiple secondary GOTs have the following layout:
// - Primary GOT
// Header
// Local entries
// Global entries
// Relocation only entries
// TLS entries
//
// - Secondary GOT
// Local entries
// Global entries
// TLS entries
// ...
//
// All GOT entries required by relocations from a single input file entirely
// belong to either primary or one of secondary GOTs. To reference GOT entries
// each GOT has its own _gp value points to the "middle" of the GOT.
// In the code this value loaded to the register which is used for GOT access.
//
// MIPS 32 function's prologue:
// lui v0,0x0
// 0: R_MIPS_HI16 _gp_disp
// addiu v0,v0,0
// 4: R_MIPS_LO16 _gp_disp
//
// MIPS 64:
// lui at,0x0
// 14: R_MIPS_GPREL16 main
//
// Dynamic linker does not know anything about secondary GOTs and cannot
// use a regular MIPS mechanism for GOT entries initialization. So we have
// to use an approach accepted by other architectures and create dynamic
// relocations R_MIPS_REL32 to initialize global entries (and local in case
// of PIC code) in secondary GOTs. But ironically MIPS dynamic linker
// requires GOT entries and correspondingly ordered dynamic symbol table
// entries to deal with dynamic relocations. To handle this problem
// relocation-only section in the primary GOT contains entries for all
// symbols referenced in global parts of secondary GOTs. Although the sum
// of local and normal global entries of the primary got should be less
// than 64K, the size of the primary got (including relocation-only entries
// can be greater than 64K, because parts of the primary got that overflow
// the 64K limit are used only by the dynamic linker at dynamic link-time
// and not by 16-bit gp-relative addressing at run-time.
//
// For complete multi-GOT description see the following link
// https://dmz-portal.mips.com/wiki/MIPS_Multi_GOT

// Number of "Header" entries.
static const unsigned HeaderEntriesNum = 2;
// Number of allocated "Page" entries.
uint32_t PageEntriesNum = 0;
// Map output sections referenced by MIPS GOT relocations
// to the first index of "Page" entries allocated for this section.
llvm::SmallMapVector<const OutputSection *, size_t, 16> PageIndexMap;

typedef std::pair<const Symbol *, uint64_t> GotEntry;
typedef std::vector<GotEntry> GotEntries;
// Map from Symbol-Addend pair to the GOT index.
llvm::DenseMap<GotEntry, size_t> EntryIndexMap;
// Local entries (16-bit access).
GotEntries LocalEntries;
// Local entries (32-bit access).
GotEntries LocalEntries32;

// Normal and reloc-only global entries.
GotEntries GlobalEntries;

// TLS entries.
std::vector<const Symbol *> TlsEntries;

uint32_t TlsIndexOff = -1;
uint64_t Size = 0;

size_t LocalEntriesNum = 0;

// Symbol and addend.
typedef std::pair<Symbol *, int64_t> GotEntry;

struct FileGot {
InputFile *File = nullptr;
size_t StartIndex = 0;

struct PageBlock {
size_t FirstIndex = 0;
size_t Count = 0;
};

// Map output sections referenced by MIPS GOT relocations
// to the description (index/count) "page" entries allocated
// for this section.
llvm::SmallMapVector<const OutputSection *, PageBlock, 16> PagesMap;
// Maps from Symbol+Addend pair or just Symbol to the GOT entry index.
llvm::MapVector<GotEntry, size_t> Local16;
llvm::MapVector<GotEntry, size_t> Local32;
llvm::MapVector<Symbol *, size_t> Global;
llvm::MapVector<Symbol *, size_t> Relocs;
llvm::MapVector<Symbol *, size_t> Tls;
// Set of symbols referenced by dynamic TLS relocations.
llvm::MapVector<Symbol *, size_t> DynTlsSymbols;

// Total number of all entries.
size_t getEntriesNum() const;
// Number of "page" entries.
size_t getPageEntriesNum() const;
// Number of entries require 16-bit index to access.
size_t getIndexedEntriesNum() const;

bool isOverflow() const;
};

// Container of GOT created for each input file.
// After building a final series of GOTs this container
// holds primary and secondary GOT's.
std::vector<FileGot> Gots;

// Return (and create if necessary) `FileGot`.
FileGot &getGot(InputFile &F);

// Try to merge two GOTs. In case of success the `Dst` contains
// result of merging and the function returns true. In case of
// ovwerflow the `Dst` is unchanged and the function returns false.
bool tryMergeGots(FileGot & Dst, FileGot & Src, bool IsPrimary);
};

class GotPltSection final : public SyntheticSection {
Expand Down Expand Up @@ -318,7 +400,15 @@ class DynamicReloc {
DynamicReloc(RelType Type, const InputSectionBase *InputSec,
uint64_t OffsetInSec, bool UseSymVA, Symbol *Sym, int64_t Addend)
: Type(Type), Sym(Sym), InputSec(InputSec), OffsetInSec(OffsetInSec),
UseSymVA(UseSymVA), Addend(Addend) {}
UseSymVA(UseSymVA), Addend(Addend), OutputSec(nullptr) {}
// This constructor records dynamic relocation settings used by MIPS
// multi-GOT implementation. It's to relocate addresses of 64kb pages
// lie inside the output section.
DynamicReloc(RelType Type, const InputSectionBase *InputSec,
uint64_t OffsetInSec, const OutputSection *OutputSec,
int64_t Addend)
: Type(Type), Sym(nullptr), InputSec(InputSec), OffsetInSec(OffsetInSec),
UseSymVA(false), Addend(Addend), OutputSec(OutputSec) {}

uint64_t getOffset() const;
uint32_t getSymIndex() const;
Expand All @@ -341,6 +431,7 @@ class DynamicReloc {
// plus the original addend as the final relocation addend.
bool UseSymVA;
int64_t Addend;
const OutputSection *OutputSec;
};

template <class ELFT> class DynamicSection final : public SyntheticSection {
Expand Down
3 changes: 3 additions & 0 deletions lld/ELF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1611,6 +1611,9 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (errorCount())
return;

if (InX::MipsGot)
InX::MipsGot->build<ELFT>();

removeUnusedSyntheticSections();

sortSections();
Expand Down
10 changes: 10 additions & 0 deletions lld/test/ELF/Inputs/mips-mgot-1.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.text
.global foo1
foo1:
addiu $2, $2, %gottprel(tls0) # tls got entry
addiu $2, $2, %gottprel(tls1) # tls got entry

.section .tdata,"awT",%progbits
.global tls1
tls1:
.word 0
17 changes: 17 additions & 0 deletions lld/test/ELF/Inputs/mips-mgot-2.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.text
.global foo2
foo2:
lw $2, %got(.data)($gp) # page entry
addi $2, $2, %lo(.data)
lw $2, %call16(foo0)($gp) # global entry
lw $2, %call16(foo2)($gp) # global entry
addiu $2, $2, %tlsgd(tls0) # tls gd entry
addiu $2, $2, %gottprel(tls0) # tls got entry

.data
.space 0x20000

.section .tdata,"awT",%progbits
.global tls2
tls2:
.word 0
36 changes: 36 additions & 0 deletions lld/test/ELF/mips-abs-got.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# REQUIRES: mips

# Check GOT relocations against absolute symbols.

# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux -o %t.o %s
# RUN: echo "SECTIONS { \
# RUN: zero = 0; foo = 0x11004; bar = 0x22000; }" > %t.script
# RUN: ld.lld --script %t.script -o %t.exe %t.o
# RUN: llvm-readobj -mips-plt-got %t.exe | FileCheck %s

# CHECK: Static GOT {
# CHECK: Local entries [
# CHECK-NEXT: Entry {
# CHECK-NEXT: Address:
# CHECK-NEXT: Access: -32736
# CHECK-NEXT: Initial: 0x0
# CHECK-NEXT: }
# CHECK-NEXT: Entry {
# CHECK-NEXT: Address:
# CHECK-NEXT: Access: -32728
# CHECK-NEXT: Initial: 0x10000
# CHECK-NEXT: }
# CHECK-NEXT: Entry {
# CHECK-NEXT: Address:
# CHECK-NEXT: Access: -32720
# CHECK-NEXT: Initial: 0x30000
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }

.text
nop
.reloc 0, R_MIPS_GOT_PAGE, 0
ld $v0, %got_page(zero)($gp)
ld $v0, %got_page(foo)($gp)
ld $v0, %got_page(bar+0x10008)($gp)
2 changes: 1 addition & 1 deletion lld/test/ELF/mips-dynamic.s
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@
# DSO: ]
# DSO: DynamicSymbols [
# DSO: Name: @
# DSO: Name: __start@
# DSO: Name: _foo@
# DSO: Name: __start@
# DSO: ]
# DSO: DynamicSection [
# DSO-NEXT: Tag Type Name/Value
Expand Down
10 changes: 2 additions & 8 deletions lld/test/ELF/mips-got-script.s
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

# REQUIRES: mips

# CHECK: 0x7000000A MIPS_LOCAL_GOTNO 5
# ^-- 2 * header + 3 local entries
# CHECK: 0x7000000A MIPS_LOCAL_GOTNO 4
# ^-- 2 * header + 2 local entries
# CHECK: Local entries [
# CHECK-NEXT: Entry {
# CHECK-NEXT: Address:
Expand All @@ -22,12 +22,6 @@
# CHECK-NEXT: Initial: 0x10000
# ^-- loc2
# CHECK-NEXT: }
# CHECK-NEXT: Entry {
# CHECK-NEXT: Address:
# CHECK-NEXT: Access: -32736
# CHECK-NEXT: Initial: 0x20000
# ^-- redundant
# CHECK-NEXT: }
# CHECK-NEXT: ]

.text
Expand Down
157 changes: 59 additions & 98 deletions lld/test/ELF/mips-got-weak.s
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
# RUN: ld.lld %t.o -shared -o %t1.so
# RUN: llvm-readobj -r -dt -dynamic-table -mips-plt-got %t1.so \
# RUN: | FileCheck -check-prefix=NOSYM %s
# RUN: | FileCheck -check-prefixes=CHECK,NOSYM %s
# RUN: ld.lld %t.o -shared -Bsymbolic -o %t2.so
# RUN: llvm-readobj -r -dt -dynamic-table -mips-plt-got %t2.so \
# RUN: | FileCheck -check-prefix=SYM %s
# RUN: | FileCheck -check-prefixes=CHECK,SYM %s

# REQUIRES: mips

# NOSYM: Relocations [
# NOSYM-NEXT: ]
# CHECK: Relocations [
# CHECK-NEXT: ]

# NOSYM: Symbol {
# NOSYM: Name: foo
Expand All @@ -22,48 +22,68 @@
# NOSYM-NEXT: Other: 0
# NOSYM-NEXT: Section: .data
# NOSYM-NEXT: }
# NOSYM-NEXT: Symbol {
# NOSYM-NEXT: Name: bar
# NOSYM-NEXT: Value: 0x0
# NOSYM-NEXT: Size: 0
# NOSYM-NEXT: Binding: Weak
# NOSYM-NEXT: Type: None
# NOSYM-NEXT: Other: 0
# NOSYM-NEXT: Section: Undefined
# NOSYM-NEXT: }
# NOSYM-NEXT: Symbol {
# NOSYM-NEXT: Name: sym

# CHECK: Symbol {
# CHECK: Name: bar
# CHECK-NEXT: Value: 0x0
# CHECK-NEXT: Size: 0
# CHECK-NEXT: Binding: Weak
# CHECK-NEXT: Type: None
# CHECK-NEXT: Other: 0
# CHECK-NEXT: Section: Undefined
# CHECK-NEXT: }

# NOSYM: Symbol {
# NOSYM: Name: sym
# NOSYM-NEXT: Value: 0x20004
# NOSYM-NEXT: Size: 0
# NOSYM-NEXT: Binding: Global
# NOSYM-NEXT: Type: None
# NOSYM-NEXT: Other: 0
# NOSYM-NEXT: Section: .data
# NOSYM-NEXT: }
# NOSYM-NEXT: ]

# NOSYM: 0x70000011 MIPS_SYMTABNO 4
# NOSYM-NEXT: 0x7000000A MIPS_LOCAL_GOTNO 2
# NOSYM-NEXT: 0x70000013 MIPS_GOTSYM 0x1
# CHECK: 0x70000011 MIPS_SYMTABNO 4

# NOSYM: Primary GOT {
# NOSYM-NEXT: Canonical gp value:
# NOSYM-NEXT: Reserved entries [
# NOSYM-NEXT: Entry {
# NOSYM-NEXT: Address:
# NOSYM-NEXT: Access: -32752
# NOSYM-NEXT: Initial: 0x0
# NOSYM-NEXT: Purpose: Lazy resolver
# NOSYM-NEXT: }
# NOSYM-NEXT: Entry {
# NOSYM-NEXT: Address:
# NOSYM-NEXT: Access: -32748
# NOSYM-NEXT: Initial: 0x80000000
# NOSYM-NEXT: Purpose: Module pointer (GNU extension)
# NOSYM-NEXT: }
# NOSYM-NEXT: ]
# NOSYM-NEXT: Local entries [
# SYM: 0x7000000A MIPS_LOCAL_GOTNO 4
# SYM: 0x70000013 MIPS_GOTSYM 0x3

# NOSYM: 0x7000000A MIPS_LOCAL_GOTNO 2
# NOSYM: 0x70000013 MIPS_GOTSYM 0x1

# CHECK: Primary GOT {
# CHECK-NEXT: Canonical gp value:
# CHECK-NEXT: Reserved entries [
# CHECK: ]

# SYM: Local entries [
# SYM-NEXT: Entry {
# SYM-NEXT: Address:
# SYM-NEXT: Access: -32744
# SYM-NEXT: Initial: 0x20000
# SYM-NEXT: }
# SYM-NEXT: Entry {
# SYM-NEXT: Address:
# SYM-NEXT: Access: -32740
# SYM-NEXT: Initial: 0x20004
# SYM-NEXT: }
# SYM-NEXT: ]

# NOSYM: Local entries [
# NOSYM-NEXT: ]

# SYM-NEXT: Global entries [
# SYM-NEXT: Entry {
# SYM-NEXT: Address:
# SYM-NEXT: Access: -32736
# SYM-NEXT: Initial: 0x0
# SYM-NEXT: Value: 0x0
# SYM-NEXT: Type: None
# SYM-NEXT: Section: Undefined
# SYM-NEXT: Name: bar
# SYM-NEXT: }
# SYM-NEXT: ]

# NOSYM-NEXT: Global entries [
# NOSYM-NEXT: Entry {
# NOSYM-NEXT: Address:
Expand Down Expand Up @@ -93,68 +113,9 @@
# NOSYM-NEXT: Name: sym
# NOSYM-NEXT: }
# NOSYM-NEXT: ]
# NOSYM-NEXT: Number of TLS and multi-GOT entries: 0
# NOSYM-NEXT: }

# SYM: Relocations [
# SYM-NEXT: ]

# SYM: Symbol {
# SYM: Name: bar
# SYM-NEXT: Value: 0x0
# SYM-NEXT: Size: 0
# SYM-NEXT: Binding: Weak
# SYM-NEXT: Type: None
# SYM-NEXT: Other: 0
# SYM-NEXT: Section: Undefined
# SYM-NEXT: }
# SYM-NEXT: ]

# SYM: 0x70000011 MIPS_SYMTABNO 4
# SYM-NEXT: 0x7000000A MIPS_LOCAL_GOTNO 4
# SYM-NEXT: 0x70000013 MIPS_GOTSYM 0x3

# SYM: Primary GOT {
# SYM-NEXT: Canonical gp value:
# SYM-NEXT: Reserved entries [
# SYM-NEXT: Entry {
# SYM-NEXT: Address:
# SYM-NEXT: Access: -32752
# SYM-NEXT: Initial: 0x0
# SYM-NEXT: Purpose: Lazy resolver
# SYM-NEXT: }
# SYM-NEXT: Entry {
# SYM-NEXT: Address:
# SYM-NEXT: Access: -32748
# SYM-NEXT: Initial: 0x80000000
# SYM-NEXT: Purpose: Module pointer (GNU extension)
# SYM-NEXT: }
# SYM-NEXT: ]
# SYM-NEXT: Local entries [
# SYM-NEXT: Entry {
# SYM-NEXT: Address:
# SYM-NEXT: Access: -32744
# SYM-NEXT: Initial: 0x20000
# SYM-NEXT: }
# SYM-NEXT: Entry {
# SYM-NEXT: Address:
# SYM-NEXT: Access: -32740
# SYM-NEXT: Initial: 0x20004
# SYM-NEXT: }
# SYM-NEXT: ]
# SYM-NEXT: Global entries [
# SYM-NEXT: Entry {
# SYM-NEXT: Address:
# SYM-NEXT: Access: -32736
# SYM-NEXT: Initial: 0x0
# SYM-NEXT: Value: 0x0
# SYM-NEXT: Type: None
# SYM-NEXT: Section: Undefined
# SYM-NEXT: Name: bar
# SYM-NEXT: }
# SYM-NEXT: ]
# SYM-NEXT: Number of TLS and multi-GOT entries: 0
# SYM-NEXT: }

# CHECK: Number of TLS and multi-GOT entries: 0
# CHECK-NEXT: }

.text
.global sym
Expand Down
129 changes: 129 additions & 0 deletions lld/test/ELF/mips-mgot.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Check MIPS multi-GOT layout.

# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t0.o
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
# RUN: %p/Inputs/mips-mgot-1.s -o %t1.o
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
# RUN: %p/Inputs/mips-mgot-2.s -o %t2.o
# RUN: ld.lld -shared -mips-got-size 52 %t0.o %t1.o %t2.o -o %t.so
# RUN: llvm-objdump -s -section=.got -t %t.so | FileCheck %s
# RUN: llvm-readobj -r -dt -mips-plt-got %t.so | FileCheck -check-prefix=GOT %s

# REQUIRES: mips

# CHECK: Contents of section .got:
# CHECK-NEXT: 60000 00000000 80000000 00010000 00010030
# CHECK-NEXT: 60010 00020000 00030000 00040000 00050000
# CHECK-NEXT: 60020 00060000 00070000 00000000 00000000
# CHECK-NEXT: 60030 00000004 00000000 00000000 00000000
# CHECK-NEXT: 60040 00000000 00020000 00030000 00040000
# CHECK-NEXT: 60050 00050000 00060000 00070000 00000000
# CHECK-NEXT: 60060 00000000 00000000 00000000 00000000

# CHECK: SYMBOL TABLE:
# CHECK: 00000000 l .tdata 00000000 loc0
# CHECK: 00010000 .text 00000000 foo0
# CHECK: 00000000 g .tdata 00000000 tls0
# CHECK: 00010020 .text 00000000 foo1
# CHECK: 00000004 g .tdata 00000000 tls1
# CHECK: 00010030 .text 00000000 foo2
# CHECK: 00000008 g .tdata 00000000 tls2

# GOT: Relocations [
# GOT-NEXT: Section (7) .rel.dyn {
# GOT-NEXT: 0x60010 R_MIPS_REL32 - 0x0
# GOT-NEXT: 0x60014 R_MIPS_REL32 - 0x0
# GOT-NEXT: 0x60018 R_MIPS_REL32 - 0x0
# GOT-NEXT: 0x6001C R_MIPS_REL32 - 0x0
# GOT-NEXT: 0x60020 R_MIPS_REL32 - 0x0
# GOT-NEXT: 0x60024 R_MIPS_REL32 - 0x0
# GOT-NEXT: 0x60044 R_MIPS_REL32 - 0x0
# GOT-NEXT: 0x60048 R_MIPS_REL32 - 0x0
# GOT-NEXT: 0x6004C R_MIPS_REL32 - 0x0
# GOT-NEXT: 0x60050 R_MIPS_REL32 - 0x0
# GOT-NEXT: 0x60054 R_MIPS_REL32 - 0x0
# GOT-NEXT: 0x60058 R_MIPS_REL32 - 0x0
# GOT-NEXT: 0x60028 R_MIPS_REL32 foo0 0x0
# GOT-NEXT: 0x6005C R_MIPS_REL32 foo0 0x0
# GOT-NEXT: 0x60060 R_MIPS_REL32 foo2 0x0
# GOT-NEXT: 0x6003C R_MIPS_TLS_DTPMOD32 - 0x0
# GOT-NEXT: 0x60030 R_MIPS_TLS_TPREL32 tls1 0x0
# GOT-NEXT: 0x6002C R_MIPS_TLS_TPREL32 tls0 0x0
# GOT-NEXT: 0x60034 R_MIPS_TLS_DTPMOD32 tls0 0x0
# GOT-NEXT: 0x60038 R_MIPS_TLS_DTPREL32 tls0 0x0
# GOT-NEXT: 0x60064 R_MIPS_TLS_TPREL32 tls0 0x0
# GOT-NEXT: 0x60068 R_MIPS_TLS_DTPMOD32 tls0 0x0
# GOT-NEXT: 0x6006C R_MIPS_TLS_DTPREL32 tls0 0x0
# GOT-NEXT: }
# GOT-NEXT: ]

# GOT: DynamicSymbols [
# GOT: Symbol {
# GOT: Name: foo0
# GOT-NEXT: Value: 0x10000
# GOT: }
# GOT-NEXT: Symbol {
# GOT-NEXT: Name: foo2
# GOT-NEXT: Value: 0x10030
# GOT: }
# GOT-NEXT: ]

# GOT: Primary GOT {
# GOT-NEXT: Canonical gp value: 0x67FF0
# GOT-NEXT: Reserved entries [
# GOT-NEXT: Entry {
# GOT-NEXT: Address:
# GOT-NEXT: Access: -32752
# GOT-NEXT: Initial: 0x0
# GOT-NEXT: Purpose: Lazy resolver
# GOT-NEXT: }
# GOT-NEXT: Entry {
# GOT-NEXT: Address:
# GOT-NEXT: Access: -32748
# GOT-NEXT: Initial: 0x80000000
# GOT-NEXT: Purpose: Module pointer (GNU extension)
# GOT-NEXT: }
# GOT-NEXT: ]
# GOT-NEXT: Local entries [
# GOT-NEXT: ]
# GOT-NEXT: Global entries [
# GOT-NEXT: Entry {
# GOT-NEXT: Address:
# GOT-NEXT: Access: -32744
# GOT-NEXT: Initial: 0x10000
# GOT-NEXT: Value: 0x10000
# GOT-NEXT: Type: None
# GOT-NEXT: Section: .text
# GOT-NEXT: Name: foo0
# GOT-NEXT: }
# GOT-NEXT: Entry {
# GOT-NEXT: Address:
# GOT-NEXT: Access: -32740
# GOT-NEXT: Initial: 0x10030
# GOT-NEXT: Value: 0x10030
# GOT-NEXT: Type: None
# GOT-NEXT: Section: .text
# GOT-NEXT: Name: foo2
# GOT-NEXT: }
# GOT-NEXT: ]
# GOT-NEXT: Number of TLS and multi-GOT entries: 24
# GOT-NEXT: }

.text
.global foo0
foo0:
lw $2, %got(.data)($gp) # page entry
addi $2, $2, %lo(.data)
lw $2, %call16(foo0)($gp) # global entry
addiu $2, $2, %tlsgd(tls0) # tls gd entry
addiu $2, $2, %gottprel(tls0) # tls got entry
addiu $2, $2, %tlsldm(loc0) # tls ld entry

.data
.space 0x20000

.section .tdata,"awT",%progbits
.global tls0
tls0:
loc0:
.word 0
8 changes: 4 additions & 4 deletions lld/test/ELF/mips-plt-copy.s
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@

# CHECK: Relocations [
# CHECK-NEXT: Section ({{.*}}) .rel.dyn {
# CHECK-NEXT: 0x{{[0-9A-F]+}} R_MIPS_COPY data0 0x0
# CHECK-NEXT: 0x{{[0-9A-F]+}} R_MIPS_COPY data1 0x0
# CHECK-DAG: 0x{{[0-9A-F]+}} R_MIPS_COPY data0 0x0
# CHECK-DAG: 0x{{[0-9A-F]+}} R_MIPS_COPY data1 0x0
# CHECK-NEXT: }
# CHECK-NEXT: Section ({{.*}}) .rel.plt {
# CHECK-NEXT: 0x{{[0-9A-F]+}} R_MIPS_JUMP_SLOT foo0 0x0
# CHECK-NEXT: 0x{{[0-9A-F]+}} R_MIPS_JUMP_SLOT foo1 0x0
# CHECK-DAG: 0x{{[0-9A-F]+}} R_MIPS_JUMP_SLOT foo0 0x0
# CHECK-DAG: 0x{{[0-9A-F]+}} R_MIPS_JUMP_SLOT foo1 0x0
# CHECK-NEXT: }
# CHECK-NEXT: ]

Expand Down
18 changes: 9 additions & 9 deletions lld/test/ELF/mips-sto-plt.s
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,23 @@
# REQUIRES: mips

# CHECK: Symbol {
# CHECK: Name: foo0@
# CHECK-NEXT: Value: 0x0
# CHECK: Name: foo1@
# CHECK-NEXT: Value: 0x[[FOO1:[0-9A-F]+]]
# CHECK-NEXT: Size: 0
# CHECK-NEXT: Binding: Global
# CHECK-NEXT: Type: Function
# CHECK-NEXT: Other: 0
# CHECK-NEXT: Other [ (0x8)
# CHECK-NEXT: STO_MIPS_PLT
# CHECK-NEXT: ]
# CHECK-NEXT: Section: Undefined
# CHECK-NEXT: }
# CHECK: Symbol {
# CHECK: Name: foo1@
# CHECK-NEXT: Value: 0x20050
# CHECK: Name: foo0@
# CHECK-NEXT: Value: 0x0
# CHECK-NEXT: Size: 0
# CHECK-NEXT: Binding: Global
# CHECK-NEXT: Type: Function
# CHECK-NEXT: Other [ (0x8)
# CHECK-NEXT: STO_MIPS_PLT
# CHECK-NEXT: ]
# CHECK-NEXT: Other: 0
# CHECK-NEXT: Section: Undefined
# CHECK-NEXT: }

Expand All @@ -48,7 +48,7 @@
# CHECK-NEXT: Entry {
# CHECK-NEXT: Address:
# CHECK-NEXT: Initial:
# CHECK-NEXT: Value: 0x20050
# CHECK-NEXT: Value: 0x[[FOO1]]
# CHECK-NEXT: Type: Function
# CHECK-NEXT: Section: Undefined
# CHECK-NEXT: Name: foo1
Expand Down
72 changes: 36 additions & 36 deletions lld/test/ELF/mips-tls-64.s
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,28 @@
# REQUIRES: mips

# DIS: __start:
# DIS-NEXT: 20000: 24 62 80 20 addiu $2, $3, -32736
# DIS-NEXT: 20004: 24 62 80 30 addiu $2, $3, -32720
# DIS-NEXT: 20008: 24 62 80 38 addiu $2, $3, -32712
# DIS-NEXT: 2000c: 24 62 80 48 addiu $2, $3, -32696
# DIS-NEXT: 20010: 24 62 80 58 addiu $2, $3, -32680
# DIS-NEXT: 20000: 24 62 80 30 addiu $2, $3, -32720
# DIS-NEXT: 20004: 24 62 80 20 addiu $2, $3, -32736
# DIS-NEXT: 20008: 24 62 80 40 addiu $2, $3, -32704
# DIS-NEXT: 2000c: 24 62 80 50 addiu $2, $3, -32688
# DIS-NEXT: 20010: 24 62 80 28 addiu $2, $3, -32728

# DIS: Contents of section .got:
# DIS-NEXT: 30010 00000000 00000000 80000000 00000000
# DIS-NEXT: 30020 00000000 00000000 00000000 00000000
# DIS-NEXT: 30030 00000000 00000000 00000000 00000001
# DIS-NEXT: 30040 00000000 00000000 00000000 00000001
# DIS-NEXT: 30050 ffffffff ffff8004 ffffffff ffff9004
# DIS-NEXT: 30020 00000000 00000000 ffffffff ffff9004
# DIS-NEXT: 30030 00000000 00000000 00000000 00000000
# DIS-NEXT: 30040 00000000 00000001 00000000 00000000
# DIS-NEXT: 30050 00000000 00000001 ffffffff ffff8004

# DIS: 0000000000000000 l .tdata 00000000 loc
# DIS: 0000000000000004 g .tdata 00000000 bar
# DIS: 0000000000000000 g *UND* 00000000 foo

# CHECK: Relocations [
# CHECK-NEXT: Section (7) .rel.dyn {
# CHECK-NEXT: 0x30020 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
# CHECK-NEXT: 0x30028 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
# CHECK-NEXT: 0x30030 R_MIPS_TLS_TPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
# CHECK-NEXT: 0x30020 R_MIPS_TLS_TPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
# CHECK-NEXT: 0x30030 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
# CHECK-NEXT: 0x30038 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: Primary GOT {
Expand All @@ -49,31 +49,31 @@
# CHECK-NEXT: Global entries [
# CHECK-NEXT: ]
# CHECK-NEXT: Number of TLS and multi-GOT entries: 8
# ^-- -32736 R_MIPS_TLS_GD R_MIPS_TLS_DTPMOD64 foo
# ^-- -32728 R_MIPS_TLS_DTPREL64 foo
# ^-- -32720 R_MIPS_TLS_GOTTPREL R_MIPS_TLS_TPREL64 foo
# ^-- -32712 R_MIPS_TLS_LDM 1 loc
# ^-- -32704 0 loc
# ^-- -32696 R_MIPS_TLS_GD 1 bar
# ^-- -32688 VA - 0x8000 bar
# ^-- -32680 R_MIPS_TLS_GOTTPREL VA - 0x7000 bar
# ^-- -32736 R_MIPS_TLS_GOTTPREL R_MIPS_TLS_TPREL64 foo
# ^-- -32728 R_MIPS_TLS_GOTTPREL VA - 0x7000 bar
# ^-- -32720 R_MIPS_TLS_GD R_MIPS_TLS_DTPMOD64 foo
# ^-- -32712 R_MIPS_TLS_DTPREL64 foo
# ^-- -32704 R_MIPS_TLS_LDM 1 loc
# ^-- -32696 0 loc
# ^-- -32688 R_MIPS_TLS_GD 1 bar
# ^-- -32680 VA - 0x8000 bar

# DIS-SO: Contents of section .got:
# DIS-SO-NEXT: 20000 00000000 00000000 80000000 00000000
# DIS-SO-NEXT: 20010 00000000 00000000 00000000 00000000
# DIS-SO-NEXT: 20010 00000000 00000000 00000000 00000004
# DIS-SO-NEXT: 20020 00000000 00000000 00000000 00000000
# DIS-SO-NEXT: 20030 00000000 00000000 00000000 00000000
# DIS-SO-NEXT: 20040 00000000 00000000 00000000 00000000

# SO: Relocations [
# SO-NEXT: Section (7) .rel.dyn {
# SO-NEXT: 0x20028 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE - 0x0
# SO-NEXT: 0x20038 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# SO-NEXT: 0x20040 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# SO-NEXT: 0x20048 R_MIPS_TLS_TPREL64/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# SO-NEXT: 0x20010 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
# SO-NEXT: 0x20018 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
# SO-NEXT: 0x20020 R_MIPS_TLS_TPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
# SO-NEXT: 0x20030 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE - 0x0
# SO-NEXT: 0x20010 R_MIPS_TLS_TPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
# SO-NEXT: 0x20020 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
# SO-NEXT: 0x20028 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
# SO-NEXT: 0x20018 R_MIPS_TLS_TPREL64/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# SO-NEXT: 0x20040 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# SO-NEXT: 0x20048 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# SO-NEXT: }
# SO-NEXT: ]
# SO-NEXT: Primary GOT {
Expand All @@ -85,14 +85,14 @@
# SO-NEXT: Global entries [
# SO-NEXT: ]
# SO-NEXT: Number of TLS and multi-GOT entries: 8
# ^-- -32736 R_MIPS_TLS_GD R_MIPS_TLS_DTPMOD64 foo
# ^-- -32728 R_MIPS_TLS_DTPREL64 foo
# ^-- -32720 R_MIPS_TLS_GOTTPREL R_MIPS_TLS_TPREL64 foo
# ^-- -32712 R_MIPS_TLS_LDM R_MIPS_TLS_DTPMOD64 loc
# ^-- -32704 0 loc
# ^-- -32696 R_MIPS_TLS_GD R_MIPS_TLS_DTPMOD64 bar
# ^-- -32688 R_MIPS_TLS_DTPREL64 bar
# ^-- -32680 R_MIPS_TLS_GOTTPREL R_MIPS_TLS_TPREL64 bar
# ^-- -32736 R_MIPS_TLS_GOTTPREL R_MIPS_TLS_TPREL64 foo
# ^-- -32728 R_MIPS_TLS_GOTTPREL R_MIPS_TLS_TPREL64 bar
# ^-- -32720 R_MIPS_TLS_GD R_MIPS_TLS_DTPMOD64 foo
# ^-- -32712 R_MIPS_TLS_DTPREL64 foo
# ^-- -32704 R_MIPS_TLS_LDM R_MIPS_TLS_DTPMOD64 loc
# ^-- -32696 0 loc
# ^-- -32688 R_MIPS_TLS_GD R_MIPS_TLS_DTPMOD64 bar
# ^-- -32680 R_MIPS_TLS_DTPREL64 bar

.text
.global __start
Expand Down
4 changes: 2 additions & 2 deletions lld/test/ELF/mips-tls-static.s
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
# CHECK: Contents of section .data:
# CHECK-NEXT: 30000 0002000c ffff8004 ffff9004
# CHECK: Contents of section .got:
# CHECK-NEXT: 30010 00000000 80000000 00000001 ffff8000
# CHECK-NEXT: 30020 00000001 00000000 ffff9000
# CHECK-NEXT: 30010 00000000 80000000 ffff9000 00000001
# CHECK-NEXT: 30020 ffff8000 00000001 00000000
#
# CHECK: SYMBOL TABLE:
# CHECK: 0002000c .text 00000000 __tls_get_addr
Expand Down
70 changes: 35 additions & 35 deletions lld/test/ELF/mips-tls.s
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,26 @@
# REQUIRES: mips

# DIS: __start:
# DIS-NEXT: 20000: 24 62 80 18 addiu $2, $3, -32744
# DIS-NEXT: 20004: 24 62 80 20 addiu $2, $3, -32736
# DIS-NEXT: 20008: 24 62 80 24 addiu $2, $3, -32732
# DIS-NEXT: 2000c: 24 62 80 2c addiu $2, $3, -32724
# DIS-NEXT: 20010: 24 62 80 34 addiu $2, $3, -32716
# DIS-NEXT: 20000: 24 62 80 20 addiu $2, $3, -32736
# DIS-NEXT: 20004: 24 62 80 18 addiu $2, $3, -32744
# DIS-NEXT: 20008: 24 62 80 28 addiu $2, $3, -32728
# DIS-NEXT: 2000c: 24 62 80 30 addiu $2, $3, -32720
# DIS-NEXT: 20010: 24 62 80 1c addiu $2, $3, -32740

# DIS: Contents of section .got:
# DIS-NEXT: 30010 00000000 80000000 00000000 00000000
# DIS-NEXT: 30020 00000000 00000001 00000000 00000001
# DIS-NEXT: 30030 ffff8004 ffff9004
# DIS-NEXT: 30010 00000000 80000000 00000000 ffff9004
# DIS-NEXT: 30020 00000000 00000000 00000001 00000000
# DIS-NEXT: 30030 00000001 ffff8004

# DIS: 00000000 l .tdata 00000000 loc
# DIS: 00000004 g .tdata 00000000 bar
# DIS: 00000000 g *UND* 00000000 foo

# CHECK: Relocations [
# CHECK-NEXT: Section (7) .rel.dyn {
# CHECK-NEXT: 0x30018 R_MIPS_TLS_DTPMOD32 foo 0x0
# CHECK-NEXT: 0x3001C R_MIPS_TLS_DTPREL32 foo 0x0
# CHECK-NEXT: 0x30020 R_MIPS_TLS_TPREL32 foo 0x0
# CHECK-NEXT: 0x30018 R_MIPS_TLS_TPREL32 foo 0x0
# CHECK-NEXT: 0x30020 R_MIPS_TLS_DTPMOD32 foo 0x0
# CHECK-NEXT: 0x30024 R_MIPS_TLS_DTPREL32 foo 0x0
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: Primary GOT {
Expand All @@ -47,29 +47,29 @@
# CHECK-NEXT: Global entries [
# CHECK-NEXT: ]
# CHECK-NEXT: Number of TLS and multi-GOT entries: 8
# ^-- -32744 R_MIPS_TLS_GD R_MIPS_TLS_DTPMOD32 foo
# ^-- -32740 R_MIPS_TLS_DTPREL32 foo
# ^-- -32736 R_MIPS_TLS_GOTTPREL R_MIPS_TLS_TPREL32 foo
# ^-- -32732 R_MIPS_TLS_LDM 1 loc
# ^-- -32728 0 loc
# ^-- -32724 R_MIPS_TLS_GD 1 bar
# ^-- -32720 VA - 0x8000 bar
# ^-- -32716 R_MIPS_TLS_GOTTPREL VA - 0x7000 bar
# ^-- -32744 R_MIPS_TLS_GOTTPREL R_MIPS_TLS_TPREL32 foo
# ^-- -32740 R_MIPS_TLS_GOTTPREL VA - 0x7000 bar
# ^-- -32736 R_MIPS_TLS_GD R_MIPS_TLS_DTPMOD32 foo
# ^-- -32732 R_MIPS_TLS_DTPREL32 foo
# ^-- -32728 R_MIPS_TLS_LDM 1 loc
# ^-- -32724 0 loc
# ^-- -32720 R_MIPS_TLS_GD 1 bar
# ^-- -32716 VA - 0x8000 bar

# DIS-SO: Contents of section .got:
# DIS-SO-NEXT: 20000 00000000 80000000 00000000 00000000
# DIS-SO-NEXT: 20000 00000000 80000000 00000000 00000004
# DIS-SO-NEXT: 20010 00000000 00000000 00000000 00000000
# DIS-SO-NEXT: 20020 00000000 00000000

# SO: Relocations [
# SO-NEXT: Section (7) .rel.dyn {
# SO-NEXT: 0x20014 R_MIPS_TLS_DTPMOD32 - 0x0
# SO-NEXT: 0x2001C R_MIPS_TLS_DTPMOD32 bar 0x0
# SO-NEXT: 0x20020 R_MIPS_TLS_DTPREL32 bar 0x0
# SO-NEXT: 0x20024 R_MIPS_TLS_TPREL32 bar 0x0
# SO-NEXT: 0x20008 R_MIPS_TLS_DTPMOD32 foo 0x0
# SO-NEXT: 0x2000C R_MIPS_TLS_DTPREL32 foo 0x0
# SO-NEXT: 0x20010 R_MIPS_TLS_TPREL32 foo 0x0
# SO-NEXT: 0x20018 R_MIPS_TLS_DTPMOD32 - 0x0
# SO-NEXT: 0x20008 R_MIPS_TLS_TPREL32 foo 0x0
# SO-NEXT: 0x20010 R_MIPS_TLS_DTPMOD32 foo 0x0
# SO-NEXT: 0x20014 R_MIPS_TLS_DTPREL32 foo 0x0
# SO-NEXT: 0x2000C R_MIPS_TLS_TPREL32 bar 0x0
# SO-NEXT: 0x20020 R_MIPS_TLS_DTPMOD32 bar 0x0
# SO-NEXT: 0x20024 R_MIPS_TLS_DTPREL32 bar 0x0
# SO-NEXT: }
# SO-NEXT: ]
# SO-NEXT: Primary GOT {
Expand All @@ -81,14 +81,14 @@
# SO-NEXT: Global entries [
# SO-NEXT: ]
# SO-NEXT: Number of TLS and multi-GOT entries: 8
# ^-- -32744 R_MIPS_TLS_GD R_MIPS_TLS_DTPMOD32 foo
# ^-- -32740 R_MIPS_TLS_DTPREL32 foo
# ^-- -32736 R_MIPS_TLS_GOTTPREL R_MIPS_TLS_TPREL32 foo
# ^-- -32732 R_MIPS_TLS_LDM R_MIPS_TLS_DTPMOD32 loc
# ^-- -32728 0 loc
# ^-- -32724 R_MIPS_TLS_GD R_MIPS_TLS_DTPMOD32 bar
# ^-- -32720 R_MIPS_TLS_DTPREL32 bar
# ^-- -32716 R_MIPS_TLS_GOTTPREL R_MIPS_TLS_TPREL32 bar
# ^-- -32744 R_MIPS_TLS_GOTTPREL R_MIPS_TLS_TPREL32 foo
# ^-- -32740 R_MIPS_TLS_GOTTPREL R_MIPS_TLS_TPREL32 bar
# ^-- -32736 R_MIPS_TLS_GD R_MIPS_TLS_DTPMOD32 foo
# ^-- -32732 R_MIPS_TLS_DTPREL32 foo
# ^-- -32728 R_MIPS_TLS_LDM R_MIPS_TLS_DTPMOD32 loc
# ^-- -32724 0 loc
# ^-- -32720 R_MIPS_TLS_GD R_MIPS_TLS_DTPMOD32 bar
# ^-- -32716 R_MIPS_TLS_DTPREL32 bar

.text
.global __start
Expand Down