From 9fae3b8a2c0c6a57cfa6b588a96f0dbcb21bd5e3 Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Tue, 29 Nov 2016 10:23:56 +0000 Subject: [PATCH] [ELF][MIPS] Do not change MipsGotSection state in the getPageEntryOffset method The MipsGotSection::getPageEntryOffset calculates index of GOT entry with a "page" address. Previously this method changes the state of MipsGotSection because it modifies PageIndexMap field. That leads to the unpredictable results if getPageEntryOffset called from multiple threads. The patch makes getPageEntryOffset constant. To do so it calculates GOT entry index but does not update PageIndexMap field. Later in the MipsGotSection::writeTo method linker calculates "page" addresses and writes them to the output. llvm-svn: 288129 --- lld/ELF/InputSection.cpp | 2 +- lld/ELF/SyntheticSections.cpp | 63 ++++++++++++++++++++++----------------- lld/ELF/SyntheticSections.h | 9 +++--- lld/test/ELF/mips-64-got.s | 2 +- lld/test/ELF/mips-got-redundant.s | 2 +- lld/test/ELF/mips-got16.s | 26 ++++++++-------- lld/test/ELF/mips-xgot-order.s | 2 +- 7 files changed, 57 insertions(+), 49 deletions(-) diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index e3eb422..2fcb39b 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -423,7 +423,7 @@ static typename ELFT::uint getSymVA(uint32_t Type, typename ELFT::uint A, // should be initialized by 'page address'. This address is high 16-bits // of sum the symbol's value and the addend. return In::MipsGot->getVA() + - In::MipsGot->getPageEntryOffset(Body.getVA(A)) - + In::MipsGot->getPageEntryOffset(Body, A) - In::MipsGot->getGp(); case R_MIPS_GOT_OFF: case R_MIPS_GOT_OFF32: diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 91d721a..f54892d 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -470,8 +470,7 @@ void MipsGotSection::addEntry(SymbolBody &Sym, uintX_t Addend, // sections referenced by GOT relocations. Then later in the `finalize` // method calculate number of "pages" required to cover all saved output // section and allocate appropriate number of GOT entries. - auto *OutSec = cast>(&Sym)->Section->OutSec; - OutSections.insert(OutSec); + PageIndexMap.insert({cast>(&Sym)->Section->OutSec, 0}); return; } if (Sym.isTls()) { @@ -528,18 +527,25 @@ template bool MipsGotSection::addTlsIndex() { return true; } +static uint64_t getMipsPageAddr(uint64_t Addr) { + return (Addr + 0x8000) & ~0xffff; +} + +static uint64_t getMipsPageCount(uint64_t Size) { + return (Size + 0xfffe) / 0xffff + 1; +} + template typename MipsGotSection::uintX_t -MipsGotSection::getPageEntryOffset(uintX_t EntryValue) { - // Initialize the entry by the %hi(EntryValue) expression - // but without right-shifting. - EntryValue = (EntryValue + 0x8000) & ~0xffff; - // Take into account MIPS GOT header. - // See comment in the MipsGotSection::writeTo. - size_t NewIndex = PageIndexMap.size(); - auto P = PageIndexMap.insert(std::make_pair(EntryValue, NewIndex)); - assert(!P.second || PageIndexMap.size() <= PageEntriesNum); - return (HeaderEntriesNum + P.first->second) * sizeof(uintX_t); +MipsGotSection::getPageEntryOffset(const SymbolBody &B, + uintX_t Addend) const { + const OutputSectionBase *OutSec = + cast>(&B)->Section->OutSec; + uintX_t SecAddr = getMipsPageAddr(OutSec->Addr); + uintX_t SymAddr = getMipsPageAddr(B.getVA(Addend)); + uintX_t Index = PageIndexMap.lookup(OutSec) + (SymAddr - SecAddr) / 0xffff; + assert(Index < PageEntriesNum); + return (HeaderEntriesNum + Index) * sizeof(uintX_t); } template @@ -589,20 +595,19 @@ unsigned MipsGotSection::getLocalEntriesNum() const { } template void MipsGotSection::finalize() { - size_t EntriesNum = TlsEntries.size(); - // Take into account MIPS GOT header. - // See comment in the MipsGotSection::writeTo. PageEntriesNum = 0; - for (const OutputSectionBase *OutSec : OutSections) { - // Calculate an upper bound of MIPS GOT entries required to store page - // addresses of local symbols. We assume the worst case - each 64kb - // page of the output section has at least one GOT relocation against it. - // Add 0x8000 to the section's size because the page address stored - // in the GOT entry is calculated as (value + 0x8000) & ~0xffff. - PageEntriesNum += (OutSec->Size + 0xfffe) / 0xffff + 1; + for (std::pair &P : PageIndexMap) { + // For each output section referenced by GOT page relocations calculate + // and save into PageIndexMap an upper bound of MIPS GOT entries required + // to store page addresses of local symbols. We assume the worst case - + // each 64kb page of the output section has at least one GOT relocation + // against it. And take in account the case when the section intersects + // page boundaries. + P.second = PageEntriesNum; + PageEntriesNum += getMipsPageCount(P.first->Size); } - EntriesNum += getLocalEntriesNum() + GlobalEntries.size(); - Size = EntriesNum * sizeof(uintX_t); + Size = (getLocalEntriesNum() + GlobalEntries.size() + TlsEntries.size()) * + sizeof(uintX_t); } template bool MipsGotSection::empty() const { @@ -640,9 +645,13 @@ template void MipsGotSection::writeTo(uint8_t *Buf) { P[1] = uintX_t(1) << (ELFT::Is64Bits ? 63 : 31); Buf += HeaderEntriesNum * sizeof(uintX_t); // Write 'page address' entries to the local part of the GOT. - for (std::pair &L : PageIndexMap) { - uint8_t *Entry = Buf + L.second * sizeof(uintX_t); - writeUint(Entry, L.first); + for (std::pair &L : PageIndexMap) { + size_t PageCount = getMipsPageCount(L.first->Size); + uintX_t FirstPageAddr = getMipsPageAddr(L.first->Addr); + for (size_t PI = 0; PI < PageCount; ++PI) { + uint8_t *Entry = Buf + (L.second + PI) * sizeof(uintX_t); + writeUint(Entry, FirstPageAddr + PI * 0x10000); + } } Buf += PageEntriesNum * sizeof(uintX_t); auto AddEntry = [&](const GotEntry &SA) { diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index e38f90c..9434c8d 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -104,7 +104,7 @@ public: void addEntry(SymbolBody &Sym, uintX_t Addend, RelExpr Expr); bool addDynTlsEntry(SymbolBody &Sym); bool addTlsIndex(); - uintX_t getPageEntryOffset(uintX_t Addr); + uintX_t getPageEntryOffset(const SymbolBody &B, uintX_t Addend) const; uintX_t getBodyEntryOffset(const SymbolBody &B, uintX_t Addend) const; uintX_t getGlobalDynOffset(const SymbolBody &B) const; @@ -168,10 +168,9 @@ private: static const unsigned HeaderEntriesNum = 2; // Number of allocated "Page" entries. uint32_t PageEntriesNum = 0; - // Output sections referenced by MIPS GOT relocations. - llvm::SmallPtrSet OutSections; - // Map from "page" address to the GOT index. - llvm::DenseMap PageIndexMap; + // Map output sections referenced by MIPS GOT relocations + // to the first index of "Page" entries allocated for this section. + llvm::SmallDenseMap PageIndexMap; typedef std::pair GotEntry; typedef std::vector GotEntries; diff --git a/lld/test/ELF/mips-64-got.s b/lld/test/ELF/mips-64-got.s index 27603c5..b120abb 100644 --- a/lld/test/ELF/mips-64-got.s +++ b/lld/test/ELF/mips-64-got.s @@ -50,7 +50,7 @@ # GOT-NEXT: Entry { # GOT-NEXT: Address: 0x30018 # GOT-NEXT: Access: -32728 -# GOT-NEXT: Initial: 0x0 +# GOT-NEXT: Initial: 0x30000 # GOT-NEXT: } # GOT-NEXT: Entry { # GOT-NEXT: Address: 0x30020 diff --git a/lld/test/ELF/mips-got-redundant.s b/lld/test/ELF/mips-got-redundant.s index 015da59..115a49f 100644 --- a/lld/test/ELF/mips-got-redundant.s +++ b/lld/test/ELF/mips-got-redundant.s @@ -22,7 +22,7 @@ # CHECK-NEXT: Entry { # CHECK-NEXT: Address: 0x20010 # CHECK-NEXT: Access: -32736 -# CHECK-NEXT: Initial: 0x0 +# CHECK-NEXT: Initial: 0x50000 # ^-- redundant # CHECK-NEXT: } # CHECK-NEXT: Entry { diff --git a/lld/test/ELF/mips-got16.s b/lld/test/ELF/mips-got16.s index d7bf44f..c4c14e4 100644 --- a/lld/test/ELF/mips-got16.s +++ b/lld/test/ELF/mips-got16.s @@ -11,11 +11,11 @@ # CHECK-NEXT: __start: # CHECK-NEXT: 10000: 8f 88 80 18 lw $8, -32744($gp) # CHECK-NEXT: 10004: 21 08 00 2c addi $8, $8, 44 -# CHECK-NEXT: 10008: 8f 88 80 1c lw $8, -32740($gp) +# CHECK-NEXT: 10008: 8f 88 80 24 lw $8, -32732($gp) # CHECK-NEXT: 1000c: 21 08 90 00 addi $8, $8, -28672 -# CHECK-NEXT: 10010: 8f 88 80 20 lw $8, -32736($gp) +# CHECK-NEXT: 10010: 8f 88 80 28 lw $8, -32728($gp) # CHECK-NEXT: 10014: 21 08 90 04 addi $8, $8, -28668 -# CHECK-NEXT: 10018: 8f 88 80 20 lw $8, -32736($gp) +# CHECK-NEXT: 10018: 8f 88 80 28 lw $8, -32728($gp) # CHECK-NEXT: 1001c: 21 08 10 04 addi $8, $8, 4100 # CHECK-NEXT: 10020: 8f 88 80 30 lw $8, -32720($gp) # CHECK-NEXT: 10024: 21 08 10 08 addi $8, $8, 4104 @@ -54,32 +54,32 @@ # GOT-NEXT: Entry { # GOT-NEXT: Address: 0x2000C # GOT-NEXT: Access: -32740 -# GOT-NEXT: Initial: 0x40000 -# ^-- (0x39000 + 0x8000) & ~0xffff +# GOT-NEXT: Initial: 0x20000 +# ^-- redundant unused entry # GOT-NEXT: } # GOT-NEXT: Entry { # GOT-NEXT: Address: 0x20010 # GOT-NEXT: Access: -32736 -# GOT-NEXT: Initial: 0x50000 -# ^-- (0x39000 + 0x10004 + 0x8000) & ~0xffff -# ^-- (0x39000 + 0x18004 + 0x8000) & ~0xffff +# GOT-NEXT: Initial: 0x30000 +# ^-- redundant unused entry # GOT-NEXT: } # GOT-NEXT: Entry { # GOT-NEXT: Address: 0x20014 # GOT-NEXT: Access: -32732 -# GOT-NEXT: Initial: 0x0 -# ^-- redundant unused entry +# GOT-NEXT: Initial: 0x40000 +# ^-- (0x39000 + 0x8000) & ~0xffff # GOT-NEXT: } # GOT-NEXT: Entry { # GOT-NEXT: Address: 0x20018 # GOT-NEXT: Access: -32728 -# GOT-NEXT: Initial: 0x0 -# ^-- redundant unused entry +# GOT-NEXT: Initial: 0x50000 +# ^-- (0x39000 + 0x10004 + 0x8000) & ~0xffff +# ^-- (0x39000 + 0x18004 + 0x8000) & ~0xffff # GOT-NEXT: } # GOT-NEXT: Entry { # GOT-NEXT: Address: 0x2001C # GOT-NEXT: Access: -32724 -# GOT-NEXT: Initial: 0x0 +# GOT-NEXT: Initial: 0x60000 # ^-- redundant unused entry # GOT-NEXT: } # GOT-NEXT: Entry { diff --git a/lld/test/ELF/mips-xgot-order.s b/lld/test/ELF/mips-xgot-order.s index 2920c87..d249715 100644 --- a/lld/test/ELF/mips-xgot-order.s +++ b/lld/test/ELF/mips-xgot-order.s @@ -20,7 +20,7 @@ # CHECK-NEXT: 20018: 20 42 00 00 addi $2, $2, 0 # CHECK: Contents of section .got: -# CHECK-NEXT: 30000 00000000 80000000 00040000 00000000 +# CHECK-NEXT: 30000 00000000 80000000 00040000 00050000 # ^ %hi(loc) # ^ redundant entry # CHECK-NEXT: 30010 00020010 00020000 00040000 -- 2.7.4