Index: vendor/lld/dist/COFF/Chunks.cpp =================================================================== --- vendor/lld/dist/COFF/Chunks.cpp (revision 317689) +++ vendor/lld/dist/COFF/Chunks.cpp (revision 317690) @@ -1,394 +1,391 @@ //===- Chunks.cpp ---------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "Chunks.h" #include "Error.h" #include "InputFiles.h" #include "Symbols.h" #include "llvm/ADT/Twine.h" #include "llvm/Object/COFF.h" #include "llvm/Support/COFF.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Endian.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> using namespace llvm; using namespace llvm::object; using namespace llvm::support::endian; using namespace llvm::COFF; using llvm::support::ulittle32_t; namespace lld { namespace coff { SectionChunk::SectionChunk(ObjectFile *F, const coff_section *H) : Chunk(SectionKind), Repl(this), Header(H), File(F), Relocs(File->getCOFFObj()->getRelocations(Header)), NumRelocs(std::distance(Relocs.begin(), Relocs.end())) { // Initialize SectionName. File->getCOFFObj()->getSectionName(Header, SectionName); Align = Header->getAlignment(); // Only COMDAT sections are subject of dead-stripping. Live = !isCOMDAT(); } static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); } static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); } static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); } static void or16(uint8_t *P, uint16_t V) { write16le(P, read16le(P) | V); } void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym, uint64_t P) const { uint64_t S = Sym->getRVA(); switch (Type) { case IMAGE_REL_AMD64_ADDR32: add32(Off, S + Config->ImageBase); break; case IMAGE_REL_AMD64_ADDR64: add64(Off, S + Config->ImageBase); break; case IMAGE_REL_AMD64_ADDR32NB: add32(Off, S); break; case IMAGE_REL_AMD64_REL32: add32(Off, S - P - 4); break; case IMAGE_REL_AMD64_REL32_1: add32(Off, S - P - 5); break; case IMAGE_REL_AMD64_REL32_2: add32(Off, S - P - 6); break; case IMAGE_REL_AMD64_REL32_3: add32(Off, S - P - 7); break; case IMAGE_REL_AMD64_REL32_4: add32(Off, S - P - 8); break; case IMAGE_REL_AMD64_REL32_5: add32(Off, S - P - 9); break; case IMAGE_REL_AMD64_SECTION: add16(Off, Sym->getSectionIndex()); break; case IMAGE_REL_AMD64_SECREL: add32(Off, Sym->getSecrel()); break; default: fatal("unsupported relocation type 0x" + Twine::utohexstr(Type)); } } void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, Defined *Sym, uint64_t P) const { uint64_t S = Sym->getRVA(); switch (Type) { case IMAGE_REL_I386_ABSOLUTE: break; case IMAGE_REL_I386_DIR32: add32(Off, S + Config->ImageBase); break; case IMAGE_REL_I386_DIR32NB: add32(Off, S); break; case IMAGE_REL_I386_REL32: add32(Off, S - P - 4); break; case IMAGE_REL_I386_SECTION: add16(Off, Sym->getSectionIndex()); break; case IMAGE_REL_I386_SECREL: add32(Off, Sym->getSecrel()); break; default: fatal("unsupported relocation type 0x" + Twine::utohexstr(Type)); } } static void applyMOV(uint8_t *Off, uint16_t V) { write16le(Off, (read16le(Off) & 0xfbf0) | ((V & 0x800) >> 1) | ((V >> 12) & 0xf)); write16le(Off + 2, (read16le(Off + 2) & 0x8f00) | ((V & 0x700) << 4) | (V & 0xff)); } static uint16_t readMOV(uint8_t *Off) { uint16_t Opcode1 = read16le(Off); uint16_t Opcode2 = read16le(Off + 2); uint16_t Imm = (Opcode2 & 0x00ff) | ((Opcode2 >> 4) & 0x0700); Imm |= ((Opcode1 << 1) & 0x0800) | ((Opcode1 & 0x000f) << 12); return Imm; } static void applyMOV32T(uint8_t *Off, uint32_t V) { uint16_t ImmW = readMOV(Off); // read MOVW operand uint16_t ImmT = readMOV(Off + 4); // read MOVT operand uint32_t Imm = ImmW | (ImmT << 16); V += Imm; // add the immediate offset applyMOV(Off, V); // set MOVW operand applyMOV(Off + 4, V >> 16); // set MOVT operand } static void applyBranch20T(uint8_t *Off, int32_t V) { uint32_t S = V < 0 ? 1 : 0; uint32_t J1 = (V >> 19) & 1; uint32_t J2 = (V >> 18) & 1; or16(Off, (S << 10) | ((V >> 12) & 0x3f)); or16(Off + 2, (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff)); } static void applyBranch24T(uint8_t *Off, int32_t V) { if (!isInt<25>(V)) fatal("relocation out of range"); uint32_t S = V < 0 ? 1 : 0; uint32_t J1 = ((~V >> 23) & 1) ^ S; uint32_t J2 = ((~V >> 22) & 1) ^ S; or16(Off, (S << 10) | ((V >> 12) & 0x3ff)); // Clear out the J1 and J2 bits which may be set. write16le(Off + 2, (read16le(Off + 2) & 0xd000) | (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff)); } void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, Defined *Sym, uint64_t P) const { uint64_t S = Sym->getRVA(); // Pointer to thumb code must have the LSB set. if (Sym->isExecutable()) S |= 1; switch (Type) { case IMAGE_REL_ARM_ADDR32: add32(Off, S + Config->ImageBase); break; case IMAGE_REL_ARM_ADDR32NB: add32(Off, S); break; case IMAGE_REL_ARM_MOV32T: applyMOV32T(Off, S + Config->ImageBase); break; case IMAGE_REL_ARM_BRANCH20T: applyBranch20T(Off, S - P - 4); break; case IMAGE_REL_ARM_BRANCH24T: applyBranch24T(Off, S - P - 4); break; case IMAGE_REL_ARM_BLX23T: applyBranch24T(Off, S - P - 4); break; case IMAGE_REL_ARM_SECREL: add32(Off, Sym->getSecrel()); break; default: fatal("unsupported relocation type 0x" + Twine::utohexstr(Type)); } } void SectionChunk::writeTo(uint8_t *Buf) const { if (!hasData()) return; // Copy section contents from source object file to output file. ArrayRef<uint8_t> A = getContents(); memcpy(Buf + OutputSectionOff, A.data(), A.size()); // Apply relocations. for (const coff_relocation &Rel : Relocs) { uint8_t *Off = Buf + OutputSectionOff + Rel.VirtualAddress; SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex); Defined *Sym = cast<Defined>(Body); uint64_t P = RVA + Rel.VirtualAddress; switch (Config->Machine) { case AMD64: applyRelX64(Off, Rel.Type, Sym, P); break; case I386: applyRelX86(Off, Rel.Type, Sym, P); break; case ARMNT: applyRelARM(Off, Rel.Type, Sym, P); break; default: llvm_unreachable("unknown machine type"); } } } void SectionChunk::addAssociative(SectionChunk *Child) { AssocChildren.push_back(Child); } static uint8_t getBaserelType(const coff_relocation &Rel) { switch (Config->Machine) { case AMD64: if (Rel.Type == IMAGE_REL_AMD64_ADDR64) return IMAGE_REL_BASED_DIR64; return IMAGE_REL_BASED_ABSOLUTE; case I386: if (Rel.Type == IMAGE_REL_I386_DIR32) return IMAGE_REL_BASED_HIGHLOW; return IMAGE_REL_BASED_ABSOLUTE; case ARMNT: if (Rel.Type == IMAGE_REL_ARM_ADDR32) return IMAGE_REL_BASED_HIGHLOW; if (Rel.Type == IMAGE_REL_ARM_MOV32T) return IMAGE_REL_BASED_ARM_MOV32T; return IMAGE_REL_BASED_ABSOLUTE; default: llvm_unreachable("unknown machine type"); } } // Windows-specific. // Collect all locations that contain absolute addresses, which need to be // fixed by the loader if load-time relocation is needed. // Only called when base relocation is enabled. void SectionChunk::getBaserels(std::vector<Baserel> *Res) { for (const coff_relocation &Rel : Relocs) { uint8_t Ty = getBaserelType(Rel); if (Ty == IMAGE_REL_BASED_ABSOLUTE) continue; SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex); if (isa<DefinedAbsolute>(Body)) continue; Res->emplace_back(RVA + Rel.VirtualAddress, Ty); } } bool SectionChunk::hasData() const { return !(Header->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA); } uint32_t SectionChunk::getPermissions() const { return Header->Characteristics & PermMask; } bool SectionChunk::isCOMDAT() const { return Header->Characteristics & IMAGE_SCN_LNK_COMDAT; } void SectionChunk::printDiscardedMessage() const { // Removed by dead-stripping. If it's removed by ICF, ICF already // printed out the name, so don't repeat that here. if (Sym && this == Repl) message("Discarded " + Sym->getName()); } StringRef SectionChunk::getDebugName() { if (Sym) return Sym->getName(); return ""; } ArrayRef<uint8_t> SectionChunk::getContents() const { ArrayRef<uint8_t> A; File->getCOFFObj()->getSectionContents(Header, A); return A; } void SectionChunk::replace(SectionChunk *Other) { Other->Repl = Repl; Other->Live = false; } CommonChunk::CommonChunk(const COFFSymbolRef S) : Sym(S) { // Common symbols are aligned on natural boundaries up to 32 bytes. // This is what MSVC link.exe does. Align = std::min(uint64_t(32), PowerOf2Ceil(Sym.getValue())); } uint32_t CommonChunk::getPermissions() const { return IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; } void StringChunk::writeTo(uint8_t *Buf) const { memcpy(Buf + OutputSectionOff, Str.data(), Str.size()); } ImportThunkChunkX64::ImportThunkChunkX64(Defined *S) : ImpSymbol(S) { // Intel Optimization Manual says that all branch targets // should be 16-byte aligned. MSVC linker does this too. Align = 16; } void ImportThunkChunkX64::writeTo(uint8_t *Buf) const { memcpy(Buf + OutputSectionOff, ImportThunkX86, sizeof(ImportThunkX86)); // The first two bytes is a JMP instruction. Fill its operand. write32le(Buf + OutputSectionOff + 2, ImpSymbol->getRVA() - RVA - getSize()); } void ImportThunkChunkX86::getBaserels(std::vector<Baserel> *Res) { Res->emplace_back(getRVA() + 2); } void ImportThunkChunkX86::writeTo(uint8_t *Buf) const { memcpy(Buf + OutputSectionOff, ImportThunkX86, sizeof(ImportThunkX86)); // The first two bytes is a JMP instruction. Fill its operand. write32le(Buf + OutputSectionOff + 2, ImpSymbol->getRVA() + Config->ImageBase); } void ImportThunkChunkARM::getBaserels(std::vector<Baserel> *Res) { Res->emplace_back(getRVA(), IMAGE_REL_BASED_ARM_MOV32T); } void ImportThunkChunkARM::writeTo(uint8_t *Buf) const { memcpy(Buf + OutputSectionOff, ImportThunkARM, sizeof(ImportThunkARM)); // Fix mov.w and mov.t operands. applyMOV32T(Buf + OutputSectionOff, ImpSymbol->getRVA() + Config->ImageBase); } void LocalImportChunk::getBaserels(std::vector<Baserel> *Res) { Res->emplace_back(getRVA()); } size_t LocalImportChunk::getSize() const { return Config->is64() ? 8 : 4; } void LocalImportChunk::writeTo(uint8_t *Buf) const { if (Config->is64()) { write64le(Buf + OutputSectionOff, Sym->getRVA() + Config->ImageBase); } else { write32le(Buf + OutputSectionOff, Sym->getRVA() + Config->ImageBase); } } void SEHTableChunk::writeTo(uint8_t *Buf) const { ulittle32_t *Begin = reinterpret_cast<ulittle32_t *>(Buf + OutputSectionOff); size_t Cnt = 0; for (Defined *D : Syms) Begin[Cnt++] = D->getRVA(); std::sort(Begin, Begin + Cnt); } // Windows-specific. This class represents a block in .reloc section. // The format is described here. // // On Windows, each DLL is linked against a fixed base address and // usually loaded to that address. However, if there's already another // DLL that overlaps, the loader has to relocate it. To do that, DLLs // contain .reloc sections which contain offsets that need to be fixed -// up at runtime. If the loader find that a DLL cannot be loaded to its +// up at runtime. If the loader finds that a DLL cannot be loaded to its // desired base address, it loads it to somewhere else, and add <actual // base address> - <desired base address> to each offset that is -// specified by .reloc section. +// specified by the .reloc section. In ELF terms, .reloc sections +// contain relative relocations in REL format (as opposed to RELA.) // -// In ELF terms, .reloc sections contain arrays of relocation offsets. -// All these offsets in the section are implicitly R_*_RELATIVE, and -// addends are read from section contents (so it is REL as opposed to -// RELA). +// This already significantly reduces the size of relocations compared +// to ELF .rel.dyn, but Windows does more to reduce it (probably because +// it was invented for PCs in the late '80s or early '90s.) Offsets in +// .reloc are grouped by page where the page size is 12 bits, and +// offsets sharing the same page address are stored consecutively to +// represent them with less space. This is very similar to the page +// table which is grouped by (multiple stages of) pages. // -// This already reduce the size of relocations to 1/3 compared to ELF -// .dynrel, but Windows does more to reduce it (probably because it was -// invented for PCs in the late '80s or early '90s.) Offsets in .reloc -// are grouped by page where page size is 16 bits, and offsets sharing -// the same page address are stored consecutively to represent them with -// less space. This is a very similar to the page table which is grouped -// by (multiple stages of) pages. +// For example, let's say we have 0x00030, 0x00500, 0x00700, 0x00A00, +// 0x20004, and 0x20008 in a .reloc section for x64. The uppermost 4 +// bits have a type IMAGE_REL_BASED_DIR64 or 0xA. In the section, they +// are represented like this: // -// For example, let's say we have 0x00030, 0x00500, 0x01000, 0x01100, -// 0x20004, and 0x20008 in a .reloc section. In the section, they are -// represented like this: -// // 0x00000 -- page address (4 bytes) // 16 -- size of this block (4 bytes) -// 0x0030 -- entries (2 bytes each) -// 0x0500 -// 0x1000 -// 0x1100 +// 0xA030 -- entries (2 bytes each) +// 0xA500 +// 0xA700 +// 0xAA00 // 0x20000 -- page address (4 bytes) // 12 -- size of this block (4 bytes) -// 0x0004 -- entries (2 bytes each) -// 0x0008 +// 0xA004 -- entries (2 bytes each) +// 0xA008 // -// Usually we have a lot of relocatinos for each page, so the number of -// bytes for one .reloc entry is close to 2 bytes. +// Usually we have a lot of relocations for each page, so the number of +// bytes for one .reloc entry is close to 2 bytes on average. BaserelChunk::BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End) { // Block header consists of 4 byte page RVA and 4 byte block size. // Each entry is 2 byte. Last entry may be padding. Data.resize(alignTo((End - Begin) * 2 + 8, 4)); uint8_t *P = Data.data(); write32le(P, Page); write32le(P + 4, Data.size()); P += 8; for (Baserel *I = Begin; I != End; ++I) { write16le(P, (I->Type << 12) | (I->RVA - Page)); P += 2; } } void BaserelChunk::writeTo(uint8_t *Buf) const { memcpy(Buf + OutputSectionOff, Data.data(), Data.size()); } uint8_t Baserel::getDefaultType() { switch (Config->Machine) { case AMD64: return IMAGE_REL_BASED_DIR64; case I386: return IMAGE_REL_BASED_HIGHLOW; default: llvm_unreachable("unknown machine type"); } } } // namespace coff } // namespace lld Index: vendor/lld/dist/COFF/Error.cpp =================================================================== --- vendor/lld/dist/COFF/Error.cpp (revision 317689) +++ vendor/lld/dist/COFF/Error.cpp (revision 317690) @@ -1,114 +1,115 @@ //===- Error.cpp ----------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "Error.h" #include "Config.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Error.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Process.h" #include "llvm/Support/raw_ostream.h" #include <mutex> #if !defined(_MSC_VER) && !defined(__MINGW32__) #include <unistd.h> #endif using namespace llvm; namespace lld { // The functions defined in this file can be called from multiple threads, // but outs() or errs() are not thread-safe. We protect them using a mutex. static std::mutex Mu; namespace coff { StringRef Argv0; uint64_t ErrorCount; raw_ostream *ErrorOS; static LLVM_ATTRIBUTE_NORETURN void exitLld(int Val) { // Dealloc/destroy ManagedStatic variables before calling // _exit(). In a non-LTO build, this is a nop. In an LTO // build allows us to get the output of -time-passes. llvm_shutdown(); outs().flush(); errs().flush(); _exit(Val); } static void print(StringRef S, raw_ostream::Colors C) { *ErrorOS << Argv0 + ": "; if (Config->ColorDiagnostics) { ErrorOS->changeColor(C, true); *ErrorOS << S; ErrorOS->resetColor(); } else { *ErrorOS << S; } } void log(const Twine &Msg) { if (Config->Verbose) { std::lock_guard<std::mutex> Lock(Mu); outs() << Argv0 << ": " << Msg << "\n"; + outs().flush(); } } void message(const Twine &Msg) { std::lock_guard<std::mutex> Lock(Mu); outs() << Msg << "\n"; outs().flush(); } void error(const Twine &Msg) { std::lock_guard<std::mutex> Lock(Mu); if (Config->ErrorLimit == 0 || ErrorCount < Config->ErrorLimit) { print("error: ", raw_ostream::RED); *ErrorOS << Msg << "\n"; } else if (ErrorCount == Config->ErrorLimit) { print("error: ", raw_ostream::RED); *ErrorOS << "too many errors emitted, stopping now" << " (use /ERRORLIMIT:0 to see all errors)\n"; exitLld(1); } ++ErrorCount; } void fatal(const Twine &Msg) { if (Config->ColorDiagnostics) { errs().changeColor(raw_ostream::RED, /*bold=*/true); errs() << "error: "; errs().resetColor(); } else { errs() << "error: "; } errs() << Msg << "\n"; exitLld(1); } void fatal(std::error_code EC, const Twine &Msg) { fatal(Msg + ": " + EC.message()); } void fatal(llvm::Error &Err, const Twine &Msg) { fatal(errorToErrorCode(std::move(Err)), Msg); } void warn(const Twine &Msg) { std::lock_guard<std::mutex> Lock(Mu); print("warning: ", raw_ostream::MAGENTA); *ErrorOS << Msg << "\n"; } } // namespace coff } // namespace lld Index: vendor/lld/dist/COFF/ICF.cpp =================================================================== --- vendor/lld/dist/COFF/ICF.cpp (revision 317689) +++ vendor/lld/dist/COFF/ICF.cpp (revision 317690) @@ -1,253 +1,261 @@ //===- ICF.cpp ------------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // ICF is short for Identical Code Folding. That is a size optimization to // identify and merge two or more read-only sections (typically functions) // that happened to have the same contents. It usually reduces output size // by a few percent. // // On Windows, ICF is enabled by default. // // See ELF/ICF.cpp for the details about the algortihm. // //===----------------------------------------------------------------------===// #include "Chunks.h" #include "Error.h" #include "Symbols.h" #include "lld/Core/Parallel.h" #include "llvm/ADT/Hashing.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <atomic> #include <vector> using namespace llvm; namespace lld { namespace coff { class ICF { public: void run(const std::vector<Chunk *> &V); private: void segregate(size_t Begin, size_t End, bool Constant); bool equalsConstant(const SectionChunk *A, const SectionChunk *B); bool equalsVariable(const SectionChunk *A, const SectionChunk *B); uint32_t getHash(SectionChunk *C); bool isEligible(SectionChunk *C); size_t findBoundary(size_t Begin, size_t End); void forEachColorRange(size_t Begin, size_t End, std::function<void(size_t, size_t)> Fn); void forEachColor(std::function<void(size_t, size_t)> Fn); std::vector<SectionChunk *> Chunks; int Cnt = 0; std::atomic<uint32_t> NextId = {1}; std::atomic<bool> Repeat = {false}; }; // Returns a hash value for S. uint32_t ICF::getHash(SectionChunk *C) { return hash_combine(C->getPermissions(), hash_value(C->SectionName), C->NumRelocs, C->getAlign(), uint32_t(C->Header->SizeOfRawData), C->Checksum); } // Returns true if section S is subject of ICF. +// +// Microsoft's documentation +// (https://msdn.microsoft.com/en-us/library/bxwfs976.aspx; visited April +// 2017) says that /opt:icf folds both functions and read-only data. +// Despite that, the MSVC linker folds only functions. We found +// a few instances of programs that are not safe for data merging. +// Therefore, we merge only functions just like the MSVC tool. bool ICF::isEligible(SectionChunk *C) { bool Global = C->Sym && C->Sym->isExternal(); + bool Executable = C->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_EXECUTE; bool Writable = C->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_WRITE; - return C->isCOMDAT() && C->isLive() && Global && !Writable; + return C->isCOMDAT() && C->isLive() && Global && Executable && !Writable; } // Split a range into smaller ranges by recoloring sections void ICF::segregate(size_t Begin, size_t End, bool Constant) { while (Begin < End) { // Divide [Begin, End) into two. Let Mid be the start index of the // second group. auto Bound = std::stable_partition( Chunks.begin() + Begin + 1, Chunks.begin() + End, [&](SectionChunk *S) { if (Constant) return equalsConstant(Chunks[Begin], S); return equalsVariable(Chunks[Begin], S); }); size_t Mid = Bound - Chunks.begin(); // Split [Begin, End) into [Begin, Mid) and [Mid, End). uint32_t Id = NextId++; for (size_t I = Begin; I < Mid; ++I) Chunks[I]->Color[(Cnt + 1) % 2] = Id; // If we created a group, we need to iterate the main loop again. if (Mid != End) Repeat = true; Begin = Mid; } } // Compare "non-moving" part of two sections, namely everything // except relocation targets. bool ICF::equalsConstant(const SectionChunk *A, const SectionChunk *B) { if (A->NumRelocs != B->NumRelocs) return false; // Compare relocations. auto Eq = [&](const coff_relocation &R1, const coff_relocation &R2) { if (R1.Type != R2.Type || R1.VirtualAddress != R2.VirtualAddress) { return false; } SymbolBody *B1 = A->File->getSymbolBody(R1.SymbolTableIndex); SymbolBody *B2 = B->File->getSymbolBody(R2.SymbolTableIndex); if (B1 == B2) return true; if (auto *D1 = dyn_cast<DefinedRegular>(B1)) if (auto *D2 = dyn_cast<DefinedRegular>(B2)) return D1->getValue() == D2->getValue() && D1->getChunk()->Color[Cnt % 2] == D2->getChunk()->Color[Cnt % 2]; return false; }; if (!std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(), Eq)) return false; // Compare section attributes and contents. return A->getPermissions() == B->getPermissions() && A->SectionName == B->SectionName && A->getAlign() == B->getAlign() && A->Header->SizeOfRawData == B->Header->SizeOfRawData && A->Checksum == B->Checksum && A->getContents() == B->getContents(); } // Compare "moving" part of two sections, namely relocation targets. bool ICF::equalsVariable(const SectionChunk *A, const SectionChunk *B) { // Compare relocations. auto Eq = [&](const coff_relocation &R1, const coff_relocation &R2) { SymbolBody *B1 = A->File->getSymbolBody(R1.SymbolTableIndex); SymbolBody *B2 = B->File->getSymbolBody(R2.SymbolTableIndex); if (B1 == B2) return true; if (auto *D1 = dyn_cast<DefinedRegular>(B1)) if (auto *D2 = dyn_cast<DefinedRegular>(B2)) return D1->getChunk()->Color[Cnt % 2] == D2->getChunk()->Color[Cnt % 2]; return false; }; return std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(), Eq); } size_t ICF::findBoundary(size_t Begin, size_t End) { for (size_t I = Begin + 1; I < End; ++I) if (Chunks[Begin]->Color[Cnt % 2] != Chunks[I]->Color[Cnt % 2]) return I; return End; } void ICF::forEachColorRange(size_t Begin, size_t End, std::function<void(size_t, size_t)> Fn) { if (Begin > 0) Begin = findBoundary(Begin - 1, End); while (Begin < End) { size_t Mid = findBoundary(Begin, Chunks.size()); Fn(Begin, Mid); Begin = Mid; } } // Call Fn on each color group. void ICF::forEachColor(std::function<void(size_t, size_t)> Fn) { // If the number of sections are too small to use threading, // call Fn sequentially. if (Chunks.size() < 1024) { forEachColorRange(0, Chunks.size(), Fn); return; } // Split sections into 256 shards and call Fn in parallel. size_t NumShards = 256; size_t Step = Chunks.size() / NumShards; parallel_for(size_t(0), NumShards, [&](size_t I) { forEachColorRange(I * Step, (I + 1) * Step, Fn); }); forEachColorRange(Step * NumShards, Chunks.size(), Fn); } // Merge identical COMDAT sections. // Two sections are considered the same if their section headers, // contents and relocations are all the same. void ICF::run(const std::vector<Chunk *> &Vec) { // Collect only mergeable sections and group by hash value. for (Chunk *C : Vec) { auto *SC = dyn_cast<SectionChunk>(C); if (!SC) continue; if (isEligible(SC)) { // Set MSB to 1 to avoid collisions with non-hash colors. SC->Color[0] = getHash(SC) | (1 << 31); Chunks.push_back(SC); } else { SC->Color[0] = NextId++; } } if (Chunks.empty()) return; // From now on, sections in Chunks are ordered so that sections in // the same group are consecutive in the vector. std::stable_sort(Chunks.begin(), Chunks.end(), [](SectionChunk *A, SectionChunk *B) { return A->Color[0] < B->Color[0]; }); // Compare static contents and assign unique IDs for each static content. forEachColor([&](size_t Begin, size_t End) { segregate(Begin, End, true); }); ++Cnt; // Split groups by comparing relocations until convergence is obtained. do { Repeat = false; forEachColor( [&](size_t Begin, size_t End) { segregate(Begin, End, false); }); ++Cnt; } while (Repeat); log("ICF needed " + Twine(Cnt) + " iterations"); // Merge sections in the same colors. forEachColor([&](size_t Begin, size_t End) { if (End - Begin == 1) return; log("Selected " + Chunks[Begin]->getDebugName()); for (size_t I = Begin + 1; I < End; ++I) { log(" Removed " + Chunks[I]->getDebugName()); Chunks[Begin]->replace(Chunks[I]); } }); } // Entry point to ICF. void doICF(const std::vector<Chunk *> &Chunks) { ICF().run(Chunks); } } // namespace coff } // namespace lld Index: vendor/lld/dist/COFF/InputFiles.cpp =================================================================== --- vendor/lld/dist/COFF/InputFiles.cpp (revision 317689) +++ vendor/lld/dist/COFF/InputFiles.cpp (revision 317690) @@ -1,399 +1,402 @@ //===- InputFiles.cpp -----------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "InputFiles.h" #include "Chunks.h" #include "Config.h" #include "Driver.h" #include "Error.h" #include "Memory.h" #include "SymbolTable.h" #include "Symbols.h" #include "llvm-c/lto.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" #include "llvm/Object/Binary.h" #include "llvm/Object/COFF.h" #include "llvm/Support/COFF.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileSystem.h" #include "llvm/Target/TargetOptions.h" #include <cstring> #include <system_error> #include <utility> using namespace llvm; using namespace llvm::COFF; using namespace llvm::object; using namespace llvm::support::endian; using llvm::Triple; using llvm::support::ulittle32_t; namespace lld { namespace coff { /// Checks that Source is compatible with being a weak alias to Target. /// If Source is Undefined and has no weak alias set, makes it a weak /// alias to Target. static void checkAndSetWeakAlias(SymbolTable *Symtab, InputFile *F, SymbolBody *Source, SymbolBody *Target) { auto *U = dyn_cast<Undefined>(Source); if (!U) return; else if (!U->WeakAlias) U->WeakAlias = Target; else if (U->WeakAlias != Target) Symtab->reportDuplicate(Source->symbol(), F); } ArchiveFile::ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {} void ArchiveFile::parse() { // Parse a MemoryBufferRef as an archive file. File = check(Archive::create(MB), toString(this)); // Read the symbol table to construct Lazy objects. for (const Archive::Symbol &Sym : File->symbols()) Symtab->addLazy(this, Sym); } // Returns a buffer pointing to a member file containing a given symbol. void ArchiveFile::addMember(const Archive::Symbol *Sym) { const Archive::Child &C = check(Sym->getMember(), "could not get the member for symbol " + Sym->getName()); // Return an empty buffer if we have already returned the same buffer. if (!Seen.insert(C.getChildOffset()).second) return; Driver->enqueueArchiveMember(C, Sym->getName(), getName()); } void ObjectFile::parse() { // Parse a memory buffer as a COFF file. std::unique_ptr<Binary> Bin = check(createBinary(MB), toString(this)); if (auto *Obj = dyn_cast<COFFObjectFile>(Bin.get())) { Bin.release(); COFFObj.reset(Obj); } else { fatal(toString(this) + " is not a COFF file"); } // Read section and symbol tables. initializeChunks(); initializeSymbols(); initializeSEH(); } void ObjectFile::initializeChunks() { uint32_t NumSections = COFFObj->getNumberOfSections(); Chunks.reserve(NumSections); SparseChunks.resize(NumSections + 1); for (uint32_t I = 1; I < NumSections + 1; ++I) { const coff_section *Sec; StringRef Name; if (auto EC = COFFObj->getSection(I, Sec)) fatal(EC, "getSection failed: #" + Twine(I)); if (auto EC = COFFObj->getSectionName(Sec, Name)) fatal(EC, "getSectionName failed: #" + Twine(I)); if (Name == ".sxdata") { SXData = Sec; continue; } if (Name == ".drectve") { ArrayRef<uint8_t> Data; COFFObj->getSectionContents(Sec, Data); Directives = std::string((const char *)Data.data(), Data.size()); continue; } // Object files may have DWARF debug info or MS CodeView debug info // (or both). // // DWARF sections don't need any special handling from the perspective // of the linker; they are just a data section containing relocations. // We can just link them to complete debug info. // // CodeView needs a linker support. We need to interpret and debug // info, and then write it to a separate .pdb file. // Ignore debug info unless /debug is given. if (!Config->Debug && Name.startswith(".debug")) continue; // CodeView sections are stored to a different vector because they are // not linked in the regular manner. if (Name == ".debug" || Name.startswith(".debug$")) { DebugChunks.push_back(new (Alloc) SectionChunk(this, Sec)); continue; } if (Sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE) continue; auto *C = new (Alloc) SectionChunk(this, Sec); Chunks.push_back(C); SparseChunks[I] = C; } } void ObjectFile::initializeSymbols() { uint32_t NumSymbols = COFFObj->getNumberOfSymbols(); SymbolBodies.reserve(NumSymbols); SparseSymbolBodies.resize(NumSymbols); SmallVector<std::pair<SymbolBody *, uint32_t>, 8> WeakAliases; int32_t LastSectionNumber = 0; for (uint32_t I = 0; I < NumSymbols; ++I) { // Get a COFFSymbolRef object. ErrorOr<COFFSymbolRef> SymOrErr = COFFObj->getSymbol(I); if (!SymOrErr) fatal(SymOrErr.getError(), "broken object file: " + toString(this)); COFFSymbolRef Sym = *SymOrErr; const void *AuxP = nullptr; if (Sym.getNumberOfAuxSymbols()) AuxP = COFFObj->getSymbol(I + 1)->getRawPtr(); bool IsFirst = (LastSectionNumber != Sym.getSectionNumber()); SymbolBody *Body = nullptr; if (Sym.isUndefined()) { Body = createUndefined(Sym); } else if (Sym.isWeakExternal()) { Body = createUndefined(Sym); uint32_t TagIndex = static_cast<const coff_aux_weak_external *>(AuxP)->TagIndex; WeakAliases.emplace_back(Body, TagIndex); } else { Body = createDefined(Sym, AuxP, IsFirst); } if (Body) { SymbolBodies.push_back(Body); SparseSymbolBodies[I] = Body; } I += Sym.getNumberOfAuxSymbols(); LastSectionNumber = Sym.getSectionNumber(); } for (auto WeakAlias : WeakAliases) checkAndSetWeakAlias(Symtab, this, WeakAlias.first, SparseSymbolBodies[WeakAlias.second]); } SymbolBody *ObjectFile::createUndefined(COFFSymbolRef Sym) { StringRef Name; COFFObj->getSymbolName(Sym, Name); return Symtab->addUndefined(Name, this, Sym.isWeakExternal())->body(); } SymbolBody *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP, bool IsFirst) { StringRef Name; if (Sym.isCommon()) { auto *C = new (Alloc) CommonChunk(Sym); Chunks.push_back(C); COFFObj->getSymbolName(Sym, Name); Symbol *S = Symtab->addCommon(this, Name, Sym.getValue(), Sym.getGeneric(), C); return S->body(); } if (Sym.isAbsolute()) { COFFObj->getSymbolName(Sym, Name); // Skip special symbols. if (Name == "@comp.id") return nullptr; // COFF spec 5.10.1. The .sxdata section. if (Name == "@feat.00") { if (Sym.getValue() & 1) SEHCompat = true; return nullptr; } if (Sym.isExternal()) return Symtab->addAbsolute(Name, Sym)->body(); else return new (Alloc) DefinedAbsolute(Name, Sym); } int32_t SectionNumber = Sym.getSectionNumber(); if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG) return nullptr; // Reserved sections numbers don't have contents. if (llvm::COFF::isReservedSectionNumber(SectionNumber)) fatal("broken object file: " + toString(this)); // This symbol references a section which is not present in the section // header. if ((uint32_t)SectionNumber >= SparseChunks.size()) fatal("broken object file: " + toString(this)); // Nothing else to do without a section chunk. auto *SC = cast_or_null<SectionChunk>(SparseChunks[SectionNumber]); if (!SC) return nullptr; // Handle section definitions if (IsFirst && AuxP) { auto *Aux = reinterpret_cast<const coff_aux_section_definition *>(AuxP); if (Aux->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) if (auto *ParentSC = cast_or_null<SectionChunk>( SparseChunks[Aux->getNumber(Sym.isBigObj())])) ParentSC->addAssociative(SC); SC->Checksum = Aux->CheckSum; } DefinedRegular *B; if (Sym.isExternal()) { COFFObj->getSymbolName(Sym, Name); Symbol *S = Symtab->addRegular(this, Name, SC->isCOMDAT(), Sym.getGeneric(), SC); B = cast<DefinedRegular>(S->body()); } else B = new (Alloc) DefinedRegular(this, /*Name*/ "", SC->isCOMDAT(), /*IsExternal*/ false, Sym.getGeneric(), SC); if (SC->isCOMDAT() && Sym.getValue() == 0 && !AuxP) SC->setSymbol(B); return B; } void ObjectFile::initializeSEH() { if (!SEHCompat || !SXData) return; ArrayRef<uint8_t> A; COFFObj->getSectionContents(SXData, A); if (A.size() % 4 != 0) fatal(".sxdata must be an array of symbol table indices"); auto *I = reinterpret_cast<const ulittle32_t *>(A.data()); auto *E = reinterpret_cast<const ulittle32_t *>(A.data() + A.size()); for (; I != E; ++I) SEHandlers.insert(SparseSymbolBodies[*I]); } MachineTypes ObjectFile::getMachineType() { if (COFFObj) return static_cast<MachineTypes>(COFFObj->getMachine()); return IMAGE_FILE_MACHINE_UNKNOWN; } StringRef ltrim1(StringRef S, const char *Chars) { if (!S.empty() && strchr(Chars, S[0])) return S.substr(1); return S; } void ImportFile::parse() { const char *Buf = MB.getBufferStart(); const char *End = MB.getBufferEnd(); const auto *Hdr = reinterpret_cast<const coff_import_header *>(Buf); // Check if the total size is valid. if ((size_t)(End - Buf) != (sizeof(*Hdr) + Hdr->SizeOfData)) fatal("broken import library"); // Read names and create an __imp_ symbol. StringRef Name = StringAlloc.save(StringRef(Buf + sizeof(*Hdr))); StringRef ImpName = StringAlloc.save("__imp_" + Name); const char *NameStart = Buf + sizeof(coff_import_header) + Name.size() + 1; DLLName = StringRef(NameStart); StringRef ExtName; switch (Hdr->getNameType()) { case IMPORT_ORDINAL: ExtName = ""; break; case IMPORT_NAME: ExtName = Name; break; case IMPORT_NAME_NOPREFIX: ExtName = ltrim1(Name, "?@_"); break; case IMPORT_NAME_UNDECORATE: ExtName = ltrim1(Name, "?@_"); ExtName = ExtName.substr(0, ExtName.find('@')); break; } this->Hdr = Hdr; ExternalName = ExtName; ImpSym = cast<DefinedImportData>( Symtab->addImportData(ImpName, this)->body()); + if (Hdr->getType() == llvm::COFF::IMPORT_CONST) + ConstSym = + cast<DefinedImportData>(Symtab->addImportData(Name, this)->body()); // If type is function, we need to create a thunk which jump to an // address pointed by the __imp_ symbol. (This allows you to call // DLL functions just like regular non-DLL functions.) if (Hdr->getType() != llvm::COFF::IMPORT_CODE) return; ThunkSym = cast<DefinedImportThunk>( Symtab->addImportThunk(Name, ImpSym, Hdr->Machine)->body()); } void BitcodeFile::parse() { Obj = check(lto::InputFile::create(MemoryBufferRef( MB.getBuffer(), Saver.save(ParentName + MB.getBufferIdentifier())))); for (const lto::InputFile::Symbol &ObjSym : Obj->symbols()) { StringRef SymName = Saver.save(ObjSym.getName()); Symbol *Sym; if (ObjSym.isUndefined()) { Sym = Symtab->addUndefined(SymName, this, false); } else if (ObjSym.isCommon()) { Sym = Symtab->addCommon(this, SymName, ObjSym.getCommonSize()); } else if (ObjSym.isWeak() && ObjSym.isIndirect()) { // Weak external. Sym = Symtab->addUndefined(SymName, this, true); std::string Fallback = ObjSym.getCOFFWeakExternalFallback(); SymbolBody *Alias = Symtab->addUndefined(Saver.save(Fallback)); checkAndSetWeakAlias(Symtab, this, Sym->body(), Alias); } else { bool IsCOMDAT = ObjSym.getComdatIndex() != -1; Sym = Symtab->addRegular(this, SymName, IsCOMDAT); } SymbolBodies.push_back(Sym->body()); } Directives = Obj->getCOFFLinkerOpts(); } MachineTypes BitcodeFile::getMachineType() { switch (Triple(Obj->getTargetTriple()).getArch()) { case Triple::x86_64: return AMD64; case Triple::x86: return I386; case Triple::arm: return ARMNT; default: return IMAGE_FILE_MACHINE_UNKNOWN; } } } // namespace coff } // namespace lld // Returns the last element of a path, which is supposed to be a filename. static StringRef getBasename(StringRef Path) { size_t Pos = Path.find_last_of("\\/"); if (Pos == StringRef::npos) return Path; return Path.substr(Pos + 1); } // Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)". std::string lld::toString(coff::InputFile *File) { if (!File) return "(internal)"; if (File->ParentName.empty()) return File->getName().lower(); std::string Res = (getBasename(File->ParentName) + "(" + getBasename(File->getName()) + ")") .str(); return StringRef(Res).lower(); } Index: vendor/lld/dist/COFF/InputFiles.h =================================================================== --- vendor/lld/dist/COFF/InputFiles.h (revision 317689) +++ vendor/lld/dist/COFF/InputFiles.h (revision 317690) @@ -1,204 +1,205 @@ //===- InputFiles.h ---------------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_COFF_INPUT_FILES_H #define LLD_COFF_INPUT_FILES_H #include "lld/Core/LLVM.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/LTO/LTO.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFF.h" #include "llvm/Support/StringSaver.h" #include <memory> #include <set> #include <vector> namespace lld { namespace coff { using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN; using llvm::COFF::MachineTypes; using llvm::object::Archive; using llvm::object::COFFObjectFile; using llvm::object::COFFSymbolRef; using llvm::object::coff_import_header; using llvm::object::coff_section; class Chunk; class Defined; class DefinedImportData; class DefinedImportThunk; class Lazy; class SectionChunk; struct Symbol; class SymbolBody; class Undefined; // The root class of input files. class InputFile { public: enum Kind { ArchiveKind, ObjectKind, ImportKind, BitcodeKind }; Kind kind() const { return FileKind; } virtual ~InputFile() {} // Returns the filename. StringRef getName() { return MB.getBufferIdentifier(); } // Reads a file (the constructor doesn't do that). virtual void parse() = 0; // Returns the CPU type this file was compiled to. virtual MachineTypes getMachineType() { return IMAGE_FILE_MACHINE_UNKNOWN; } MemoryBufferRef MB; // An archive file name if this file is created from an archive. StringRef ParentName; // Returns .drectve section contents if exist. StringRef getDirectives() { return StringRef(Directives).trim(); } protected: InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {} std::string Directives; private: const Kind FileKind; }; // .lib or .a file. class ArchiveFile : public InputFile { public: explicit ArchiveFile(MemoryBufferRef M); static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; } void parse() override; // Enqueues an archive member load for the given symbol. If we've already // enqueued a load for the same archive member, this function does nothing, // which ensures that we don't load the same member more than once. void addMember(const Archive::Symbol *Sym); private: std::unique_ptr<Archive> File; std::string Filename; llvm::DenseSet<uint64_t> Seen; }; // .obj or .o file. This may be a member of an archive file. class ObjectFile : public InputFile { public: explicit ObjectFile(MemoryBufferRef M) : InputFile(ObjectKind, M) {} static bool classof(const InputFile *F) { return F->kind() == ObjectKind; } void parse() override; MachineTypes getMachineType() override; std::vector<Chunk *> &getChunks() { return Chunks; } std::vector<SectionChunk *> &getDebugChunks() { return DebugChunks; } std::vector<SymbolBody *> &getSymbols() { return SymbolBodies; } // Returns a SymbolBody object for the SymbolIndex'th symbol in the // underlying object file. SymbolBody *getSymbolBody(uint32_t SymbolIndex) { return SparseSymbolBodies[SymbolIndex]; } // Returns the underying COFF file. COFFObjectFile *getCOFFObj() { return COFFObj.get(); } // True if this object file is compatible with SEH. // COFF-specific and x86-only. bool SEHCompat = false; // The list of safe exception handlers listed in .sxdata section. // COFF-specific and x86-only. std::set<SymbolBody *> SEHandlers; private: void initializeChunks(); void initializeSymbols(); void initializeSEH(); SymbolBody *createDefined(COFFSymbolRef Sym, const void *Aux, bool IsFirst); SymbolBody *createUndefined(COFFSymbolRef Sym); std::unique_ptr<COFFObjectFile> COFFObj; llvm::BumpPtrAllocator Alloc; const coff_section *SXData = nullptr; // List of all chunks defined by this file. This includes both section // chunks and non-section chunks for common symbols. std::vector<Chunk *> Chunks; // CodeView debug info sections. std::vector<SectionChunk *> DebugChunks; // This vector contains the same chunks as Chunks, but they are // indexed such that you can get a SectionChunk by section index. // Nonexistent section indices are filled with null pointers. // (Because section number is 1-based, the first slot is always a // null pointer.) std::vector<Chunk *> SparseChunks; // List of all symbols referenced or defined by this file. std::vector<SymbolBody *> SymbolBodies; // This vector contains the same symbols as SymbolBodies, but they // are indexed such that you can get a SymbolBody by symbol // index. Nonexistent indices (which are occupied by auxiliary // symbols in the real symbol table) are filled with null pointers. std::vector<SymbolBody *> SparseSymbolBodies; }; // This type represents import library members that contain DLL names // and symbols exported from the DLLs. See Microsoft PE/COFF spec. 7 // for details about the format. class ImportFile : public InputFile { public: explicit ImportFile(MemoryBufferRef M) : InputFile(ImportKind, M), StringAlloc(StringAllocAux) {} static bool classof(const InputFile *F) { return F->kind() == ImportKind; } DefinedImportData *ImpSym = nullptr; + DefinedImportData *ConstSym = nullptr; DefinedImportThunk *ThunkSym = nullptr; std::string DLLName; private: void parse() override; llvm::BumpPtrAllocator StringAllocAux; llvm::StringSaver StringAlloc; public: StringRef ExternalName; const coff_import_header *Hdr; Chunk *Location = nullptr; }; // Used for LTO. class BitcodeFile : public InputFile { public: explicit BitcodeFile(MemoryBufferRef M) : InputFile(BitcodeKind, M) {} static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; } std::vector<SymbolBody *> &getSymbols() { return SymbolBodies; } MachineTypes getMachineType() override; std::unique_ptr<llvm::lto::InputFile> Obj; private: void parse() override; std::vector<SymbolBody *> SymbolBodies; }; } // namespace coff std::string toString(coff::InputFile *File); } // namespace lld #endif Index: vendor/lld/dist/COFF/MapFile.cpp =================================================================== --- vendor/lld/dist/COFF/MapFile.cpp (revision 317689) +++ vendor/lld/dist/COFF/MapFile.cpp (revision 317690) @@ -1,114 +1,125 @@ //===- MapFile.cpp --------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the /lldmap option. It shows lists in order and // hierarchically the output sections, input sections, input files and // symbol: // -// Address Size Align Out In File Symbol -// ================================================================= -// 00201000 00000015 4 .text -// 00201000 0000000e 4 .text -// 00201000 0000000e 4 test.o -// 0020100e 00000000 0 local -// 00201005 00000000 0 f(int) +// Address Size Align Out File Symbol +// 00201000 00000015 4 .text +// 00201000 0000000e 4 test.o:(.text) +// 0020100e 00000000 0 local +// 00201005 00000000 0 f(int) // //===----------------------------------------------------------------------===// #include "MapFile.h" #include "Error.h" +#include "SymbolTable.h" #include "Symbols.h" #include "Writer.h" +#include "lld/Core/Parallel.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace llvm::object; using namespace lld; using namespace lld::coff; -static void writeOutSecLine(raw_fd_ostream &OS, uint64_t Address, uint64_t Size, - uint64_t Align, StringRef Name) { - OS << format("%08llx %08llx %5lld ", Address, Size, Align) - << left_justify(Name, 7); -} +typedef DenseMap<const SectionChunk *, SmallVector<DefinedRegular *, 4>> + SymbolMapTy; -static void writeInSecLine(raw_fd_ostream &OS, uint64_t Address, uint64_t Size, - uint64_t Align, StringRef Name) { - // Pass an empty name to align the text to the correct column. - writeOutSecLine(OS, Address, Size, Align, ""); - OS << ' ' << left_justify(Name, 7); +// Print out the first three columns of a line. +static void writeHeader(raw_ostream &OS, uint64_t Addr, uint64_t Size, + uint64_t Align) { + OS << format("%08llx %08llx %5lld ", Addr, Size, Align); } -static void writeFileLine(raw_fd_ostream &OS, uint64_t Address, uint64_t Size, - uint64_t Align, StringRef Name) { - // Pass an empty name to align the text to the correct column. - writeInSecLine(OS, Address, Size, Align, ""); - OS << ' ' << left_justify(Name, 7); -} +static std::string indent(int Depth) { return std::string(Depth * 8, ' '); } -static void writeSymbolLine(raw_fd_ostream &OS, uint64_t Address, uint64_t Size, - StringRef Name) { - // Pass an empty name to align the text to the correct column. - writeFileLine(OS, Address, Size, 0, ""); - OS << ' ' << left_justify(Name, 7); +// Returns a list of all symbols that we want to print out. +static std::vector<DefinedRegular *> getSymbols() { + std::vector<DefinedRegular *> V; + for (coff::ObjectFile *File : Symtab->ObjectFiles) + for (SymbolBody *B : File->getSymbols()) + if (auto *Sym = dyn_cast<DefinedRegular>(B)) + if (Sym && !Sym->getCOFFSymbol().isSectionDefinition()) + V.push_back(Sym); + return V; } -static void writeSectionChunk(raw_fd_ostream &OS, const SectionChunk *SC, - StringRef &PrevName) { - StringRef Name = SC->getSectionName(); - if (Name != PrevName) { - writeInSecLine(OS, SC->getRVA(), SC->getSize(), SC->getAlign(), Name); - OS << '\n'; - PrevName = Name; +// Returns a map from sections to their symbols. +static SymbolMapTy getSectionSyms(ArrayRef<DefinedRegular *> Syms) { + SymbolMapTy Ret; + for (DefinedRegular *S : Syms) + Ret[S->getChunk()].push_back(S); + + // Sort symbols by address. + for (auto &It : Ret) { + SmallVectorImpl<DefinedRegular *> &V = It.second; + std::sort(V.begin(), V.end(), [](DefinedRegular *A, DefinedRegular *B) { + return A->getRVA() < B->getRVA(); + }); } - coff::ObjectFile *File = SC->File; - if (!File) - return; - writeFileLine(OS, SC->getRVA(), SC->getSize(), SC->getAlign(), - toString(File)); - OS << '\n'; - ArrayRef<SymbolBody *> Syms = File->getSymbols(); - for (SymbolBody *Sym : Syms) { - auto *DR = dyn_cast<DefinedRegular>(Sym); - if (!DR || DR->getChunk() != SC || - DR->getCOFFSymbol().isSectionDefinition()) - continue; - writeSymbolLine(OS, DR->getRVA(), SC->getSize(), toString(*Sym)); - OS << '\n'; - } + return Ret; } -static void writeMapFile2(raw_fd_ostream &OS, - ArrayRef<OutputSection *> OutputSections) { - OS << "Address Size Align Out In File Symbol\n"; +// Construct a map from symbols to their stringified representations. +static DenseMap<DefinedRegular *, std::string> +getSymbolStrings(ArrayRef<DefinedRegular *> Syms) { + std::vector<std::string> Str(Syms.size()); + parallel_for((size_t)0, Syms.size(), [&](size_t I) { + raw_string_ostream OS(Str[I]); + writeHeader(OS, Syms[I]->getRVA(), 0, 0); + OS << indent(2) << toString(*Syms[I]); + }); - for (OutputSection *Sec : OutputSections) { - uint32_t VA = Sec->getRVA(); - writeOutSecLine(OS, VA, Sec->getVirtualSize(), /*Align=*/PageSize, - Sec->getName()); - OS << '\n'; - StringRef PrevName = ""; - for (Chunk *C : Sec->getChunks()) - if (const auto *SC = dyn_cast<SectionChunk>(C)) - writeSectionChunk(OS, SC, PrevName); - } + DenseMap<DefinedRegular *, std::string> Ret; + for (size_t I = 0, E = Syms.size(); I < E; ++I) + Ret[Syms[I]] = std::move(Str[I]); + return Ret; } void coff::writeMapFile(ArrayRef<OutputSection *> OutputSections) { if (Config->MapFile.empty()) return; std::error_code EC; raw_fd_ostream OS(Config->MapFile, EC, sys::fs::F_None); if (EC) fatal("cannot open " + Config->MapFile + ": " + EC.message()); - writeMapFile2(OS, OutputSections); + + // Collect symbol info that we want to print out. + std::vector<DefinedRegular *> Syms = getSymbols(); + SymbolMapTy SectionSyms = getSectionSyms(Syms); + DenseMap<DefinedRegular *, std::string> SymStr = getSymbolStrings(Syms); + + // Print out the header line. + OS << "Address Size Align Out In Symbol\n"; + + // Print out file contents. + for (OutputSection *Sec : OutputSections) { + writeHeader(OS, Sec->getRVA(), Sec->getVirtualSize(), /*Align=*/PageSize); + OS << Sec->getName() << '\n'; + + for (Chunk *C : Sec->getChunks()) { + auto *SC = dyn_cast<SectionChunk>(C); + if (!SC) + continue; + + writeHeader(OS, SC->getRVA(), SC->getSize(), SC->getAlign()); + OS << indent(1) << SC->File->getName() << ":(" << SC->getSectionName() + << ")\n"; + for (DefinedRegular *Sym : SectionSyms[SC]) + OS << SymStr[Sym] << '\n'; + } + } } Index: vendor/lld/dist/ELF/Config.h =================================================================== --- vendor/lld/dist/ELF/Config.h (revision 317689) +++ vendor/lld/dist/ELF/Config.h (revision 317690) @@ -1,229 +1,229 @@ //===- Config.h -------------------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_ELF_CONFIG_H #define LLD_ELF_CONFIG_H #include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/CachePruning.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" #include <vector> namespace lld { namespace elf { class InputFile; struct Symbol; enum ELFKind { ELFNoneKind, ELF32LEKind, ELF32BEKind, ELF64LEKind, ELF64BEKind }; // For --build-id. enum class BuildIdKind { None, Fast, Md5, Sha1, Hexstring, Uuid }; // For --discard-{all,locals,none}. enum class DiscardPolicy { Default, All, Locals, None }; // For --strip-{all,debug}. enum class StripPolicy { None, All, Debug }; // For --unresolved-symbols. enum class UnresolvedPolicy { ReportError, Warn, WarnAll, Ignore, IgnoreAll }; // For --sort-section and linkerscript sorting rules. enum class SortSectionPolicy { Default, None, Alignment, Name, Priority }; // For --target2 enum class Target2Policy { Abs, Rel, GotRel }; struct SymbolVersion { llvm::StringRef Name; bool IsExternCpp; bool HasWildcard; }; // This struct contains symbols version definition that // can be found in version script if it is used for link. struct VersionDefinition { llvm::StringRef Name; uint16_t Id = 0; std::vector<SymbolVersion> Globals; size_t NameOff = 0; // Offset in the string table }; // This struct contains the global configuration for the linker. // Most fields are direct mapping from the command line options // and such fields have the same name as the corresponding options. // Most fields are initialized by the driver. struct Configuration { InputFile *FirstElf = nullptr; uint8_t OSABI = 0; llvm::CachePruningPolicy ThinLTOCachePolicy; llvm::StringMap<uint64_t> SectionStartMap; llvm::StringRef DynamicLinker; llvm::StringRef Entry; llvm::StringRef Emulation; llvm::StringRef Fini; llvm::StringRef Init; llvm::StringRef LTOAAPipeline; llvm::StringRef LTONewPmPasses; llvm::StringRef MapFile; llvm::StringRef OutputFile; llvm::StringRef OptRemarksFilename; llvm::StringRef SoName; llvm::StringRef Sysroot; llvm::StringRef ThinLTOCacheDir; - std::string RPath; + std::string Rpath; std::vector<VersionDefinition> VersionDefinitions; std::vector<llvm::StringRef> AuxiliaryList; std::vector<llvm::StringRef> SearchPaths; std::vector<llvm::StringRef> SymbolOrderingFile; std::vector<llvm::StringRef> Undefined; std::vector<SymbolVersion> VersionScriptGlobals; std::vector<SymbolVersion> VersionScriptLocals; std::vector<uint8_t> BuildIdVector; bool AllowMultipleDefinition; bool ArchiveWithoutSymbolsSeen = false; bool AsNeeded = false; bool Bsymbolic; bool BsymbolicFunctions; bool ColorDiagnostics = false; bool CompressDebugSections; bool DefineCommon; bool Demangle = true; bool DisableVerify; bool EhFrameHdr; bool EmitRelocs; bool EnableNewDtags; bool ExportDynamic; bool FatalWarnings; bool GcSections; bool GdbIndex; bool GnuHash; bool ICF; bool MipsN32Abi = false; bool NoGnuUnique; bool NoUndefinedVersion; bool Nostdlib; bool OFormatBinary; bool Omagic; bool OptRemarksWithHotness; bool Pie; bool PrintGcSections; bool Relocatable; bool SaveTemps; bool SingleRoRx; bool Shared; bool Static = false; bool SysvHash; bool Target1Rel; bool Threads; bool Trace; bool Verbose; bool WarnCommon; bool WarnMissingEntry; bool ZCombreloc; bool ZExecstack; bool ZNocopyreloc; bool ZNodelete; bool ZNodlopen; bool ZNow; bool ZOrigin; bool ZRelro; bool ZText; bool ExitEarly; bool ZWxneeded; DiscardPolicy Discard; SortSectionPolicy SortSection; StripPolicy Strip; UnresolvedPolicy UnresolvedSymbols; Target2Policy Target2; BuildIdKind BuildId = BuildIdKind::None; ELFKind EKind = ELFNoneKind; uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL; uint16_t EMachine = llvm::ELF::EM_NONE; uint64_t ErrorLimit = 20; uint64_t ImageBase; uint64_t MaxPageSize; uint64_t ZStackSize; unsigned LTOPartitions; unsigned LTOO; unsigned Optimize; unsigned ThinLTOJobs; // The following config options do not directly correspond to any // particualr command line options. // True if we need to pass through relocations in input files to the // output file. Usually false because we consume relocations. bool CopyRelocs; // True if the target is ELF64. False if ELF32. bool Is64; // True if the target is little-endian. False if big-endian. bool IsLE; // endianness::little if IsLE is true. endianness::big otherwise. llvm::support::endianness Endianness; // True if the target is the little-endian MIPS64. // // The reason why we have this variable only for the MIPS is because // we use this often. Some ELF headers for MIPS64EL are in a // mixed-endian (which is horrible and I'd say that's a serious spec // bug), and we need to know whether we are reading MIPS ELF files or // not in various places. // // (Note that MIPS64EL is not a typo for MIPS64LE. This is the official // name whatever that means. A fun hypothesis is that "EL" is short for // little-endian written in the little-endian order, but I don't know // if that's true.) bool IsMips64EL; // The ELF spec defines two types of relocation table entries, RELA and // REL. RELA is a triplet of (offset, info, addend) while REL is a // tuple of (offset, info). Addends for REL are implicit and read from // the location where the relocations are applied. So, REL is more // compact than RELA but requires a bit of more work to process. // // (From the linker writer's view, this distinction is not necessary. // If the ELF had chosen whichever and sticked with it, it would have // been easier to write code to process relocations, but it's too late // to change the spec.) // // Each ABI defines its relocation type. IsRela is true if target // uses RELA. As far as we know, all 64-bit ABIs are using RELA. A // few 32-bit ABIs are using RELA too. bool IsRela; // True if we are creating position-independent code. bool Pic; // 4 for ELF32, 8 for ELF64. int Wordsize; }; // The only instance of Configuration struct. extern Configuration *Config; } // namespace elf } // namespace lld #endif Index: vendor/lld/dist/ELF/Driver.cpp =================================================================== --- vendor/lld/dist/ELF/Driver.cpp (revision 317689) +++ vendor/lld/dist/ELF/Driver.cpp (revision 317690) @@ -1,1000 +1,999 @@ //===- Driver.cpp ---------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // The driver drives the entire linking process. It is responsible for // parsing command line options and doing whatever it is instructed to do. // // One notable thing in the LLD's driver when compared to other linkers is // that the LLD's driver is agnostic on the host operating system. // Other linkers usually have implicit default values (such as a dynamic // linker path or library paths) for each host OS. // // I don't think implicit default values are useful because they are // usually explicitly specified by the compiler driver. They can even // be harmful when you are doing cross-linking. Therefore, in LLD, we // simply trust the compiler driver to pass all required options and // don't try to make effort on our side. // //===----------------------------------------------------------------------===// #include "Driver.h" #include "Config.h" #include "Error.h" #include "Filesystem.h" #include "ICF.h" #include "InputFiles.h" #include "InputSection.h" #include "LinkerScript.h" #include "Memory.h" #include "OutputSections.h" #include "ScriptParser.h" #include "Strings.h" #include "SymbolTable.h" #include "Target.h" #include "Threads.h" #include "Writer.h" #include "lld/Config/Version.h" #include "lld/Driver/Driver.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Object/Decompressor.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Path.h" #include "llvm/Support/TarWriter.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" #include <cstdlib> #include <utility> using namespace llvm; using namespace llvm::ELF; using namespace llvm::object; using namespace llvm::sys; using namespace lld; using namespace lld::elf; Configuration *elf::Config; LinkerDriver *elf::Driver; BumpPtrAllocator elf::BAlloc; StringSaver elf::Saver{BAlloc}; std::vector<SpecificAllocBase *> elf::SpecificAllocBase::Instances; static void setConfigs(); bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Error) { ErrorCount = 0; ErrorOS = &Error; Argv0 = Args[0]; InputSections.clear(); Tar = nullptr; Config = make<Configuration>(); Driver = make<LinkerDriver>(); Script = make<LinkerScript>(); Driver->main(Args, CanExitEarly); freeArena(); return !ErrorCount; } // Parses a linker -m option. static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) { uint8_t OSABI = 0; StringRef S = Emul; if (S.endswith("_fbsd")) { S = S.drop_back(5); OSABI = ELFOSABI_FREEBSD; } std::pair<ELFKind, uint16_t> Ret = StringSwitch<std::pair<ELFKind, uint16_t>>(S) .Cases("aarch64elf", "aarch64linux", {ELF64LEKind, EM_AARCH64}) .Case("armelf_linux_eabi", {ELF32LEKind, EM_ARM}) .Case("elf32_x86_64", {ELF32LEKind, EM_X86_64}) .Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS}) .Cases("elf32ltsmip", "elf32ltsmipn32", {ELF32LEKind, EM_MIPS}) .Case("elf32ppc", {ELF32BEKind, EM_PPC}) .Case("elf64btsmip", {ELF64BEKind, EM_MIPS}) .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS}) .Case("elf64ppc", {ELF64BEKind, EM_PPC64}) .Cases("elf_amd64", "elf_x86_64", {ELF64LEKind, EM_X86_64}) .Case("elf_i386", {ELF32LEKind, EM_386}) .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU}) .Default({ELFNoneKind, EM_NONE}); if (Ret.first == ELFNoneKind) { if (S == "i386pe" || S == "i386pep" || S == "thumb2pe") error("Windows targets are not supported on the ELF frontend: " + Emul); else error("unknown emulation: " + Emul); } return std::make_tuple(Ret.first, Ret.second, OSABI); } // Returns slices of MB by parsing MB as an archive file. // Each slice consists of a member file in the archive. std::vector<MemoryBufferRef> -LinkerDriver::getArchiveMembers(MemoryBufferRef MB) { +static getArchiveMembers(MemoryBufferRef MB) { std::unique_ptr<Archive> File = check(Archive::create(MB), MB.getBufferIdentifier() + ": failed to parse archive"); std::vector<MemoryBufferRef> V; Error Err = Error::success(); for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) { Archive::Child C = check(COrErr, MB.getBufferIdentifier() + ": could not get the child of the archive"); MemoryBufferRef MBRef = check(C.getMemoryBufferRef(), MB.getBufferIdentifier() + ": could not get the buffer for a child of the archive"); V.push_back(MBRef); } if (Err) fatal(MB.getBufferIdentifier() + ": Archive::children failed: " + toString(std::move(Err))); // Take ownership of memory buffers created for members of thin archives. for (std::unique_ptr<MemoryBuffer> &MB : File->takeThinBuffers()) make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); return V; } // Opens and parses a file. Path has to be resolved already. // Newly created memory buffers are owned by this driver. void LinkerDriver::addFile(StringRef Path, bool WithLOption) { using namespace sys::fs; Optional<MemoryBufferRef> Buffer = readFile(Path); if (!Buffer.hasValue()) return; MemoryBufferRef MBRef = *Buffer; if (InBinary) { Files.push_back(make<BinaryFile>(MBRef)); return; } switch (identify_magic(MBRef.getBuffer())) { case file_magic::unknown: readLinkerScript(MBRef); return; case file_magic::archive: if (InWholeArchive) { for (MemoryBufferRef MB : getArchiveMembers(MBRef)) Files.push_back(createObjectFile(MB, Path)); return; } Files.push_back(make<ArchiveFile>(MBRef)); return; case file_magic::elf_shared_object: if (Config->Relocatable) { error("attempted static link of dynamic object " + Path); return; } // DSOs usually have DT_SONAME tags in their ELF headers, and the // sonames are used to identify DSOs. But if they are missing, // they are identified by filenames. We don't know whether the new // file has a DT_SONAME or not because we haven't parsed it yet. // Here, we set the default soname for the file because we might // need it later. // // If a file was specified by -lfoo, the directory part is not // significant, as a user did not specify it. This behavior is // compatible with GNU. Files.push_back(createSharedFile( MBRef, WithLOption ? sys::path::filename(Path) : Path)); return; default: if (InLib) Files.push_back(make<LazyObjectFile>(MBRef)); else Files.push_back(createObjectFile(MBRef)); } } // Add a given library by searching it from input search paths. void LinkerDriver::addLibrary(StringRef Name) { if (Optional<std::string> Path = searchLibrary(Name)) addFile(*Path, /*WithLOption=*/true); else error("unable to find library -l" + Name); } // This function is called on startup. We need this for LTO since // LTO calls LLVM functions to compile bitcode files to native code. // Technically this can be delayed until we read bitcode files, but // we don't bother to do lazily because the initialization is fast. static void initLLVM(opt::InputArgList &Args) { InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); InitializeAllAsmParsers(); // Parse and evaluate -mllvm options. std::vector<const char *> V; V.push_back("lld (LLVM option parsing)"); for (auto *Arg : Args.filtered(OPT_mllvm)) V.push_back(Arg->getValue()); cl::ParseCommandLineOptions(V.size(), V.data()); } // Some command line options or some combinations of them are not allowed. // This function checks for such errors. static void checkOptions(opt::InputArgList &Args) { // The MIPS ABI as of 2016 does not support the GNU-style symbol lookup // table which is a relatively new feature. if (Config->EMachine == EM_MIPS && Config->GnuHash) error("the .gnu.hash section is not compatible with the MIPS target."); if (Config->Pie && Config->Shared) error("-shared and -pie may not be used together"); + if (!Config->Shared && !Config->AuxiliaryList.empty()) + error("-f may not be used without -shared"); + if (Config->Relocatable) { if (Config->Shared) error("-r and -shared may not be used together"); if (Config->GcSections) error("-r and --gc-sections may not be used together"); if (Config->ICF) error("-r and --icf may not be used together"); if (Config->Pie) error("-r and -pie may not be used together"); } } static StringRef getString(opt::InputArgList &Args, unsigned Key, StringRef Default = "") { if (auto *Arg = Args.getLastArg(Key)) return Arg->getValue(); return Default; } static int getInteger(opt::InputArgList &Args, unsigned Key, int Default) { int V = Default; if (auto *Arg = Args.getLastArg(Key)) { StringRef S = Arg->getValue(); if (S.getAsInteger(10, V)) error(Arg->getSpelling() + ": number expected, but got " + S); } return V; } static const char *getReproduceOption(opt::InputArgList &Args) { if (auto *Arg = Args.getLastArg(OPT_reproduce)) return Arg->getValue(); return getenv("LLD_REPRODUCE"); } static bool hasZOption(opt::InputArgList &Args, StringRef Key) { for (auto *Arg : Args.filtered(OPT_z)) if (Key == Arg->getValue()) return true; return false; } static uint64_t getZOptionValue(opt::InputArgList &Args, StringRef Key, uint64_t Default) { for (auto *Arg : Args.filtered(OPT_z)) { StringRef Value = Arg->getValue(); size_t Pos = Value.find("="); if (Pos != StringRef::npos && Key == Value.substr(0, Pos)) { Value = Value.substr(Pos + 1); uint64_t Result; if (Value.getAsInteger(0, Result)) error("invalid " + Key + ": " + Value); return Result; } } return Default; } void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) { ELFOptTable Parser; opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); // Interpret this flag early because error() depends on them. Config->ErrorLimit = getInteger(Args, OPT_error_limit, 20); // Handle -help if (Args.hasArg(OPT_help)) { printHelp(ArgsArr[0]); return; } // Handle -v or -version. // // A note about "compatible with GNU linkers" message: this is a hack for // scripts generated by GNU Libtool 2.4.6 (released in February 2014 and // still the newest version in March 2017) or earlier to recognize LLD as // a GNU compatible linker. As long as an output for the -v option // contains "GNU" or "with BFD", they recognize us as GNU-compatible. // // This is somewhat ugly hack, but in reality, we had no choice other // than doing this. Considering the very long release cycle of Libtool, // it is not easy to improve it to recognize LLD as a GNU compatible // linker in a timely manner. Even if we can make it, there are still a // lot of "configure" scripts out there that are generated by old version // of Libtool. We cannot convince every software developer to migrate to // the latest version and re-generate scripts. So we have this hack. if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version)) message(getLLDVersion() + " (compatible with GNU linkers)"); // ld.bfd always exits after printing out the version string. // ld.gold proceeds if a given option is -v. Because gold's behavior // is more permissive than ld.bfd, we chose what gold does here. if (Args.hasArg(OPT_version)) return; Config->ExitEarly = CanExitEarly && !Args.hasArg(OPT_full_shutdown); if (const char *Path = getReproduceOption(Args)) { // Note that --reproduce is a debug option so you can ignore it // if you are trying to understand the whole picture of the code. Expected<std::unique_ptr<TarWriter>> ErrOrWriter = TarWriter::create(Path, path::stem(Path)); if (ErrOrWriter) { Tar = ErrOrWriter->get(); Tar->append("response.txt", createResponseFile(Args)); Tar->append("version.txt", getLLDVersion() + "\n"); make<std::unique_ptr<TarWriter>>(std::move(*ErrOrWriter)); } else { error(Twine("--reproduce: failed to open ") + Path + ": " + toString(ErrOrWriter.takeError())); } } readConfigs(Args); initLLVM(Args); createFiles(Args); inferMachineType(); setConfigs(); checkOptions(Args); if (ErrorCount) return; switch (Config->EKind) { case ELF32LEKind: link<ELF32LE>(Args); return; case ELF32BEKind: link<ELF32BE>(Args); return; case ELF64LEKind: link<ELF64LE>(Args); return; case ELF64BEKind: link<ELF64BE>(Args); return; default: llvm_unreachable("unknown Config->EKind"); } } static bool getArg(opt::InputArgList &Args, unsigned K1, unsigned K2, bool Default) { if (auto *Arg = Args.getLastArg(K1, K2)) return Arg->getOption().getID() == K1; return Default; } static std::vector<StringRef> getArgs(opt::InputArgList &Args, int Id) { std::vector<StringRef> V; for (auto *Arg : Args.filtered(Id)) V.push_back(Arg->getValue()); return V; } -static std::string getRPath(opt::InputArgList &Args) { +static std::string getRpath(opt::InputArgList &Args) { std::vector<StringRef> V = getArgs(Args, OPT_rpath); return llvm::join(V.begin(), V.end(), ":"); } // Determines what we should do if there are remaining unresolved // symbols after the name resolution. static UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &Args) { // -noinhibit-exec or -r imply some default values. if (Args.hasArg(OPT_noinhibit_exec)) return UnresolvedPolicy::WarnAll; if (Args.hasArg(OPT_relocatable)) return UnresolvedPolicy::IgnoreAll; UnresolvedPolicy ErrorOrWarn = getArg(Args, OPT_error_unresolved_symbols, OPT_warn_unresolved_symbols, true) ? UnresolvedPolicy::ReportError : UnresolvedPolicy::Warn; // Process the last of -unresolved-symbols, -no-undefined or -z defs. for (auto *Arg : llvm::reverse(Args)) { switch (Arg->getOption().getID()) { case OPT_unresolved_symbols: { StringRef S = Arg->getValue(); if (S == "ignore-all" || S == "ignore-in-object-files") return UnresolvedPolicy::Ignore; if (S == "ignore-in-shared-libs" || S == "report-all") return ErrorOrWarn; error("unknown --unresolved-symbols value: " + S); continue; } case OPT_no_undefined: return ErrorOrWarn; case OPT_z: if (StringRef(Arg->getValue()) == "defs") return ErrorOrWarn; continue; } } // -shared implies -unresolved-symbols=ignore-all because missing // symbols are likely to be resolved at runtime using other DSOs. if (Config->Shared) return UnresolvedPolicy::Ignore; return ErrorOrWarn; } static Target2Policy getTarget2(opt::InputArgList &Args) { - if (auto *Arg = Args.getLastArg(OPT_target2)) { - StringRef S = Arg->getValue(); - if (S == "rel") - return Target2Policy::Rel; - if (S == "abs") - return Target2Policy::Abs; - if (S == "got-rel") - return Target2Policy::GotRel; - error("unknown --target2 option: " + S); - } + StringRef S = getString(Args, OPT_target2, "got-rel"); + if (S == "rel") + return Target2Policy::Rel; + if (S == "abs") + return Target2Policy::Abs; + if (S == "got-rel") + return Target2Policy::GotRel; + error("unknown --target2 option: " + S); return Target2Policy::GotRel; } static bool isOutputFormatBinary(opt::InputArgList &Args) { if (auto *Arg = Args.getLastArg(OPT_oformat)) { StringRef S = Arg->getValue(); if (S == "binary") return true; error("unknown --oformat value: " + S); } return false; } static DiscardPolicy getDiscard(opt::InputArgList &Args) { if (Args.hasArg(OPT_relocatable)) return DiscardPolicy::None; auto *Arg = Args.getLastArg(OPT_discard_all, OPT_discard_locals, OPT_discard_none); if (!Arg) return DiscardPolicy::Default; if (Arg->getOption().getID() == OPT_discard_all) return DiscardPolicy::All; if (Arg->getOption().getID() == OPT_discard_locals) return DiscardPolicy::Locals; return DiscardPolicy::None; } static StringRef getDynamicLinker(opt::InputArgList &Args) { auto *Arg = Args.getLastArg(OPT_dynamic_linker, OPT_no_dynamic_linker); if (!Arg || Arg->getOption().getID() == OPT_no_dynamic_linker) return ""; return Arg->getValue(); } static StripPolicy getStrip(opt::InputArgList &Args) { if (Args.hasArg(OPT_relocatable)) return StripPolicy::None; auto *Arg = Args.getLastArg(OPT_strip_all, OPT_strip_debug); if (!Arg) return StripPolicy::None; if (Arg->getOption().getID() == OPT_strip_all) return StripPolicy::All; return StripPolicy::Debug; } static uint64_t parseSectionAddress(StringRef S, opt::Arg *Arg) { uint64_t VA = 0; if (S.startswith("0x")) S = S.drop_front(2); if (S.getAsInteger(16, VA)) error("invalid argument: " + toString(Arg)); return VA; } static StringMap<uint64_t> getSectionStartMap(opt::InputArgList &Args) { StringMap<uint64_t> Ret; for (auto *Arg : Args.filtered(OPT_section_start)) { StringRef Name; StringRef Addr; std::tie(Name, Addr) = StringRef(Arg->getValue()).split('='); Ret[Name] = parseSectionAddress(Addr, Arg); } if (auto *Arg = Args.getLastArg(OPT_Ttext)) Ret[".text"] = parseSectionAddress(Arg->getValue(), Arg); if (auto *Arg = Args.getLastArg(OPT_Tdata)) Ret[".data"] = parseSectionAddress(Arg->getValue(), Arg); if (auto *Arg = Args.getLastArg(OPT_Tbss)) Ret[".bss"] = parseSectionAddress(Arg->getValue(), Arg); return Ret; } static SortSectionPolicy getSortSection(opt::InputArgList &Args) { StringRef S = getString(Args, OPT_sort_section); if (S == "alignment") return SortSectionPolicy::Alignment; if (S == "name") return SortSectionPolicy::Name; if (!S.empty()) error("unknown --sort-section rule: " + S); return SortSectionPolicy::Default; } static std::pair<bool, bool> getHashStyle(opt::InputArgList &Args) { StringRef S = getString(Args, OPT_hash_style, "sysv"); if (S == "sysv") return {true, false}; if (S == "gnu") return {false, true}; if (S != "both") error("unknown -hash-style: " + S); return {true, true}; } +// Parse --build-id or --build-id=<style>. We handle "tree" as a +// synonym for "sha1" because all our hash functions including +// -build-id=sha1 are actually tree hashes for performance reasons. +static std::pair<BuildIdKind, std::vector<uint8_t>> +getBuildId(opt::InputArgList &Args) { + if (Args.hasArg(OPT_build_id)) + return {BuildIdKind::Fast, {}}; + + StringRef S = getString(Args, OPT_build_id_eq, "none"); + if (S == "md5") + return {BuildIdKind::Md5, {}}; + if (S == "sha1" || S == "tree") + return {BuildIdKind::Sha1, {}}; + if (S == "uuid") + return {BuildIdKind::Uuid, {}}; + if (S.startswith("0x")) + return {BuildIdKind::Hexstring, parseHex(S.substr(2))}; + + if (S != "none") + error("unknown --build-id style: " + S); + return {BuildIdKind::None, {}}; +} + static std::vector<StringRef> getLines(MemoryBufferRef MB) { SmallVector<StringRef, 0> Arr; MB.getBuffer().split(Arr, '\n'); std::vector<StringRef> Ret; for (StringRef S : Arr) { S = S.trim(); if (!S.empty()) Ret.push_back(S); } return Ret; } static bool getCompressDebugSections(opt::InputArgList &Args) { - if (auto *Arg = Args.getLastArg(OPT_compress_debug_sections)) { - StringRef S = Arg->getValue(); - if (S == "zlib") - return zlib::isAvailable(); - if (S != "none") - error("unknown --compress-debug-sections value: " + S); - } - return false; + StringRef S = getString(Args, OPT_compress_debug_sections, "none"); + if (S == "none") + return false; + if (S != "zlib") + error("unknown --compress-debug-sections value: " + S); + if (!zlib::isAvailable()) + error("--compress-debug-sections: zlib is not available"); + return true; } // Initializes Config members by the command line options. void LinkerDriver::readConfigs(opt::InputArgList &Args) { Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition); Config->AuxiliaryList = getArgs(Args, OPT_auxiliary); Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic); Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions); Config->CompressDebugSections = getCompressDebugSections(Args); Config->DefineCommon = getArg(Args, OPT_define_common, OPT_no_define_common, !Args.hasArg(OPT_relocatable)); Config->Demangle = getArg(Args, OPT_demangle, OPT_no_demangle, true); Config->DisableVerify = Args.hasArg(OPT_disable_verify); Config->Discard = getDiscard(Args); Config->DynamicLinker = getDynamicLinker(Args); Config->EhFrameHdr = Args.hasArg(OPT_eh_frame_hdr); Config->EmitRelocs = Args.hasArg(OPT_emit_relocs); Config->EnableNewDtags = !Args.hasArg(OPT_disable_new_dtags); Config->Entry = getString(Args, OPT_entry); Config->ExportDynamic = getArg(Args, OPT_export_dynamic, OPT_no_export_dynamic, false); Config->FatalWarnings = getArg(Args, OPT_fatal_warnings, OPT_no_fatal_warnings, false); Config->Fini = getString(Args, OPT_fini, "_fini"); Config->GcSections = getArg(Args, OPT_gc_sections, OPT_no_gc_sections, false); Config->GdbIndex = Args.hasArg(OPT_gdb_index); Config->ICF = Args.hasArg(OPT_icf); Config->Init = getString(Args, OPT_init, "_init"); Config->LTOAAPipeline = getString(Args, OPT_lto_aa_pipeline); Config->LTONewPmPasses = getString(Args, OPT_lto_newpm_passes); Config->LTOO = getInteger(Args, OPT_lto_O, 2); Config->LTOPartitions = getInteger(Args, OPT_lto_partitions, 1); Config->MapFile = getString(Args, OPT_Map); Config->NoGnuUnique = Args.hasArg(OPT_no_gnu_unique); Config->NoUndefinedVersion = Args.hasArg(OPT_no_undefined_version); Config->Nostdlib = Args.hasArg(OPT_nostdlib); Config->OFormatBinary = isOutputFormatBinary(Args); Config->Omagic = Args.hasArg(OPT_omagic); Config->OptRemarksFilename = getString(Args, OPT_opt_remarks_filename); Config->OptRemarksWithHotness = Args.hasArg(OPT_opt_remarks_with_hotness); Config->Optimize = getInteger(Args, OPT_O, 1); Config->OutputFile = getString(Args, OPT_o); Config->Pie = getArg(Args, OPT_pie, OPT_nopie, false); Config->PrintGcSections = Args.hasArg(OPT_print_gc_sections); - Config->RPath = getRPath(Args); + Config->Rpath = getRpath(Args); Config->Relocatable = Args.hasArg(OPT_relocatable); Config->SaveTemps = Args.hasArg(OPT_save_temps); Config->SearchPaths = getArgs(Args, OPT_L); Config->SectionStartMap = getSectionStartMap(Args); Config->Shared = Args.hasArg(OPT_shared); Config->SingleRoRx = Args.hasArg(OPT_no_rosegment); Config->SoName = getString(Args, OPT_soname); Config->SortSection = getSortSection(Args); Config->Strip = getStrip(Args); Config->Sysroot = getString(Args, OPT_sysroot); Config->Target1Rel = getArg(Args, OPT_target1_rel, OPT_target1_abs, false); Config->Target2 = getTarget2(Args); Config->ThinLTOCacheDir = getString(Args, OPT_thinlto_cache_dir); Config->ThinLTOCachePolicy = check(parseCachePruningPolicy(getString(Args, OPT_thinlto_cache_policy)), "--thinlto-cache-policy: invalid cache policy"); Config->ThinLTOJobs = getInteger(Args, OPT_thinlto_jobs, -1u); Config->Threads = getArg(Args, OPT_threads, OPT_no_threads, true); Config->Trace = Args.hasArg(OPT_trace); Config->Undefined = getArgs(Args, OPT_undefined); Config->UnresolvedSymbols = getUnresolvedSymbolPolicy(Args); Config->Verbose = Args.hasArg(OPT_verbose); Config->WarnCommon = Args.hasArg(OPT_warn_common); Config->ZCombreloc = !hasZOption(Args, "nocombreloc"); Config->ZExecstack = hasZOption(Args, "execstack"); Config->ZNocopyreloc = hasZOption(Args, "nocopyreloc"); Config->ZNodelete = hasZOption(Args, "nodelete"); Config->ZNodlopen = hasZOption(Args, "nodlopen"); Config->ZNow = hasZOption(Args, "now"); Config->ZOrigin = hasZOption(Args, "origin"); Config->ZRelro = !hasZOption(Args, "norelro"); Config->ZStackSize = getZOptionValue(Args, "stack-size", 0); Config->ZText = !hasZOption(Args, "notext"); Config->ZWxneeded = hasZOption(Args, "wxneeded"); if (Config->LTOO > 3) error("invalid optimization level for LTO: " + getString(Args, OPT_lto_O)); if (Config->LTOPartitions == 0) error("--lto-partitions: number of threads must be > 0"); if (Config->ThinLTOJobs == 0) error("--thinlto-jobs: number of threads must be > 0"); if (auto *Arg = Args.getLastArg(OPT_m)) { // Parse ELF{32,64}{LE,BE} and CPU type. StringRef S = Arg->getValue(); std::tie(Config->EKind, Config->EMachine, Config->OSABI) = parseEmulation(S); Config->MipsN32Abi = (S == "elf32btsmipn32" || S == "elf32ltsmipn32"); Config->Emulation = S; } if (Args.hasArg(OPT_print_map)) Config->MapFile = "-"; // --omagic is an option to create old-fashioned executables in which // .text segments are writable. Today, the option is still in use to // create special-purpose programs such as boot loaders. It doesn't // make sense to create PT_GNU_RELRO for such executables. if (Config->Omagic) Config->ZRelro = false; std::tie(Config->SysvHash, Config->GnuHash) = getHashStyle(Args); - - // Parse --build-id or --build-id=<style>. We handle "tree" as a - // synonym for "sha1" because all of our hash functions including - // -build-id=sha1 are tree hashes for performance reasons. - if (Args.hasArg(OPT_build_id)) - Config->BuildId = BuildIdKind::Fast; - if (auto *Arg = Args.getLastArg(OPT_build_id_eq)) { - StringRef S = Arg->getValue(); - if (S == "md5") { - Config->BuildId = BuildIdKind::Md5; - } else if (S == "sha1" || S == "tree") { - Config->BuildId = BuildIdKind::Sha1; - } else if (S == "uuid") { - Config->BuildId = BuildIdKind::Uuid; - } else if (S == "none") { - Config->BuildId = BuildIdKind::None; - } else if (S.startswith("0x")) { - Config->BuildId = BuildIdKind::Hexstring; - Config->BuildIdVector = parseHex(S.substr(2)); - } else { - error("unknown --build-id style: " + S); - } - } - - if (!Config->Shared && !Config->AuxiliaryList.empty()) - error("-f may not be used without -shared"); + std::tie(Config->BuildId, Config->BuildIdVector) = getBuildId(Args); if (auto *Arg = Args.getLastArg(OPT_symbol_ordering_file)) if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) Config->SymbolOrderingFile = getLines(*Buffer); // If --retain-symbol-file is used, we'll keep only the symbols listed in // the file and discard all others. if (auto *Arg = Args.getLastArg(OPT_retain_symbols_file)) { Config->DefaultSymbolVersion = VER_NDX_LOCAL; if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) for (StringRef S : getLines(*Buffer)) Config->VersionScriptGlobals.push_back( {S, /*IsExternCpp*/ false, /*HasWildcard*/ false}); } bool HasExportDynamic = getArg(Args, OPT_export_dynamic, OPT_no_export_dynamic, false); // Parses -dynamic-list and -export-dynamic-symbol. They make some // symbols private. Note that -export-dynamic takes precedence over them // as it says all symbols should be exported. if (!HasExportDynamic) { for (auto *Arg : Args.filtered(OPT_dynamic_list)) if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) readDynamicList(*Buffer); for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol)) Config->VersionScriptGlobals.push_back( {Arg->getValue(), /*IsExternCpp*/ false, /*HasWildcard*/ false}); // Dynamic lists are a simplified linker script that doesn't need the // "global:" and implicitly ends with a "local:*". Set the variables // needed to simulate that. if (Args.hasArg(OPT_dynamic_list) || Args.hasArg(OPT_export_dynamic_symbol)) { Config->ExportDynamic = true; if (!Config->Shared) Config->DefaultSymbolVersion = VER_NDX_LOCAL; } } if (auto *Arg = Args.getLastArg(OPT_version_script)) if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) readVersionScript(*Buffer); } // Some Config members do not directly correspond to any particular // command line options, but computed based on other Config values. // This function initialize such members. See Config.h for the details // of these values. static void setConfigs() { ELFKind Kind = Config->EKind; uint16_t Machine = Config->EMachine; // There is an ILP32 ABI for x86-64, although it's not very popular. // It is called the x32 ABI. bool IsX32 = (Kind == ELF32LEKind && Machine == EM_X86_64); Config->CopyRelocs = (Config->Relocatable || Config->EmitRelocs); Config->Is64 = (Kind == ELF64LEKind || Kind == ELF64BEKind); Config->IsLE = (Kind == ELF32LEKind || Kind == ELF64LEKind); Config->Endianness = Config->IsLE ? support::endianness::little : support::endianness::big; Config->IsMips64EL = (Kind == ELF64LEKind && Machine == EM_MIPS); Config->IsRela = Config->Is64 || IsX32 || Config->MipsN32Abi; Config->Pic = Config->Pie || Config->Shared; Config->Wordsize = Config->Is64 ? 8 : 4; } // Returns a value of "-format" option. static bool getBinaryOption(StringRef S) { if (S == "binary") return true; if (S == "elf" || S == "default") return false; error("unknown -format value: " + S + " (supported formats: elf, default, binary)"); return false; } void LinkerDriver::createFiles(opt::InputArgList &Args) { for (auto *Arg : Args) { switch (Arg->getOption().getID()) { case OPT_l: addLibrary(Arg->getValue()); break; case OPT_INPUT: addFile(Arg->getValue(), /*WithLOption=*/false); break; case OPT_alias_script_T: case OPT_script: if (Optional<MemoryBufferRef> MB = readFile(Arg->getValue())) readLinkerScript(*MB); break; case OPT_as_needed: Config->AsNeeded = true; break; case OPT_format: InBinary = getBinaryOption(Arg->getValue()); break; case OPT_no_as_needed: Config->AsNeeded = false; break; case OPT_Bstatic: Config->Static = true; break; case OPT_Bdynamic: Config->Static = false; break; case OPT_whole_archive: InWholeArchive = true; break; case OPT_no_whole_archive: InWholeArchive = false; break; case OPT_start_lib: InLib = true; break; case OPT_end_lib: InLib = false; break; } } if (Files.empty() && ErrorCount == 0) error("no input files"); } // If -m <machine_type> was not given, infer it from object files. void LinkerDriver::inferMachineType() { if (Config->EKind != ELFNoneKind) return; for (InputFile *F : Files) { if (F->EKind == ELFNoneKind) continue; Config->EKind = F->EKind; Config->EMachine = F->EMachine; Config->OSABI = F->OSABI; Config->MipsN32Abi = Config->EMachine == EM_MIPS && isMipsN32Abi(F); return; } error("target emulation unknown: -m or at least one .o file required"); } // Parse -z max-page-size=<value>. The default value is defined by // each target. static uint64_t getMaxPageSize(opt::InputArgList &Args) { uint64_t Val = getZOptionValue(Args, "max-page-size", Target->DefaultMaxPageSize); if (!isPowerOf2_64(Val)) error("max-page-size: value isn't a power of 2"); return Val; } // Parses -image-base option. static uint64_t getImageBase(opt::InputArgList &Args) { // Use default if no -image-base option is given. // Because we are using "Target" here, this function // has to be called after the variable is initialized. auto *Arg = Args.getLastArg(OPT_image_base); if (!Arg) return Config->Pic ? 0 : Target->DefaultImageBase; StringRef S = Arg->getValue(); uint64_t V; if (S.getAsInteger(0, V)) { error("-image-base: number expected, but got " + S); return 0; } if ((V % Config->MaxPageSize) != 0) warn("-image-base: address isn't multiple of page size: " + S); return V; } // Parses --defsym=alias option. static std::vector<std::pair<StringRef, StringRef>> getDefsym(opt::InputArgList &Args) { std::vector<std::pair<StringRef, StringRef>> Ret; for (auto *Arg : Args.filtered(OPT_defsym)) { StringRef From; StringRef To; std::tie(From, To) = StringRef(Arg->getValue()).split('='); if (!isValidCIdentifier(To)) error("--defsym: symbol name expected, but got " + To); Ret.push_back({From, To}); } return Ret; } // Do actual linking. Note that when this function is called, // all linker scripts have already been parsed. template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { SymbolTable<ELFT> Symtab; elf::Symtab<ELFT>::X = &Symtab; Target = createTarget(); Config->MaxPageSize = getMaxPageSize(Args); Config->ImageBase = getImageBase(Args); // Default output filename is "a.out" by the Unix tradition. if (Config->OutputFile.empty()) Config->OutputFile = "a.out"; // Fail early if the output file or map file is not writable. If a user has a // long link, e.g. due to a large LTO link, they do not wish to run it and // find that it failed because there was a mistake in their command-line. if (auto E = tryCreateFile(Config->OutputFile)) error("cannot open output file " + Config->OutputFile + ": " + E.message()); if (auto E = tryCreateFile(Config->MapFile)) error("cannot open map file " + Config->MapFile + ": " + E.message()); if (ErrorCount) return; // Use default entry point name if no name was given via the command // line nor linker scripts. For some reason, MIPS entry point name is // different from others. Config->WarnMissingEntry = (!Config->Entry.empty() || (!Config->Shared && !Config->Relocatable)); if (Config->Entry.empty() && !Config->Relocatable) Config->Entry = (Config->EMachine == EM_MIPS) ? "__start" : "_start"; // Handle --trace-symbol. for (auto *Arg : Args.filtered(OPT_trace_symbol)) Symtab.trace(Arg->getValue()); // Add all files to the symbol table. This will add almost all // symbols that we need to the symbol table. for (InputFile *F : Files) Symtab.addFile(F); // If an entry symbol is in a static archive, pull out that file now // to complete the symbol table. After this, no new names except a // few linker-synthesized ones will be added to the symbol table. if (Symtab.find(Config->Entry)) Symtab.addUndefined(Config->Entry); // Return if there were name resolution errors. if (ErrorCount) return; Symtab.scanUndefinedFlags(); Symtab.scanShlibUndefined(); Symtab.scanVersionScript(); Symtab.addCombinedLTOObject(); if (ErrorCount) return; // Some symbols (such as __ehdr_start) are defined lazily only when there // are undefined symbols for them, so we add these to trigger that logic. for (StringRef Sym : Script->Opt.ReferencedSymbols) Symtab.addUndefined(Sym); for (auto *Arg : Args.filtered(OPT_wrap)) Symtab.wrap(Arg->getValue()); // Handle --defsym=sym=alias option. for (std::pair<StringRef, StringRef> &Def : getDefsym(Args)) Symtab.alias(Def.first, Def.second); // Now that we have a complete list of input files. // Beyond this point, no new files are added. // Aggregate all input sections into one place. for (elf::ObjectFile<ELFT> *F : Symtab.getObjectFiles()) for (InputSectionBase *S : F->getSections()) if (S && S != &InputSection::Discarded) InputSections.push_back(S); for (BinaryFile *F : Symtab.getBinaryFiles()) for (InputSectionBase *S : F->getSections()) InputSections.push_back(cast<InputSection>(S)); // Do size optimizations: garbage collection and identical code folding. if (Config->GcSections) markLive<ELFT>(); if (Config->ICF) doIcf<ELFT>(); // MergeInputSection::splitIntoPieces needs to be called before // any call of MergeInputSection::getOffset. Do that. parallelForEach(InputSections.begin(), InputSections.end(), [](InputSectionBase *S) { if (!S->Live) return; if (Decompressor::isCompressedELFSection(S->Flags, S->Name)) S->uncompress(); if (auto *MS = dyn_cast<MergeInputSection>(S)) MS->splitIntoPieces(); }); // Write the result to the file. writeResult<ELFT>(); } Index: vendor/lld/dist/ELF/Driver.h =================================================================== --- vendor/lld/dist/ELF/Driver.h (revision 317689) +++ vendor/lld/dist/ELF/Driver.h (revision 317690) @@ -1,78 +1,77 @@ //===- Driver.h -------------------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_ELF_DRIVER_H #define LLD_ELF_DRIVER_H #include "SymbolTable.h" #include "lld/Core/LLVM.h" #include "lld/Core/Reproduce.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/raw_ostream.h" namespace lld { namespace elf { extern class LinkerDriver *Driver; class LinkerDriver { public: void main(ArrayRef<const char *> Args, bool CanExitEarly); void addFile(StringRef Path, bool WithLOption); void addLibrary(StringRef Name); private: - std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef MB); void readConfigs(llvm::opt::InputArgList &Args); void createFiles(llvm::opt::InputArgList &Args); void inferMachineType(); template <class ELFT> void link(llvm::opt::InputArgList &Args); // True if we are in --whole-archive and --no-whole-archive. bool InWholeArchive = false; // True if we are in --start-lib and --end-lib. bool InLib = false; // True if we are in -format=binary and -format=elf. bool InBinary = false; std::vector<InputFile *> Files; }; // Parses command line options. class ELFOptTable : public llvm::opt::OptTable { public: ELFOptTable(); llvm::opt::InputArgList parse(ArrayRef<const char *> Argv); }; // Create enum with OPT_xxx values for each option in Options.td enum { OPT_INVALID = 0, #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID, #include "Options.inc" #undef OPTION }; void printHelp(const char *Argv0); std::vector<uint8_t> parseHexstring(StringRef S); std::string createResponseFile(const llvm::opt::InputArgList &Args); llvm::Optional<std::string> findFromSearchPaths(StringRef Path); llvm::Optional<std::string> searchLibrary(StringRef Path); } // namespace elf } // namespace lld #endif Index: vendor/lld/dist/ELF/Error.cpp =================================================================== --- vendor/lld/dist/ELF/Error.cpp (revision 317689) +++ vendor/lld/dist/ELF/Error.cpp (revision 317690) @@ -1,116 +1,117 @@ //===- Error.cpp ----------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "Error.h" #include "Config.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Error.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/raw_ostream.h" #include <mutex> #if !defined(_MSC_VER) && !defined(__MINGW32__) #include <unistd.h> #endif using namespace llvm; using namespace lld; using namespace lld::elf; uint64_t elf::ErrorCount; raw_ostream *elf::ErrorOS; StringRef elf::Argv0; // The functions defined in this file can be called from multiple threads, // but outs() or errs() are not thread-safe. We protect them using a mutex. static std::mutex Mu; // Prints "\n" or does nothing, depending on Msg contents of // the previous call of this function. static void newline(const Twine &Msg) { // True if the previous error message contained "\n". // We want to separate multi-line error messages with a newline. static bool Flag; if (Flag) *ErrorOS << "\n"; Flag = (StringRef(Msg.str()).find('\n') != StringRef::npos); } static void print(StringRef S, raw_ostream::Colors C) { *ErrorOS << Argv0 + ": "; if (Config->ColorDiagnostics) { ErrorOS->changeColor(C, true); *ErrorOS << S; ErrorOS->resetColor(); } else { *ErrorOS << S; } } void elf::log(const Twine &Msg) { if (Config->Verbose) { std::lock_guard<std::mutex> Lock(Mu); outs() << Argv0 << ": " << Msg << "\n"; + outs().flush(); } } void elf::message(const Twine &Msg) { std::lock_guard<std::mutex> Lock(Mu); outs() << Msg << "\n"; outs().flush(); } void elf::warn(const Twine &Msg) { if (Config->FatalWarnings) { error(Msg); return; } std::lock_guard<std::mutex> Lock(Mu); newline(Msg); print("warning: ", raw_ostream::MAGENTA); *ErrorOS << Msg << "\n"; } void elf::error(const Twine &Msg) { std::lock_guard<std::mutex> Lock(Mu); newline(Msg); if (Config->ErrorLimit == 0 || ErrorCount < Config->ErrorLimit) { print("error: ", raw_ostream::RED); *ErrorOS << Msg << "\n"; } else if (ErrorCount == Config->ErrorLimit) { print("error: ", raw_ostream::RED); *ErrorOS << "too many errors emitted, stopping now" << " (use -error-limit=0 to see all errors)\n"; if (Config->ExitEarly) exitLld(1); } ++ErrorCount; } void elf::exitLld(int Val) { // Dealloc/destroy ManagedStatic variables before calling // _exit(). In a non-LTO build, this is a nop. In an LTO // build allows us to get the output of -time-passes. llvm_shutdown(); outs().flush(); errs().flush(); _exit(Val); } void elf::fatal(const Twine &Msg) { error(Msg); exitLld(1); } Index: vendor/lld/dist/ELF/InputFiles.cpp =================================================================== --- vendor/lld/dist/ELF/InputFiles.cpp (revision 317689) +++ vendor/lld/dist/ELF/InputFiles.cpp (revision 317690) @@ -1,1053 +1,1076 @@ //===- InputFiles.cpp -----------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "InputFiles.h" #include "Error.h" #include "InputSection.h" #include "LinkerScript.h" #include "Memory.h" #include "SymbolTable.h" #include "Symbols.h" #include "SyntheticSections.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/Analysis.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/LTO/LTO.h" #include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Path.h" #include "llvm/Support/TarWriter.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace llvm::ELF; using namespace llvm::object; using namespace llvm::sys::fs; using namespace lld; using namespace lld::elf; TarWriter *elf::Tar; InputFile::InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {} namespace { // In ELF object file all section addresses are zero. If we have multiple // .text sections (when using -ffunction-section or comdat group) then // LLVM DWARF parser will not be able to parse .debug_line correctly, unless // we assign each section some unique address. This callback method assigns // each section an address equal to its offset in ELF object file. class ObjectInfo : public LoadedObjectInfo { public: uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const override { return static_cast<const ELFSectionRef &>(Sec).getOffset(); } std::unique_ptr<LoadedObjectInfo> clone() const override { return std::unique_ptr<LoadedObjectInfo>(); } }; } Optional<MemoryBufferRef> elf::readFile(StringRef Path) { log(Path); auto MBOrErr = MemoryBuffer::getFile(Path); if (auto EC = MBOrErr.getError()) { error("cannot open " + Path + ": " + EC.message()); return None; } std::unique_ptr<MemoryBuffer> &MB = *MBOrErr; MemoryBufferRef MBRef = MB->getMemBufferRef(); make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); // take MB ownership if (Tar) Tar->append(relativeToRoot(Path), MBRef.getBuffer()); return MBRef; } template <class ELFT> void elf::ObjectFile<ELFT>::initializeDwarfLine() { std::unique_ptr<object::ObjectFile> Obj = check(object::ObjectFile::createObjectFile(this->MB), toString(this)); ObjectInfo ObjInfo; DWARFContextInMemory Dwarf(*Obj, &ObjInfo); DwarfLine.reset(new DWARFDebugLine(&Dwarf.getLineSection().Relocs)); DataExtractor LineData(Dwarf.getLineSection().Data, Config->IsLE, Config->Wordsize); // The second parameter is offset in .debug_line section // for compilation unit (CU) of interest. We have only one // CU (object file), so offset is always 0. DwarfLine->getOrParseLineTable(LineData, 0); } // Returns source line information for a given offset // using DWARF debug info. template <class ELFT> Optional<DILineInfo> elf::ObjectFile<ELFT>::getDILineInfo(InputSectionBase *S, uint64_t Offset) { if (!DwarfLine) initializeDwarfLine(); // The offset to CU is 0. const DWARFDebugLine::LineTable *Tbl = DwarfLine->getLineTable(0); if (!Tbl) return None; // Use fake address calcuated by adding section file offset and offset in // section. See comments for ObjectInfo class. DILineInfo Info; Tbl->getFileLineInfoForAddress( S->getOffsetInFile() + Offset, nullptr, DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, Info); if (Info.Line == 0) return None; return Info; } // Returns source line information for a given offset // using DWARF debug info. template <class ELFT> std::string elf::ObjectFile<ELFT>::getLineInfo(InputSectionBase *S, uint64_t Offset) { if (Optional<DILineInfo> Info = getDILineInfo(S, Offset)) return Info->FileName + ":" + std::to_string(Info->Line); return ""; } -// Returns "(internal)", "foo.a(bar.o)" or "baz.o". +// Returns "<internal>", "foo.a(bar.o)" or "baz.o". std::string lld::toString(const InputFile *F) { if (!F) - return "(internal)"; + return "<internal>"; if (F->ToStringCache.empty()) { if (F->ArchiveName.empty()) F->ToStringCache = F->getName(); else F->ToStringCache = (F->ArchiveName + "(" + F->getName() + ")").str(); } return F->ToStringCache; } -template <class ELFT> static ELFKind getELFKind() { - if (ELFT::TargetEndianness == support::little) - return ELFT::Is64Bits ? ELF64LEKind : ELF32LEKind; - return ELFT::Is64Bits ? ELF64BEKind : ELF32BEKind; -} - template <class ELFT> ELFFileBase<ELFT>::ELFFileBase(Kind K, MemoryBufferRef MB) : InputFile(K, MB) { - EKind = getELFKind<ELFT>(); + if (ELFT::TargetEndianness == support::little) + EKind = ELFT::Is64Bits ? ELF64LEKind : ELF32LEKind; + else + EKind = ELFT::Is64Bits ? ELF64BEKind : ELF32BEKind; + EMachine = getObj().getHeader()->e_machine; OSABI = getObj().getHeader()->e_ident[llvm::ELF::EI_OSABI]; } template <class ELFT> typename ELFT::SymRange ELFFileBase<ELFT>::getGlobalSymbols() { return makeArrayRef(Symbols.begin() + FirstNonLocal, Symbols.end()); } template <class ELFT> uint32_t ELFFileBase<ELFT>::getSectionIndex(const Elf_Sym &Sym) const { return check(getObj().getSectionIndex(&Sym, Symbols, SymtabSHNDX), toString(this)); } template <class ELFT> void ELFFileBase<ELFT>::initSymtab(ArrayRef<Elf_Shdr> Sections, const Elf_Shdr *Symtab) { FirstNonLocal = Symtab->sh_info; Symbols = check(getObj().symbols(Symtab), toString(this)); if (FirstNonLocal == 0 || FirstNonLocal > Symbols.size()) fatal(toString(this) + ": invalid sh_info in symbol table"); StringTable = check(getObj().getStringTableForSymtab(*Symtab, Sections), toString(this)); } template <class ELFT> -elf::ObjectFile<ELFT>::ObjectFile(MemoryBufferRef M) - : ELFFileBase<ELFT>(Base::ObjectKind, M) {} +elf::ObjectFile<ELFT>::ObjectFile(MemoryBufferRef M, StringRef ArchiveName) + : ELFFileBase<ELFT>(Base::ObjectKind, M) { + this->ArchiveName = ArchiveName; +} template <class ELFT> ArrayRef<SymbolBody *> elf::ObjectFile<ELFT>::getLocalSymbols() { if (this->SymbolBodies.empty()) return this->SymbolBodies; return makeArrayRef(this->SymbolBodies).slice(1, this->FirstNonLocal - 1); } template <class ELFT> ArrayRef<SymbolBody *> elf::ObjectFile<ELFT>::getSymbols() { if (this->SymbolBodies.empty()) return this->SymbolBodies; return makeArrayRef(this->SymbolBodies).slice(1); } template <class ELFT> void elf::ObjectFile<ELFT>::parse(DenseSet<CachedHashStringRef> &ComdatGroups) { // Read section and symbol tables. initializeSections(ComdatGroups); initializeSymbols(); } // Sections with SHT_GROUP and comdat bits define comdat section groups. // They are identified and deduplicated by group name. This function // returns a group name. template <class ELFT> StringRef elf::ObjectFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> Sections, const Elf_Shdr &Sec) { if (this->Symbols.empty()) this->initSymtab( Sections, check(object::getSection<ELFT>(Sections, Sec.sh_link), toString(this))); const Elf_Sym *Sym = check( object::getSymbol<ELFT>(this->Symbols, Sec.sh_info), toString(this)); return check(Sym->getName(this->StringTable), toString(this)); } template <class ELFT> ArrayRef<typename elf::ObjectFile<ELFT>::Elf_Word> elf::ObjectFile<ELFT>::getShtGroupEntries(const Elf_Shdr &Sec) { const ELFFile<ELFT> &Obj = this->getObj(); ArrayRef<Elf_Word> Entries = check( Obj.template getSectionContentsAsArray<Elf_Word>(&Sec), toString(this)); if (Entries.empty() || Entries[0] != GRP_COMDAT) fatal(toString(this) + ": unsupported SHT_GROUP format"); return Entries.slice(1); } template <class ELFT> bool elf::ObjectFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) { // We don't merge sections if -O0 (default is -O1). This makes sometimes // the linker significantly faster, although the output will be bigger. if (Config->Optimize == 0) return false; // Do not merge sections if generating a relocatable object. It makes // the code simpler because we do not need to update relocation addends // to reflect changes introduced by merging. Instead of that we write // such "merge" sections into separate OutputSections and keep SHF_MERGE // / SHF_STRINGS flags and sh_entsize value to be able to perform merging // later during a final linking. if (Config->Relocatable) return false; // A mergeable section with size 0 is useless because they don't have // any data to merge. A mergeable string section with size 0 can be // argued as invalid because it doesn't end with a null character. // We'll avoid a mess by handling them as if they were non-mergeable. if (Sec.sh_size == 0) return false; // Check for sh_entsize. The ELF spec is not clear about the zero // sh_entsize. It says that "the member [sh_entsize] contains 0 if // the section does not hold a table of fixed-size entries". We know // that Rust 1.13 produces a string mergeable section with a zero // sh_entsize. Here we just accept it rather than being picky about it. uint64_t EntSize = Sec.sh_entsize; if (EntSize == 0) return false; if (Sec.sh_size % EntSize) fatal(toString(this) + ": SHF_MERGE section size must be a multiple of sh_entsize"); uint64_t Flags = Sec.sh_flags; if (!(Flags & SHF_MERGE)) return false; if (Flags & SHF_WRITE) fatal(toString(this) + ": writable SHF_MERGE section is not supported"); // Don't try to merge if the alignment is larger than the sh_entsize and this // is not SHF_STRINGS. // // Since this is not a SHF_STRINGS, we would need to pad after every entity. // It would be equivalent for the producer of the .o to just set a larger // sh_entsize. if (Flags & SHF_STRINGS) return true; return Sec.sh_addralign <= EntSize; } template <class ELFT> void elf::ObjectFile<ELFT>::initializeSections( DenseSet<CachedHashStringRef> &ComdatGroups) { ArrayRef<Elf_Shdr> ObjSections = check(this->getObj().sections(), toString(this)); const ELFFile<ELFT> &Obj = this->getObj(); uint64_t Size = ObjSections.size(); this->Sections.resize(Size); unsigned I = -1; StringRef SectionStringTable = check(Obj.getSectionStringTable(ObjSections), toString(this)); for (const Elf_Shdr &Sec : ObjSections) { ++I; if (this->Sections[I] == &InputSection::Discarded) continue; // SHF_EXCLUDE'ed sections are discarded by the linker. However, // if -r is given, we'll let the final link discard such sections. // This is compatible with GNU. if ((Sec.sh_flags & SHF_EXCLUDE) && !Config->Relocatable) { this->Sections[I] = &InputSection::Discarded; continue; } switch (Sec.sh_type) { case SHT_GROUP: this->Sections[I] = &InputSection::Discarded; if (ComdatGroups .insert( CachedHashStringRef(getShtGroupSignature(ObjSections, Sec))) .second) continue; for (uint32_t SecIndex : getShtGroupEntries(Sec)) { if (SecIndex >= Size) fatal(toString(this) + ": invalid section index in group: " + Twine(SecIndex)); this->Sections[SecIndex] = &InputSection::Discarded; } break; case SHT_SYMTAB: this->initSymtab(ObjSections, &Sec); break; case SHT_SYMTAB_SHNDX: this->SymtabSHNDX = check(Obj.getSHNDXTable(Sec, ObjSections), toString(this)); break; case SHT_STRTAB: case SHT_NULL: break; default: this->Sections[I] = createInputSection(Sec, SectionStringTable); } // .ARM.exidx sections have a reverse dependency on the InputSection they // have a SHF_LINK_ORDER dependency, this is identified by the sh_link. if (Sec.sh_flags & SHF_LINK_ORDER) { if (Sec.sh_link >= this->Sections.size()) fatal(toString(this) + ": invalid sh_link index: " + Twine(Sec.sh_link)); this->Sections[Sec.sh_link]->DependentSections.push_back( this->Sections[I]); } } } template <class ELFT> InputSectionBase *elf::ObjectFile<ELFT>::getRelocTarget(const Elf_Shdr &Sec) { uint32_t Idx = Sec.sh_info; if (Idx >= this->Sections.size()) fatal(toString(this) + ": invalid relocated section index: " + Twine(Idx)); InputSectionBase *Target = this->Sections[Idx]; // Strictly speaking, a relocation section must be included in the // group of the section it relocates. However, LLVM 3.3 and earlier // would fail to do so, so we gracefully handle that case. if (Target == &InputSection::Discarded) return nullptr; if (!Target) fatal(toString(this) + ": unsupported relocation reference"); return Target; } +// Create a regular InputSection class that has the same contents +// as a given section. +InputSectionBase *toRegularSection(MergeInputSection *Sec) { + auto *Ret = make<InputSection>(Sec->Flags, Sec->Type, Sec->Alignment, + Sec->Data, Sec->Name); + Ret->File = Sec->File; + return Ret; +} + template <class ELFT> InputSectionBase * elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec, StringRef SectionStringTable) { StringRef Name = check( this->getObj().getSectionName(&Sec, SectionStringTable), toString(this)); switch (Sec.sh_type) { case SHT_ARM_ATTRIBUTES: // FIXME: ARM meta-data section. Retain the first attribute section // we see. The eglibc ARM dynamic loaders require the presence of an // attribute section for dlopen to work. // In a full implementation we would merge all attribute sections. if (In<ELFT>::ARMAttributes == nullptr) { In<ELFT>::ARMAttributes = make<InputSection>(this, &Sec, Name); return In<ELFT>::ARMAttributes; } return &InputSection::Discarded; case SHT_RELA: case SHT_REL: { // Find the relocation target section and associate this // section with it. Target can be discarded, for example // if it is a duplicated member of SHT_GROUP section, we // do not create or proccess relocatable sections then. InputSectionBase *Target = getRelocTarget(Sec); if (!Target) return nullptr; // This section contains relocation information. // If -r is given, we do not interpret or apply relocation // but just copy relocation sections to output. if (Config->Relocatable) return make<InputSection>(this, &Sec, Name); if (Target->FirstRelocation) fatal(toString(this) + ": multiple relocation sections to one section are not supported"); - if (isa<MergeInputSection>(Target)) - fatal(toString(this) + - ": relocations pointing to SHF_MERGE are not supported"); + // Mergeable sections with relocations are tricky because relocations + // need to be taken into account when comparing section contents for + // merging. It doesn't worth supporting such mergeable sections because + // they are rare and it'd complicates the internal design (we usually + // have to determine if two sections are mergeable early in the link + // process much before applying relocations). We simply handle mergeable + // sections with relocations as non-mergeable. + if (auto *MS = dyn_cast<MergeInputSection>(Target)) { + Target = toRegularSection(MS); + this->Sections[Sec.sh_info] = Target; + } + size_t NumRelocations; if (Sec.sh_type == SHT_RELA) { ArrayRef<Elf_Rela> Rels = check(this->getObj().relas(&Sec), toString(this)); Target->FirstRelocation = Rels.begin(); NumRelocations = Rels.size(); Target->AreRelocsRela = true; } else { ArrayRef<Elf_Rel> Rels = check(this->getObj().rels(&Sec), toString(this)); Target->FirstRelocation = Rels.begin(); NumRelocations = Rels.size(); Target->AreRelocsRela = false; } assert(isUInt<31>(NumRelocations)); Target->NumRelocations = NumRelocations; // Relocation sections processed by the linker are usually removed // from the output, so returning `nullptr` for the normal case. // However, if -emit-relocs is given, we need to leave them in the output. // (Some post link analysis tools need this information.) if (Config->EmitRelocs) { InputSection *RelocSec = make<InputSection>(this, &Sec, Name); // We will not emit relocation section if target was discarded. Target->DependentSections.push_back(RelocSec); return RelocSec; } return nullptr; } } // The GNU linker uses .note.GNU-stack section as a marker indicating // that the code in the object file does not expect that the stack is // executable (in terms of NX bit). If all input files have the marker, // the GNU linker adds a PT_GNU_STACK segment to tells the loader to // make the stack non-executable. Most object files have this section as // of 2017. // // But making the stack non-executable is a norm today for security // reasons. Failure to do so may result in a serious security issue. // Therefore, we make LLD always add PT_GNU_STACK unless it is // explicitly told to do otherwise (by -z execstack). Because the stack // executable-ness is controlled solely by command line options, // .note.GNU-stack sections are simply ignored. if (Name == ".note.GNU-stack") return &InputSection::Discarded; // Split stacks is a feature to support a discontiguous stack. At least // as of 2017, it seems that the feature is not being used widely. // Only GNU gold supports that. We don't. For the details about that, // see https://gcc.gnu.org/wiki/SplitStacks if (Name == ".note.GNU-split-stack") { error(toString(this) + ": object file compiled with -fsplit-stack is not supported"); return &InputSection::Discarded; } if (Config->Strip != StripPolicy::None && Name.startswith(".debug")) return &InputSection::Discarded; + // If -gdb-index is given, LLD creates .gdb_index section, and that + // section serves the same purpose as .debug_gnu_pub{names,types} sections. + // If that's the case, we want to eliminate .debug_gnu_pub{names,types} + // because they are redundant and can waste large amount of disk space + // (for example, they are about 400 MiB in total for a clang debug build.) + if (Config->GdbIndex && + (Name == ".debug_gnu_pubnames" || Name == ".debug_gnu_pubtypes")) + return &InputSection::Discarded; + // The linkonce feature is a sort of proto-comdat. Some glibc i386 object // files contain definitions of symbol "__x86.get_pc_thunk.bx" in linkonce // sections. Drop those sections to avoid duplicate symbol errors. // FIXME: This is glibc PR20543, we should remove this hack once that has been // fixed for a while. if (Name.startswith(".gnu.linkonce.")) return &InputSection::Discarded; // The linker merges EH (exception handling) frames and creates a // .eh_frame_hdr section for runtime. So we handle them with a special // class. For relocatable outputs, they are just passed through. if (Name == ".eh_frame" && !Config->Relocatable) return make<EhInputSection>(this, &Sec, Name); if (shouldMerge(Sec)) return make<MergeInputSection>(this, &Sec, Name); return make<InputSection>(this, &Sec, Name); } template <class ELFT> void elf::ObjectFile<ELFT>::initializeSymbols() { SymbolBodies.reserve(this->Symbols.size()); for (const Elf_Sym &Sym : this->Symbols) SymbolBodies.push_back(createSymbolBody(&Sym)); } template <class ELFT> InputSectionBase *elf::ObjectFile<ELFT>::getSection(const Elf_Sym &Sym) const { uint32_t Index = this->getSectionIndex(Sym); if (Index >= this->Sections.size()) fatal(toString(this) + ": invalid section index: " + Twine(Index)); InputSectionBase *S = this->Sections[Index]; // We found that GNU assembler 2.17.50 [FreeBSD] 2007-07-03 could // generate broken objects. STT_SECTION/STT_NOTYPE symbols can be // associated with SHT_REL[A]/SHT_SYMTAB/SHT_STRTAB sections. // In this case it is fine for section to be null here as we do not // allocate sections of these types. if (!S) { if (Index == 0 || Sym.getType() == STT_SECTION || Sym.getType() == STT_NOTYPE) return nullptr; fatal(toString(this) + ": invalid section index: " + Twine(Index)); } if (S == &InputSection::Discarded) return S; return S->Repl; } template <class ELFT> SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) { int Binding = Sym->getBinding(); InputSectionBase *Sec = getSection(*Sym); uint8_t StOther = Sym->st_other; uint8_t Type = Sym->getType(); uint64_t Value = Sym->st_value; uint64_t Size = Sym->st_size; if (Binding == STB_LOCAL) { if (Sym->getType() == STT_FILE) SourceFile = check(Sym->getName(this->StringTable), toString(this)); if (this->StringTable.size() <= Sym->st_name) fatal(toString(this) + ": invalid symbol name offset"); StringRefZ Name = this->StringTable.data() + Sym->st_name; if (Sym->st_shndx == SHN_UNDEF) return make<Undefined>(Name, /*IsLocal=*/true, StOther, Type, this); return make<DefinedRegular>(Name, /*IsLocal=*/true, StOther, Type, Value, Size, Sec, this); } StringRef Name = check(Sym->getName(this->StringTable), toString(this)); switch (Sym->st_shndx) { case SHN_UNDEF: return elf::Symtab<ELFT>::X ->addUndefined(Name, /*IsLocal=*/false, Binding, StOther, Type, /*CanOmitFromDynSym=*/false, this) ->body(); case SHN_COMMON: if (Value == 0 || Value >= UINT32_MAX) fatal(toString(this) + ": common symbol '" + Name + "' has invalid alignment: " + Twine(Value)); return elf::Symtab<ELFT>::X ->addCommon(Name, Size, Value, Binding, StOther, Type, this) ->body(); } switch (Binding) { default: fatal(toString(this) + ": unexpected binding: " + Twine(Binding)); case STB_GLOBAL: case STB_WEAK: case STB_GNU_UNIQUE: if (Sec == &InputSection::Discarded) return elf::Symtab<ELFT>::X ->addUndefined(Name, /*IsLocal=*/false, Binding, StOther, Type, /*CanOmitFromDynSym=*/false, this) ->body(); return elf::Symtab<ELFT>::X ->addRegular(Name, StOther, Type, Value, Size, Binding, Sec, this) ->body(); } } template <class ELFT> void ArchiveFile::parse() { File = check(Archive::create(MB), MB.getBufferIdentifier() + ": failed to parse archive"); // Read the symbol table to construct Lazy objects. for (const Archive::Symbol &Sym : File->symbols()) { Symtab<ELFT>::X->addLazyArchive(this, Sym); } if (File->symbols().begin() == File->symbols().end()) Config->ArchiveWithoutSymbolsSeen = true; } // Returns a buffer pointing to a member file containing a given symbol. std::pair<MemoryBufferRef, uint64_t> ArchiveFile::getMember(const Archive::Symbol *Sym) { Archive::Child C = check(Sym->getMember(), toString(this) + ": could not get the member for symbol " + Sym->getName()); if (!Seen.insert(C.getChildOffset()).second) return {MemoryBufferRef(), 0}; MemoryBufferRef Ret = check(C.getMemoryBufferRef(), toString(this) + ": could not get the buffer for the member defining symbol " + Sym->getName()); if (C.getParent()->isThin() && Tar) Tar->append(relativeToRoot(check(C.getFullName(), toString(this))), Ret.getBuffer()); if (C.getParent()->isThin()) return {Ret, 0}; return {Ret, C.getChildOffset()}; } template <class ELFT> SharedFile<ELFT>::SharedFile(MemoryBufferRef M, StringRef DefaultSoName) : ELFFileBase<ELFT>(Base::SharedKind, M), SoName(DefaultSoName), AsNeeded(Config->AsNeeded) {} template <class ELFT> const typename ELFT::Shdr * SharedFile<ELFT>::getSection(const Elf_Sym &Sym) const { return check( this->getObj().getSection(&Sym, this->Symbols, this->SymtabSHNDX), toString(this)); } // Partially parse the shared object file so that we can call // getSoName on this object. template <class ELFT> void SharedFile<ELFT>::parseSoName() { const Elf_Shdr *DynamicSec = nullptr; const ELFFile<ELFT> Obj = this->getObj(); ArrayRef<Elf_Shdr> Sections = check(Obj.sections(), toString(this)); // Search for .dynsym, .dynamic, .symtab, .gnu.version and .gnu.version_d. for (const Elf_Shdr &Sec : Sections) { switch (Sec.sh_type) { default: continue; case SHT_DYNSYM: this->initSymtab(Sections, &Sec); break; case SHT_DYNAMIC: DynamicSec = &Sec; break; case SHT_SYMTAB_SHNDX: this->SymtabSHNDX = check(Obj.getSHNDXTable(Sec, Sections), toString(this)); break; case SHT_GNU_versym: this->VersymSec = &Sec; break; case SHT_GNU_verdef: this->VerdefSec = &Sec; break; } } if (this->VersymSec && this->Symbols.empty()) error("SHT_GNU_versym should be associated with symbol table"); // Search for a DT_SONAME tag to initialize this->SoName. if (!DynamicSec) return; ArrayRef<Elf_Dyn> Arr = check(Obj.template getSectionContentsAsArray<Elf_Dyn>(DynamicSec), toString(this)); for (const Elf_Dyn &Dyn : Arr) { if (Dyn.d_tag == DT_SONAME) { uint64_t Val = Dyn.getVal(); if (Val >= this->StringTable.size()) fatal(toString(this) + ": invalid DT_SONAME entry"); - SoName = StringRef(this->StringTable.data() + Val); + SoName = this->StringTable.data() + Val; return; } } } // Parse the version definitions in the object file if present. Returns a vector // whose nth element contains a pointer to the Elf_Verdef for version identifier // n. Version identifiers that are not definitions map to nullptr. The array // always has at least length 1. template <class ELFT> std::vector<const typename ELFT::Verdef *> SharedFile<ELFT>::parseVerdefs(const Elf_Versym *&Versym) { std::vector<const Elf_Verdef *> Verdefs(1); // We only need to process symbol versions for this DSO if it has both a // versym and a verdef section, which indicates that the DSO contains symbol // version definitions. if (!VersymSec || !VerdefSec) return Verdefs; // The location of the first global versym entry. const char *Base = this->MB.getBuffer().data(); Versym = reinterpret_cast<const Elf_Versym *>(Base + VersymSec->sh_offset) + this->FirstNonLocal; // We cannot determine the largest verdef identifier without inspecting // every Elf_Verdef, but both bfd and gold assign verdef identifiers // sequentially starting from 1, so we predict that the largest identifier // will be VerdefCount. unsigned VerdefCount = VerdefSec->sh_info; Verdefs.resize(VerdefCount + 1); // Build the Verdefs array by following the chain of Elf_Verdef objects // from the start of the .gnu.version_d section. const char *Verdef = Base + VerdefSec->sh_offset; for (unsigned I = 0; I != VerdefCount; ++I) { auto *CurVerdef = reinterpret_cast<const Elf_Verdef *>(Verdef); Verdef += CurVerdef->vd_next; unsigned VerdefIndex = CurVerdef->vd_ndx; if (Verdefs.size() <= VerdefIndex) Verdefs.resize(VerdefIndex + 1); Verdefs[VerdefIndex] = CurVerdef; } return Verdefs; } // Fully parse the shared object file. This must be called after parseSoName(). template <class ELFT> void SharedFile<ELFT>::parseRest() { // Create mapping from version identifiers to Elf_Verdef entries. const Elf_Versym *Versym = nullptr; std::vector<const Elf_Verdef *> Verdefs = parseVerdefs(Versym); Elf_Sym_Range Syms = this->getGlobalSymbols(); for (const Elf_Sym &Sym : Syms) { unsigned VersymIndex = 0; if (Versym) { VersymIndex = Versym->vs_index; ++Versym; } bool Hidden = VersymIndex & VERSYM_HIDDEN; VersymIndex = VersymIndex & ~VERSYM_HIDDEN; StringRef Name = check(Sym.getName(this->StringTable), toString(this)); if (Sym.isUndefined()) { Undefs.push_back(Name); continue; } // Ignore local symbols. if (Versym && VersymIndex == VER_NDX_LOCAL) continue; const Elf_Verdef *V = VersymIndex == VER_NDX_GLOBAL ? nullptr : Verdefs[VersymIndex]; if (!Hidden) elf::Symtab<ELFT>::X->addShared(this, Name, Sym, V); // Also add the symbol with the versioned name to handle undefined symbols // with explicit versions. if (V) { StringRef VerName = this->StringTable.data() + V->getAux()->vda_name; - Name = Saver.save(Twine(Name) + "@" + VerName); + Name = Saver.save(Name + "@" + VerName); elf::Symtab<ELFT>::X->addShared(this, Name, Sym, V); } } } static ELFKind getBitcodeELFKind(const Triple &T) { if (T.isLittleEndian()) return T.isArch64Bit() ? ELF64LEKind : ELF32LEKind; return T.isArch64Bit() ? ELF64BEKind : ELF32BEKind; } static uint8_t getBitcodeMachineKind(StringRef Path, const Triple &T) { switch (T.getArch()) { case Triple::aarch64: return EM_AARCH64; case Triple::arm: case Triple::thumb: return EM_ARM; case Triple::mips: case Triple::mipsel: case Triple::mips64: case Triple::mips64el: return EM_MIPS; case Triple::ppc: return EM_PPC; case Triple::ppc64: return EM_PPC64; case Triple::x86: return T.isOSIAMCU() ? EM_IAMCU : EM_386; case Triple::x86_64: return EM_X86_64; default: fatal(Path + ": could not infer e_machine from bitcode target triple " + T.str()); } } BitcodeFile::BitcodeFile(MemoryBufferRef MB, StringRef ArchiveName, uint64_t OffsetInArchive) : InputFile(BitcodeKind, MB) { this->ArchiveName = ArchiveName; // Here we pass a new MemoryBufferRef which is identified by ArchiveName // (the fully resolved path of the archive) + member name + offset of the // member in the archive. // ThinLTO uses the MemoryBufferRef identifier to access its internal // data structures and if two archives define two members with the same name, // this causes a collision which result in only one of the objects being // taken into consideration at LTO time (which very likely causes undefined // symbols later in the link stage). MemoryBufferRef MBRef(MB.getBuffer(), Saver.save(ArchiveName + MB.getBufferIdentifier() + utostr(OffsetInArchive))); Obj = check(lto::InputFile::create(MBRef), toString(this)); Triple T(Obj->getTargetTriple()); EKind = getBitcodeELFKind(T); EMachine = getBitcodeMachineKind(MB.getBufferIdentifier(), T); } static uint8_t mapVisibility(GlobalValue::VisibilityTypes GvVisibility) { switch (GvVisibility) { case GlobalValue::DefaultVisibility: return STV_DEFAULT; case GlobalValue::HiddenVisibility: return STV_HIDDEN; case GlobalValue::ProtectedVisibility: return STV_PROTECTED; } llvm_unreachable("unknown visibility"); } template <class ELFT> static Symbol *createBitcodeSymbol(const std::vector<bool> &KeptComdats, const lto::InputFile::Symbol &ObjSym, BitcodeFile *F) { StringRef NameRef = Saver.save(ObjSym.getName()); uint32_t Binding = ObjSym.isWeak() ? STB_WEAK : STB_GLOBAL; uint8_t Type = ObjSym.isTLS() ? STT_TLS : STT_NOTYPE; uint8_t Visibility = mapVisibility(ObjSym.getVisibility()); bool CanOmitFromDynSym = ObjSym.canBeOmittedFromSymbolTable(); int C = ObjSym.getComdatIndex(); if (C != -1 && !KeptComdats[C]) return Symtab<ELFT>::X->addUndefined(NameRef, /*IsLocal=*/false, Binding, Visibility, Type, CanOmitFromDynSym, F); if (ObjSym.isUndefined()) return Symtab<ELFT>::X->addUndefined(NameRef, /*IsLocal=*/false, Binding, Visibility, Type, CanOmitFromDynSym, F); if (ObjSym.isCommon()) return Symtab<ELFT>::X->addCommon(NameRef, ObjSym.getCommonSize(), ObjSym.getCommonAlignment(), Binding, Visibility, STT_OBJECT, F); return Symtab<ELFT>::X->addBitcode(NameRef, Binding, Visibility, Type, CanOmitFromDynSym, F); } template <class ELFT> void BitcodeFile::parse(DenseSet<CachedHashStringRef> &ComdatGroups) { std::vector<bool> KeptComdats; for (StringRef S : Obj->getComdatTable()) KeptComdats.push_back(ComdatGroups.insert(CachedHashStringRef(S)).second); for (const lto::InputFile::Symbol &ObjSym : Obj->symbols()) Symbols.push_back(createBitcodeSymbol<ELFT>(KeptComdats, ObjSym, this)); } -// Small bit of template meta programming to handle the SharedFile constructor -// being the only one with a DefaultSoName parameter. -template <template <class> class T, class E> -typename std::enable_if<std::is_same<T<E>, SharedFile<E>>::value, - InputFile *>::type -createELFAux(MemoryBufferRef MB, StringRef DefaultSoName) { - return make<T<E>>(MB, DefaultSoName); -} -template <template <class> class T, class E> -typename std::enable_if<!std::is_same<T<E>, SharedFile<E>>::value, - InputFile *>::type -createELFAux(MemoryBufferRef MB, StringRef DefaultSoName) { - return make<T<E>>(MB); -} - -template <template <class> class T> -static InputFile *createELFFile(MemoryBufferRef MB, StringRef DefaultSoName) { +static ELFKind getELFKind(MemoryBufferRef MB) { unsigned char Size; unsigned char Endian; std::tie(Size, Endian) = getElfArchType(MB.getBuffer()); + if (Endian != ELFDATA2LSB && Endian != ELFDATA2MSB) fatal(MB.getBufferIdentifier() + ": invalid data encoding"); + if (Size != ELFCLASS32 && Size != ELFCLASS64) + fatal(MB.getBufferIdentifier() + ": invalid file class"); size_t BufSize = MB.getBuffer().size(); if ((Size == ELFCLASS32 && BufSize < sizeof(Elf32_Ehdr)) || (Size == ELFCLASS64 && BufSize < sizeof(Elf64_Ehdr))) fatal(MB.getBufferIdentifier() + ": file is too short"); - InputFile *Obj; - if (Size == ELFCLASS32 && Endian == ELFDATA2LSB) - Obj = createELFAux<T, ELF32LE>(MB, DefaultSoName); - else if (Size == ELFCLASS32 && Endian == ELFDATA2MSB) - Obj = createELFAux<T, ELF32BE>(MB, DefaultSoName); - else if (Size == ELFCLASS64 && Endian == ELFDATA2LSB) - Obj = createELFAux<T, ELF64LE>(MB, DefaultSoName); - else if (Size == ELFCLASS64 && Endian == ELFDATA2MSB) - Obj = createELFAux<T, ELF64BE>(MB, DefaultSoName); - else - fatal(MB.getBufferIdentifier() + ": invalid file class"); - - if (!Config->FirstElf) - Config->FirstElf = Obj; - return Obj; + if (Size == ELFCLASS32) + return (Endian == ELFDATA2LSB) ? ELF32LEKind : ELF32BEKind; + return (Endian == ELFDATA2LSB) ? ELF64LEKind : ELF64BEKind; } template <class ELFT> void BinaryFile::parse() { - StringRef Buf = MB.getBuffer(); - ArrayRef<uint8_t> Data = - makeArrayRef<uint8_t>((const uint8_t *)Buf.data(), Buf.size()); - - std::string Filename = MB.getBufferIdentifier(); - std::transform(Filename.begin(), Filename.end(), Filename.begin(), - [](char C) { return isalnum(C) ? C : '_'; }); - Filename = "_binary_" + Filename; - StringRef StartName = Saver.save(Twine(Filename) + "_start"); - StringRef EndName = Saver.save(Twine(Filename) + "_end"); - StringRef SizeName = Saver.save(Twine(Filename) + "_size"); - + ArrayRef<uint8_t> Data = toArrayRef(MB.getBuffer()); auto *Section = make<InputSection>(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, 8, Data, ".data"); Sections.push_back(Section); - elf::Symtab<ELFT>::X->addRegular(StartName, STV_DEFAULT, STT_OBJECT, 0, 0, - STB_GLOBAL, Section, nullptr); - elf::Symtab<ELFT>::X->addRegular(EndName, STV_DEFAULT, STT_OBJECT, - Data.size(), 0, STB_GLOBAL, Section, + // For each input file foo that is embedded to a result as a binary + // blob, we define _binary_foo_{start,end,size} symbols, so that + // user programs can access blobs by name. Non-alphanumeric + // characters in a filename are replaced with underscore. + std::string S = "_binary_" + MB.getBufferIdentifier().str(); + for (size_t I = 0; I < S.size(); ++I) + if (!isalnum(S[I])) + S[I] = '_'; + + elf::Symtab<ELFT>::X->addRegular(Saver.save(S + "_start"), STV_DEFAULT, + STT_OBJECT, 0, 0, STB_GLOBAL, Section, nullptr); - elf::Symtab<ELFT>::X->addRegular(SizeName, STV_DEFAULT, STT_OBJECT, - Data.size(), 0, STB_GLOBAL, nullptr, - nullptr); + elf::Symtab<ELFT>::X->addRegular(Saver.save(S + "_end"), STV_DEFAULT, + STT_OBJECT, Data.size(), 0, STB_GLOBAL, + Section, nullptr); + elf::Symtab<ELFT>::X->addRegular(Saver.save(S + "_size"), STV_DEFAULT, + STT_OBJECT, Data.size(), 0, STB_GLOBAL, + nullptr, nullptr); } static bool isBitcode(MemoryBufferRef MB) { using namespace sys::fs; return identify_magic(MB.getBuffer()) == file_magic::bitcode; } InputFile *elf::createObjectFile(MemoryBufferRef MB, StringRef ArchiveName, uint64_t OffsetInArchive) { - InputFile *F = isBitcode(MB) - ? make<BitcodeFile>(MB, ArchiveName, OffsetInArchive) - : createELFFile<ObjectFile>(MB, ""); - F->ArchiveName = ArchiveName; - return F; + if (isBitcode(MB)) + return make<BitcodeFile>(MB, ArchiveName, OffsetInArchive); + + switch (getELFKind(MB)) { + case ELF32LEKind: + return make<ObjectFile<ELF32LE>>(MB, ArchiveName); + case ELF32BEKind: + return make<ObjectFile<ELF32BE>>(MB, ArchiveName); + case ELF64LEKind: + return make<ObjectFile<ELF64LE>>(MB, ArchiveName); + case ELF64BEKind: + return make<ObjectFile<ELF64BE>>(MB, ArchiveName); + default: + llvm_unreachable("getELFKind"); + } } InputFile *elf::createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName) { - return createELFFile<SharedFile>(MB, DefaultSoName); + switch (getELFKind(MB)) { + case ELF32LEKind: + return make<SharedFile<ELF32LE>>(MB, DefaultSoName); + case ELF32BEKind: + return make<SharedFile<ELF32BE>>(MB, DefaultSoName); + case ELF64LEKind: + return make<SharedFile<ELF64LE>>(MB, DefaultSoName); + case ELF64BEKind: + return make<SharedFile<ELF64BE>>(MB, DefaultSoName); + default: + llvm_unreachable("getELFKind"); + } } MemoryBufferRef LazyObjectFile::getBuffer() { if (Seen) return MemoryBufferRef(); Seen = true; return MB; } template <class ELFT> void LazyObjectFile::parse() { for (StringRef Sym : getSymbols()) Symtab<ELFT>::X->addLazyObject(Sym, *this); } template <class ELFT> std::vector<StringRef> LazyObjectFile::getElfSymbols() { typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::SymRange Elf_Sym_Range; const ELFFile<ELFT> Obj(this->MB.getBuffer()); ArrayRef<Elf_Shdr> Sections = check(Obj.sections(), toString(this)); for (const Elf_Shdr &Sec : Sections) { if (Sec.sh_type != SHT_SYMTAB) continue; Elf_Sym_Range Syms = check(Obj.symbols(&Sec), toString(this)); uint32_t FirstNonLocal = Sec.sh_info; StringRef StringTable = check(Obj.getStringTableForSymtab(Sec, Sections), toString(this)); std::vector<StringRef> V; for (const Elf_Sym &Sym : Syms.slice(FirstNonLocal)) if (Sym.st_shndx != SHN_UNDEF) V.push_back(check(Sym.getName(StringTable), toString(this))); return V; } return {}; } std::vector<StringRef> LazyObjectFile::getBitcodeSymbols() { std::unique_ptr<lto::InputFile> Obj = check(lto::InputFile::create(this->MB), toString(this)); std::vector<StringRef> V; for (const lto::InputFile::Symbol &Sym : Obj->symbols()) if (!Sym.isUndefined()) V.push_back(Saver.save(Sym.getName())); return V; } // Returns a vector of globally-visible defined symbol names. std::vector<StringRef> LazyObjectFile::getSymbols() { if (isBitcode(this->MB)) return getBitcodeSymbols(); - unsigned char Size; - unsigned char Endian; - std::tie(Size, Endian) = getElfArchType(this->MB.getBuffer()); - if (Size == ELFCLASS32) { - if (Endian == ELFDATA2LSB) - return getElfSymbols<ELF32LE>(); + switch (getELFKind(this->MB)) { + case ELF32LEKind: + return getElfSymbols<ELF32LE>(); + case ELF32BEKind: return getElfSymbols<ELF32BE>(); - } - if (Endian == ELFDATA2LSB) + case ELF64LEKind: return getElfSymbols<ELF64LE>(); - return getElfSymbols<ELF64BE>(); + case ELF64BEKind: + return getElfSymbols<ELF64BE>(); + default: + llvm_unreachable("getELFKind"); + } } template void ArchiveFile::parse<ELF32LE>(); template void ArchiveFile::parse<ELF32BE>(); template void ArchiveFile::parse<ELF64LE>(); template void ArchiveFile::parse<ELF64BE>(); template void BitcodeFile::parse<ELF32LE>(DenseSet<CachedHashStringRef> &); template void BitcodeFile::parse<ELF32BE>(DenseSet<CachedHashStringRef> &); template void BitcodeFile::parse<ELF64LE>(DenseSet<CachedHashStringRef> &); template void BitcodeFile::parse<ELF64BE>(DenseSet<CachedHashStringRef> &); template void LazyObjectFile::parse<ELF32LE>(); template void LazyObjectFile::parse<ELF32BE>(); template void LazyObjectFile::parse<ELF64LE>(); template void LazyObjectFile::parse<ELF64BE>(); template class elf::ELFFileBase<ELF32LE>; template class elf::ELFFileBase<ELF32BE>; template class elf::ELFFileBase<ELF64LE>; template class elf::ELFFileBase<ELF64BE>; template class elf::ObjectFile<ELF32LE>; template class elf::ObjectFile<ELF32BE>; template class elf::ObjectFile<ELF64LE>; template class elf::ObjectFile<ELF64BE>; template class elf::SharedFile<ELF32LE>; template class elf::SharedFile<ELF32BE>; template class elf::SharedFile<ELF64LE>; template class elf::SharedFile<ELF64BE>; template void BinaryFile::parse<ELF32LE>(); template void BinaryFile::parse<ELF32BE>(); template void BinaryFile::parse<ELF64LE>(); template void BinaryFile::parse<ELF64BE>(); Index: vendor/lld/dist/ELF/InputFiles.h =================================================================== --- vendor/lld/dist/ELF/InputFiles.h (revision 317689) +++ vendor/lld/dist/ELF/InputFiles.h (revision 317690) @@ -1,333 +1,333 @@ //===- InputFiles.h ---------------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_ELF_INPUT_FILES_H #define LLD_ELF_INPUT_FILES_H #include "Config.h" #include "InputSection.h" #include "Error.h" #include "Symbols.h" #include "lld/Core/LLVM.h" #include "lld/Core/Reproduce.h" #include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/IR/Comdat.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ELF.h" #include "llvm/Object/IRObjectFile.h" #include <map> namespace llvm { class DWARFDebugLine; class TarWriter; struct DILineInfo; namespace lto { class InputFile; } } namespace lld { namespace elf { class InputFile; } // Returns "(internal)", "foo.a(bar.o)" or "baz.o". std::string toString(const elf::InputFile *F); namespace elf { using llvm::object::Archive; class Lazy; class SymbolBody; // If -reproduce option is given, all input files are written // to this tar archive. extern llvm::TarWriter *Tar; // Opens a given file. llvm::Optional<MemoryBufferRef> readFile(StringRef Path); // The root class of input files. class InputFile { public: enum Kind { ObjectKind, SharedKind, LazyObjectKind, ArchiveKind, BitcodeKind, BinaryKind, }; Kind kind() const { return FileKind; } StringRef getName() const { return MB.getBufferIdentifier(); } MemoryBufferRef MB; // Returns sections. It is a runtime error to call this function // on files that don't have the notion of sections. ArrayRef<InputSectionBase *> getSections() const { assert(FileKind == ObjectKind || FileKind == BinaryKind); return Sections; } // Filename of .a which contained this file. If this file was // not in an archive file, it is the empty string. We use this // string for creating error messages. StringRef ArchiveName; // If this is an architecture-specific file, the following members // have ELF type (i.e. ELF{32,64}{LE,BE}) and target machine type. ELFKind EKind = ELFNoneKind; uint16_t EMachine = llvm::ELF::EM_NONE; uint8_t OSABI = 0; // Cache for toString(). Only toString() should use this member. mutable std::string ToStringCache; protected: InputFile(Kind K, MemoryBufferRef M); std::vector<InputSectionBase *> Sections; private: const Kind FileKind; }; template <typename ELFT> class ELFFileBase : public InputFile { public: typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::Word Elf_Word; typedef typename ELFT::SymRange Elf_Sym_Range; ELFFileBase(Kind K, MemoryBufferRef M); static bool classof(const InputFile *F) { Kind K = F->kind(); return K == ObjectKind || K == SharedKind; } llvm::object::ELFFile<ELFT> getObj() const { return llvm::object::ELFFile<ELFT>(MB.getBuffer()); } StringRef getStringTable() const { return StringTable; } uint32_t getSectionIndex(const Elf_Sym &Sym) const; Elf_Sym_Range getGlobalSymbols(); protected: ArrayRef<Elf_Sym> Symbols; uint32_t FirstNonLocal = 0; ArrayRef<Elf_Word> SymtabSHNDX; StringRef StringTable; void initSymtab(ArrayRef<Elf_Shdr> Sections, const Elf_Shdr *Symtab); }; // .o file. template <class ELFT> class ObjectFile : public ELFFileBase<ELFT> { typedef ELFFileBase<ELFT> Base; typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rela Elf_Rela; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Word Elf_Word; StringRef getShtGroupSignature(ArrayRef<Elf_Shdr> Sections, const Elf_Shdr &Sec); ArrayRef<Elf_Word> getShtGroupEntries(const Elf_Shdr &Sec); public: static bool classof(const InputFile *F) { return F->kind() == Base::ObjectKind; } ArrayRef<SymbolBody *> getSymbols(); ArrayRef<SymbolBody *> getLocalSymbols(); - explicit ObjectFile(MemoryBufferRef M); + ObjectFile(MemoryBufferRef M, StringRef ArchiveName); void parse(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups); InputSectionBase *getSection(const Elf_Sym &Sym) const; SymbolBody &getSymbolBody(uint32_t SymbolIndex) const { if (SymbolIndex >= SymbolBodies.size()) fatal(toString(this) + ": invalid symbol index"); return *SymbolBodies[SymbolIndex]; } template <typename RelT> SymbolBody &getRelocTargetSym(const RelT &Rel) const { uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL); return getSymbolBody(SymIndex); } // Returns source line information for a given offset. // If no information is available, returns "". std::string getLineInfo(InputSectionBase *S, uint64_t Offset); llvm::Optional<llvm::DILineInfo> getDILineInfo(InputSectionBase *, uint64_t); // MIPS GP0 value defined by this file. This value represents the gp value // used to create the relocatable object and required to support // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations. uint32_t MipsGp0 = 0; // Name of source file obtained from STT_FILE symbol value, // or empty string if there is no such symbol in object file // symbol table. StringRef SourceFile; private: void initializeSections(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups); void initializeSymbols(); void initializeDwarfLine(); InputSectionBase *getRelocTarget(const Elf_Shdr &Sec); InputSectionBase *createInputSection(const Elf_Shdr &Sec, StringRef SectionStringTable); bool shouldMerge(const Elf_Shdr &Sec); SymbolBody *createSymbolBody(const Elf_Sym *Sym); // List of all symbols referenced or defined by this file. std::vector<SymbolBody *> SymbolBodies; // Debugging information to retrieve source file and line for error // reporting. Linker may find reasonable number of errors in a // single object file, so we cache debugging information in order to // parse it only once for each object file we link. std::unique_ptr<llvm::DWARFDebugLine> DwarfLine; }; // LazyObjectFile is analogous to ArchiveFile in the sense that // the file contains lazy symbols. The difference is that // LazyObjectFile wraps a single file instead of multiple files. // // This class is used for --start-lib and --end-lib options which // instruct the linker to link object files between them with the // archive file semantics. class LazyObjectFile : public InputFile { public: explicit LazyObjectFile(MemoryBufferRef M) : InputFile(LazyObjectKind, M) {} static bool classof(const InputFile *F) { return F->kind() == LazyObjectKind; } template <class ELFT> void parse(); MemoryBufferRef getBuffer(); private: std::vector<StringRef> getSymbols(); template <class ELFT> std::vector<StringRef> getElfSymbols(); std::vector<StringRef> getBitcodeSymbols(); bool Seen = false; }; // An ArchiveFile object represents a .a file. class ArchiveFile : public InputFile { public: explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {} static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; } template <class ELFT> void parse(); // Returns a memory buffer for a given symbol and the offset in the archive // for the member. An empty memory buffer and an offset of zero // is returned if we have already returned the same memory buffer. // (So that we don't instantiate same members more than once.) std::pair<MemoryBufferRef, uint64_t> getMember(const Archive::Symbol *Sym); private: std::unique_ptr<Archive> File; llvm::DenseSet<uint64_t> Seen; }; class BitcodeFile : public InputFile { public: BitcodeFile(MemoryBufferRef M, StringRef ArchiveName, uint64_t OffsetInArchive); static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; } template <class ELFT> void parse(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups); ArrayRef<Symbol *> getSymbols() { return Symbols; } std::unique_ptr<llvm::lto::InputFile> Obj; private: std::vector<Symbol *> Symbols; }; // .so file. template <class ELFT> class SharedFile : public ELFFileBase<ELFT> { typedef ELFFileBase<ELFT> Base; typedef typename ELFT::Dyn Elf_Dyn; typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::SymRange Elf_Sym_Range; typedef typename ELFT::Verdef Elf_Verdef; typedef typename ELFT::Versym Elf_Versym; std::vector<StringRef> Undefs; const Elf_Shdr *VersymSec = nullptr; const Elf_Shdr *VerdefSec = nullptr; public: std::string SoName; const Elf_Shdr *getSection(const Elf_Sym &Sym) const; llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; } static bool classof(const InputFile *F) { return F->kind() == Base::SharedKind; } SharedFile(MemoryBufferRef M, StringRef DefaultSoName); void parseSoName(); void parseRest(); std::vector<const Elf_Verdef *> parseVerdefs(const Elf_Versym *&Versym); struct NeededVer { // The string table offset of the version name in the output file. size_t StrTab; // The version identifier for this version name. uint16_t Index; }; // Mapping from Elf_Verdef data structures to information about Elf_Vernaux // data structures in the output file. std::map<const Elf_Verdef *, NeededVer> VerdefMap; // Used for --as-needed bool AsNeeded = false; bool IsUsed = false; bool isNeeded() const { return !AsNeeded || IsUsed; } }; class BinaryFile : public InputFile { public: explicit BinaryFile(MemoryBufferRef M) : InputFile(BinaryKind, M) {} static bool classof(const InputFile *F) { return F->kind() == BinaryKind; } template <class ELFT> void parse(); }; InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "", uint64_t OffsetInArchive = 0); InputFile *createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName); } // namespace elf } // namespace lld #endif Index: vendor/lld/dist/ELF/InputSection.cpp =================================================================== --- vendor/lld/dist/ELF/InputSection.cpp (revision 317689) +++ vendor/lld/dist/ELF/InputSection.cpp (revision 317690) @@ -1,931 +1,929 @@ //===- InputSection.cpp ---------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "InputSection.h" #include "Config.h" #include "EhFrame.h" #include "Error.h" #include "InputFiles.h" #include "LinkerScript.h" #include "Memory.h" #include "OutputSections.h" #include "Relocations.h" #include "SyntheticSections.h" #include "Target.h" #include "Thunks.h" #include "llvm/Object/Decompressor.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Path.h" #include <mutex> using namespace llvm; using namespace llvm::ELF; using namespace llvm::object; using namespace llvm::support; using namespace llvm::support::endian; using namespace llvm::sys; using namespace lld; using namespace lld::elf; std::vector<InputSectionBase *> elf::InputSections; // Returns a string to construct an error message. std::string lld::toString(const InputSectionBase *Sec) { - // File can be absent if section is synthetic. - std::string FileName = Sec->File ? Sec->File->getName() : "<internal>"; - return (FileName + ":(" + Sec->Name + ")").str(); + return (toString(Sec->File) + ":(" + Sec->Name + ")").str(); } template <class ELFT> static ArrayRef<uint8_t> getSectionContents(elf::ObjectFile<ELFT> *File, const typename ELFT::Shdr *Hdr) { if (!File || Hdr->sh_type == SHT_NOBITS) return makeArrayRef<uint8_t>(nullptr, Hdr->sh_size); return check(File->getObj().getSectionContents(Hdr)); } InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags, uint32_t Type, uint64_t Entsize, uint32_t Link, uint32_t Info, uint32_t Alignment, ArrayRef<uint8_t> Data, StringRef Name, Kind SectionKind) : SectionBase(SectionKind, Name, Flags, Entsize, Alignment, Type, Info, Link), File(File), Data(Data), Repl(this) { Live = !Config->GcSections || !(Flags & SHF_ALLOC); Assigned = false; NumRelocations = 0; AreRelocsRela = false; // The ELF spec states that a value of 0 means the section has // no alignment constraits. uint32_t V = std::max<uint64_t>(Alignment, 1); if (!isPowerOf2_64(V)) fatal(toString(File) + ": section sh_addralign is not a power of 2"); this->Alignment = V; } // GNU assembler 2.24 and LLVM 4.0.0's MC (the newest release as of // March 2017) fail to infer section types for sections starting with // ".init_array." or ".fini_array.". They set SHT_PROGBITS instead of // SHF_INIT_ARRAY. As a result, the following assembler directive // creates ".init_array.100" with SHT_PROGBITS, for example. // // .section .init_array.100, "aw" // // This function forces SHT_{INIT,FINI}_ARRAY so that we can handle // incorrect inputs as if they were correct from the beginning. static uint64_t getType(uint64_t Type, StringRef Name) { if (Type == SHT_PROGBITS && Name.startswith(".init_array.")) return SHT_INIT_ARRAY; if (Type == SHT_PROGBITS && Name.startswith(".fini_array.")) return SHT_FINI_ARRAY; return Type; } template <class ELFT> InputSectionBase::InputSectionBase(elf::ObjectFile<ELFT> *File, const typename ELFT::Shdr *Hdr, StringRef Name, Kind SectionKind) : InputSectionBase(File, Hdr->sh_flags & ~SHF_INFO_LINK, getType(Hdr->sh_type, Name), Hdr->sh_entsize, Hdr->sh_link, Hdr->sh_info, Hdr->sh_addralign, getSectionContents(File, Hdr), Name, SectionKind) { // We reject object files having insanely large alignments even though // they are allowed by the spec. I think 4GB is a reasonable limitation. // We might want to relax this in the future. if (Hdr->sh_addralign > UINT32_MAX) fatal(toString(File) + ": section sh_addralign is too large"); } size_t InputSectionBase::getSize() const { if (auto *S = dyn_cast<SyntheticSection>(this)) return S->getSize(); return Data.size(); } uint64_t InputSectionBase::getOffsetInFile() const { const uint8_t *FileStart = (const uint8_t *)File->MB.getBufferStart(); const uint8_t *SecStart = Data.begin(); return SecStart - FileStart; } uint64_t SectionBase::getOffset(uint64_t Offset) const { switch (kind()) { case Output: { auto *OS = cast<OutputSection>(this); // For output sections we treat offset -1 as the end of the section. return Offset == uint64_t(-1) ? OS->Size : Offset; } case Regular: return cast<InputSection>(this)->OutSecOff + Offset; case Synthetic: { auto *IS = cast<InputSection>(this); // For synthetic sections we treat offset -1 as the end of the section. return IS->OutSecOff + (Offset == uint64_t(-1) ? IS->getSize() : Offset); } case EHFrame: // The file crtbeginT.o has relocations pointing to the start of an empty // .eh_frame that is known to be the first in the link. It does that to // identify the start of the output .eh_frame. return Offset; case Merge: const MergeInputSection *MS = cast<MergeInputSection>(this); if (MS->MergeSec) return MS->MergeSec->OutSecOff + MS->getOffset(Offset); return MS->getOffset(Offset); } llvm_unreachable("invalid section kind"); } OutputSection *SectionBase::getOutputSection() { if (auto *IS = dyn_cast<InputSection>(this)) return IS->OutSec; if (auto *MS = dyn_cast<MergeInputSection>(this)) return MS->MergeSec ? MS->MergeSec->OutSec : nullptr; if (auto *EH = dyn_cast<EhInputSection>(this)) return EH->EHSec->OutSec; return cast<OutputSection>(this); } // Uncompress section contents. Note that this function is called // from parallel_for_each, so it must be thread-safe. void InputSectionBase::uncompress() { Decompressor Dec = check(Decompressor::create(Name, toStringRef(Data), Config->IsLE, Config->Is64)); size_t Size = Dec.getDecompressedSize(); char *OutputBuf; { static std::mutex Mu; std::lock_guard<std::mutex> Lock(Mu); OutputBuf = BAlloc.Allocate<char>(Size); } if (Error E = Dec.decompress({OutputBuf, Size})) fatal(toString(this) + ": decompress failed: " + llvm::toString(std::move(E))); Data = ArrayRef<uint8_t>((uint8_t *)OutputBuf, Size); } uint64_t SectionBase::getOffset(const DefinedRegular &Sym) const { return getOffset(Sym.Value); } InputSectionBase *InputSectionBase::getLinkOrderDep() const { if ((Flags & SHF_LINK_ORDER) && Link != 0) return File->getSections()[Link]; return nullptr; } // Returns a source location string. Used to construct an error message. template <class ELFT> std::string InputSectionBase::getLocation(uint64_t Offset) { // We don't have file for synthetic sections. if (getFile<ELFT>() == nullptr) return (Config->OutputFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")") .str(); // First check if we can get desired values from debugging information. std::string LineInfo = getFile<ELFT>()->getLineInfo(this, Offset); if (!LineInfo.empty()) return LineInfo; // File->SourceFile contains STT_FILE symbol that contains a // source file name. If it's missing, we use an object file name. std::string SrcFile = getFile<ELFT>()->SourceFile; if (SrcFile.empty()) SrcFile = toString(File); // Find a function symbol that encloses a given location. for (SymbolBody *B : getFile<ELFT>()->getSymbols()) if (auto *D = dyn_cast<DefinedRegular>(B)) if (D->Section == this && D->Type == STT_FUNC) if (D->Value <= Offset && Offset < D->Value + D->Size) return SrcFile + ":(function " + toString(*D) + ")"; // If there's no symbol, print out the offset in the section. return (SrcFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")").str(); } // Returns a source location string. This function is intended to be // used for constructing an error message. The returned message looks // like this: // // foo.c:42 (/home/alice/possibly/very/long/path/foo.c:42) // // Returns an empty string if there's no way to get line info. template <class ELFT> std::string InputSectionBase::getSrcMsg(uint64_t Offset) { // Synthetic sections don't have input files. elf::ObjectFile<ELFT> *File = getFile<ELFT>(); if (!File) return ""; Optional<DILineInfo> Info = File->getDILineInfo(this, Offset); // File->SourceFile contains STT_FILE symbol, and that is a last resort. if (!Info) return File->SourceFile; std::string Path = Info->FileName; std::string Filename = path::filename(Path); std::string Lineno = ":" + std::to_string(Info->Line); if (Filename == Path) return Filename + Lineno; return Filename + Lineno + " (" + Path + Lineno + ")"; } // Returns a filename string along with an optional section name. This // function is intended to be used for constructing an error // message. The returned message looks like this: // // path/to/foo.o:(function bar) // // or // // path/to/foo.o:(function bar) in archive path/to/bar.a template <class ELFT> std::string InputSectionBase::getObjMsg(uint64_t Off) { // Synthetic sections don't have input files. elf::ObjectFile<ELFT> *File = getFile<ELFT>(); std::string Filename = File ? File->getName() : "(internal)"; std::string Archive; if (!File->ArchiveName.empty()) Archive = (" in archive " + File->ArchiveName).str(); // Find a symbol that encloses a given location. for (SymbolBody *B : getFile<ELFT>()->getSymbols()) if (auto *D = dyn_cast<DefinedRegular>(B)) if (D->Section == this && D->Value <= Off && Off < D->Value + D->Size) return Filename + ":(" + toString(*D) + ")" + Archive; // If there's no symbol, print out the offset in the section. return (Filename + ":(" + Name + "+0x" + utohexstr(Off) + ")" + Archive) .str(); } InputSectionBase InputSectionBase::Discarded; InputSection::InputSection(uint64_t Flags, uint32_t Type, uint32_t Alignment, ArrayRef<uint8_t> Data, StringRef Name, Kind K) : InputSectionBase(nullptr, Flags, Type, /*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, Alignment, Data, Name, K) {} template <class ELFT> InputSection::InputSection(elf::ObjectFile<ELFT> *F, const typename ELFT::Shdr *Header, StringRef Name) : InputSectionBase(F, Header, Name, InputSectionBase::Regular) {} bool InputSection::classof(const SectionBase *S) { return S->kind() == SectionBase::Regular || S->kind() == SectionBase::Synthetic; } bool InputSectionBase::classof(const SectionBase *S) { return S->kind() != Output; } InputSectionBase *InputSection::getRelocatedSection() { assert(this->Type == SHT_RELA || this->Type == SHT_REL); ArrayRef<InputSectionBase *> Sections = this->File->getSections(); return Sections[this->Info]; } // This is used for -r and --emit-relocs. We can't use memcpy to copy // relocations because we need to update symbol table offset and section index // for each relocation. So we copy relocations one by one. template <class ELFT, class RelTy> void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { InputSectionBase *RelocatedSection = getRelocatedSection(); // Loop is slow and have complexity O(N*M), where N - amount of // relocations and M - amount of symbols in symbol table. // That happens because getSymbolIndex(...) call below performs // simple linear search. for (const RelTy &Rel : Rels) { uint32_t Type = Rel.getType(Config->IsMips64EL); SymbolBody &Body = this->getFile<ELFT>()->getRelocTargetSym(Rel); auto *P = reinterpret_cast<typename ELFT::Rela *>(Buf); Buf += sizeof(RelTy); if (Config->IsRela) P->r_addend = getAddend<ELFT>(Rel); // Output section VA is zero for -r, so r_offset is an offset within the // section, but for --emit-relocs it is an virtual address. P->r_offset = RelocatedSection->OutSec->Addr + RelocatedSection->getOffset(Rel.r_offset); P->setSymbolAndType(In<ELFT>::SymTab->getSymbolIndex(&Body), Type, Config->IsMips64EL); if (Body.Type == STT_SECTION) { // We combine multiple section symbols into only one per // section. This means we have to update the addend. That is // trivial for Elf_Rela, but for Elf_Rel we have to write to the // section data. We do that by adding to the Relocation vector. // .eh_frame is horribly special and can reference discarded sections. To // avoid having to parse and recreate .eh_frame, we just replace any // relocation in it pointing to discarded sections with R_*_NONE, which // hopefully creates a frame that is ignored at runtime. SectionBase *Section = cast<DefinedRegular>(Body).Section; if (Section == &InputSection::Discarded) { P->setSymbolAndType(0, 0, false); continue; } if (Config->IsRela) { P->r_addend += Body.getVA() - Section->getOutputSection()->Addr; } else if (Config->Relocatable) { const uint8_t *BufLoc = RelocatedSection->Data.begin() + Rel.r_offset; RelocatedSection->Relocations.push_back( {R_ABS, Type, Rel.r_offset, Target->getImplicitAddend(BufLoc, Type), &Body}); } } } } static uint32_t getARMUndefinedRelativeWeakVA(uint32_t Type, uint32_t A, uint32_t P) { switch (Type) { case R_ARM_THM_JUMP11: return P + 2; case R_ARM_CALL: case R_ARM_JUMP24: case R_ARM_PC24: case R_ARM_PLT32: case R_ARM_PREL31: case R_ARM_THM_JUMP19: case R_ARM_THM_JUMP24: return P + 4; case R_ARM_THM_CALL: // We don't want an interworking BLX to ARM return P + 5; default: return A; } } static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t Type, uint64_t A, uint64_t P) { switch (Type) { case R_AARCH64_CALL26: case R_AARCH64_CONDBR19: case R_AARCH64_JUMP26: case R_AARCH64_TSTBR14: return P + 4; default: return A; } } template <class ELFT> static typename ELFT::uint getRelocTargetVA(uint32_t Type, int64_t A, typename ELFT::uint P, const SymbolBody &Body, RelExpr Expr) { switch (Expr) { case R_ABS: case R_RELAX_GOT_PC_NOPIC: return Body.getVA(A); case R_GOT: case R_RELAX_TLS_GD_TO_IE_ABS: return Body.getGotVA<ELFT>() + A; case R_GOTONLY_PC: return In<ELFT>::Got->getVA() + A - P; case R_GOTONLY_PC_FROM_END: return In<ELFT>::Got->getVA() + A - P + In<ELFT>::Got->getSize(); case R_GOTREL: return Body.getVA(A) - In<ELFT>::Got->getVA(); case R_GOTREL_FROM_END: return Body.getVA(A) - In<ELFT>::Got->getVA() - In<ELFT>::Got->getSize(); case R_GOT_FROM_END: case R_RELAX_TLS_GD_TO_IE_END: return Body.getGotOffset() + A - In<ELFT>::Got->getSize(); case R_GOT_OFF: return Body.getGotOffset() + A; case R_GOT_PAGE_PC: case R_RELAX_TLS_GD_TO_IE_PAGE_PC: return getAArch64Page(Body.getGotVA<ELFT>() + A) - getAArch64Page(P); case R_GOT_PC: case R_RELAX_TLS_GD_TO_IE: return Body.getGotVA<ELFT>() + A - P; case R_HINT: case R_NONE: case R_TLSDESC_CALL: llvm_unreachable("cannot relocate hint relocs"); case R_MIPS_GOTREL: return Body.getVA(A) - In<ELFT>::MipsGot->getGp(); case R_MIPS_GOT_GP: return In<ELFT>::MipsGot->getGp() + A; case R_MIPS_GOT_GP_PC: { // R_MIPS_LO16 expression has R_MIPS_GOT_GP_PC type iif the target // is _gp_disp symbol. In that case we should use the following // formula for calculation "AHL + GP - P + 4". For details see p. 4-19 at // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf uint64_t V = In<ELFT>::MipsGot->getGp() + A - P; if (Type == R_MIPS_LO16) V += 4; return V; } case R_MIPS_GOT_LOCAL_PAGE: // If relocation against MIPS local symbol requires GOT entry, this entry // should be initialized by 'page address'. This address is high 16-bits // of sum the symbol's value and the addend. return In<ELFT>::MipsGot->getVA() + In<ELFT>::MipsGot->getPageEntryOffset(Body, A) - In<ELFT>::MipsGot->getGp(); case R_MIPS_GOT_OFF: case R_MIPS_GOT_OFF32: // In case of MIPS if a GOT relocation has non-zero addend this addend // should be applied to the GOT entry content not to the GOT entry offset. // That is why we use separate expression type. return In<ELFT>::MipsGot->getVA() + In<ELFT>::MipsGot->getBodyEntryOffset(Body, A) - In<ELFT>::MipsGot->getGp(); case R_MIPS_TLSGD: return In<ELFT>::MipsGot->getVA() + In<ELFT>::MipsGot->getTlsOffset() + In<ELFT>::MipsGot->getGlobalDynOffset(Body) - In<ELFT>::MipsGot->getGp(); case R_MIPS_TLSLD: return In<ELFT>::MipsGot->getVA() + In<ELFT>::MipsGot->getTlsOffset() + In<ELFT>::MipsGot->getTlsIndexOff() - In<ELFT>::MipsGot->getGp(); case R_PAGE_PC: case R_PLT_PAGE_PC: if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak()) return getAArch64Page(A); return getAArch64Page(Body.getVA(A)) - getAArch64Page(P); case R_PC: if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak()) { // On ARM and AArch64 a branch to an undefined weak resolves to the // next instruction, otherwise the place. if (Config->EMachine == EM_ARM) return getARMUndefinedRelativeWeakVA(Type, A, P); if (Config->EMachine == EM_AARCH64) return getAArch64UndefinedRelativeWeakVA(Type, A, P); } return Body.getVA(A) - P; case R_PLT: return Body.getPltVA() + A; case R_PLT_PC: case R_PPC_PLT_OPD: return Body.getPltVA() + A - P; case R_PPC_OPD: { uint64_t SymVA = Body.getVA(A); // If we have an undefined weak symbol, we might get here with a symbol // address of zero. That could overflow, but the code must be unreachable, // so don't bother doing anything at all. if (!SymVA) return 0; if (Out::Opd) { // If this is a local call, and we currently have the address of a // function-descriptor, get the underlying code address instead. uint64_t OpdStart = Out::Opd->Addr; uint64_t OpdEnd = OpdStart + Out::Opd->Size; bool InOpd = OpdStart <= SymVA && SymVA < OpdEnd; if (InOpd) SymVA = read64be(&Out::OpdBuf[SymVA - OpdStart]); } return SymVA - P; } case R_PPC_TOC: return getPPC64TocBase() + A; case R_RELAX_GOT_PC: return Body.getVA(A) - P; case R_RELAX_TLS_GD_TO_LE: case R_RELAX_TLS_IE_TO_LE: case R_RELAX_TLS_LD_TO_LE: case R_TLS: // A weak undefined TLS symbol resolves to the base of the TLS // block, i.e. gets a value of zero. If we pass --gc-sections to // lld and .tbss is not referenced, it gets reclaimed and we don't // create a TLS program header. Therefore, we resolve this // statically to zero. if (Body.isTls() && (Body.isLazy() || Body.isUndefined()) && Body.symbol()->isWeak()) return 0; if (Target->TcbSize) return Body.getVA(A) + alignTo(Target->TcbSize, Out::TlsPhdr->p_align); return Body.getVA(A) - Out::TlsPhdr->p_memsz; case R_RELAX_TLS_GD_TO_LE_NEG: case R_NEG_TLS: return Out::TlsPhdr->p_memsz - Body.getVA(A); case R_SIZE: return Body.getSize<ELFT>() + A; case R_TLSDESC: return In<ELFT>::Got->getGlobalDynAddr(Body) + A; case R_TLSDESC_PAGE: return getAArch64Page(In<ELFT>::Got->getGlobalDynAddr(Body) + A) - getAArch64Page(P); case R_TLSGD: return In<ELFT>::Got->getGlobalDynOffset(Body) + A - In<ELFT>::Got->getSize(); case R_TLSGD_PC: return In<ELFT>::Got->getGlobalDynAddr(Body) + A - P; case R_TLSLD: return In<ELFT>::Got->getTlsIndexOff() + A - In<ELFT>::Got->getSize(); case R_TLSLD_PC: return In<ELFT>::Got->getTlsIndexVA() + A - P; } llvm_unreachable("Invalid expression"); } // This function applies relocations to sections without SHF_ALLOC bit. // Such sections are never mapped to memory at runtime. Debug sections are // an example. Relocations in non-alloc sections are much easier to // handle than in allocated sections because it will never need complex // treatement such as GOT or PLT (because at runtime no one refers them). // So, we handle relocations for non-alloc sections directly in this // function as a performance optimization. template <class ELFT, class RelTy> void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) { for (const RelTy &Rel : Rels) { uint32_t Type = Rel.getType(Config->IsMips64EL); uint64_t Offset = getOffset(Rel.r_offset); uint8_t *BufLoc = Buf + Offset; int64_t Addend = getAddend<ELFT>(Rel); if (!RelTy::IsRela) Addend += Target->getImplicitAddend(BufLoc, Type); SymbolBody &Sym = this->getFile<ELFT>()->getRelocTargetSym(Rel); RelExpr Expr = Target->getRelExpr(Type, Sym, BufLoc); if (Expr == R_NONE) continue; if (Expr != R_ABS) { error(this->getLocation<ELFT>(Offset) + ": has non-ABS reloc"); return; } uint64_t AddrLoc = this->OutSec->Addr + Offset; uint64_t SymVA = 0; if (!Sym.isTls() || Out::TlsPhdr) SymVA = SignExtend64<sizeof(typename ELFT::uint) * 8>( getRelocTargetVA<ELFT>(Type, Addend, AddrLoc, Sym, R_ABS)); Target->relocateOne(BufLoc, Type, SymVA); } } template <class ELFT> elf::ObjectFile<ELFT> *InputSectionBase::getFile() const { return cast_or_null<elf::ObjectFile<ELFT>>(File); } template <class ELFT> void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) { // scanReloc function in Writer.cpp constructs Relocations // vector only for SHF_ALLOC'ed sections. For other sections, // we handle relocations directly here. auto *IS = dyn_cast<InputSection>(this); if (IS && !(IS->Flags & SHF_ALLOC)) { if (IS->AreRelocsRela) IS->relocateNonAlloc<ELFT>(Buf, IS->template relas<ELFT>()); else IS->relocateNonAlloc<ELFT>(Buf, IS->template rels<ELFT>()); return; } const unsigned Bits = sizeof(typename ELFT::uint) * 8; for (const Relocation &Rel : Relocations) { uint64_t Offset = getOffset(Rel.Offset); uint8_t *BufLoc = Buf + Offset; uint32_t Type = Rel.Type; uint64_t AddrLoc = getOutputSection()->Addr + Offset; RelExpr Expr = Rel.Expr; uint64_t TargetVA = SignExtend64<Bits>( getRelocTargetVA<ELFT>(Type, Rel.Addend, AddrLoc, *Rel.Sym, Expr)); switch (Expr) { case R_RELAX_GOT_PC: case R_RELAX_GOT_PC_NOPIC: Target->relaxGot(BufLoc, TargetVA); break; case R_RELAX_TLS_IE_TO_LE: Target->relaxTlsIeToLe(BufLoc, Type, TargetVA); break; case R_RELAX_TLS_LD_TO_LE: Target->relaxTlsLdToLe(BufLoc, Type, TargetVA); break; case R_RELAX_TLS_GD_TO_LE: case R_RELAX_TLS_GD_TO_LE_NEG: Target->relaxTlsGdToLe(BufLoc, Type, TargetVA); break; case R_RELAX_TLS_GD_TO_IE: case R_RELAX_TLS_GD_TO_IE_ABS: case R_RELAX_TLS_GD_TO_IE_PAGE_PC: case R_RELAX_TLS_GD_TO_IE_END: Target->relaxTlsGdToIe(BufLoc, Type, TargetVA); break; case R_PPC_PLT_OPD: // Patch a nop (0x60000000) to a ld. if (BufLoc + 8 <= BufEnd && read32be(BufLoc + 4) == 0x60000000) write32be(BufLoc + 4, 0xe8410028); // ld %r2, 40(%r1) // fallthrough default: Target->relocateOne(BufLoc, Type, TargetVA); break; } } } template <class ELFT> void InputSection::writeTo(uint8_t *Buf) { if (this->Type == SHT_NOBITS) return; if (auto *S = dyn_cast<SyntheticSection>(this)) { S->writeTo(Buf + OutSecOff); return; } // If -r or --emit-relocs is given, then an InputSection // may be a relocation section. if (this->Type == SHT_RELA) { copyRelocations<ELFT>(Buf + OutSecOff, this->template getDataAs<typename ELFT::Rela>()); return; } if (this->Type == SHT_REL) { copyRelocations<ELFT>(Buf + OutSecOff, this->template getDataAs<typename ELFT::Rel>()); return; } // Copy section contents from source object file to output file // and then apply relocations. memcpy(Buf + OutSecOff, Data.data(), Data.size()); uint8_t *BufEnd = Buf + OutSecOff + Data.size(); this->relocate<ELFT>(Buf, BufEnd); } void InputSection::replace(InputSection *Other) { this->Alignment = std::max(this->Alignment, Other->Alignment); Other->Repl = this->Repl; Other->Live = false; } template <class ELFT> EhInputSection::EhInputSection(elf::ObjectFile<ELFT> *F, const typename ELFT::Shdr *Header, StringRef Name) : InputSectionBase(F, Header, Name, InputSectionBase::EHFrame) { // Mark .eh_frame sections as live by default because there are // usually no relocations that point to .eh_frames. Otherwise, // the garbage collector would drop all .eh_frame sections. this->Live = true; } bool EhInputSection::classof(const SectionBase *S) { return S->kind() == InputSectionBase::EHFrame; } // Returns the index of the first relocation that points to a region between // Begin and Begin+Size. template <class IntTy, class RelTy> static unsigned getReloc(IntTy Begin, IntTy Size, const ArrayRef<RelTy> &Rels, unsigned &RelocI) { // Start search from RelocI for fast access. That works because the // relocations are sorted in .eh_frame. for (unsigned N = Rels.size(); RelocI < N; ++RelocI) { const RelTy &Rel = Rels[RelocI]; if (Rel.r_offset < Begin) continue; if (Rel.r_offset < Begin + Size) return RelocI; return -1; } return -1; } // .eh_frame is a sequence of CIE or FDE records. // This function splits an input section into records and returns them. template <class ELFT> void EhInputSection::split() { // Early exit if already split. if (!this->Pieces.empty()) return; if (this->NumRelocations) { if (this->AreRelocsRela) split<ELFT>(this->relas<ELFT>()); else split<ELFT>(this->rels<ELFT>()); return; } split<ELFT>(makeArrayRef<typename ELFT::Rela>(nullptr, nullptr)); } template <class ELFT, class RelTy> void EhInputSection::split(ArrayRef<RelTy> Rels) { ArrayRef<uint8_t> Data = this->Data; unsigned RelI = 0; for (size_t Off = 0, End = Data.size(); Off != End;) { size_t Size = readEhRecordSize<ELFT>(this, Off); this->Pieces.emplace_back(Off, this, Size, getReloc(Off, Size, Rels, RelI)); // The empty record is the end marker. if (Size == 4) break; Off += Size; } } static size_t findNull(ArrayRef<uint8_t> A, size_t EntSize) { // Optimize the common case. StringRef S((const char *)A.data(), A.size()); if (EntSize == 1) return S.find(0); for (unsigned I = 0, N = S.size(); I != N; I += EntSize) { const char *B = S.begin() + I; if (std::all_of(B, B + EntSize, [](char C) { return C == 0; })) return I; } return StringRef::npos; } // Split SHF_STRINGS section. Such section is a sequence of // null-terminated strings. void MergeInputSection::splitStrings(ArrayRef<uint8_t> Data, size_t EntSize) { size_t Off = 0; bool IsAlloc = this->Flags & SHF_ALLOC; while (!Data.empty()) { size_t End = findNull(Data, EntSize); if (End == StringRef::npos) fatal(toString(this) + ": string is not null terminated"); size_t Size = End + EntSize; Pieces.emplace_back(Off, !IsAlloc); Hashes.push_back(hash_value(toStringRef(Data.slice(0, Size)))); Data = Data.slice(Size); Off += Size; } } // Split non-SHF_STRINGS section. Such section is a sequence of // fixed size records. void MergeInputSection::splitNonStrings(ArrayRef<uint8_t> Data, size_t EntSize) { size_t Size = Data.size(); assert((Size % EntSize) == 0); bool IsAlloc = this->Flags & SHF_ALLOC; for (unsigned I = 0, N = Size; I != N; I += EntSize) { Hashes.push_back(hash_value(toStringRef(Data.slice(I, EntSize)))); Pieces.emplace_back(I, !IsAlloc); } } template <class ELFT> MergeInputSection::MergeInputSection(elf::ObjectFile<ELFT> *F, const typename ELFT::Shdr *Header, StringRef Name) : InputSectionBase(F, Header, Name, InputSectionBase::Merge) {} // This function is called after we obtain a complete list of input sections // that need to be linked. This is responsible to split section contents // into small chunks for further processing. // // Note that this function is called from parallel_for_each. This must be // thread-safe (i.e. no memory allocation from the pools). void MergeInputSection::splitIntoPieces() { ArrayRef<uint8_t> Data = this->Data; uint64_t EntSize = this->Entsize; if (this->Flags & SHF_STRINGS) splitStrings(Data, EntSize); else splitNonStrings(Data, EntSize); if (Config->GcSections && (this->Flags & SHF_ALLOC)) for (uint64_t Off : LiveOffsets) this->getSectionPiece(Off)->Live = true; } bool MergeInputSection::classof(const SectionBase *S) { return S->kind() == InputSectionBase::Merge; } // Do binary search to get a section piece at a given input offset. SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) { auto *This = static_cast<const MergeInputSection *>(this); return const_cast<SectionPiece *>(This->getSectionPiece(Offset)); } template <class It, class T, class Compare> static It fastUpperBound(It First, It Last, const T &Value, Compare Comp) { size_t Size = std::distance(First, Last); assert(Size != 0); while (Size != 1) { size_t H = Size / 2; const It MI = First + H; Size -= H; First = Comp(Value, *MI) ? First : First + H; } return Comp(Value, *First) ? First : First + 1; } const SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) const { uint64_t Size = this->Data.size(); if (Offset >= Size) fatal(toString(this) + ": entry is past the end of the section"); // Find the element this offset points to. auto I = fastUpperBound( Pieces.begin(), Pieces.end(), Offset, [](const uint64_t &A, const SectionPiece &B) { return A < B.InputOff; }); --I; return &*I; } // Returns the offset in an output section for a given input offset. // Because contents of a mergeable section is not contiguous in output, // it is not just an addition to a base output offset. uint64_t MergeInputSection::getOffset(uint64_t Offset) const { // Initialize OffsetMap lazily. std::call_once(InitOffsetMap, [&] { OffsetMap.reserve(Pieces.size()); for (const SectionPiece &Piece : Pieces) OffsetMap[Piece.InputOff] = Piece.OutputOff; }); // Find a string starting at a given offset. auto It = OffsetMap.find(Offset); if (It != OffsetMap.end()) return It->second; if (!this->Live) return 0; // If Offset is not at beginning of a section piece, it is not in the map. // In that case we need to search from the original section piece vector. const SectionPiece &Piece = *this->getSectionPiece(Offset); if (!Piece.Live) return 0; uint64_t Addend = Offset - Piece.InputOff; return Piece.OutputOff + Addend; } template InputSection::InputSection(elf::ObjectFile<ELF32LE> *, const ELF32LE::Shdr *, StringRef); template InputSection::InputSection(elf::ObjectFile<ELF32BE> *, const ELF32BE::Shdr *, StringRef); template InputSection::InputSection(elf::ObjectFile<ELF64LE> *, const ELF64LE::Shdr *, StringRef); template InputSection::InputSection(elf::ObjectFile<ELF64BE> *, const ELF64BE::Shdr *, StringRef); template std::string InputSectionBase::getLocation<ELF32LE>(uint64_t); template std::string InputSectionBase::getLocation<ELF32BE>(uint64_t); template std::string InputSectionBase::getLocation<ELF64LE>(uint64_t); template std::string InputSectionBase::getLocation<ELF64BE>(uint64_t); template std::string InputSectionBase::getSrcMsg<ELF32LE>(uint64_t); template std::string InputSectionBase::getSrcMsg<ELF32BE>(uint64_t); template std::string InputSectionBase::getSrcMsg<ELF64LE>(uint64_t); template std::string InputSectionBase::getSrcMsg<ELF64BE>(uint64_t); template std::string InputSectionBase::getObjMsg<ELF32LE>(uint64_t); template std::string InputSectionBase::getObjMsg<ELF32BE>(uint64_t); template std::string InputSectionBase::getObjMsg<ELF64LE>(uint64_t); template std::string InputSectionBase::getObjMsg<ELF64BE>(uint64_t); template void InputSection::writeTo<ELF32LE>(uint8_t *); template void InputSection::writeTo<ELF32BE>(uint8_t *); template void InputSection::writeTo<ELF64LE>(uint8_t *); template void InputSection::writeTo<ELF64BE>(uint8_t *); template elf::ObjectFile<ELF32LE> *InputSectionBase::getFile<ELF32LE>() const; template elf::ObjectFile<ELF32BE> *InputSectionBase::getFile<ELF32BE>() const; template elf::ObjectFile<ELF64LE> *InputSectionBase::getFile<ELF64LE>() const; template elf::ObjectFile<ELF64BE> *InputSectionBase::getFile<ELF64BE>() const; template MergeInputSection::MergeInputSection(elf::ObjectFile<ELF32LE> *, const ELF32LE::Shdr *, StringRef); template MergeInputSection::MergeInputSection(elf::ObjectFile<ELF32BE> *, const ELF32BE::Shdr *, StringRef); template MergeInputSection::MergeInputSection(elf::ObjectFile<ELF64LE> *, const ELF64LE::Shdr *, StringRef); template MergeInputSection::MergeInputSection(elf::ObjectFile<ELF64BE> *, const ELF64BE::Shdr *, StringRef); template EhInputSection::EhInputSection(elf::ObjectFile<ELF32LE> *, const ELF32LE::Shdr *, StringRef); template EhInputSection::EhInputSection(elf::ObjectFile<ELF32BE> *, const ELF32BE::Shdr *, StringRef); template EhInputSection::EhInputSection(elf::ObjectFile<ELF64LE> *, const ELF64LE::Shdr *, StringRef); template EhInputSection::EhInputSection(elf::ObjectFile<ELF64BE> *, const ELF64BE::Shdr *, StringRef); template void EhInputSection::split<ELF32LE>(); template void EhInputSection::split<ELF32BE>(); template void EhInputSection::split<ELF64LE>(); template void EhInputSection::split<ELF64BE>(); Index: vendor/lld/dist/ELF/LTO.cpp =================================================================== --- vendor/lld/dist/ELF/LTO.cpp (revision 317689) +++ vendor/lld/dist/ELF/LTO.cpp (revision 317690) @@ -1,185 +1,190 @@ //===- LTO.cpp ------------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "LTO.h" #include "Config.h" #include "Error.h" #include "InputFiles.h" #include "Symbols.h" #include "lld/Core/TargetOptionsCommandFlags.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/LTO/Caching.h" #include "llvm/LTO/Config.h" #include "llvm/LTO/LTO.h" #include "llvm/Object/SymbolicFile.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cstddef> #include <memory> #include <string> #include <system_error> #include <vector> using namespace llvm; using namespace llvm::object; using namespace llvm::ELF; using namespace lld; using namespace lld::elf; // This is for use when debugging LTO. static void saveBuffer(StringRef Buffer, const Twine &Path) { std::error_code EC; raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None); if (EC) error("cannot create " + Path + ": " + EC.message()); OS << Buffer; } static void diagnosticHandler(const DiagnosticInfo &DI) { SmallString<128> ErrStorage; raw_svector_ostream OS(ErrStorage); DiagnosticPrinterRawOStream DP(OS); DI.print(DP); warn(ErrStorage); } static void checkError(Error E) { handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) -> Error { error(EIB.message()); return Error::success(); }); } static std::unique_ptr<lto::LTO> createLTO() { lto::Config Conf; // LLD supports the new relocations. Conf.Options = InitTargetOptionsFromCodeGenFlags(); Conf.Options.RelaxELFRelocations = true; Conf.RelocModel = Config->Pic ? Reloc::PIC_ : Reloc::Static; Conf.CodeModel = GetCodeModelFromCMModel(); Conf.DisableVerify = Config->DisableVerify; Conf.DiagHandler = diagnosticHandler; Conf.OptLevel = Config->LTOO; // Set up a custom pipeline if we've been asked to. Conf.OptPipeline = Config->LTONewPmPasses; Conf.AAPipeline = Config->LTOAAPipeline; // Set up optimization remarks if we've been asked to. Conf.RemarksFilename = Config->OptRemarksFilename; Conf.RemarksWithHotness = Config->OptRemarksWithHotness; if (Config->SaveTemps) checkError(Conf.addSaveTemps(std::string(Config->OutputFile) + ".", /*UseInputModulePath*/ true)); lto::ThinBackend Backend; if (Config->ThinLTOJobs != -1u) Backend = lto::createInProcessThinBackend(Config->ThinLTOJobs); return llvm::make_unique<lto::LTO>(std::move(Conf), Backend, Config->LTOPartitions); } BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) {} BitcodeCompiler::~BitcodeCompiler() = default; static void undefine(Symbol *S) { replaceBody<Undefined>(S, S->body()->getName(), /*IsLocal=*/false, STV_DEFAULT, S->body()->Type, nullptr); + // It shouldn't normally matter what the binding is, but if a bug in the LTO + // implementation causes it to fail to provide a definition for a symbol, + // setting the binding to STB_GLOBAL will cause the linker to report an + // undefined symbol error, even if the definition was weak. + S->Binding = STB_GLOBAL; } void BitcodeCompiler::add(BitcodeFile &F) { lto::InputFile &Obj = *F.Obj; unsigned SymNum = 0; std::vector<Symbol *> Syms = F.getSymbols(); std::vector<lto::SymbolResolution> Resols(Syms.size()); // Provide a resolution to the LTO API for each symbol. for (const lto::InputFile::Symbol &ObjSym : Obj.symbols()) { Symbol *Sym = Syms[SymNum]; lto::SymbolResolution &R = Resols[SymNum]; ++SymNum; SymbolBody *B = Sym->body(); // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile // reports two symbols for module ASM defined. Without this check, lld // flags an undefined in IR with a definition in ASM as prevailing. // Once IRObjectFile is fixed to report only one symbol this hack can // be removed. R.Prevailing = !ObjSym.isUndefined() && B->File == &F; R.VisibleToRegularObj = Sym->IsUsedInRegularObj || (R.Prevailing && Sym->includeInDynsym()); if (R.Prevailing) undefine(Sym); } checkError(LTOObj->add(std::move(F.Obj), Resols)); } // Merge all the bitcode files we have seen, codegen the result // and return the resulting ObjectFile(s). std::vector<InputFile *> BitcodeCompiler::compile() { std::vector<InputFile *> Ret; unsigned MaxTasks = LTOObj->getMaxTasks(); Buff.resize(MaxTasks); Files.resize(MaxTasks); // The --thinlto-cache-dir option specifies the path to a directory in which // to cache native object files for ThinLTO incremental builds. If a path was // specified, configure LTO to use it as the cache directory. lto::NativeObjectCache Cache; if (!Config->ThinLTOCacheDir.empty()) Cache = check( lto::localCache(Config->ThinLTOCacheDir, [&](size_t Task, std::unique_ptr<MemoryBuffer> MB) { Files[Task] = std::move(MB); })); checkError(LTOObj->run( [&](size_t Task) { return llvm::make_unique<lto::NativeObjectStream>( llvm::make_unique<raw_svector_ostream>(Buff[Task])); }, Cache)); if (!Config->ThinLTOCacheDir.empty()) pruneCache(Config->ThinLTOCacheDir, Config->ThinLTOCachePolicy); for (unsigned I = 0; I != MaxTasks; ++I) { if (Buff[I].empty()) continue; if (Config->SaveTemps) { if (I == 0) saveBuffer(Buff[I], Config->OutputFile + ".lto.o"); else saveBuffer(Buff[I], Config->OutputFile + Twine(I) + ".lto.o"); } InputFile *Obj = createObjectFile(MemoryBufferRef(Buff[I], "lto.tmp")); Ret.push_back(Obj); } for (std::unique_ptr<MemoryBuffer> &File : Files) if (File) Ret.push_back(createObjectFile(*File)); return Ret; } Index: vendor/lld/dist/ELF/LinkerScript.cpp =================================================================== --- vendor/lld/dist/ELF/LinkerScript.cpp (revision 317689) +++ vendor/lld/dist/ELF/LinkerScript.cpp (revision 317690) @@ -1,1021 +1,1068 @@ //===- LinkerScript.cpp ---------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file contains the parser/evaluator of the linker script. // //===----------------------------------------------------------------------===// #include "LinkerScript.h" #include "Config.h" #include "InputSection.h" #include "Memory.h" #include "OutputSections.h" #include "Strings.h" #include "SymbolTable.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Writer.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include <algorithm> #include <cassert> #include <cstddef> #include <cstdint> #include <iterator> #include <limits> #include <string> #include <vector> using namespace llvm; using namespace llvm::ELF; using namespace llvm::object; using namespace llvm::support::endian; using namespace lld; using namespace lld::elf; LinkerScript *elf::Script; uint64_t ExprValue::getValue() const { if (Sec) return Sec->getOffset(Val) + Sec->getOutputSection()->Addr; return Val; } uint64_t ExprValue::getSecAddr() const { if (Sec) return Sec->getOffset(0) + Sec->getOutputSection()->Addr; return 0; } template <class ELFT> static SymbolBody *addRegular(SymbolAssignment *Cmd) { Symbol *Sym; uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; std::tie(Sym, std::ignore) = Symtab<ELFT>::X->insert( Cmd->Name, /*Type*/ 0, Visibility, /*CanOmitFromDynSym*/ false, /*File*/ nullptr); Sym->Binding = STB_GLOBAL; ExprValue Value = Cmd->Expression(); SectionBase *Sec = Value.isAbsolute() ? nullptr : Value.Sec; // We want to set symbol values early if we can. This allows us to use symbols // as variables in linker scripts. Doing so allows us to write expressions // like this: `alignment = 16; . = ALIGN(., alignment)` uint64_t SymValue = Value.isAbsolute() ? Value.getValue() : 0; replaceBody<DefinedRegular>(Sym, Cmd->Name, /*IsLocal=*/false, Visibility, STT_NOTYPE, SymValue, 0, Sec, nullptr); return Sym->body(); } OutputSection *LinkerScript::getOutputSection(const Twine &Loc, StringRef Name) { for (OutputSection *Sec : *OutputSections) if (Sec->Name == Name) return Sec; static OutputSection Dummy("", 0, 0); if (ErrorOnMissingSection) error(Loc + ": undefined section " + Name); return &Dummy; } // This function is essentially the same as getOutputSection(Name)->Size, // but it won't print out an error message if a given section is not found. // // Linker script does not create an output section if its content is empty. // We want to allow SIZEOF(.foo) where .foo is a section which happened to // be empty. That is why this function is different from getOutputSection(). uint64_t LinkerScript::getOutputSectionSize(StringRef Name) { for (OutputSection *Sec : *OutputSections) if (Sec->Name == Name) return Sec->Size; return 0; } void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) { uint64_t Val = E().getValue(); if (Val < Dot) { if (InSec) error(Loc + ": unable to move location counter backward for: " + CurOutSec->Name); else error(Loc + ": unable to move location counter backward"); } Dot = Val; // Update to location counter means update to section size. if (InSec) CurOutSec->Size = Dot - CurOutSec->Addr; } // Sets value of a symbol. Two kinds of symbols are processed: synthetic // symbols, whose value is an offset from beginning of section and regular // symbols whose value is absolute. void LinkerScript::assignSymbol(SymbolAssignment *Cmd, bool InSec) { if (Cmd->Name == ".") { setDot(Cmd->Expression, Cmd->Location, InSec); return; } if (!Cmd->Sym) return; auto *Sym = cast<DefinedRegular>(Cmd->Sym); ExprValue V = Cmd->Expression(); if (V.isAbsolute()) { Sym->Value = V.getValue(); } else { Sym->Section = V.Sec; if (Sym->Section->Flags & SHF_ALLOC) Sym->Value = V.Val; else Sym->Value = V.getValue(); } } static SymbolBody *findSymbol(StringRef S) { switch (Config->EKind) { case ELF32LEKind: return Symtab<ELF32LE>::X->find(S); case ELF32BEKind: return Symtab<ELF32BE>::X->find(S); case ELF64LEKind: return Symtab<ELF64LE>::X->find(S); case ELF64BEKind: return Symtab<ELF64BE>::X->find(S); default: llvm_unreachable("unknown Config->EKind"); } } static SymbolBody *addRegularSymbol(SymbolAssignment *Cmd) { switch (Config->EKind) { case ELF32LEKind: return addRegular<ELF32LE>(Cmd); case ELF32BEKind: return addRegular<ELF32BE>(Cmd); case ELF64LEKind: return addRegular<ELF64LE>(Cmd); case ELF64BEKind: return addRegular<ELF64BE>(Cmd); default: llvm_unreachable("unknown Config->EKind"); } } void LinkerScript::addSymbol(SymbolAssignment *Cmd) { if (Cmd->Name == ".") return; // If a symbol was in PROVIDE(), we need to define it only when // it is a referenced undefined symbol. SymbolBody *B = findSymbol(Cmd->Name); if (Cmd->Provide && (!B || B->isDefined())) return; Cmd->Sym = addRegularSymbol(Cmd); } bool SymbolAssignment::classof(const BaseCommand *C) { return C->Kind == AssignmentKind; } bool OutputSectionCommand::classof(const BaseCommand *C) { return C->Kind == OutputSectionKind; } bool InputSectionDescription::classof(const BaseCommand *C) { return C->Kind == InputSectionKind; } bool AssertCommand::classof(const BaseCommand *C) { return C->Kind == AssertKind; } bool BytesDataCommand::classof(const BaseCommand *C) { return C->Kind == BytesDataKind; } static StringRef basename(InputSectionBase *S) { if (S->File) return sys::path::filename(S->File->getName()); return ""; } bool LinkerScript::shouldKeep(InputSectionBase *S) { for (InputSectionDescription *ID : Opt.KeptSections) if (ID->FilePat.match(basename(S))) for (SectionPattern &P : ID->SectionPatterns) if (P.SectionPat.match(S->Name)) return true; return false; } // A helper function for the SORT() command. static std::function<bool(InputSectionBase *, InputSectionBase *)> getComparator(SortSectionPolicy K) { switch (K) { case SortSectionPolicy::Alignment: return [](InputSectionBase *A, InputSectionBase *B) { // ">" is not a mistake. Sections with larger alignments are placed // before sections with smaller alignments in order to reduce the // amount of padding necessary. This is compatible with GNU. return A->Alignment > B->Alignment; }; case SortSectionPolicy::Name: return [](InputSectionBase *A, InputSectionBase *B) { return A->Name < B->Name; }; case SortSectionPolicy::Priority: return [](InputSectionBase *A, InputSectionBase *B) { return getPriority(A->Name) < getPriority(B->Name); }; default: llvm_unreachable("unknown sort policy"); } } // A helper function for the SORT() command. static bool matchConstraints(ArrayRef<InputSectionBase *> Sections, ConstraintKind Kind) { if (Kind == ConstraintKind::NoConstraint) return true; bool IsRW = llvm::any_of(Sections, [](InputSectionBase *Sec) { return static_cast<InputSectionBase *>(Sec)->Flags & SHF_WRITE; }); return (IsRW && Kind == ConstraintKind::ReadWrite) || (!IsRW && Kind == ConstraintKind::ReadOnly); } static void sortSections(InputSectionBase **Begin, InputSectionBase **End, SortSectionPolicy K) { if (K != SortSectionPolicy::Default && K != SortSectionPolicy::None) std::stable_sort(Begin, End, getComparator(K)); } // Compute and remember which sections the InputSectionDescription matches. std::vector<InputSectionBase *> LinkerScript::computeInputSections(const InputSectionDescription *Cmd) { std::vector<InputSectionBase *> Ret; // Collects all sections that satisfy constraints of Cmd. for (const SectionPattern &Pat : Cmd->SectionPatterns) { size_t SizeBefore = Ret.size(); for (InputSectionBase *Sec : InputSections) { if (Sec->Assigned) continue; // For -emit-relocs we have to ignore entries like // .rela.dyn : { *(.rela.data) } // which are common because they are in the default bfd script. if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA) continue; StringRef Filename = basename(Sec); if (!Cmd->FilePat.match(Filename) || Pat.ExcludedFilePat.match(Filename) || !Pat.SectionPat.match(Sec->Name)) continue; Ret.push_back(Sec); Sec->Assigned = true; } // Sort sections as instructed by SORT-family commands and --sort-section // option. Because SORT-family commands can be nested at most two depth // (e.g. SORT_BY_NAME(SORT_BY_ALIGNMENT(.text.*))) and because the command // line option is respected even if a SORT command is given, the exact // behavior we have here is a bit complicated. Here are the rules. // // 1. If two SORT commands are given, --sort-section is ignored. // 2. If one SORT command is given, and if it is not SORT_NONE, // --sort-section is handled as an inner SORT command. // 3. If one SORT command is given, and if it is SORT_NONE, don't sort. // 4. If no SORT command is given, sort according to --sort-section. InputSectionBase **Begin = Ret.data() + SizeBefore; InputSectionBase **End = Ret.data() + Ret.size(); if (Pat.SortOuter != SortSectionPolicy::None) { if (Pat.SortInner == SortSectionPolicy::Default) sortSections(Begin, End, Config->SortSection); else sortSections(Begin, End, Pat.SortInner); sortSections(Begin, End, Pat.SortOuter); } } return Ret; } void LinkerScript::discard(ArrayRef<InputSectionBase *> V) { for (InputSectionBase *S : V) { S->Live = false; if (S == InX::ShStrTab) error("discarding .shstrtab section is not allowed"); discard(S->DependentSections); } } std::vector<InputSectionBase *> LinkerScript::createInputSectionList(OutputSectionCommand &OutCmd) { std::vector<InputSectionBase *> Ret; for (BaseCommand *Base : OutCmd.Commands) { auto *Cmd = dyn_cast<InputSectionDescription>(Base); if (!Cmd) continue; Cmd->Sections = computeInputSections(Cmd); Ret.insert(Ret.end(), Cmd->Sections.begin(), Cmd->Sections.end()); } return Ret; } void LinkerScript::processCommands(OutputSectionFactory &Factory) { // A symbol can be assigned before any section is mentioned in the linker // script. In an DSO, the symbol values are addresses, so the only important // section values are: // * SHN_UNDEF // * SHN_ABS // * Any value meaning a regular section. // To handle that, create a dummy aether section that fills the void before // the linker scripts switches to another section. It has an index of one // which will map to whatever the first actual section is. Aether = make<OutputSection>("", 0, SHF_ALLOC); Aether->SectionIndex = 1; CurOutSec = Aether; Dot = 0; for (size_t I = 0; I < Opt.Commands.size(); ++I) { // Handle symbol assignments outside of any output section. if (auto *Cmd = dyn_cast<SymbolAssignment>(Opt.Commands[I])) { addSymbol(Cmd); continue; } if (auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I])) { std::vector<InputSectionBase *> V = createInputSectionList(*Cmd); // The output section name `/DISCARD/' is special. // Any input section assigned to it is discarded. if (Cmd->Name == "/DISCARD/") { discard(V); continue; } // This is for ONLY_IF_RO and ONLY_IF_RW. An output section directive // ".foo : ONLY_IF_R[OW] { ... }" is handled only if all member input // sections satisfy a given constraint. If not, a directive is handled // as if it wasn't present from the beginning. // // Because we'll iterate over Commands many more times, the easiest // way to "make it as if it wasn't present" is to just remove it. if (!matchConstraints(V, Cmd->Constraint)) { for (InputSectionBase *S : V) S->Assigned = false; Opt.Commands.erase(Opt.Commands.begin() + I); --I; continue; } // A directive may contain symbol definitions like this: // ".foo : { ...; bar = .; }". Handle them. for (BaseCommand *Base : Cmd->Commands) if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base)) addSymbol(OutCmd); // Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign // is given, input sections are aligned to that value, whether the // given value is larger or smaller than the original section alignment. if (Cmd->SubalignExpr) { uint32_t Subalign = Cmd->SubalignExpr().getValue(); for (InputSectionBase *S : V) S->Alignment = Subalign; } // Add input sections to an output section. - for (InputSectionBase *S : V) - Factory.addInputSec(S, Cmd->Name); + unsigned Pos = 0; + for (InputSectionBase *S : V) { + // The actual offset will be computed during + // assignAddresses. For now, use the index as a very crude + // approximation so that it is at least easy for other code to + // know the section order. + cast<InputSection>(S)->OutSecOff = Pos++; + Factory.addInputSec(S, Cmd->Name, Cmd->Sec); + } } } CurOutSec = nullptr; } void LinkerScript::fabricateDefaultCommands(bool AllocateHeader) { std::vector<BaseCommand *> Commands; // Define start address uint64_t StartAddr = Config->ImageBase; if (AllocateHeader) StartAddr += elf::getHeaderSize(); // The Sections with -T<section> are sorted in order of ascending address // we must use this if it is lower than StartAddr as calls to setDot() must // be monotonically increasing if (!Config->SectionStartMap.empty()) { uint64_t LowestSecStart = Config->SectionStartMap.begin()->second; StartAddr = std::min(StartAddr, LowestSecStart); } Commands.push_back( make<SymbolAssignment>(".", [=] { return StartAddr; }, "")); // For each OutputSection that needs a VA fabricate an OutputSectionCommand // with an InputSectionDescription describing the InputSections for (OutputSection *Sec : *OutputSections) { if (!(Sec->Flags & SHF_ALLOC)) continue; auto I = Config->SectionStartMap.find(Sec->Name); if (I != Config->SectionStartMap.end()) Commands.push_back( make<SymbolAssignment>(".", [=] { return I->second; }, "")); auto *OSCmd = make<OutputSectionCommand>(Sec->Name); OSCmd->Sec = Sec; if (Sec->PageAlign) OSCmd->AddrExpr = [=] { return alignTo(Script->getDot(), Config->MaxPageSize); }; Commands.push_back(OSCmd); if (Sec->Sections.size()) { auto *ISD = make<InputSectionDescription>(""); OSCmd->Commands.push_back(ISD); for (InputSection *ISec : Sec->Sections) { ISD->Sections.push_back(ISec); ISec->Assigned = true; } } } // SECTIONS commands run before other non SECTIONS commands Commands.insert(Commands.end(), Opt.Commands.begin(), Opt.Commands.end()); Opt.Commands = std::move(Commands); } // Add sections that didn't match any sections command. void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) { - for (InputSectionBase *S : InputSections) - if (S->Live && !S->OutSec) - Factory.addInputSec(S, getOutputSectionName(S->Name)); + for (InputSectionBase *S : InputSections) { + if (!S->Live || S->OutSec) + continue; + StringRef Name = getOutputSectionName(S->Name); + auto I = std::find_if( + Opt.Commands.begin(), Opt.Commands.end(), [&](BaseCommand *Base) { + if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) + return Cmd->Name == Name; + return false; + }); + if (I == Opt.Commands.end()) { + Factory.addInputSec(S, Name); + } else { + auto *Cmd = cast<OutputSectionCommand>(*I); + Factory.addInputSec(S, Name, Cmd->Sec); + auto *ISD = make<InputSectionDescription>(""); + ISD->Sections.push_back(S); + Cmd->Commands.push_back(ISD); + } + } } static bool isTbss(OutputSection *Sec) { return (Sec->Flags & SHF_TLS) && Sec->Type == SHT_NOBITS; } void LinkerScript::output(InputSection *S) { - if (!AlreadyOutputIS.insert(S).second) - return; bool IsTbss = isTbss(CurOutSec); uint64_t Pos = IsTbss ? Dot + ThreadBssOffset : Dot; Pos = alignTo(Pos, S->Alignment); S->OutSecOff = Pos - CurOutSec->Addr; Pos += S->getSize(); // Update output section size after adding each section. This is so that // SIZEOF works correctly in the case below: // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) } CurOutSec->Size = Pos - CurOutSec->Addr; // If there is a memory region associated with this input section, then // place the section in that region and update the region index. if (CurMemRegion) { CurMemRegion->Offset += CurOutSec->Size; uint64_t CurSize = CurMemRegion->Offset - CurMemRegion->Origin; if (CurSize > CurMemRegion->Length) { uint64_t OverflowAmt = CurSize - CurMemRegion->Length; error("section '" + CurOutSec->Name + "' will not fit in region '" + CurMemRegion->Name + "': overflowed by " + Twine(OverflowAmt) + " bytes"); } } if (IsTbss) ThreadBssOffset = Pos - Dot; else Dot = Pos; } -void LinkerScript::flush() { - assert(CurOutSec); - if (!AlreadyOutputOS.insert(CurOutSec).second) - return; - for (InputSection *I : CurOutSec->Sections) - output(I); -} - void LinkerScript::switchTo(OutputSection *Sec) { if (CurOutSec == Sec) return; - if (AlreadyOutputOS.count(Sec)) - return; CurOutSec = Sec; Dot = alignTo(Dot, CurOutSec->Alignment); CurOutSec->Addr = isTbss(CurOutSec) ? Dot + ThreadBssOffset : Dot; // If neither AT nor AT> is specified for an allocatable section, the linker // will set the LMA such that the difference between VMA and LMA for the // section is the same as the preceding output section in the same region // https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html if (LMAOffset) CurOutSec->LMAOffset = LMAOffset(); } void LinkerScript::process(BaseCommand &Base) { // This handles the assignments to symbol or to the dot. if (auto *Cmd = dyn_cast<SymbolAssignment>(&Base)) { assignSymbol(Cmd, true); return; } // Handle BYTE(), SHORT(), LONG(), or QUAD(). if (auto *Cmd = dyn_cast<BytesDataCommand>(&Base)) { Cmd->Offset = Dot - CurOutSec->Addr; Dot += Cmd->Size; CurOutSec->Size = Dot - CurOutSec->Addr; return; } // Handle ASSERT(). if (auto *Cmd = dyn_cast<AssertCommand>(&Base)) { Cmd->Expression(); return; } // Handle a single input section description command. // It calculates and assigns the offsets for each section and also // updates the output section size. auto &Cmd = cast<InputSectionDescription>(Base); for (InputSectionBase *Sec : Cmd.Sections) { // We tentatively added all synthetic sections at the beginning and removed // empty ones afterwards (because there is no way to know whether they were // going be empty or not other than actually running linker scripts.) // We need to ignore remains of empty sections. if (auto *S = dyn_cast<SyntheticSection>(Sec)) if (S->empty()) continue; if (!Sec->Live) continue; - assert(CurOutSec == Sec->OutSec || AlreadyOutputOS.count(Sec->OutSec)); + assert(CurOutSec == Sec->OutSec); output(cast<InputSection>(Sec)); } } -static OutputSection * -findSection(StringRef Name, const std::vector<OutputSection *> &Sections) { - for (OutputSection *Sec : Sections) - if (Sec->Name == Name) - return Sec; - return nullptr; -} - // This function searches for a memory region to place the given output // section in. If found, a pointer to the appropriate memory region is // returned. Otherwise, a nullptr is returned. MemoryRegion *LinkerScript::findMemoryRegion(OutputSectionCommand *Cmd) { // If a memory region name was specified in the output section command, // then try to find that region first. if (!Cmd->MemoryRegionName.empty()) { auto It = Opt.MemoryRegions.find(Cmd->MemoryRegionName); if (It != Opt.MemoryRegions.end()) return &It->second; error("memory region '" + Cmd->MemoryRegionName + "' not declared"); return nullptr; } // If at least one memory region is defined, all sections must // belong to some memory region. Otherwise, we don't need to do // anything for memory regions. if (Opt.MemoryRegions.empty()) return nullptr; OutputSection *Sec = Cmd->Sec; // See if a region can be found by matching section flags. for (auto &Pair : Opt.MemoryRegions) { MemoryRegion &M = Pair.second; if ((M.Flags & Sec->Flags) && (M.NegFlags & Sec->Flags) == 0) return &M; } // Otherwise, no suitable region was found. if (Sec->Flags & SHF_ALLOC) error("no memory region specified for section '" + Sec->Name + "'"); return nullptr; } // This function assigns offsets to input sections and an output section // for a single sections command (e.g. ".text { *(.text); }"). void LinkerScript::assignOffsets(OutputSectionCommand *Cmd) { OutputSection *Sec = Cmd->Sec; if (!Sec) return; if (Cmd->AddrExpr && (Sec->Flags & SHF_ALLOC)) setDot(Cmd->AddrExpr, Cmd->Location, false); if (Cmd->LMAExpr) { uint64_t D = Dot; LMAOffset = [=] { return Cmd->LMAExpr().getValue() - D; }; } CurMemRegion = Cmd->MemRegion; if (CurMemRegion) Dot = CurMemRegion->Offset; switchTo(Sec); - // flush() may add orphan sections, so the order of flush() and - // symbol assignments is important. We want to call flush() first so - // that symbols pointing the end of the current section points to - // the location after orphan sections. - auto Mid = - std::find_if(Cmd->Commands.rbegin(), Cmd->Commands.rend(), - [](BaseCommand *Cmd) { return !isa<SymbolAssignment>(Cmd); }) - .base(); - for (auto I = Cmd->Commands.begin(); I != Mid; ++I) - process(**I); - flush(); - for (auto I = Mid, E = Cmd->Commands.end(); I != E; ++I) - process(**I); + for (BaseCommand *C : Cmd->Commands) + process(*C); } void LinkerScript::removeEmptyCommands() { // It is common practice to use very generic linker scripts. So for any // given run some of the output sections in the script will be empty. // We could create corresponding empty output sections, but that would // clutter the output. // We instead remove trivially empty sections. The bfd linker seems even // more aggressive at removing them. auto Pos = std::remove_if( Opt.Commands.begin(), Opt.Commands.end(), [&](BaseCommand *Base) { if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) - return !Cmd->Sec; + return std::find(OutputSections->begin(), OutputSections->end(), + Cmd->Sec) == OutputSections->end(); return false; }); Opt.Commands.erase(Pos, Opt.Commands.end()); } static bool isAllSectionDescription(const OutputSectionCommand &Cmd) { for (BaseCommand *Base : Cmd.Commands) if (!isa<InputSectionDescription>(*Base)) return false; return true; } void LinkerScript::adjustSectionsBeforeSorting() { // If the output section contains only symbol assignments, create a // corresponding output section. The bfd linker seems to only create them if // '.' is assigned to, but creating these section should not have any bad // consequeces and gives us a section to put the symbol in. uint64_t Flags = SHF_ALLOC; uint32_t Type = SHT_PROGBITS; for (BaseCommand *Base : Opt.Commands) { auto *Cmd = dyn_cast<OutputSectionCommand>(Base); if (!Cmd) continue; - if (OutputSection *Sec = findSection(Cmd->Name, *OutputSections)) { - Cmd->Sec = Sec; + if (OutputSection *Sec = Cmd->Sec) { Flags = Sec->Flags; Type = Sec->Type; continue; } if (isAllSectionDescription(*Cmd)) continue; auto *OutSec = make<OutputSection>(Cmd->Name, Type, Flags); OutputSections->push_back(OutSec); Cmd->Sec = OutSec; } } void LinkerScript::adjustSectionsAfterSorting() { placeOrphanSections(); // Try and find an appropriate memory region to assign offsets in. for (BaseCommand *Base : Opt.Commands) { if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) { Cmd->MemRegion = findMemoryRegion(Cmd); // Handle align (e.g. ".foo : ALIGN(16) { ... }"). if (Cmd->AlignExpr) Cmd->Sec->updateAlignment(Cmd->AlignExpr().getValue()); } } // If output section command doesn't specify any segments, // and we haven't previously assigned any section to segment, // then we simply assign section to the very first load segment. // Below is an example of such linker script: // PHDRS { seg PT_LOAD; } // SECTIONS { .aaa : { *(.aaa) } } std::vector<StringRef> DefPhdrs; auto FirstPtLoad = std::find_if(Opt.PhdrsCommands.begin(), Opt.PhdrsCommands.end(), [](const PhdrsCommand &Cmd) { return Cmd.Type == PT_LOAD; }); if (FirstPtLoad != Opt.PhdrsCommands.end()) DefPhdrs.push_back(FirstPtLoad->Name); // Walk the commands and propagate the program headers to commands that don't // explicitly specify them. for (BaseCommand *Base : Opt.Commands) { auto *Cmd = dyn_cast<OutputSectionCommand>(Base); if (!Cmd) continue; if (Cmd->Phdrs.empty()) Cmd->Phdrs = DefPhdrs; else DefPhdrs = Cmd->Phdrs; } removeEmptyCommands(); } // When placing orphan sections, we want to place them after symbol assignments // so that an orphan after // begin_foo = .; // foo : { *(foo) } // end_foo = .; // doesn't break the intended meaning of the begin/end symbols. // We don't want to go over sections since Writer<ELFT>::sortSections is the // one in charge of deciding the order of the sections. // We don't want to go over alignments, since doing so in // rx_sec : { *(rx_sec) } // . = ALIGN(0x1000); // /* The RW PT_LOAD starts here*/ // rw_sec : { *(rw_sec) } // would mean that the RW PT_LOAD would become unaligned. static bool shouldSkip(BaseCommand *Cmd) { if (isa<OutputSectionCommand>(Cmd)) return false; if (auto *Assign = dyn_cast<SymbolAssignment>(Cmd)) return Assign->Name != "."; return true; } // Orphan sections are sections present in the input files which are // not explicitly placed into the output file by the linker script. // // When the control reaches this function, Opt.Commands contains // output section commands for non-orphan sections only. This function // adds new elements for orphan sections so that all sections are // explicitly handled by Opt.Commands. // // Writer<ELFT>::sortSections has already sorted output sections. // What we need to do is to scan OutputSections vector and // Opt.Commands in parallel to find orphan sections. If there is an // output section that doesn't have a corresponding entry in // Opt.Commands, we will insert a new entry to Opt.Commands. // // There is some ambiguity as to where exactly a new entry should be // inserted, because Opt.Commands contains not only output section // commands but also other types of commands such as symbol assignment // expressions. There's no correct answer here due to the lack of the // formal specification of the linker script. We use heuristics to // determine whether a new output command should be added before or // after another commands. For the details, look at shouldSkip // function. void LinkerScript::placeOrphanSections() { // The OutputSections are already in the correct order. // This loops creates or moves commands as needed so that they are in the // correct order. int CmdIndex = 0; // As a horrible special case, skip the first . assignment if it is before any // section. We do this because it is common to set a load address by starting // the script with ". = 0xabcd" and the expectation is that every section is // after that. auto FirstSectionOrDotAssignment = std::find_if(Opt.Commands.begin(), Opt.Commands.end(), [](BaseCommand *Cmd) { return !shouldSkip(Cmd); }); if (FirstSectionOrDotAssignment != Opt.Commands.end()) { CmdIndex = FirstSectionOrDotAssignment - Opt.Commands.begin(); if (isa<SymbolAssignment>(**FirstSectionOrDotAssignment)) ++CmdIndex; } for (OutputSection *Sec : *OutputSections) { StringRef Name = Sec->Name; // Find the last spot where we can insert a command and still get the // correct result. auto CmdIter = Opt.Commands.begin() + CmdIndex; auto E = Opt.Commands.end(); while (CmdIter != E && shouldSkip(*CmdIter)) { ++CmdIter; ++CmdIndex; } + // If there is no command corresponding to this output section, + // create one and put a InputSectionDescription in it so that both + // representations agree on which input sections to use. auto Pos = std::find_if(CmdIter, E, [&](BaseCommand *Base) { auto *Cmd = dyn_cast<OutputSectionCommand>(Base); return Cmd && Cmd->Name == Name; }); if (Pos == E) { auto *Cmd = make<OutputSectionCommand>(Name); - Cmd->Sec = Sec; Opt.Commands.insert(CmdIter, Cmd); ++CmdIndex; + + Cmd->Sec = Sec; + auto *ISD = make<InputSectionDescription>(""); + for (InputSection *IS : Sec->Sections) + ISD->Sections.push_back(IS); + Cmd->Commands.push_back(ISD); + continue; } // Continue from where we found it. CmdIndex = (Pos - Opt.Commands.begin()) + 1; } } void LinkerScript::processNonSectionCommands() { for (BaseCommand *Base : Opt.Commands) { if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) assignSymbol(Cmd, false); else if (auto *Cmd = dyn_cast<AssertCommand>(Base)) Cmd->Expression(); + } +} + +// Do a last effort at synchronizing the linker script "AST" and the section +// list. This is needed to account for last minute changes, like adding a +// .ARM.exidx terminator and sorting SHF_LINK_ORDER sections. +// +// FIXME: We should instead create the "AST" earlier and the above changes would +// be done directly in the "AST". +// +// This can only handle new sections being added and sections being reordered. +void LinkerScript::synchronize() { + for (BaseCommand *Base : Opt.Commands) { + auto *Cmd = dyn_cast<OutputSectionCommand>(Base); + if (!Cmd) + continue; + ArrayRef<InputSection *> Sections = Cmd->Sec->Sections; + std::vector<InputSectionBase **> ScriptSections; + DenseSet<InputSectionBase *> ScriptSectionsSet; + for (BaseCommand *Base : Cmd->Commands) { + auto *ISD = dyn_cast<InputSectionDescription>(Base); + if (!ISD) + continue; + for (InputSectionBase *&IS : ISD->Sections) { + if (IS->Live) { + ScriptSections.push_back(&IS); + ScriptSectionsSet.insert(IS); + } + } + } + std::vector<InputSectionBase *> Missing; + for (InputSection *IS : Sections) + if (!ScriptSectionsSet.count(IS)) + Missing.push_back(IS); + if (!Missing.empty()) { + auto ISD = make<InputSectionDescription>(""); + ISD->Sections = Missing; + Cmd->Commands.push_back(ISD); + for (InputSectionBase *&IS : ISD->Sections) + if (IS->Live) + ScriptSections.push_back(&IS); + } + assert(ScriptSections.size() == Sections.size()); + for (int I = 0, N = Sections.size(); I < N; ++I) + *ScriptSections[I] = Sections[I]; } } void LinkerScript::assignAddresses(std::vector<PhdrEntry> &Phdrs) { // Assign addresses as instructed by linker script SECTIONS sub-commands. Dot = 0; ErrorOnMissingSection = true; switchTo(Aether); for (BaseCommand *Base : Opt.Commands) { if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) { assignSymbol(Cmd, false); continue; } if (auto *Cmd = dyn_cast<AssertCommand>(Base)) { Cmd->Expression(); continue; } auto *Cmd = cast<OutputSectionCommand>(Base); assignOffsets(Cmd); } uint64_t MinVA = std::numeric_limits<uint64_t>::max(); for (OutputSection *Sec : *OutputSections) { if (Sec->Flags & SHF_ALLOC) MinVA = std::min<uint64_t>(MinVA, Sec->Addr); else Sec->Addr = 0; } allocateHeaders(Phdrs, *OutputSections, MinVA); } // Creates program headers as instructed by PHDRS linker script command. std::vector<PhdrEntry> LinkerScript::createPhdrs() { std::vector<PhdrEntry> Ret; // Process PHDRS and FILEHDR keywords because they are not // real output sections and cannot be added in the following loop. for (const PhdrsCommand &Cmd : Opt.PhdrsCommands) { Ret.emplace_back(Cmd.Type, Cmd.Flags == UINT_MAX ? PF_R : Cmd.Flags); PhdrEntry &Phdr = Ret.back(); if (Cmd.HasFilehdr) Phdr.add(Out::ElfHeader); if (Cmd.HasPhdrs) Phdr.add(Out::ProgramHeaders); if (Cmd.LMAExpr) { Phdr.p_paddr = Cmd.LMAExpr().getValue(); Phdr.HasLMA = true; } } // Add output sections to program headers. for (OutputSection *Sec : *OutputSections) { if (!(Sec->Flags & SHF_ALLOC)) break; // Assign headers specified by linker script for (size_t Id : getPhdrIndices(Sec->Name)) { Ret[Id].add(Sec); if (Opt.PhdrsCommands[Id].Flags == UINT_MAX) Ret[Id].p_flags |= Sec->getPhdrFlags(); } } return Ret; } bool LinkerScript::ignoreInterpSection() { // Ignore .interp section in case we have PHDRS specification // and PT_INTERP isn't listed. if (Opt.PhdrsCommands.empty()) return false; for (PhdrsCommand &Cmd : Opt.PhdrsCommands) if (Cmd.Type == PT_INTERP) return false; return true; } Optional<uint32_t> LinkerScript::getFiller(StringRef Name) { for (BaseCommand *Base : Opt.Commands) if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) if (Cmd->Name == Name) return Cmd->Filler; return None; } static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) { if (Size == 1) *Buf = Data; else if (Size == 2) write16(Buf, Data, Config->Endianness); else if (Size == 4) write32(Buf, Data, Config->Endianness); else if (Size == 8) write64(Buf, Data, Config->Endianness); else llvm_unreachable("unsupported Size argument"); } void LinkerScript::writeDataBytes(StringRef Name, uint8_t *Buf) { int I = getSectionIndex(Name); if (I == INT_MAX) return; auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I]); for (BaseCommand *Base : Cmd->Commands) if (auto *Data = dyn_cast<BytesDataCommand>(Base)) writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size); } bool LinkerScript::hasLMA(StringRef Name) { for (BaseCommand *Base : Opt.Commands) if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) if (Cmd->LMAExpr && Cmd->Name == Name) return true; return false; } // Returns the index of the given section name in linker script // SECTIONS commands. Sections are laid out as the same order as they // were in the script. If a given name did not appear in the script, // it returns INT_MAX, so that it will be laid out at end of file. int LinkerScript::getSectionIndex(StringRef Name) { for (int I = 0, E = Opt.Commands.size(); I != E; ++I) if (auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I])) if (Cmd->Name == Name) return I; return INT_MAX; } ExprValue LinkerScript::getSymbolValue(const Twine &Loc, StringRef S) { if (S == ".") return {CurOutSec, Dot - CurOutSec->Addr}; if (SymbolBody *B = findSymbol(S)) { if (auto *D = dyn_cast<DefinedRegular>(B)) return {D->Section, D->Value}; if (auto *C = dyn_cast<DefinedCommon>(B)) return {InX::Common, C->Offset}; } error(Loc + ": symbol not found: " + S); return 0; } bool LinkerScript::isDefined(StringRef S) { return findSymbol(S) != nullptr; } // Returns indices of ELF headers containing specific section, identified // by Name. Each index is a zero based number of ELF header listed within // PHDRS {} script block. std::vector<size_t> LinkerScript::getPhdrIndices(StringRef SectionName) { for (BaseCommand *Base : Opt.Commands) { auto *Cmd = dyn_cast<OutputSectionCommand>(Base); if (!Cmd || Cmd->Name != SectionName) continue; std::vector<size_t> Ret; for (StringRef PhdrName : Cmd->Phdrs) Ret.push_back(getPhdrIndex(Cmd->Location, PhdrName)); return Ret; } return {}; } size_t LinkerScript::getPhdrIndex(const Twine &Loc, StringRef PhdrName) { size_t I = 0; for (PhdrsCommand &Cmd : Opt.PhdrsCommands) { if (Cmd.Name == PhdrName) return I; ++I; } error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS"); return 0; } Index: vendor/lld/dist/ELF/LinkerScript.h =================================================================== --- vendor/lld/dist/ELF/LinkerScript.h (revision 317689) +++ vendor/lld/dist/ELF/LinkerScript.h (revision 317690) @@ -1,290 +1,287 @@ //===- LinkerScript.h -------------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_ELF_LINKER_SCRIPT_H #define LLD_ELF_LINKER_SCRIPT_H #include "Config.h" #include "Strings.h" #include "Writer.h" #include "lld/Core/LLVM.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/MemoryBuffer.h" #include <cstddef> #include <cstdint> #include <functional> #include <memory> #include <vector> namespace lld { namespace elf { class DefinedCommon; class SymbolBody; class InputSectionBase; class InputSection; class OutputSection; class OutputSectionFactory; class InputSectionBase; class SectionBase; struct ExprValue { SectionBase *Sec; uint64_t Val; bool ForceAbsolute; ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val) : Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute) {} ExprValue(SectionBase *Sec, uint64_t Val) : ExprValue(Sec, false, Val) {} ExprValue(uint64_t Val) : ExprValue(nullptr, Val) {} bool isAbsolute() const { return ForceAbsolute || Sec == nullptr; } uint64_t getValue() const; uint64_t getSecAddr() const; }; // This represents an expression in the linker script. // ScriptParser::readExpr reads an expression and returns an Expr. // Later, we evaluate the expression by calling the function. typedef std::function<ExprValue()> Expr; // This enum is used to implement linker script SECTIONS command. // https://sourceware.org/binutils/docs/ld/SECTIONS.html#SECTIONS enum SectionsCommandKind { AssignmentKind, // . = expr or <sym> = expr OutputSectionKind, InputSectionKind, AssertKind, // ASSERT(expr) BytesDataKind // BYTE(expr), SHORT(expr), LONG(expr) or QUAD(expr) }; struct BaseCommand { BaseCommand(int K) : Kind(K) {} int Kind; }; // This represents ". = <expr>" or "<symbol> = <expr>". struct SymbolAssignment : BaseCommand { SymbolAssignment(StringRef Name, Expr E, std::string Loc) : BaseCommand(AssignmentKind), Name(Name), Expression(E), Location(Loc) {} static bool classof(const BaseCommand *C); // The LHS of an expression. Name is either a symbol name or ".". StringRef Name; SymbolBody *Sym = nullptr; // The RHS of an expression. Expr Expression; // Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN. bool Provide = false; bool Hidden = false; // Holds file name and line number for error reporting. std::string Location; }; // Linker scripts allow additional constraints to be put on ouput sections. // If an output section is marked as ONLY_IF_RO, the section is created // only if its input sections are read-only. Likewise, an output section // with ONLY_IF_RW is created if all input sections are RW. enum class ConstraintKind { NoConstraint, ReadOnly, ReadWrite }; // This struct is used to represent the location and size of regions of // target memory. Instances of the struct are created by parsing the // MEMORY command. struct MemoryRegion { std::string Name; uint64_t Origin; uint64_t Length; uint64_t Offset; uint32_t Flags; uint32_t NegFlags; }; struct OutputSectionCommand : BaseCommand { OutputSectionCommand(StringRef Name) : BaseCommand(OutputSectionKind), Name(Name) {} static bool classof(const BaseCommand *C); OutputSection *Sec = nullptr; MemoryRegion *MemRegion = nullptr; StringRef Name; Expr AddrExpr; Expr AlignExpr; Expr LMAExpr; Expr SubalignExpr; std::vector<BaseCommand *> Commands; std::vector<StringRef> Phdrs; llvm::Optional<uint32_t> Filler; ConstraintKind Constraint = ConstraintKind::NoConstraint; std::string Location; std::string MemoryRegionName; }; // This struct represents one section match pattern in SECTIONS() command. // It can optionally have negative match pattern for EXCLUDED_FILE command. // Also it may be surrounded with SORT() command, so contains sorting rules. struct SectionPattern { SectionPattern(StringMatcher &&Pat1, StringMatcher &&Pat2) : ExcludedFilePat(Pat1), SectionPat(Pat2) {} StringMatcher ExcludedFilePat; StringMatcher SectionPat; SortSectionPolicy SortOuter; SortSectionPolicy SortInner; }; struct InputSectionDescription : BaseCommand { InputSectionDescription(StringRef FilePattern) : BaseCommand(InputSectionKind), FilePat(FilePattern) {} static bool classof(const BaseCommand *C); StringMatcher FilePat; // Input sections that matches at least one of SectionPatterns // will be associated with this InputSectionDescription. std::vector<SectionPattern> SectionPatterns; std::vector<InputSectionBase *> Sections; }; // Represents an ASSERT(). struct AssertCommand : BaseCommand { AssertCommand(Expr E) : BaseCommand(AssertKind), Expression(E) {} static bool classof(const BaseCommand *C); Expr Expression; }; // Represents BYTE(), SHORT(), LONG(), or QUAD(). struct BytesDataCommand : BaseCommand { BytesDataCommand(Expr E, unsigned Size) : BaseCommand(BytesDataKind), Expression(E), Size(Size) {} static bool classof(const BaseCommand *C); Expr Expression; unsigned Offset; unsigned Size; }; struct PhdrsCommand { StringRef Name; unsigned Type; bool HasFilehdr; bool HasPhdrs; unsigned Flags; Expr LMAExpr; }; // ScriptConfiguration holds linker script parse results. struct ScriptConfiguration { // Used to assign addresses to sections. std::vector<BaseCommand *> Commands; // Used to assign sections to headers. std::vector<PhdrsCommand> PhdrsCommands; bool HasSections = false; // List of section patterns specified with KEEP commands. They will // be kept even if they are unused and --gc-sections is specified. std::vector<InputSectionDescription *> KeptSections; // A map from memory region name to a memory region descriptor. llvm::DenseMap<llvm::StringRef, MemoryRegion> MemoryRegions; // A list of symbols referenced by the script. std::vector<llvm::StringRef> ReferencedSymbols; }; class LinkerScript { protected: void assignSymbol(SymbolAssignment *Cmd, bool InSec); void setDot(Expr E, const Twine &Loc, bool InSec); std::vector<InputSectionBase *> computeInputSections(const InputSectionDescription *); std::vector<InputSectionBase *> createInputSectionList(OutputSectionCommand &Cmd); std::vector<size_t> getPhdrIndices(StringRef SectionName); size_t getPhdrIndex(const Twine &Loc, StringRef PhdrName); MemoryRegion *findMemoryRegion(OutputSectionCommand *Cmd); void switchTo(OutputSection *Sec); - void flush(); void output(InputSection *Sec); void process(BaseCommand &Base); OutputSection *Aether; bool ErrorOnMissingSection = false; uint64_t Dot; uint64_t ThreadBssOffset = 0; std::function<uint64_t()> LMAOffset; OutputSection *CurOutSec = nullptr; MemoryRegion *CurMemRegion = nullptr; - llvm::DenseSet<OutputSection *> AlreadyOutputOS; - llvm::DenseSet<InputSectionBase *> AlreadyOutputIS; - public: bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); } uint64_t getDot() { return Dot; } OutputSection *getOutputSection(const Twine &Loc, StringRef S); uint64_t getOutputSectionSize(StringRef S); void discard(ArrayRef<InputSectionBase *> V); ExprValue getSymbolValue(const Twine &Loc, StringRef S); bool isDefined(StringRef S); std::vector<OutputSection *> *OutputSections; void fabricateDefaultCommands(bool AllocateHeader); void addOrphanSections(OutputSectionFactory &Factory); void removeEmptyCommands(); void adjustSectionsBeforeSorting(); void adjustSectionsAfterSorting(); std::vector<PhdrEntry> createPhdrs(); bool ignoreInterpSection(); llvm::Optional<uint32_t> getFiller(StringRef Name); bool hasLMA(StringRef Name); bool shouldKeep(InputSectionBase *S); void assignOffsets(OutputSectionCommand *Cmd); void placeOrphanSections(); void processNonSectionCommands(); + void synchronize(); void assignAddresses(std::vector<PhdrEntry> &Phdrs); int getSectionIndex(StringRef Name); void writeDataBytes(StringRef Name, uint8_t *Buf); void addSymbol(SymbolAssignment *Cmd); void processCommands(OutputSectionFactory &Factory); // Parsed linker script configurations are set to this struct. ScriptConfiguration Opt; }; extern LinkerScript *Script; } // end namespace elf } // end namespace lld #endif // LLD_ELF_LINKER_SCRIPT_H Index: vendor/lld/dist/ELF/MapFile.cpp =================================================================== --- vendor/lld/dist/ELF/MapFile.cpp (revision 317689) +++ vendor/lld/dist/ELF/MapFile.cpp (revision 317690) @@ -1,131 +1,142 @@ //===- MapFile.cpp --------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the -Map option. It shows lists in order and // hierarchically the output sections, input sections, input files and // symbol: // -// Address Size Align Out In File Symbol -// ================================================================= -// 00201000 00000015 4 .text -// 00201000 0000000e 4 .text -// 00201000 0000000e 4 test.o -// 0020100e 00000000 0 local -// 00201005 00000000 0 f(int) +// Address Size Align Out In Symbol +// 00201000 00000015 4 .text +// 00201000 0000000e 4 test.o:(.text) +// 0020100e 00000000 0 local +// 00201005 00000000 0 f(int) // //===----------------------------------------------------------------------===// #include "MapFile.h" #include "InputFiles.h" #include "Strings.h" +#include "SymbolTable.h" +#include "Threads.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace llvm::object; using namespace lld; using namespace lld::elf; -static void writeOutSecLine(raw_fd_ostream &OS, int Width, uint64_t Address, - uint64_t Size, uint64_t Align, StringRef Name) { - OS << format("%0*llx %0*llx %5lld ", Width, Address, Width, Size, Align) - << left_justify(Name, 7); -} +typedef DenseMap<const SectionBase *, SmallVector<DefinedRegular *, 4>> + SymbolMapTy; -static void writeInSecLine(raw_fd_ostream &OS, int Width, uint64_t Address, - uint64_t Size, uint64_t Align, StringRef Name) { - // Pass an empty name to align the text to the correct column. - writeOutSecLine(OS, Width, Address, Size, Align, ""); - OS << ' ' << left_justify(Name, 7); +// Print out the first three columns of a line. +template <class ELFT> +static void writeHeader(raw_ostream &OS, uint64_t Addr, uint64_t Size, + uint64_t Align) { + int W = ELFT::Is64Bits ? 16 : 8; + OS << format("%0*llx %0*llx %5lld ", W, Addr, W, Size, Align); } -static void writeFileLine(raw_fd_ostream &OS, int Width, uint64_t Address, - uint64_t Size, uint64_t Align, StringRef Name) { - // Pass an empty name to align the text to the correct column. - writeInSecLine(OS, Width, Address, Size, Align, ""); - OS << ' ' << left_justify(Name, 7); -} +static std::string indent(int Depth) { return std::string(Depth * 8, ' '); } -static void writeSymbolLine(raw_fd_ostream &OS, int Width, uint64_t Address, - uint64_t Size, StringRef Name) { - // Pass an empty name to align the text to the correct column. - writeFileLine(OS, Width, Address, Size, 0, ""); - OS << ' ' << left_justify(Name, 7); +// Returns a list of all symbols that we want to print out. +template <class ELFT> std::vector<DefinedRegular *> getSymbols() { + std::vector<DefinedRegular *> V; + for (elf::ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) + for (SymbolBody *B : File->getSymbols()) + if (B->File == File && !B->isSection()) + if (auto *Sym = dyn_cast<DefinedRegular>(B)) + if (Sym->Section) + V.push_back(Sym); + return V; } +// Returns a map from sections to their symbols. template <class ELFT> -static void writeInputSection(raw_fd_ostream &OS, const InputSection *IS, - StringRef &PrevName) { - int Width = ELFT::Is64Bits ? 16 : 8; - StringRef Name = IS->Name; - if (Name != PrevName) { - writeInSecLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff, IS->getSize(), - IS->Alignment, Name); - OS << '\n'; - PrevName = Name; - } +SymbolMapTy getSectionSyms(ArrayRef<DefinedRegular *> Syms) { + SymbolMapTy Ret; + for (DefinedRegular *S : Syms) + Ret[S->Section].push_back(S); - elf::ObjectFile<ELFT> *File = IS->template getFile<ELFT>(); - if (!File) - return; - writeFileLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff, IS->getSize(), - IS->Alignment, toString(File)); - OS << '\n'; - - for (SymbolBody *Sym : File->getSymbols()) { - auto *DR = dyn_cast<DefinedRegular>(Sym); - if (!DR) - continue; - if (DR->Section != IS) - continue; - if (DR->isSection()) - continue; - writeSymbolLine(OS, Width, Sym->getVA(), Sym->getSize<ELFT>(), - toString(*Sym)); - OS << '\n'; + // Sort symbols by address. We want to print out symbols in the + // order in the output file rather than the order they appeared + // in the input files. + for (auto &It : Ret) { + SmallVectorImpl<DefinedRegular *> &V = It.second; + std::sort(V.begin(), V.end(), [](DefinedRegular *A, DefinedRegular *B) { + return A->getVA() < B->getVA(); + }); } + return Ret; } +// Construct a map from symbols to their stringified representations. +// Demangling symbols (which is what toString() does) is slow, so +// we do that in batch using parallel-for. template <class ELFT> -static void writeMapFile2(raw_fd_ostream &OS, - ArrayRef<OutputSection *> OutputSections) { - int Width = ELFT::Is64Bits ? 16 : 8; +DenseMap<DefinedRegular *, std::string> +getSymbolStrings(ArrayRef<DefinedRegular *> Syms) { + std::vector<std::string> Str(Syms.size()); + parallelFor(0, Syms.size(), [&](size_t I) { + raw_string_ostream OS(Str[I]); + writeHeader<ELFT>(OS, Syms[I]->getVA(), Syms[I]->template getSize<ELFT>(), + 0); + OS << indent(2) << toString(*Syms[I]); + }); - OS << left_justify("Address", Width) << ' ' << left_justify("Size", Width) - << " Align Out In File Symbol\n"; - - for (OutputSection *Sec : OutputSections) { - writeOutSecLine(OS, Width, Sec->Addr, Sec->Size, Sec->Alignment, Sec->Name); - OS << '\n'; - - StringRef PrevName = ""; - for (InputSection *IS : Sec->Sections) { - writeInputSection<ELFT>(OS, IS, PrevName); - } - } + DenseMap<DefinedRegular *, std::string> Ret; + for (size_t I = 0, E = Syms.size(); I < E; ++I) + Ret[Syms[I]] = std::move(Str[I]); + return Ret; } template <class ELFT> void elf::writeMapFile(ArrayRef<OutputSection *> OutputSections) { if (Config->MapFile.empty()) return; + // Open a map file for writing. std::error_code EC; raw_fd_ostream OS(Config->MapFile, EC, sys::fs::F_None); - if (EC) + if (EC) { error("cannot open " + Config->MapFile + ": " + EC.message()); - else - writeMapFile2<ELFT>(OS, OutputSections); + return; + } + + // Collect symbol info that we want to print out. + std::vector<DefinedRegular *> Syms = getSymbols<ELFT>(); + SymbolMapTy SectionSyms = getSectionSyms<ELFT>(Syms); + DenseMap<DefinedRegular *, std::string> SymStr = getSymbolStrings<ELFT>(Syms); + + // Print out the header line. + int W = ELFT::Is64Bits ? 16 : 8; + OS << left_justify("Address", W) << ' ' << left_justify("Size", W) + << " Align Out In Symbol\n"; + + // Print out file contents. + for (OutputSection *OSec : OutputSections) { + writeHeader<ELFT>(OS, OSec->Addr, OSec->Size, OSec->Alignment); + OS << OSec->Name << '\n'; + + // Dump symbols for each input section. + for (InputSection *IS : OSec->Sections) { + writeHeader<ELFT>(OS, OSec->Addr + IS->OutSecOff, IS->getSize(), + IS->Alignment); + OS << indent(1) << toString(IS) << '\n'; + for (DefinedRegular *Sym : SectionSyms[IS]) + OS << SymStr[Sym] << '\n'; + } + } } template void elf::writeMapFile<ELF32LE>(ArrayRef<OutputSection *>); template void elf::writeMapFile<ELF32BE>(ArrayRef<OutputSection *>); template void elf::writeMapFile<ELF64LE>(ArrayRef<OutputSection *>); template void elf::writeMapFile<ELF64BE>(ArrayRef<OutputSection *>); Index: vendor/lld/dist/ELF/Options.td =================================================================== --- vendor/lld/dist/ELF/Options.td (revision 317689) +++ vendor/lld/dist/ELF/Options.td (revision 317690) @@ -1,404 +1,405 @@ include "llvm/Option/OptParser.td" // For options whose names are multiple letters, either one dash or // two can precede the option name except those that start with 'o'. class F<string name>: Flag<["--", "-"], name>; class J<string name>: Joined<["--", "-"], name>; class S<string name>: Separate<["--", "-"], name>; class JS<string name>: JoinedOrSeparate<["--", "-"], name>; def auxiliary: S<"auxiliary">, HelpText<"Set DT_AUXILIARY field to the specified name">; def Bsymbolic: F<"Bsymbolic">, HelpText<"Bind defined symbols locally">; def Bsymbolic_functions: F<"Bsymbolic-functions">, HelpText<"Bind defined function symbols locally">; def Bdynamic: F<"Bdynamic">, HelpText<"Link against shared libraries">; def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries">; def build_id: F<"build-id">, HelpText<"Generate build ID note">; def build_id_eq: J<"build-id=">, HelpText<"Generate build ID note">; def compress_debug_sections : J<"compress-debug-sections=">, HelpText<"Compress DWARF debug sections">; def defsym: J<"defsym=">, HelpText<"Define a symbol alias">; def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">, HelpText<"Add a directory to the library search path">; def O: Joined<["-"], "O">, HelpText<"Optimize output file size">; def Tbss: S<"Tbss">, HelpText<"Same as --section-start with .bss as the sectionname">; def Tdata: S<"Tdata">, HelpText<"Same as --section-start with .data as the sectionname">; def Ttext: S<"Ttext">, HelpText<"Same as --section-start with .text as the sectionname">; def allow_multiple_definition: F<"allow-multiple-definition">, HelpText<"Allow multiple definitions">; def as_needed: F<"as-needed">, HelpText<"Only set DT_NEEDED for shared libraries if used">; def color_diagnostics: F<"color-diagnostics">, HelpText<"Use colors in diagnostics">; def color_diagnostics_eq: J<"color-diagnostics=">, HelpText<"Use colors in diagnostics">; def define_common: F<"define-common">, HelpText<"Assign space to common symbols">; def demangle: F<"demangle">, HelpText<"Demangle symbol names">; def disable_new_dtags: F<"disable-new-dtags">, HelpText<"Disable new dynamic tags">; def discard_all: F<"discard-all">, HelpText<"Delete all local symbols">; def discard_locals: F<"discard-locals">, HelpText<"Delete temporary local symbols">; def discard_none: F<"discard-none">, HelpText<"Keep all symbols in the symbol table">; def dynamic_linker: S<"dynamic-linker">, HelpText<"Which dynamic linker to use">; def dynamic_list: S<"dynamic-list">, HelpText<"Read a list of dynamic symbols">; def eh_frame_hdr: F<"eh-frame-hdr">, HelpText<"Request creation of .eh_frame_hdr section and PT_GNU_EH_FRAME segment header">; def emit_relocs: F<"emit-relocs">, HelpText<"Generate relocations in output">; def enable_new_dtags: F<"enable-new-dtags">, HelpText<"Enable new dynamic tags">; def end_lib: F<"end-lib">, HelpText<"End a grouping of objects that should be treated as if they were together in an archive">; def entry: S<"entry">, MetaVarName<"<entry>">, HelpText<"Name of entry point symbol">; def error_limit: S<"error-limit">, HelpText<"Maximum number of errors to emit before stopping (0 = no limit)">; def error_unresolved_symbols: F<"error-unresolved-symbols">, HelpText<"Report unresolved symbols as errors">; def export_dynamic: F<"export-dynamic">, HelpText<"Put symbols in the dynamic symbol table">; def export_dynamic_symbol: S<"export-dynamic-symbol">, HelpText<"Put a symbol in the dynamic symbol table">; def fatal_warnings: F<"fatal-warnings">, HelpText<"Treat warnings as errors">; def fini: S<"fini">, MetaVarName<"<symbol>">, HelpText<"Specify a finalizer function">; def full_shutdown : F<"full-shutdown">, HelpText<"Perform a full shutdown instead of calling _exit">; def format: J<"format=">, MetaVarName<"<input-format>">, HelpText<"Change the input format of the inputs following this option">; def gc_sections: F<"gc-sections">, HelpText<"Enable garbage collection of unused sections">; def gdb_index: F<"gdb-index">, HelpText<"Generate .gdb_index section">; def hash_style: S<"hash-style">, HelpText<"Specify hash style (sysv, gnu or both)">; def help: F<"help">, HelpText<"Print option help">; def icf: F<"icf=all">, HelpText<"Enable identical code folding">; def image_base : J<"image-base=">, HelpText<"Set the base address">; def init: S<"init">, MetaVarName<"<symbol>">, HelpText<"Specify an initializer function">; def l: JoinedOrSeparate<["-"], "l">, MetaVarName<"<libName>">, HelpText<"Root name of library to use">; def lto_O: J<"lto-O">, MetaVarName<"<opt-level>">, HelpText<"Optimization level for LTO">; def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target emulation">; def Map: JS<"Map">, HelpText<"Print a link map to the specified file">; def nostdlib: F<"nostdlib">, HelpText<"Only search directories specified on the command line">; def no_as_needed: F<"no-as-needed">, HelpText<"Always DT_NEEDED for shared libraries">; def no_color_diagnostics: F<"no-color-diagnostics">, HelpText<"Do not use colors in diagnostics">; def no_define_common: F<"no-define-common">, HelpText<"Do not assign space to common symbols">; def no_demangle: F<"no-demangle">, HelpText<"Do not demangle symbol names">; def no_dynamic_linker: F<"no-dynamic-linker">, HelpText<"Inhibit output of .interp section">; def no_export_dynamic: F<"no-export-dynamic">; def no_fatal_warnings: F<"no-fatal-warnings">; def no_gc_sections: F<"no-gc-sections">, HelpText<"Disable garbage collection of unused sections">; def no_gnu_unique: F<"no-gnu-unique">, HelpText<"Disable STB_GNU_UNIQUE symbol binding">; def no_threads: F<"no-threads">, HelpText<"Do not run the linker multi-threaded">; def no_whole_archive: F<"no-whole-archive">, HelpText<"Restores the default behavior of loading archive members">; def noinhibit_exec: F<"noinhibit-exec">, HelpText<"Retain the executable output file whenever it is still usable">; def nopie: F<"nopie">, HelpText<"Do not create a position independent executable">; def no_rosegment: F<"no-rosegment">, HelpText<"Do not put read-only non-executable sections in their own segment">; def no_undefined: F<"no-undefined">, HelpText<"Report unresolved symbols even if the linker is creating a shared library">; def no_undefined_version: F<"no-undefined-version">, HelpText<"Report version scripts that refer undefined symbols">; def o: JoinedOrSeparate<["-"], "o">, MetaVarName<"<path>">, HelpText<"Path to file to write output">; def oformat: Separate<["--"], "oformat">, MetaVarName<"<format>">, HelpText<"Specify the binary format for the output object file">; def omagic: Flag<["--"], "omagic">, MetaVarName<"<magic>">, HelpText<"Set the text and data sections to be readable and writable">; def pie: F<"pie">, HelpText<"Create a position independent executable">; def print_gc_sections: F<"print-gc-sections">, HelpText<"List removed unused sections">; def print_map: F<"print-map">, HelpText<"Print a link map to the standard output">; def reproduce: S<"reproduce">, HelpText<"Dump linker invocation and input files for debugging">; def rpath: S<"rpath">, HelpText<"Add a DT_RUNPATH to the output">; def relocatable: F<"relocatable">, HelpText<"Create relocatable object file">; def retain_symbols_file: J<"retain-symbols-file=">, MetaVarName<"<file>">, HelpText<"Retain only the symbols listed in the file">; def script: S<"script">, HelpText<"Read linker script">; def section_start: S<"section-start">, MetaVarName<"<address>">, HelpText<"Set address of section">; def shared: F<"shared">, HelpText<"Build a shared object">; def soname: J<"soname=">, HelpText<"Set DT_SONAME">; def sort_section: S<"sort-section">, HelpText<"Specifies sections sorting rule when linkerscript is used">; def start_lib: F<"start-lib">, HelpText<"Start a grouping of objects that should be treated as if they were together in an archive">; def strip_all: F<"strip-all">, HelpText<"Strip all symbols">; def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">; def symbol_ordering_file: S<"symbol-ordering-file">, HelpText<"Layout sections in the order specified by symbol file">; def sysroot: J<"sysroot=">, HelpText<"Set the system root">; def target1_rel: F<"target1-rel">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_REL32">; def target1_abs: F<"target1-abs">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_ABS32">; def target2: J<"target2=">, MetaVarName<"<type>">, HelpText<"Interpret R_ARM_TARGET2 as <type>, where <type> is one of rel, abs, or got-rel">; def threads: F<"threads">, HelpText<"Run the linker multi-threaded">; def trace: F<"trace">, HelpText<"Print the names of the input files">; def trace_symbol : S<"trace-symbol">, HelpText<"Trace references to symbols">; def undefined: S<"undefined">, HelpText<"Force undefined symbol during linking">; def unresolved_symbols: J<"unresolved-symbols=">, HelpText<"Determine how to handle unresolved symbols">; def rsp_quoting: J<"rsp-quoting=">, HelpText<"Quoting style for response files. Values supported: windows|posix">; def v: Flag<["-"], "v">, HelpText<"Display the version number">; def verbose: F<"verbose">, HelpText<"Verbose mode">; def version: F<"version">, HelpText<"Display the version number and exit">; def version_script: S<"version-script">, HelpText<"Read a version script">; def warn_common: F<"warn-common">, HelpText<"Warn about duplicate common symbols">; def warn_unresolved_symbols: F<"warn-unresolved-symbols">, HelpText<"Report unresolved symbols as warnings">; def whole_archive: F<"whole-archive">, HelpText<"Force load of all members in a static library">; def wrap: S<"wrap">, MetaVarName<"<symbol>">, HelpText<"Use wrapper functions for symbol">; def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">, HelpText<"Linker option extensions">; // Aliases def alias_auxiliary: Separate<["-"], "f">, Alias<auxiliary>; def alias_Bdynamic_call_shared: F<"call_shared">, Alias<Bdynamic>; def alias_Bdynamic_dy: F<"dy">, Alias<Bdynamic>; def alias_Bstatic_dn: F<"dn">, Alias<Bstatic>; def alias_Bstatic_non_shared: F<"non_shared">, Alias<Bstatic>; def alias_Bstatic_static: F<"static">, Alias<Bstatic>; def alias_L__library_path: J<"library-path=">, Alias<L>; def alias_define_common_d: Flag<["-"], "d">, Alias<define_common>; def alias_define_common_dc: F<"dc">, Alias<define_common>; def alias_define_common_dp: F<"dp">, Alias<define_common>; def alias_discard_all_x: Flag<["-"], "x">, Alias<discard_all>; def alias_discard_locals_X: Flag<["-"], "X">, Alias<discard_locals>; def alias_dynamic_list: J<"dynamic-list=">, Alias<dynamic_list>; def alias_emit_relocs: Flag<["-"], "q">, Alias<emit_relocs>; def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>; def alias_entry_entry: J<"entry=">, Alias<entry>; def alias_error_limit: J<"error-limit=">, Alias<error_limit>; def alias_export_dynamic_E: Flag<["-"], "E">, Alias<export_dynamic>; def alias_export_dynamic_symbol: J<"export-dynamic-symbol=">, Alias<export_dynamic_symbol>; def alias_fini_fini: J<"fini=">, Alias<fini>; def alias_format_b: S<"b">, Alias<format>; def alias_hash_style_hash_style: J<"hash-style=">, Alias<hash_style>; def alias_init_init: J<"init=">, Alias<init>; def alias_l__library: J<"library=">, Alias<l>; def alias_Map_eq: J<"Map=">, Alias<Map>; def alias_omagic: Flag<["-"], "N">, Alias<omagic>; def alias_o_output: Joined<["--"], "output=">, Alias<o>; def alias_o_output2 : Separate<["--"], "output">, Alias<o>; def alias_pie_pic_executable: F<"pic-executable">, Alias<pie>; def alias_print_map_M: Flag<["-"], "M">, Alias<print_map>; def alias_relocatable_r: Flag<["-"], "r">, Alias<relocatable>; def alias_retain_symbols_file: S<"retain-symbols-file">, Alias<retain_symbols_file>; def alias_rpath_R: JoinedOrSeparate<["-"], "R">, Alias<rpath>; def alias_rpath_rpath: J<"rpath=">, Alias<rpath>; def alias_script_T: JoinedOrSeparate<["-"], "T">, Alias<script>; def alias_shared_Bshareable: F<"Bshareable">, Alias<shared>; def alias_soname_h: JoinedOrSeparate<["-"], "h">, Alias<soname>; def alias_soname_soname: S<"soname">, Alias<soname>; def alias_sort_section: J<"sort-section=">, Alias<sort_section>; def alias_script: J<"script=">, Alias<script>; def alias_strip_all: Flag<["-"], "s">, Alias<strip_all>; def alias_strip_debug_S: Flag<["-"], "S">, Alias<strip_debug>; def alias_Tbss: J<"Tbss=">, Alias<Tbss>; def alias_Tdata: J<"Tdata=">, Alias<Tdata>; def alias_trace: Flag<["-"], "t">, Alias<trace>; def trace_trace_symbol_eq : J<"trace-symbol=">, Alias<trace_symbol>; def alias_trace_symbol_y : JoinedOrSeparate<["-"], "y">, Alias<trace_symbol>; def alias_Ttext: J<"Ttext=">, Alias<Ttext>; def alias_Ttext_segment: S<"Ttext-segment">, Alias<Ttext>; def alias_Ttext_segment_eq: J<"Ttext-segment=">, Alias<Ttext>; def alias_undefined_eq: J<"undefined=">, Alias<undefined>; def alias_undefined_u: JoinedOrSeparate<["-"], "u">, Alias<undefined>; def alias_version_V: Flag<["-"], "V">, Alias<version>; def alias_wrap_wrap: J<"wrap=">, Alias<wrap>; // Our symbol resolution algorithm handles symbols in archive files differently // than traditional linkers, so we don't need --start-group and --end-group. // These options are recongized for compatibility but ignored. def end_group: F<"end-group">; def end_group_paren: Flag<["-"], ")">; def start_group: F<"start-group">; def start_group_paren: Flag<["-"], "(">; +// LTO-related options. +def lto_aa_pipeline: J<"lto-aa-pipeline=">, + HelpText<"AA pipeline to run during LTO. Used in conjunction with -lto-newpm-passes">; +def lto_newpm_passes: J<"lto-newpm-passes=">, + HelpText<"Passes to run during LTO">; +def lto_partitions: J<"lto-partitions=">, + HelpText<"Number of LTO codegen partitions">; +def disable_verify: F<"disable-verify">; +def mllvm: S<"mllvm">; +def opt_remarks_filename: Separate<["--"], "opt-remarks-filename">, + HelpText<"YAML output file for optimization remarks">; +def opt_remarks_with_hotness: Flag<["--"], "opt-remarks-with-hotness">, + HelpText<"Include hotness informations in the optimization remarks file">; +def save_temps: F<"save-temps">; +def thinlto_cache_dir: J<"thinlto-cache-dir=">, + HelpText<"Path to ThinLTO cached object file directory">; +def thinlto_cache_policy: S<"thinlto-cache-policy">, + HelpText<"Pruning policy for the ThinLTO cache">; +def thinlto_jobs: J<"thinlto-jobs=">, HelpText<"Number of ThinLTO jobs">; + // Ignore LTO plugin-related options. // clang -flto passes -plugin and -plugin-opt to the linker. This is required // for ld.gold and ld.bfd to get LTO working. But it's not for lld which doesn't // rely on a plugin. Instead of detecting which linker is used on clang side we // just ignore the option on lld side as it's easier. In fact, the linker could // be called 'ld' and understanding which linker is used would require parsing of // --version output. def plugin: S<"plugin">; def plugin_eq: J<"plugin=">; def plugin_opt: S<"plugin-opt">; def plugin_opt_eq: J<"plugin-opt=">; // Options listed below are silently ignored for now for compatibility. def allow_shlib_undefined: F<"allow-shlib-undefined">; def cref: Flag<["--"], "cref">; def detect_odr_violations: F<"detect-odr-violations">; def g: Flag<["-"], "g">; def no_add_needed: F<"no-add-needed">; def no_allow_shlib_undefined: F<"no-allow-shlib-undefined">; def no_copy_dt_needed_entries: F<"no-copy-dt-needed-entries">, Alias<no_add_needed>; +def no_keep_memory: F<"no-keep-memory">; def no_mmap_output_file: F<"no-mmap-output-file">; def no_warn_common: F<"no-warn-common">; def no_warn_mismatch: F<"no-warn-mismatch">; def rpath_link: S<"rpath-link">; def rpath_link_eq: J<"rpath-link=">; def sort_common: F<"sort-common">; def stats: F<"stats">; def warn_execstack: F<"warn-execstack">; def warn_shared_textrel: F<"warn-shared-textrel">; def EB : F<"EB">; def EL : F<"EL">; def G: JoinedOrSeparate<["-"], "G">; def Qy : F<"Qy">; // Aliases for ignored options def alias_version_script_version_script: J<"version-script=">, Alias<version_script>; - -// LTO-related options. -def lto_aa_pipeline: J<"lto-aa-pipeline=">, - HelpText<"AA pipeline to run during LTO. Used in conjunction with -lto-newpm-passes">; -def lto_newpm_passes: J<"lto-newpm-passes=">, - HelpText<"Passes to run during LTO">; -def lto_partitions: J<"lto-partitions=">, - HelpText<"Number of LTO codegen partitions">; -def disable_verify: F<"disable-verify">; -def mllvm: S<"mllvm">; -def opt_remarks_filename: Separate<["--"], "opt-remarks-filename">, - HelpText<"YAML output file for optimization remarks">; -def opt_remarks_with_hotness: Flag<["--"], "opt-remarks-with-hotness">, - HelpText<"Include hotness informations in the optimization remarks file">; -def save_temps: F<"save-temps">; -def thinlto_cache_dir: J<"thinlto-cache-dir=">, - HelpText<"Path to ThinLTO cached object file directory">; -def thinlto_cache_policy: S<"thinlto-cache-policy">, - HelpText<"Pruning policy for the ThinLTO cache">; -def thinlto_jobs: J<"thinlto-jobs=">, HelpText<"Number of ThinLTO jobs">; Index: vendor/lld/dist/ELF/OutputSections.cpp =================================================================== --- vendor/lld/dist/ELF/OutputSections.cpp (revision 317689) +++ vendor/lld/dist/ELF/OutputSections.cpp (revision 317690) @@ -1,472 +1,478 @@ //===- OutputSections.cpp -------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "OutputSections.h" #include "Config.h" #include "LinkerScript.h" #include "Memory.h" #include "Strings.h" #include "SymbolTable.h" #include "SyntheticSections.h" #include "Target.h" #include "Threads.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/MD5.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/SHA1.h" using namespace llvm; using namespace llvm::dwarf; using namespace llvm::object; using namespace llvm::support::endian; using namespace llvm::ELF; using namespace lld; using namespace lld::elf; uint8_t Out::First; OutputSection *Out::Opd; uint8_t *Out::OpdBuf; PhdrEntry *Out::TlsPhdr; OutputSection *Out::DebugInfo; OutputSection *Out::ElfHeader; OutputSection *Out::ProgramHeaders; OutputSection *Out::PreinitArray; OutputSection *Out::InitArray; OutputSection *Out::FiniArray; uint32_t OutputSection::getPhdrFlags() const { uint32_t Ret = PF_R; if (Flags & SHF_WRITE) Ret |= PF_W; if (Flags & SHF_EXECINSTR) Ret |= PF_X; return Ret; } template <class ELFT> void OutputSection::writeHeaderTo(typename ELFT::Shdr *Shdr) { Shdr->sh_entsize = Entsize; Shdr->sh_addralign = Alignment; Shdr->sh_type = Type; Shdr->sh_offset = Offset; Shdr->sh_flags = Flags; Shdr->sh_info = Info; Shdr->sh_link = Link; Shdr->sh_addr = Addr; Shdr->sh_size = Size; Shdr->sh_name = ShName; } OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags) : SectionBase(Output, Name, Flags, /*Entsize*/ 0, /*Alignment*/ 1, Type, /*Info*/ 0, /*Link*/ 0) {} static bool compareByFilePosition(InputSection *A, InputSection *B) { // Synthetic doesn't have link order dependecy, stable_sort will keep it last if (A->kind() == InputSectionBase::Synthetic || B->kind() == InputSectionBase::Synthetic) return false; auto *LA = cast<InputSection>(A->getLinkOrderDep()); auto *LB = cast<InputSection>(B->getLinkOrderDep()); OutputSection *AOut = LA->OutSec; OutputSection *BOut = LB->OutSec; if (AOut != BOut) return AOut->SectionIndex < BOut->SectionIndex; return LA->OutSecOff < LB->OutSecOff; } // Compress section contents if this section contains debug info. template <class ELFT> void OutputSection::maybeCompress() { typedef typename ELFT::Chdr Elf_Chdr; // Compress only DWARF debug sections. if (!Config->CompressDebugSections || (Flags & SHF_ALLOC) || !Name.startswith(".debug_")) return; // Create a section header. ZDebugHeader.resize(sizeof(Elf_Chdr)); auto *Hdr = reinterpret_cast<Elf_Chdr *>(ZDebugHeader.data()); Hdr->ch_type = ELFCOMPRESS_ZLIB; Hdr->ch_size = Size; Hdr->ch_addralign = Alignment; // Write section contents to a temporary buffer and compress it. std::vector<uint8_t> Buf(Size); writeTo<ELFT>(Buf.data()); if (Error E = zlib::compress(toStringRef(Buf), CompressedData)) fatal("compress failed: " + llvm::toString(std::move(E))); // Update section headers. Size = sizeof(Elf_Chdr) + CompressedData.size(); Flags |= SHF_COMPRESSED; } template <class ELFT> void OutputSection::finalize() { if ((this->Flags & SHF_LINK_ORDER) && !this->Sections.empty()) { std::sort(Sections.begin(), Sections.end(), compareByFilePosition); assignOffsets(); // We must preserve the link order dependency of sections with the // SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We // need to translate the InputSection sh_link to the OutputSection sh_link, // all InputSections in the OutputSection have the same dependency. if (auto *D = this->Sections.front()->getLinkOrderDep()) this->Link = D->OutSec->SectionIndex; } uint32_t Type = this->Type; if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL)) return; InputSection *First = Sections[0]; if (isa<SyntheticSection>(First)) return; this->Link = In<ELFT>::SymTab->OutSec->SectionIndex; // sh_info for SHT_REL[A] sections should contain the section header index of // the section to which the relocation applies. InputSectionBase *S = First->getRelocatedSection(); this->Info = S->OutSec->SectionIndex; } void OutputSection::addSection(InputSection *S) { assert(S->Live); Sections.push_back(S); S->OutSec = this; this->updateAlignment(S->Alignment); // If this section contains a table of fixed-size entries, sh_entsize // holds the element size. Consequently, if this contains two or more // input sections, all of them must have the same sh_entsize. However, // you can put different types of input sections into one output // sectin by using linker scripts. I don't know what to do here. // Probably we sholuld handle that as an error. But for now we just // pick the largest sh_entsize. this->Entsize = std::max(this->Entsize, S->Entsize); } // This function is called after we sort input sections // and scan relocations to setup sections' offsets. void OutputSection::assignOffsets() { uint64_t Off = 0; for (InputSection *S : Sections) { Off = alignTo(Off, S->Alignment); S->OutSecOff = Off; Off += S->getSize(); } this->Size = Off; } void OutputSection::sort(std::function<int(InputSectionBase *S)> Order) { typedef std::pair<unsigned, InputSection *> Pair; auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; }; std::vector<Pair> V; for (InputSection *S : Sections) V.push_back({Order(S), S}); std::stable_sort(V.begin(), V.end(), Comp); Sections.clear(); for (Pair &P : V) Sections.push_back(P.second); } // Sorts input sections by section name suffixes, so that .foo.N comes // before .foo.M if N < M. Used to sort .{init,fini}_array.N sections. // We want to keep the original order if the priorities are the same // because the compiler keeps the original initialization order in a // translation unit and we need to respect that. // For more detail, read the section of the GCC's manual about init_priority. void OutputSection::sortInitFini() { // Sort sections by priority. sort([](InputSectionBase *S) { return getPriority(S->Name); }); } // Returns true if S matches /Filename.?\.o$/. static bool isCrtBeginEnd(StringRef S, StringRef Filename) { if (!S.endswith(".o")) return false; S = S.drop_back(2); if (S.endswith(Filename)) return true; return !S.empty() && S.drop_back().endswith(Filename); } static bool isCrtbegin(StringRef S) { return isCrtBeginEnd(S, "crtbegin"); } static bool isCrtend(StringRef S) { return isCrtBeginEnd(S, "crtend"); } // .ctors and .dtors are sorted by this priority from highest to lowest. // // 1. The section was contained in crtbegin (crtbegin contains // some sentinel value in its .ctors and .dtors so that the runtime // can find the beginning of the sections.) // // 2. The section has an optional priority value in the form of ".ctors.N" // or ".dtors.N" where N is a number. Unlike .{init,fini}_array, // they are compared as string rather than number. // // 3. The section is just ".ctors" or ".dtors". // // 4. The section was contained in crtend, which contains an end marker. // // In an ideal world, we don't need this function because .init_array and // .ctors are duplicate features (and .init_array is newer.) However, there // are too many real-world use cases of .ctors, so we had no choice to // support that with this rather ad-hoc semantics. static bool compCtors(const InputSection *A, const InputSection *B) { bool BeginA = isCrtbegin(A->File->getName()); bool BeginB = isCrtbegin(B->File->getName()); if (BeginA != BeginB) return BeginA; bool EndA = isCrtend(A->File->getName()); bool EndB = isCrtend(B->File->getName()); if (EndA != EndB) return EndB; StringRef X = A->Name; StringRef Y = B->Name; assert(X.startswith(".ctors") || X.startswith(".dtors")); assert(Y.startswith(".ctors") || Y.startswith(".dtors")); X = X.substr(6); Y = Y.substr(6); if (X.empty() && Y.empty()) return false; return X < Y; } // Sorts input sections by the special rules for .ctors and .dtors. // Unfortunately, the rules are different from the one for .{init,fini}_array. // Read the comment above. void OutputSection::sortCtorsDtors() { std::stable_sort(Sections.begin(), Sections.end(), compCtors); } // Fill [Buf, Buf + Size) with Filler. // This is used for linker script "=fillexp" command. static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) { size_t I = 0; for (; I + 4 < Size; I += 4) memcpy(Buf + I, &Filler, 4); memcpy(Buf + I, &Filler, Size - I); } uint32_t OutputSection::getFiller() { // Determine what to fill gaps between InputSections with, as specified by the // linker script. If nothing is specified and this is an executable section, // fall back to trap instructions to prevent bad diassembly and detect invalid // jumps to padding. if (Optional<uint32_t> Filler = Script->getFiller(Name)) return *Filler; if (Flags & SHF_EXECINSTR) return Target->TrapInstr; return 0; } template <class ELFT> void OutputSection::writeTo(uint8_t *Buf) { Loc = Buf; // We may have already rendered compressed content when using // -compress-debug-sections option. Write it together with header. if (!CompressedData.empty()) { memcpy(Buf, ZDebugHeader.data(), ZDebugHeader.size()); memcpy(Buf + ZDebugHeader.size(), CompressedData.data(), CompressedData.size()); return; } // Write leading padding. uint32_t Filler = getFiller(); if (Filler) fill(Buf, Sections.empty() ? Size : Sections[0]->OutSecOff, Filler); parallelFor(0, Sections.size(), [=](size_t I) { InputSection *Sec = Sections[I]; Sec->writeTo<ELFT>(Buf); // Fill gaps between sections. if (Filler) { uint8_t *Start = Buf + Sec->OutSecOff + Sec->getSize(); uint8_t *End; if (I + 1 == Sections.size()) End = Buf + Size; else End = Buf + Sections[I + 1]->OutSecOff; fill(Start, End - Start, Filler); } }); // Linker scripts may have BYTE()-family commands with which you // can write arbitrary bytes to the output. Process them if any. Script->writeDataBytes(Name, Buf); } static uint64_t getOutFlags(InputSectionBase *S) { return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED; } static SectionKey createKey(InputSectionBase *C, StringRef OutsecName) { // The ELF spec just says // ---------------------------------------------------------------- // In the first phase, input sections that match in name, type and // attribute flags should be concatenated into single sections. // ---------------------------------------------------------------- // // However, it is clear that at least some flags have to be ignored for // section merging. At the very least SHF_GROUP and SHF_COMPRESSED have to be // ignored. We should not have two output .text sections just because one was // in a group and another was not for example. // // It also seems that that wording was a late addition and didn't get the // necessary scrutiny. // // Merging sections with different flags is expected by some users. One // reason is that if one file has // // int *const bar __attribute__((section(".foo"))) = (int *)0; // // gcc with -fPIC will produce a read only .foo section. But if another // file has // // int zed; // int *const bar __attribute__((section(".foo"))) = (int *)&zed; // // gcc with -fPIC will produce a read write section. // // Last but not least, when using linker script the merge rules are forced by // the script. Unfortunately, linker scripts are name based. This means that // expressions like *(.foo*) can refer to multiple input sections with // different flags. We cannot put them in different output sections or we // would produce wrong results for // // start = .; *(.foo.*) end = .; *(.bar) // // and a mapping of .foo1 and .bar1 to one section and .foo2 and .bar2 to // another. The problem is that there is no way to layout those output // sections such that the .foo sections are the only thing between the start // and end symbols. // // Given the above issues, we instead merge sections by name and error on // incompatible types and flags. uint32_t Alignment = 0; uint64_t Flags = 0; if (Config->Relocatable && (C->Flags & SHF_MERGE)) { Alignment = std::max<uint64_t>(C->Alignment, C->Entsize); Flags = C->Flags & (SHF_MERGE | SHF_STRINGS); } return SectionKey{OutsecName, Flags, Alignment}; } OutputSectionFactory::OutputSectionFactory( std::vector<OutputSection *> &OutputSections) : OutputSections(OutputSections) {} static uint64_t getIncompatibleFlags(uint64_t Flags) { return Flags & (SHF_ALLOC | SHF_TLS); } // We allow sections of types listed below to merged into a // single progbits section. This is typically done by linker // scripts. Merging nobits and progbits will force disk space // to be allocated for nobits sections. Other ones don't require // any special treatment on top of progbits, so there doesn't // seem to be a harm in merging them. static bool canMergeToProgbits(unsigned Type) { return Type == SHT_NOBITS || Type == SHT_PROGBITS || Type == SHT_INIT_ARRAY || Type == SHT_PREINIT_ARRAY || Type == SHT_FINI_ARRAY || Type == SHT_NOTE; } static void reportDiscarded(InputSectionBase *IS) { if (!Config->PrintGcSections) return; message("removing unused section from '" + IS->Name + "' in file '" + IS->File->getName()); } void OutputSectionFactory::addInputSec(InputSectionBase *IS, StringRef OutsecName) { + SectionKey Key = createKey(IS, OutsecName); + OutputSection *&Sec = Map[Key]; + return addInputSec(IS, OutsecName, Sec); +} + +void OutputSectionFactory::addInputSec(InputSectionBase *IS, + StringRef OutsecName, + OutputSection *&Sec) { if (!IS->Live) { reportDiscarded(IS); return; } - SectionKey Key = createKey(IS, OutsecName); uint64_t Flags = getOutFlags(IS); - OutputSection *&Sec = Map[Key]; if (Sec) { if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(IS->Flags)) error("incompatible section flags for " + Sec->Name + "\n>>> " + toString(IS) + ": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Sec->Name + ": 0x" + utohexstr(Sec->Flags)); if (Sec->Type != IS->Type) { if (canMergeToProgbits(Sec->Type) && canMergeToProgbits(IS->Type)) Sec->Type = SHT_PROGBITS; else error("Section has different type from others with the same name " + toString(IS)); } Sec->Flags |= Flags; } else { - Sec = make<OutputSection>(Key.Name, IS->Type, Flags); + Sec = make<OutputSection>(OutsecName, IS->Type, Flags); OutputSections.push_back(Sec); } Sec->addSection(cast<InputSection>(IS)); } OutputSectionFactory::~OutputSectionFactory() {} SectionKey DenseMapInfo<SectionKey>::getEmptyKey() { return SectionKey{DenseMapInfo<StringRef>::getEmptyKey(), 0, 0}; } SectionKey DenseMapInfo<SectionKey>::getTombstoneKey() { return SectionKey{DenseMapInfo<StringRef>::getTombstoneKey(), 0, 0}; } unsigned DenseMapInfo<SectionKey>::getHashValue(const SectionKey &Val) { return hash_combine(Val.Name, Val.Flags, Val.Alignment); } bool DenseMapInfo<SectionKey>::isEqual(const SectionKey &LHS, const SectionKey &RHS) { return DenseMapInfo<StringRef>::isEqual(LHS.Name, RHS.Name) && LHS.Flags == RHS.Flags && LHS.Alignment == RHS.Alignment; } uint64_t elf::getHeaderSize() { if (Config->OFormatBinary) return 0; return Out::ElfHeader->Size + Out::ProgramHeaders->Size; } template void OutputSection::writeHeaderTo<ELF32LE>(ELF32LE::Shdr *Shdr); template void OutputSection::writeHeaderTo<ELF32BE>(ELF32BE::Shdr *Shdr); template void OutputSection::writeHeaderTo<ELF64LE>(ELF64LE::Shdr *Shdr); template void OutputSection::writeHeaderTo<ELF64BE>(ELF64BE::Shdr *Shdr); template void OutputSection::finalize<ELF32LE>(); template void OutputSection::finalize<ELF32BE>(); template void OutputSection::finalize<ELF64LE>(); template void OutputSection::finalize<ELF64BE>(); template void OutputSection::maybeCompress<ELF32LE>(); template void OutputSection::maybeCompress<ELF32BE>(); template void OutputSection::maybeCompress<ELF64LE>(); template void OutputSection::maybeCompress<ELF64BE>(); template void OutputSection::writeTo<ELF32LE>(uint8_t *Buf); template void OutputSection::writeTo<ELF32BE>(uint8_t *Buf); template void OutputSection::writeTo<ELF64LE>(uint8_t *Buf); template void OutputSection::writeTo<ELF64BE>(uint8_t *Buf); Index: vendor/lld/dist/ELF/OutputSections.h =================================================================== --- vendor/lld/dist/ELF/OutputSections.h (revision 317689) +++ vendor/lld/dist/ELF/OutputSections.h (revision 317690) @@ -1,156 +1,158 @@ //===- OutputSections.h -----------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_ELF_OUTPUT_SECTIONS_H #define LLD_ELF_OUTPUT_SECTIONS_H #include "Config.h" #include "InputSection.h" #include "Relocations.h" #include "lld/Core/LLVM.h" #include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/ELF.h" namespace lld { namespace elf { struct PhdrEntry; class SymbolBody; struct EhSectionPiece; class EhInputSection; class InputSection; class InputSectionBase; class MergeInputSection; class OutputSection; template <class ELFT> class ObjectFile; template <class ELFT> class SharedFile; class SharedSymbol; class DefinedRegular; // This represents a section in an output file. // It is composed of multiple InputSections. // The writer creates multiple OutputSections and assign them unique, // non-overlapping file offsets and VAs. class OutputSection final : public SectionBase { public: OutputSection(StringRef Name, uint32_t Type, uint64_t Flags); static bool classof(const SectionBase *S) { return S->kind() == SectionBase::Output; } uint64_t getLMA() const { return Addr + LMAOffset; } template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *SHdr); unsigned SectionIndex; uint32_t getPhdrFlags() const; void updateAlignment(uint32_t Val) { if (Val > Alignment) Alignment = Val; } // If true, this section will be page aligned on disk. // Typically the first section of each PT_LOAD segment has this flag. bool PageAlign = false; // Pointer to the first section in PT_LOAD segment, which this section // also resides in. This field is used to correctly compute file offset // of a section. When two sections share the same load segment, difference // between their file offsets should be equal to difference between their // virtual addresses. To compute some section offset we use the following // formula: Off = Off_first + VA - VA_first. OutputSection *FirstInPtLoad = nullptr; // The following fields correspond to Elf_Shdr members. uint64_t Size = 0; uint64_t Offset = 0; uint64_t LMAOffset = 0; uint64_t Addr = 0; uint32_t ShName = 0; void addSection(InputSection *S); void sort(std::function<int(InputSectionBase *S)> Order); void sortInitFini(); void sortCtorsDtors(); uint32_t getFiller(); template <class ELFT> void writeTo(uint8_t *Buf); template <class ELFT> void finalize(); template <class ELFT> void maybeCompress(); void assignOffsets(); std::vector<InputSection *> Sections; // Used for implementation of --compress-debug-sections option. std::vector<uint8_t> ZDebugHeader; llvm::SmallVector<char, 1> CompressedData; // Location in the output buffer. uint8_t *Loc = nullptr; }; // All output sections that are handled by the linker specially are // globally accessible. Writer initializes them, so don't use them // until Writer is initialized. struct Out { static uint8_t First; static OutputSection *Opd; static uint8_t *OpdBuf; static PhdrEntry *TlsPhdr; static OutputSection *DebugInfo; static OutputSection *ElfHeader; static OutputSection *ProgramHeaders; static OutputSection *PreinitArray; static OutputSection *InitArray; static OutputSection *FiniArray; }; struct SectionKey { StringRef Name; uint64_t Flags; uint32_t Alignment; }; } } namespace llvm { template <> struct DenseMapInfo<lld::elf::SectionKey> { static lld::elf::SectionKey getEmptyKey(); static lld::elf::SectionKey getTombstoneKey(); static unsigned getHashValue(const lld::elf::SectionKey &Val); static bool isEqual(const lld::elf::SectionKey &LHS, const lld::elf::SectionKey &RHS); }; } namespace lld { namespace elf { // This class knows how to create an output section for a given // input section. Output section type is determined by various // factors, including input section's sh_flags, sh_type and // linker scripts. class OutputSectionFactory { public: OutputSectionFactory(std::vector<OutputSection *> &OutputSections); ~OutputSectionFactory(); void addInputSec(InputSectionBase *IS, StringRef OutsecName); + void addInputSec(InputSectionBase *IS, StringRef OutsecName, + OutputSection *&Sec); private: llvm::SmallDenseMap<SectionKey, OutputSection *> Map; std::vector<OutputSection *> &OutputSections; }; uint64_t getHeaderSize(); } // namespace elf } // namespace lld #endif Index: vendor/lld/dist/ELF/Strings.h =================================================================== --- vendor/lld/dist/ELF/Strings.h (revision 317689) +++ vendor/lld/dist/ELF/Strings.h (revision 317690) @@ -1,82 +1,86 @@ //===- Strings.h ------------------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_ELF_STRINGS_H #define LLD_ELF_STRINGS_H #include "lld/Core/LLVM.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/GlobPattern.h" #include <vector> namespace lld { namespace elf { int getPriority(StringRef S); bool hasWildcard(StringRef S); std::vector<uint8_t> parseHex(StringRef S); bool isValidCIdentifier(StringRef S); StringRef unquote(StringRef S); // This is a lazy version of StringRef. String size is computed lazily // when it is needed. It is more efficient than StringRef to instantiate // if you have a string whose size is unknown. // // ELF string tables contain a lot of null-terminated strings. // Most of them are not necessary for the linker because they are names // of local symbols and the linker doesn't use local symbol names for // name resolution. So, we use this class to represents strings read // from string tables. class StringRefZ { public: StringRefZ() : Start(nullptr), Size(0) {} StringRefZ(const char *S, size_t Size) : Start(S), Size(Size) {} /*implicit*/ StringRefZ(const char *S) : Start(S), Size(-1) {} /*implicit*/ StringRefZ(llvm::StringRef S) : Start(S.data()), Size(S.size()) {} operator llvm::StringRef() const { if (Size == (size_t)-1) Size = strlen(Start); return {Start, Size}; } private: const char *Start; mutable size_t Size; }; // This class represents multiple glob patterns. class StringMatcher { public: StringMatcher() = default; explicit StringMatcher(ArrayRef<StringRef> Pat); bool match(StringRef S) const; private: std::vector<llvm::GlobPattern> Patterns; }; // Returns a demangled C++ symbol name. If Name is not a mangled // name, it returns Optional::None. llvm::Optional<std::string> demangle(StringRef Name); inline StringRef toStringRef(ArrayRef<uint8_t> Arr) { return {(const char *)Arr.data(), Arr.size()}; } + +inline ArrayRef<uint8_t> toArrayRef(StringRef S) { + return {(const uint8_t *)S.data(), S.size()}; +} } } #endif Index: vendor/lld/dist/ELF/SymbolTable.cpp =================================================================== --- vendor/lld/dist/ELF/SymbolTable.cpp (revision 317689) +++ vendor/lld/dist/ELF/SymbolTable.cpp (revision 317690) @@ -1,735 +1,738 @@ //===- SymbolTable.cpp ----------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Symbol table is a bag of all known symbols. We put all symbols of // all input files to the symbol table. The symbol table is basically // a hash table with the logic to resolve symbol name conflicts using // the symbol types. // //===----------------------------------------------------------------------===// #include "SymbolTable.h" #include "Config.h" #include "Error.h" #include "LinkerScript.h" #include "Memory.h" #include "Symbols.h" #include "llvm/ADT/STLExtras.h" using namespace llvm; using namespace llvm::object; using namespace llvm::ELF; using namespace lld; using namespace lld::elf; // All input object files must be for the same architecture // (e.g. it does not make sense to link x86 object files with // MIPS object files.) This function checks for that error. template <class ELFT> static bool isCompatible(InputFile *F) { if (!isa<ELFFileBase<ELFT>>(F) && !isa<BitcodeFile>(F)) return true; if (F->EKind == Config->EKind && F->EMachine == Config->EMachine) { if (Config->EMachine != EM_MIPS) return true; if (isMipsN32Abi(F) == Config->MipsN32Abi) return true; } if (!Config->Emulation.empty()) error(toString(F) + " is incompatible with " + Config->Emulation); else error(toString(F) + " is incompatible with " + toString(Config->FirstElf)); return false; } // Add symbols in File to the symbol table. template <class ELFT> void SymbolTable<ELFT>::addFile(InputFile *File) { + if (!Config->FirstElf && isa<ELFFileBase<ELFT>>(File)) + Config->FirstElf = File; + if (!isCompatible<ELFT>(File)) return; // Binary file if (auto *F = dyn_cast<BinaryFile>(File)) { BinaryFiles.push_back(F); F->parse<ELFT>(); return; } // .a file if (auto *F = dyn_cast<ArchiveFile>(File)) { F->parse<ELFT>(); return; } // Lazy object file if (auto *F = dyn_cast<LazyObjectFile>(File)) { F->parse<ELFT>(); return; } if (Config->Trace) message(toString(File)); // .so file if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) { // DSOs are uniquified not by filename but by soname. F->parseSoName(); if (ErrorCount || !SoNames.insert(F->SoName).second) return; SharedFiles.push_back(F); F->parseRest(); return; } // LLVM bitcode file if (auto *F = dyn_cast<BitcodeFile>(File)) { BitcodeFiles.push_back(F); F->parse<ELFT>(ComdatGroups); return; } // Regular object file auto *F = cast<ObjectFile<ELFT>>(File); ObjectFiles.push_back(F); F->parse(ComdatGroups); } // This function is where all the optimizations of link-time // optimization happens. When LTO is in use, some input files are // not in native object file format but in the LLVM bitcode format. // This function compiles bitcode files into a few big native files // using LLVM functions and replaces bitcode symbols with the results. // Because all bitcode files that consist of a program are passed // to the compiler at once, it can do whole-program optimization. template <class ELFT> void SymbolTable<ELFT>::addCombinedLTOObject() { if (BitcodeFiles.empty()) return; // Compile bitcode files and replace bitcode symbols. LTO.reset(new BitcodeCompiler); for (BitcodeFile *F : BitcodeFiles) LTO->add(*F); for (InputFile *File : LTO->compile()) { ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(File); DenseSet<CachedHashStringRef> DummyGroups; Obj->parse(DummyGroups); ObjectFiles.push_back(Obj); } } template <class ELFT> DefinedRegular *SymbolTable<ELFT>::addAbsolute(StringRef Name, uint8_t Visibility, uint8_t Binding) { Symbol *Sym = addRegular(Name, Visibility, STT_NOTYPE, 0, 0, Binding, nullptr, nullptr); return cast<DefinedRegular>(Sym->body()); } // Add Name as an "ignored" symbol. An ignored symbol is a regular // linker-synthesized defined symbol, but is only defined if needed. template <class ELFT> DefinedRegular *SymbolTable<ELFT>::addIgnored(StringRef Name, uint8_t Visibility) { SymbolBody *S = find(Name); if (!S || S->isInCurrentDSO()) return nullptr; return addAbsolute(Name, Visibility); } // Set a flag for --trace-symbol so that we can print out a log message // if a new symbol with the same name is inserted into the symbol table. template <class ELFT> void SymbolTable<ELFT>::trace(StringRef Name) { Symtab.insert({CachedHashStringRef(Name), {-1, true}}); } // Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM. // Used to implement --wrap. template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) { SymbolBody *B = find(Name); if (!B) return; Symbol *Sym = B->symbol(); Symbol *Real = addUndefined(Saver.save("__real_" + Name)); Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name)); // We rename symbols by replacing the old symbol's SymbolBody with the new // symbol's SymbolBody. This causes all SymbolBody pointers referring to the // old symbol to instead refer to the new symbol. memcpy(Real->Body.buffer, Sym->Body.buffer, sizeof(Sym->Body)); memcpy(Sym->Body.buffer, Wrap->Body.buffer, sizeof(Wrap->Body)); } // Creates alias for symbol. Used to implement --defsym=ALIAS=SYM. template <class ELFT> void SymbolTable<ELFT>::alias(StringRef Alias, StringRef Name) { SymbolBody *B = find(Name); if (!B) { error("-defsym: undefined symbol: " + Name); return; } Symbol *Sym = B->symbol(); Symbol *AliasSym = addUndefined(Alias); memcpy(AliasSym->Body.buffer, Sym->Body.buffer, sizeof(AliasSym->Body)); } static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { if (VA == STV_DEFAULT) return VB; if (VB == STV_DEFAULT) return VA; return std::min(VA, VB); } // Find an existing symbol or create and insert a new one. template <class ELFT> std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) { auto P = Symtab.insert( {CachedHashStringRef(Name), SymIndex((int)SymVector.size(), false)}); SymIndex &V = P.first->second; bool IsNew = P.second; if (V.Idx == -1) { IsNew = true; V = SymIndex((int)SymVector.size(), true); } Symbol *Sym; if (IsNew) { Sym = make<Symbol>(); Sym->InVersionScript = false; Sym->Binding = STB_WEAK; Sym->Visibility = STV_DEFAULT; Sym->IsUsedInRegularObj = false; Sym->ExportDynamic = false; Sym->Traced = V.Traced; Sym->VersionId = Config->DefaultSymbolVersion; SymVector.push_back(Sym); } else { Sym = SymVector[V.Idx]; } return {Sym, IsNew}; } // Find an existing symbol or create and insert a new one, then apply the given // attributes. template <class ELFT> std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name, uint8_t Type, uint8_t Visibility, bool CanOmitFromDynSym, InputFile *File) { bool IsUsedInRegularObj = !File || File->kind() == InputFile::ObjectKind; Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name); // Merge in the new symbol's visibility. S->Visibility = getMinVisibility(S->Visibility, Visibility); if (!CanOmitFromDynSym && (Config->Shared || Config->ExportDynamic)) S->ExportDynamic = true; if (IsUsedInRegularObj) S->IsUsedInRegularObj = true; if (!WasInserted && S->body()->Type != SymbolBody::UnknownType && ((Type == STT_TLS) != S->body()->isTls())) { error("TLS attribute mismatch: " + toString(*S->body()) + "\n>>> defined in " + toString(S->body()->File) + "\n>>> defined in " + toString(File)); } return {S, WasInserted}; } template <class ELFT> Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name) { return addUndefined(Name, /*IsLocal=*/false, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0, /*CanOmitFromDynSym*/ false, /*File*/ nullptr); } static uint8_t getVisibility(uint8_t StOther) { return StOther & 3; } template <class ELFT> Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, bool IsLocal, uint8_t Binding, uint8_t StOther, uint8_t Type, bool CanOmitFromDynSym, InputFile *File) { Symbol *S; bool WasInserted; uint8_t Visibility = getVisibility(StOther); std::tie(S, WasInserted) = insert(Name, Type, Visibility, CanOmitFromDynSym, File); // An undefined symbol with non default visibility must be satisfied // in the same DSO. if (WasInserted || (isa<SharedSymbol>(S->body()) && Visibility != STV_DEFAULT)) { S->Binding = Binding; replaceBody<Undefined>(S, Name, IsLocal, StOther, Type, File); return S; } if (Binding != STB_WEAK) { if (S->body()->isShared() || S->body()->isLazy()) S->Binding = Binding; if (auto *SS = dyn_cast<SharedSymbol>(S->body())) cast<SharedFile<ELFT>>(SS->File)->IsUsed = true; } if (auto *L = dyn_cast<Lazy>(S->body())) { // An undefined weak will not fetch archive members, but we have to remember // its type. See also comment in addLazyArchive. if (S->isWeak()) L->Type = Type; else if (InputFile *F = L->fetch()) addFile(F); } return S; } // We have a new defined symbol with the specified binding. Return 1 if the new // symbol should win, -1 if the new symbol should lose, or 0 if both symbols are // strong defined symbols. static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) { if (WasInserted) return 1; SymbolBody *Body = S->body(); if (Body->isLazy() || !Body->isInCurrentDSO()) return 1; if (Binding == STB_WEAK) return -1; if (S->isWeak()) return 1; return 0; } // We have a new non-common defined symbol with the specified binding. Return 1 // if the new symbol should win, -1 if the new symbol should lose, or 0 if there // is a conflict. If the new symbol wins, also update the binding. template <typename ELFT> static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding, bool IsAbsolute, typename ELFT::uint Value) { if (int Cmp = compareDefined(S, WasInserted, Binding)) { if (Cmp > 0) S->Binding = Binding; return Cmp; } SymbolBody *B = S->body(); if (isa<DefinedCommon>(B)) { // Non-common symbols take precedence over common symbols. if (Config->WarnCommon) warn("common " + S->body()->getName() + " is overridden"); return 1; } else if (auto *R = dyn_cast<DefinedRegular>(B)) { if (R->Section == nullptr && Binding == STB_GLOBAL && IsAbsolute && R->Value == Value) return -1; } return 0; } template <class ELFT> Symbol *SymbolTable<ELFT>::addCommon(StringRef N, uint64_t Size, uint32_t Alignment, uint8_t Binding, uint8_t StOther, uint8_t Type, InputFile *File) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(N, Type, getVisibility(StOther), /*CanOmitFromDynSym*/ false, File); int Cmp = compareDefined(S, WasInserted, Binding); if (Cmp > 0) { S->Binding = Binding; replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File); } else if (Cmp == 0) { auto *C = dyn_cast<DefinedCommon>(S->body()); if (!C) { // Non-common symbols take precedence over common symbols. if (Config->WarnCommon) warn("common " + S->body()->getName() + " is overridden"); return S; } if (Config->WarnCommon) warn("multiple common of " + S->body()->getName()); Alignment = C->Alignment = std::max(C->Alignment, Alignment); if (Size > C->Size) replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File); } return S; } static void warnOrError(const Twine &Msg) { if (Config->AllowMultipleDefinition) warn(Msg); else error(Msg); } static void reportDuplicate(SymbolBody *Sym, InputFile *NewFile) { warnOrError("duplicate symbol: " + toString(*Sym) + "\n>>> defined in " + toString(Sym->File) + "\n>>> defined in " + toString(NewFile)); } template <class ELFT> static void reportDuplicate(SymbolBody *Sym, InputSectionBase *ErrSec, typename ELFT::uint ErrOffset) { DefinedRegular *D = dyn_cast<DefinedRegular>(Sym); if (!D || !D->Section || !ErrSec) { reportDuplicate(Sym, ErrSec ? ErrSec->getFile<ELFT>() : nullptr); return; } // Construct and print an error message in the form of: // // ld.lld: error: duplicate symbol: foo // >>> defined at bar.c:30 // >>> bar.o (/home/alice/src/bar.o) // >>> defined at baz.c:563 // >>> baz.o in archive libbaz.a auto *Sec1 = cast<InputSectionBase>(D->Section); std::string Src1 = Sec1->getSrcMsg<ELFT>(D->Value); std::string Obj1 = Sec1->getObjMsg<ELFT>(D->Value); std::string Src2 = ErrSec->getSrcMsg<ELFT>(ErrOffset); std::string Obj2 = ErrSec->getObjMsg<ELFT>(ErrOffset); std::string Msg = "duplicate symbol: " + toString(*Sym) + "\n>>> defined at "; if (!Src1.empty()) Msg += Src1 + "\n>>> "; Msg += Obj1 + "\n>>> defined at "; if (!Src2.empty()) Msg += Src2 + "\n>>> "; Msg += Obj2; warnOrError(Msg); } template <typename ELFT> Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size, uint8_t Binding, SectionBase *Section, InputFile *File) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther), /*CanOmitFromDynSym*/ false, File); int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, Binding, Section == nullptr, Value); if (Cmp > 0) replaceBody<DefinedRegular>(S, Name, /*IsLocal=*/false, StOther, Type, Value, Size, Section, File); else if (Cmp == 0) reportDuplicate<ELFT>(S->body(), dyn_cast_or_null<InputSectionBase>(Section), Value); return S; } template <typename ELFT> void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *File, StringRef Name, const Elf_Sym &Sym, const typename ELFT::Verdef *Verdef) { // DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT // as the visibility, which will leave the visibility in the symbol table // unchanged. Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, Sym.getType(), STV_DEFAULT, /*CanOmitFromDynSym*/ true, File); // Make sure we preempt DSO symbols with default visibility. if (Sym.getVisibility() == STV_DEFAULT) S->ExportDynamic = true; SymbolBody *Body = S->body(); // An undefined symbol with non default visibility must be satisfied // in the same DSO. if (WasInserted || (isa<Undefined>(Body) && Body->getVisibility() == STV_DEFAULT)) { replaceBody<SharedSymbol>(S, File, Name, Sym.st_other, Sym.getType(), &Sym, Verdef); if (!S->isWeak()) File->IsUsed = true; } } template <class ELFT> Symbol *SymbolTable<ELFT>::addBitcode(StringRef Name, uint8_t Binding, uint8_t StOther, uint8_t Type, bool CanOmitFromDynSym, BitcodeFile *F) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, F); int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, Binding, /*IsAbs*/ false, /*Value*/ 0); if (Cmp > 0) replaceBody<DefinedRegular>(S, Name, /*IsLocal=*/false, StOther, Type, 0, 0, nullptr, F); else if (Cmp == 0) reportDuplicate(S->body(), F); return S; } template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) { auto It = Symtab.find(CachedHashStringRef(Name)); if (It == Symtab.end()) return nullptr; SymIndex V = It->second; if (V.Idx == -1) return nullptr; return SymVector[V.Idx]->body(); } template <class ELFT> SymbolBody *SymbolTable<ELFT>::findInCurrentDSO(StringRef Name) { if (SymbolBody *S = find(Name)) if (S->isInCurrentDSO()) return S; return nullptr; } template <class ELFT> void SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F, const object::Archive::Symbol Sym) { Symbol *S; bool WasInserted; StringRef Name = Sym.getName(); std::tie(S, WasInserted) = insert(Name); if (WasInserted) { replaceBody<LazyArchive>(S, *F, Sym, SymbolBody::UnknownType); return; } if (!S->body()->isUndefined()) return; // Weak undefined symbols should not fetch members from archives. If we were // to keep old symbol we would not know that an archive member was available // if a strong undefined symbol shows up afterwards in the link. If a strong // undefined symbol never shows up, this lazy symbol will get to the end of // the link and must be treated as the weak undefined one. We already marked // this symbol as used when we added it to the symbol table, but we also need // to preserve its type. FIXME: Move the Type field to Symbol. if (S->isWeak()) { replaceBody<LazyArchive>(S, *F, Sym, S->body()->Type); return; } std::pair<MemoryBufferRef, uint64_t> MBInfo = F->getMember(&Sym); if (!MBInfo.first.getBuffer().empty()) addFile(createObjectFile(MBInfo.first, F->getName(), MBInfo.second)); } template <class ELFT> void SymbolTable<ELFT>::addLazyObject(StringRef Name, LazyObjectFile &Obj) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name); if (WasInserted) { replaceBody<LazyObject>(S, Name, Obj, SymbolBody::UnknownType); return; } if (!S->body()->isUndefined()) return; // See comment for addLazyArchive above. if (S->isWeak()) { replaceBody<LazyObject>(S, Name, Obj, S->body()->Type); } else { MemoryBufferRef MBRef = Obj.getBuffer(); if (!MBRef.getBuffer().empty()) addFile(createObjectFile(MBRef)); } } // Process undefined (-u) flags by loading lazy symbols named by those flags. template <class ELFT> void SymbolTable<ELFT>::scanUndefinedFlags() { for (StringRef S : Config->Undefined) if (auto *L = dyn_cast_or_null<Lazy>(find(S))) if (InputFile *File = L->fetch()) addFile(File); } // This function takes care of the case in which shared libraries depend on // the user program (not the other way, which is usual). Shared libraries // may have undefined symbols, expecting that the user program provides // the definitions for them. An example is BSD's __progname symbol. // We need to put such symbols to the main program's .dynsym so that // shared libraries can find them. // Except this, we ignore undefined symbols in DSOs. template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() { for (SharedFile<ELFT> *File : SharedFiles) { for (StringRef U : File->getUndefinedSymbols()) { SymbolBody *Sym = find(U); if (!Sym || !Sym->isDefined()) continue; Sym->symbol()->ExportDynamic = true; // If -dynamic-list is given, the default version is set to // VER_NDX_LOCAL, which prevents a symbol to be exported via .dynsym. // Set to VER_NDX_GLOBAL so the symbol will be handled as if it were // specified by -dynamic-list. Sym->symbol()->VersionId = VER_NDX_GLOBAL; } } } // Initialize DemangledSyms with a map from demangled symbols to symbol // objects. Used to handle "extern C++" directive in version scripts. // // The map will contain all demangled symbols. That can be very large, // and in LLD we generally want to avoid do anything for each symbol. // Then, why are we doing this? Here's why. // // Users can use "extern C++ {}" directive to match against demangled // C++ symbols. For example, you can write a pattern such as // "llvm::*::foo(int, ?)". Obviously, there's no way to handle this // other than trying to match a pattern against all demangled symbols. // So, if "extern C++" feature is used, we need to demangle all known // symbols. template <class ELFT> StringMap<std::vector<SymbolBody *>> &SymbolTable<ELFT>::getDemangledSyms() { if (!DemangledSyms) { DemangledSyms.emplace(); for (Symbol *Sym : SymVector) { SymbolBody *B = Sym->body(); if (B->isUndefined()) continue; if (Optional<std::string> S = demangle(B->getName())) (*DemangledSyms)[*S].push_back(B); else (*DemangledSyms)[B->getName()].push_back(B); } } return *DemangledSyms; } template <class ELFT> std::vector<SymbolBody *> SymbolTable<ELFT>::findByVersion(SymbolVersion Ver) { if (Ver.IsExternCpp) return getDemangledSyms().lookup(Ver.Name); if (SymbolBody *B = find(Ver.Name)) if (!B->isUndefined()) return {B}; return {}; } template <class ELFT> std::vector<SymbolBody *> SymbolTable<ELFT>::findAllByVersion(SymbolVersion Ver) { std::vector<SymbolBody *> Res; StringMatcher M(Ver.Name); if (Ver.IsExternCpp) { for (auto &P : getDemangledSyms()) if (M.match(P.first())) Res.insert(Res.end(), P.second.begin(), P.second.end()); return Res; } for (Symbol *Sym : SymVector) { SymbolBody *B = Sym->body(); if (!B->isUndefined() && M.match(B->getName())) Res.push_back(B); } return Res; } // If there's only one anonymous version definition in a version // script file, the script does not actually define any symbol version, // but just specifies symbols visibilities. template <class ELFT> void SymbolTable<ELFT>::handleAnonymousVersion() { for (SymbolVersion &Ver : Config->VersionScriptGlobals) assignExactVersion(Ver, VER_NDX_GLOBAL, "global"); for (SymbolVersion &Ver : Config->VersionScriptGlobals) assignWildcardVersion(Ver, VER_NDX_GLOBAL); for (SymbolVersion &Ver : Config->VersionScriptLocals) assignExactVersion(Ver, VER_NDX_LOCAL, "local"); for (SymbolVersion &Ver : Config->VersionScriptLocals) assignWildcardVersion(Ver, VER_NDX_LOCAL); } // Set symbol versions to symbols. This function handles patterns // containing no wildcard characters. template <class ELFT> void SymbolTable<ELFT>::assignExactVersion(SymbolVersion Ver, uint16_t VersionId, StringRef VersionName) { if (Ver.HasWildcard) return; // Get a list of symbols which we need to assign the version to. std::vector<SymbolBody *> Syms = findByVersion(Ver); if (Syms.empty()) { if (Config->NoUndefinedVersion) error("version script assignment of '" + VersionName + "' to symbol '" + Ver.Name + "' failed: symbol not defined"); return; } // Assign the version. for (SymbolBody *B : Syms) { Symbol *Sym = B->symbol(); if (Sym->InVersionScript) warn("duplicate symbol '" + Ver.Name + "' in version script"); Sym->VersionId = VersionId; Sym->InVersionScript = true; } } template <class ELFT> void SymbolTable<ELFT>::assignWildcardVersion(SymbolVersion Ver, uint16_t VersionId) { if (!Ver.HasWildcard) return; std::vector<SymbolBody *> Syms = findAllByVersion(Ver); // Exact matching takes precendence over fuzzy matching, // so we set a version to a symbol only if no version has been assigned // to the symbol. This behavior is compatible with GNU. for (SymbolBody *B : Syms) if (B->symbol()->VersionId == Config->DefaultSymbolVersion) B->symbol()->VersionId = VersionId; } // This function processes version scripts by updating VersionId // member of symbols. template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() { // Symbol themselves might know their versions because symbols // can contain versions in the form of <name>@<version>. // Let them parse their names. if (!Config->VersionDefinitions.empty()) for (Symbol *Sym : SymVector) Sym->body()->parseSymbolVersion(); // Handle edge cases first. handleAnonymousVersion(); if (Config->VersionDefinitions.empty()) return; // Now we have version definitions, so we need to set version ids to symbols. // Each version definition has a glob pattern, and all symbols that match // with the pattern get that version. // First, we assign versions to exact matching symbols, // i.e. version definitions not containing any glob meta-characters. for (VersionDefinition &V : Config->VersionDefinitions) for (SymbolVersion &Ver : V.Globals) assignExactVersion(Ver, V.Id, V.Name); // Next, we assign versions to fuzzy matching symbols, // i.e. version definitions containing glob meta-characters. // Note that because the last match takes precedence over previous matches, // we iterate over the definitions in the reverse order. for (VersionDefinition &V : llvm::reverse(Config->VersionDefinitions)) for (SymbolVersion &Ver : V.Globals) assignWildcardVersion(Ver, V.Id); } template class elf::SymbolTable<ELF32LE>; template class elf::SymbolTable<ELF32BE>; template class elf::SymbolTable<ELF64LE>; template class elf::SymbolTable<ELF64BE>; Index: vendor/lld/dist/ELF/SyntheticSections.cpp =================================================================== --- vendor/lld/dist/ELF/SyntheticSections.cpp (revision 317689) +++ vendor/lld/dist/ELF/SyntheticSections.cpp (revision 317690) @@ -1,2347 +1,2354 @@ //===- SyntheticSections.cpp ----------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file contains linker-synthesized sections. Currently, // synthetic sections are created either output sections or input sections, // but we are rewriting code so that all synthetic sections are created as // input sections. // //===----------------------------------------------------------------------===// #include "SyntheticSections.h" #include "Config.h" #include "Error.h" #include "InputFiles.h" #include "LinkerScript.h" #include "Memory.h" #include "OutputSections.h" #include "Strings.h" #include "SymbolTable.h" #include "Target.h" #include "Threads.h" #include "Writer.h" #include "lld/Config/Version.h" #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Endian.h" #include "llvm/Support/MD5.h" #include "llvm/Support/RandomNumberGenerator.h" #include "llvm/Support/SHA1.h" #include "llvm/Support/xxhash.h" #include <cstdlib> using namespace llvm; using namespace llvm::dwarf; using namespace llvm::ELF; using namespace llvm::object; using namespace llvm::support; using namespace llvm::support::endian; using namespace lld; using namespace lld::elf; uint64_t SyntheticSection::getVA() const { if (this->OutSec) return this->OutSec->Addr + this->OutSecOff; return 0; } template <class ELFT> static std::vector<DefinedCommon *> getCommonSymbols() { std::vector<DefinedCommon *> V; for (Symbol *S : Symtab<ELFT>::X->getSymbols()) if (auto *B = dyn_cast<DefinedCommon>(S->body())) V.push_back(B); return V; } // Find all common symbols and allocate space for them. template <class ELFT> InputSection *elf::createCommonSection() { if (!Config->DefineCommon) return nullptr; // Sort the common symbols by alignment as an heuristic to pack them better. std::vector<DefinedCommon *> Syms = getCommonSymbols<ELFT>(); if (Syms.empty()) return nullptr; std::stable_sort(Syms.begin(), Syms.end(), [](const DefinedCommon *A, const DefinedCommon *B) { return A->Alignment > B->Alignment; }); BssSection *Sec = make<BssSection>("COMMON"); for (DefinedCommon *Sym : Syms) Sym->Offset = Sec->reserveSpace(Sym->Size, Sym->Alignment); return Sec; } // Returns an LLD version string. static ArrayRef<uint8_t> getVersion() { // Check LLD_VERSION first for ease of testing. // You can get consitent output by using the environment variable. // This is only for testing. StringRef S = getenv("LLD_VERSION"); if (S.empty()) S = Saver.save(Twine("Linker: ") + getLLDVersion()); // +1 to include the terminating '\0'. return {(const uint8_t *)S.data(), S.size() + 1}; } // Creates a .comment section containing LLD version info. // With this feature, you can identify LLD-generated binaries easily -// by "objdump -s -j .comment <file>". +// by "readelf --string-dump .comment <file>". // The returned object is a mergeable string section. template <class ELFT> MergeInputSection *elf::createCommentSection() { typename ELFT::Shdr Hdr = {}; Hdr.sh_flags = SHF_MERGE | SHF_STRINGS; Hdr.sh_type = SHT_PROGBITS; Hdr.sh_entsize = 1; Hdr.sh_addralign = 1; auto *Ret = make<MergeInputSection>((ObjectFile<ELFT> *)nullptr, &Hdr, ".comment"); Ret->Data = getVersion(); Ret->splitIntoPieces(); return Ret; } // .MIPS.abiflags section. template <class ELFT> MipsAbiFlagsSection<ELFT>::MipsAbiFlagsSection(Elf_Mips_ABIFlags Flags) : SyntheticSection(SHF_ALLOC, SHT_MIPS_ABIFLAGS, 8, ".MIPS.abiflags"), Flags(Flags) { this->Entsize = sizeof(Elf_Mips_ABIFlags); } template <class ELFT> void MipsAbiFlagsSection<ELFT>::writeTo(uint8_t *Buf) { memcpy(Buf, &Flags, sizeof(Flags)); } template <class ELFT> MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() { Elf_Mips_ABIFlags Flags = {}; bool Create = false; for (InputSectionBase *Sec : InputSections) { if (Sec->Type != SHT_MIPS_ABIFLAGS) continue; Sec->Live = false; Create = true; std::string Filename = toString(Sec->getFile<ELFT>()); const size_t Size = Sec->Data.size(); // Older version of BFD (such as the default FreeBSD linker) concatenate // .MIPS.abiflags instead of merging. To allow for this case (or potential // zero padding) we ignore everything after the first Elf_Mips_ABIFlags if (Size < sizeof(Elf_Mips_ABIFlags)) { error(Filename + ": invalid size of .MIPS.abiflags section: got " + Twine(Size) + " instead of " + Twine(sizeof(Elf_Mips_ABIFlags))); return nullptr; } auto *S = reinterpret_cast<const Elf_Mips_ABIFlags *>(Sec->Data.data()); if (S->version != 0) { error(Filename + ": unexpected .MIPS.abiflags version " + Twine(S->version)); return nullptr; } // LLD checks ISA compatibility in getMipsEFlags(). Here we just // select the highest number of ISA/Rev/Ext. Flags.isa_level = std::max(Flags.isa_level, S->isa_level); Flags.isa_rev = std::max(Flags.isa_rev, S->isa_rev); Flags.isa_ext = std::max(Flags.isa_ext, S->isa_ext); Flags.gpr_size = std::max(Flags.gpr_size, S->gpr_size); Flags.cpr1_size = std::max(Flags.cpr1_size, S->cpr1_size); Flags.cpr2_size = std::max(Flags.cpr2_size, S->cpr2_size); Flags.ases |= S->ases; Flags.flags1 |= S->flags1; Flags.flags2 |= S->flags2; Flags.fp_abi = elf::getMipsFpAbiFlag(Flags.fp_abi, S->fp_abi, Filename); }; if (Create) return make<MipsAbiFlagsSection<ELFT>>(Flags); return nullptr; } // .MIPS.options section. template <class ELFT> MipsOptionsSection<ELFT>::MipsOptionsSection(Elf_Mips_RegInfo Reginfo) : SyntheticSection(SHF_ALLOC, SHT_MIPS_OPTIONS, 8, ".MIPS.options"), Reginfo(Reginfo) { this->Entsize = sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo); } template <class ELFT> void MipsOptionsSection<ELFT>::writeTo(uint8_t *Buf) { auto *Options = reinterpret_cast<Elf_Mips_Options *>(Buf); Options->kind = ODK_REGINFO; Options->size = getSize(); if (!Config->Relocatable) Reginfo.ri_gp_value = In<ELFT>::MipsGot->getGp(); memcpy(Buf + sizeof(Elf_Mips_Options), &Reginfo, sizeof(Reginfo)); } template <class ELFT> MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() { // N64 ABI only. if (!ELFT::Is64Bits) return nullptr; Elf_Mips_RegInfo Reginfo = {}; bool Create = false; for (InputSectionBase *Sec : InputSections) { if (Sec->Type != SHT_MIPS_OPTIONS) continue; Sec->Live = false; Create = true; std::string Filename = toString(Sec->getFile<ELFT>()); ArrayRef<uint8_t> D = Sec->Data; while (!D.empty()) { if (D.size() < sizeof(Elf_Mips_Options)) { error(Filename + ": invalid size of .MIPS.options section"); break; } auto *Opt = reinterpret_cast<const Elf_Mips_Options *>(D.data()); if (Opt->kind == ODK_REGINFO) { if (Config->Relocatable && Opt->getRegInfo().ri_gp_value) error(Filename + ": unsupported non-zero ri_gp_value"); Reginfo.ri_gprmask |= Opt->getRegInfo().ri_gprmask; Sec->getFile<ELFT>()->MipsGp0 = Opt->getRegInfo().ri_gp_value; break; } if (!Opt->size) fatal(Filename + ": zero option descriptor size"); D = D.slice(Opt->size); } }; if (Create) return make<MipsOptionsSection<ELFT>>(Reginfo); return nullptr; } // MIPS .reginfo section. template <class ELFT> MipsReginfoSection<ELFT>::MipsReginfoSection(Elf_Mips_RegInfo Reginfo) : SyntheticSection(SHF_ALLOC, SHT_MIPS_REGINFO, 4, ".reginfo"), Reginfo(Reginfo) { this->Entsize = sizeof(Elf_Mips_RegInfo); } template <class ELFT> void MipsReginfoSection<ELFT>::writeTo(uint8_t *Buf) { if (!Config->Relocatable) Reginfo.ri_gp_value = In<ELFT>::MipsGot->getGp(); memcpy(Buf, &Reginfo, sizeof(Reginfo)); } template <class ELFT> MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() { // Section should be alive for O32 and N32 ABIs only. if (ELFT::Is64Bits) return nullptr; Elf_Mips_RegInfo Reginfo = {}; bool Create = false; for (InputSectionBase *Sec : InputSections) { if (Sec->Type != SHT_MIPS_REGINFO) continue; Sec->Live = false; Create = true; if (Sec->Data.size() != sizeof(Elf_Mips_RegInfo)) { error(toString(Sec->getFile<ELFT>()) + ": invalid size of .reginfo section"); return nullptr; } auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(Sec->Data.data()); if (Config->Relocatable && R->ri_gp_value) error(toString(Sec->getFile<ELFT>()) + ": unsupported non-zero ri_gp_value"); Reginfo.ri_gprmask |= R->ri_gprmask; Sec->getFile<ELFT>()->MipsGp0 = R->ri_gp_value; }; if (Create) return make<MipsReginfoSection<ELFT>>(Reginfo); return nullptr; } InputSection *elf::createInterpSection() { // StringSaver guarantees that the returned string ends with '\0'. StringRef S = Saver.save(Config->DynamicLinker); ArrayRef<uint8_t> Contents = {(const uint8_t *)S.data(), S.size() + 1}; auto *Sec = make<InputSection>(SHF_ALLOC, SHT_PROGBITS, 1, Contents, ".interp"); Sec->Live = true; return Sec; } template <class ELFT> SymbolBody *elf::addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value, uint64_t Size, InputSectionBase *Section) { auto *S = make<DefinedRegular>(Name, /*IsLocal*/ true, STV_DEFAULT, Type, Value, Size, Section, nullptr); if (In<ELFT>::SymTab) In<ELFT>::SymTab->addSymbol(S); return S; } static size_t getHashSize() { switch (Config->BuildId) { case BuildIdKind::Fast: return 8; case BuildIdKind::Md5: case BuildIdKind::Uuid: return 16; case BuildIdKind::Sha1: return 20; case BuildIdKind::Hexstring: return Config->BuildIdVector.size(); default: llvm_unreachable("unknown BuildIdKind"); } } BuildIdSection::BuildIdSection() : SyntheticSection(SHF_ALLOC, SHT_NOTE, 1, ".note.gnu.build-id"), HashSize(getHashSize()) {} void BuildIdSection::writeTo(uint8_t *Buf) { endianness E = Config->Endianness; write32(Buf, 4, E); // Name size write32(Buf + 4, HashSize, E); // Content size write32(Buf + 8, NT_GNU_BUILD_ID, E); // Type memcpy(Buf + 12, "GNU", 4); // Name string HashBuf = Buf + 16; } // Split one uint8 array into small pieces of uint8 arrays. static std::vector<ArrayRef<uint8_t>> split(ArrayRef<uint8_t> Arr, size_t ChunkSize) { std::vector<ArrayRef<uint8_t>> Ret; while (Arr.size() > ChunkSize) { Ret.push_back(Arr.take_front(ChunkSize)); Arr = Arr.drop_front(ChunkSize); } if (!Arr.empty()) Ret.push_back(Arr); return Ret; } // Computes a hash value of Data using a given hash function. // In order to utilize multiple cores, we first split data into 1MB // chunks, compute a hash for each chunk, and then compute a hash value // of the hash values. void BuildIdSection::computeHash( llvm::ArrayRef<uint8_t> Data, std::function<void(uint8_t *Dest, ArrayRef<uint8_t> Arr)> HashFn) { std::vector<ArrayRef<uint8_t>> Chunks = split(Data, 1024 * 1024); std::vector<uint8_t> Hashes(Chunks.size() * HashSize); // Compute hash values. parallelFor(0, Chunks.size(), [&](size_t I) { HashFn(Hashes.data() + I * HashSize, Chunks[I]); }); // Write to the final output buffer. HashFn(HashBuf, Hashes); } BssSection::BssSection(StringRef Name) : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, 0, Name) {} size_t BssSection::reserveSpace(uint64_t Size, uint32_t Alignment) { if (OutSec) OutSec->updateAlignment(Alignment); this->Size = alignTo(this->Size, Alignment) + Size; this->Alignment = std::max(this->Alignment, Alignment); return this->Size - Size; } void BuildIdSection::writeBuildId(ArrayRef<uint8_t> Buf) { switch (Config->BuildId) { case BuildIdKind::Fast: computeHash(Buf, [](uint8_t *Dest, ArrayRef<uint8_t> Arr) { write64le(Dest, xxHash64(toStringRef(Arr))); }); break; case BuildIdKind::Md5: computeHash(Buf, [](uint8_t *Dest, ArrayRef<uint8_t> Arr) { memcpy(Dest, MD5::hash(Arr).data(), 16); }); break; case BuildIdKind::Sha1: computeHash(Buf, [](uint8_t *Dest, ArrayRef<uint8_t> Arr) { memcpy(Dest, SHA1::hash(Arr).data(), 20); }); break; case BuildIdKind::Uuid: if (getRandomBytes(HashBuf, HashSize)) error("entropy source failure"); break; case BuildIdKind::Hexstring: memcpy(HashBuf, Config->BuildIdVector.data(), Config->BuildIdVector.size()); break; default: llvm_unreachable("unknown BuildIdKind"); } } template <class ELFT> EhFrameSection<ELFT>::EhFrameSection() : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 1, ".eh_frame") {} // Search for an existing CIE record or create a new one. // CIE records from input object files are uniquified by their contents // and where their relocations point to. template <class ELFT> template <class RelTy> CieRecord *EhFrameSection<ELFT>::addCie(EhSectionPiece &Piece, ArrayRef<RelTy> Rels) { auto *Sec = cast<EhInputSection>(Piece.ID); const endianness E = ELFT::TargetEndianness; if (read32<E>(Piece.data().data() + 4) != 0) fatal(toString(Sec) + ": CIE expected at beginning of .eh_frame"); SymbolBody *Personality = nullptr; unsigned FirstRelI = Piece.FirstRelocation; if (FirstRelI != (unsigned)-1) Personality = &Sec->template getFile<ELFT>()->getRelocTargetSym(Rels[FirstRelI]); // Search for an existing CIE by CIE contents/relocation target pair. CieRecord *Cie = &CieMap[{Piece.data(), Personality}]; // If not found, create a new one. if (Cie->Piece == nullptr) { Cie->Piece = &Piece; Cies.push_back(Cie); } return Cie; } // There is one FDE per function. Returns true if a given FDE // points to a live function. template <class ELFT> template <class RelTy> bool EhFrameSection<ELFT>::isFdeLive(EhSectionPiece &Piece, ArrayRef<RelTy> Rels) { auto *Sec = cast<EhInputSection>(Piece.ID); unsigned FirstRelI = Piece.FirstRelocation; if (FirstRelI == (unsigned)-1) return false; const RelTy &Rel = Rels[FirstRelI]; SymbolBody &B = Sec->template getFile<ELFT>()->getRelocTargetSym(Rel); auto *D = dyn_cast<DefinedRegular>(&B); if (!D || !D->Section) return false; auto *Target = cast<InputSectionBase>(cast<InputSectionBase>(D->Section)->Repl); return Target && Target->Live; } // .eh_frame is a sequence of CIE or FDE records. In general, there // is one CIE record per input object file which is followed by // a list of FDEs. This function searches an existing CIE or create a new // one and associates FDEs to the CIE. template <class ELFT> template <class RelTy> void EhFrameSection<ELFT>::addSectionAux(EhInputSection *Sec, ArrayRef<RelTy> Rels) { const endianness E = ELFT::TargetEndianness; DenseMap<size_t, CieRecord *> OffsetToCie; for (EhSectionPiece &Piece : Sec->Pieces) { // The empty record is the end marker. if (Piece.size() == 4) return; size_t Offset = Piece.InputOff; uint32_t ID = read32<E>(Piece.data().data() + 4); if (ID == 0) { OffsetToCie[Offset] = addCie(Piece, Rels); continue; } uint32_t CieOffset = Offset + 4 - ID; CieRecord *Cie = OffsetToCie[CieOffset]; if (!Cie) fatal(toString(Sec) + ": invalid CIE reference"); if (!isFdeLive(Piece, Rels)) continue; Cie->FdePieces.push_back(&Piece); NumFdes++; } } template <class ELFT> void EhFrameSection<ELFT>::addSection(InputSectionBase *C) { auto *Sec = cast<EhInputSection>(C); Sec->EHSec = this; updateAlignment(Sec->Alignment); Sections.push_back(Sec); for (auto *DS : Sec->DependentSections) DependentSections.push_back(DS); // .eh_frame is a sequence of CIE or FDE records. This function // splits it into pieces so that we can call // SplitInputSection::getSectionPiece on the section. Sec->split<ELFT>(); if (Sec->Pieces.empty()) return; if (Sec->NumRelocations) { if (Sec->AreRelocsRela) addSectionAux(Sec, Sec->template relas<ELFT>()); else addSectionAux(Sec, Sec->template rels<ELFT>()); return; } addSectionAux(Sec, makeArrayRef<Elf_Rela>(nullptr, nullptr)); } template <class ELFT> static void writeCieFde(uint8_t *Buf, ArrayRef<uint8_t> D) { memcpy(Buf, D.data(), D.size()); // Fix the size field. -4 since size does not include the size field itself. const endianness E = ELFT::TargetEndianness; write32<E>(Buf, alignTo(D.size(), sizeof(typename ELFT::uint)) - 4); } template <class ELFT> void EhFrameSection<ELFT>::finalizeContents() { if (this->Size) return; // Already finalized. size_t Off = 0; for (CieRecord *Cie : Cies) { Cie->Piece->OutputOff = Off; Off += alignTo(Cie->Piece->size(), Config->Wordsize); for (EhSectionPiece *Fde : Cie->FdePieces) { Fde->OutputOff = Off; Off += alignTo(Fde->size(), Config->Wordsize); } } + + // The LSB standard does not allow a .eh_frame section with zero + // Call Frame Information records. Therefore add a CIE record length + // 0 as a terminator if this .eh_frame section is empty. + if (Off == 0) + Off = 4; + this->Size = Off; } template <class ELFT> static uint64_t readFdeAddr(uint8_t *Buf, int Size) { const endianness E = ELFT::TargetEndianness; switch (Size) { case DW_EH_PE_udata2: return read16<E>(Buf); case DW_EH_PE_udata4: return read32<E>(Buf); case DW_EH_PE_udata8: return read64<E>(Buf); case DW_EH_PE_absptr: if (ELFT::Is64Bits) return read64<E>(Buf); return read32<E>(Buf); } fatal("unknown FDE size encoding"); } // Returns the VA to which a given FDE (on a mmap'ed buffer) is applied to. // We need it to create .eh_frame_hdr section. template <class ELFT> uint64_t EhFrameSection<ELFT>::getFdePc(uint8_t *Buf, size_t FdeOff, uint8_t Enc) { // The starting address to which this FDE applies is // stored at FDE + 8 byte. size_t Off = FdeOff + 8; uint64_t Addr = readFdeAddr<ELFT>(Buf + Off, Enc & 0x7); if ((Enc & 0x70) == DW_EH_PE_absptr) return Addr; if ((Enc & 0x70) == DW_EH_PE_pcrel) return Addr + this->OutSec->Addr + Off; fatal("unknown FDE size relative encoding"); } template <class ELFT> void EhFrameSection<ELFT>::writeTo(uint8_t *Buf) { const endianness E = ELFT::TargetEndianness; for (CieRecord *Cie : Cies) { size_t CieOffset = Cie->Piece->OutputOff; writeCieFde<ELFT>(Buf + CieOffset, Cie->Piece->data()); for (EhSectionPiece *Fde : Cie->FdePieces) { size_t Off = Fde->OutputOff; writeCieFde<ELFT>(Buf + Off, Fde->data()); // FDE's second word should have the offset to an associated CIE. // Write it. write32<E>(Buf + Off + 4, Off + 4 - CieOffset); } } for (EhInputSection *S : Sections) S->template relocate<ELFT>(Buf, nullptr); // Construct .eh_frame_hdr. .eh_frame_hdr is a binary search table // to get a FDE from an address to which FDE is applied. So here // we obtain two addresses and pass them to EhFrameHdr object. if (In<ELFT>::EhFrameHdr) { for (CieRecord *Cie : Cies) { uint8_t Enc = getFdeEncoding<ELFT>(Cie->Piece); for (SectionPiece *Fde : Cie->FdePieces) { uint64_t Pc = getFdePc(Buf, Fde->OutputOff, Enc); uint64_t FdeVA = this->OutSec->Addr + Fde->OutputOff; In<ELFT>::EhFrameHdr->addFde(Pc, FdeVA); } } } } template <class ELFT> GotSection<ELFT>::GotSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Target->GotEntrySize, ".got") {} template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody &Sym) { Sym.GotIndex = NumEntries; ++NumEntries; } template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) { if (Sym.GlobalDynIndex != -1U) return false; Sym.GlobalDynIndex = NumEntries; // Global Dynamic TLS entries take two GOT slots. NumEntries += 2; return true; } // Reserves TLS entries for a TLS module ID and a TLS block offset. // In total it takes two GOT slots. template <class ELFT> bool GotSection<ELFT>::addTlsIndex() { if (TlsIndexOff != uint32_t(-1)) return false; TlsIndexOff = NumEntries * Config->Wordsize; NumEntries += 2; return true; } template <class ELFT> uint64_t GotSection<ELFT>::getGlobalDynAddr(const SymbolBody &B) const { return this->getVA() + B.GlobalDynIndex * Config->Wordsize; } template <class ELFT> uint64_t GotSection<ELFT>::getGlobalDynOffset(const SymbolBody &B) const { return B.GlobalDynIndex * Config->Wordsize; } template <class ELFT> void GotSection<ELFT>::finalizeContents() { Size = NumEntries * Config->Wordsize; } template <class ELFT> bool GotSection<ELFT>::empty() const { // If we have a relocation that is relative to GOT (such as GOTOFFREL), // we need to emit a GOT even if it's empty. return NumEntries == 0 && !HasGotOffRel; } template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) { this->template relocate<ELFT>(Buf, Buf + Size); } MipsGotSection::MipsGotSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, SHT_PROGBITS, 16, ".got") {} void MipsGotSection::addEntry(SymbolBody &Sym, int64_t Addend, RelExpr Expr) { // For "true" local symbols which can be referenced from the same module // only compiler creates two instructions for address loading: // // lw $8, 0($gp) # R_MIPS_GOT16 // addi $8, $8, 0 # R_MIPS_LO16 // // The first instruction loads high 16 bits of the symbol address while // the second adds an offset. That allows to reduce number of required // GOT entries because only one global offset table entry is necessary // for every 64 KBytes of local data. So for local symbols we need to // allocate number of GOT entries to hold all required "page" addresses. // // All global symbols (hidden and regular) considered by compiler uniformly. // It always generates a single `lw` instruction and R_MIPS_GOT16 relocation // to load address of the symbol. So for each such symbol we need to // allocate dedicated GOT entry to store its address. // // If a symbol is preemptible we need help of dynamic linker to get its // final address. The corresponding GOT entries are allocated in the // "global" part of GOT. Entries for non preemptible global symbol allocated // in the "local" part of GOT. // // See "Global Offset Table" in Chapter 5: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf if (Expr == R_MIPS_GOT_LOCAL_PAGE) { // At this point we do not know final symbol value so to reduce number // of allocated GOT entries do the following trick. Save all output // 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 *DefSym = cast<DefinedRegular>(&Sym); PageIndexMap.insert({DefSym->Section->getOutputSection(), 0}); return; } if (Sym.isTls()) { // GOT entries created for MIPS TLS relocations behave like // almost GOT entries from other ABIs. They go to the end // of the global offset table. Sym.GotIndex = TlsEntries.size(); TlsEntries.push_back(&Sym); return; } auto AddEntry = [&](SymbolBody &S, uint64_t A, GotEntries &Items) { if (S.isInGot() && !A) return; size_t NewIndex = Items.size(); if (!EntryIndexMap.insert({{&S, A}, NewIndex}).second) return; Items.emplace_back(&S, A); if (!A) S.GotIndex = NewIndex; }; if (Sym.isPreemptible()) { // Ignore addends for preemptible symbols. They got single GOT entry anyway. AddEntry(Sym, 0, GlobalEntries); Sym.IsInGlobalMipsGot = true; } else if (Expr == R_MIPS_GOT_OFF32) { AddEntry(Sym, Addend, LocalEntries32); Sym.Is32BitMipsGot = true; } else { // Hold local GOT entries accessed via a 16-bit index separately. // That allows to write them in the beginning of the GOT and keep // their indexes as less as possible to escape relocation's overflow. AddEntry(Sym, Addend, LocalEntries); } } bool MipsGotSection::addDynTlsEntry(SymbolBody &Sym) { if (Sym.GlobalDynIndex != -1U) return false; Sym.GlobalDynIndex = TlsEntries.size(); // Global Dynamic TLS entries take two GOT slots. TlsEntries.push_back(nullptr); TlsEntries.push_back(&Sym); return true; } // Reserves TLS entries for a TLS module ID and a TLS block offset. // In total it takes two GOT slots. bool MipsGotSection::addTlsIndex() { if (TlsIndexOff != uint32_t(-1)) return false; TlsIndexOff = TlsEntries.size() * Config->Wordsize; TlsEntries.push_back(nullptr); TlsEntries.push_back(nullptr); 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; } uint64_t MipsGotSection::getPageEntryOffset(const SymbolBody &B, int64_t Addend) const { const OutputSection *OutSec = cast<DefinedRegular>(&B)->Section->getOutputSection(); uint64_t SecAddr = getMipsPageAddr(OutSec->Addr); uint64_t SymAddr = getMipsPageAddr(B.getVA(Addend)); uint64_t Index = PageIndexMap.lookup(OutSec) + (SymAddr - SecAddr) / 0xffff; assert(Index < PageEntriesNum); return (HeaderEntriesNum + Index) * Config->Wordsize; } uint64_t MipsGotSection::getBodyEntryOffset(const SymbolBody &B, int64_t Addend) const { // Calculate offset of the GOT entries block: TLS, global, local. uint64_t Index = HeaderEntriesNum + PageEntriesNum; if (B.isTls()) Index += LocalEntries.size() + LocalEntries32.size() + GlobalEntries.size(); else if (B.IsInGlobalMipsGot) Index += LocalEntries.size() + LocalEntries32.size(); else if (B.Is32BitMipsGot) Index += LocalEntries.size(); // Calculate offset of the GOT entry in the block. if (B.isInGot()) Index += B.GotIndex; else { auto It = EntryIndexMap.find({&B, Addend}); assert(It != EntryIndexMap.end()); Index += It->second; } return Index * Config->Wordsize; } uint64_t MipsGotSection::getTlsOffset() const { return (getLocalEntriesNum() + GlobalEntries.size()) * Config->Wordsize; } uint64_t MipsGotSection::getGlobalDynOffset(const SymbolBody &B) const { return B.GlobalDynIndex * Config->Wordsize; } const SymbolBody *MipsGotSection::getFirstGlobalEntry() const { return GlobalEntries.empty() ? nullptr : GlobalEntries.front().first; } unsigned MipsGotSection::getLocalEntriesNum() const { return HeaderEntriesNum + PageEntriesNum + LocalEntries.size() + LocalEntries32.size(); } void MipsGotSection::finalizeContents() { updateAllocSize(); } void MipsGotSection::updateAllocSize() { PageEntriesNum = 0; for (std::pair<const OutputSection *, size_t> &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); } Size = (getLocalEntriesNum() + GlobalEntries.size() + TlsEntries.size()) * Config->Wordsize; } bool MipsGotSection::empty() const { // We add the .got section to the result for dynamic MIPS target because // its address and properties are mentioned in the .dynamic section. return Config->Relocatable; } uint64_t MipsGotSection::getGp() const { return ElfSym::MipsGp->getVA(0); } static uint64_t readUint(uint8_t *Buf) { if (Config->Is64) return read64(Buf, Config->Endianness); return read32(Buf, Config->Endianness); } static void writeUint(uint8_t *Buf, uint64_t Val) { if (Config->Is64) write64(Buf, Val, Config->Endianness); else write32(Buf, Val, Config->Endianness); } void MipsGotSection::writeTo(uint8_t *Buf) { // Set the MSB of the second GOT slot. This is not required by any // MIPS ABI documentation, though. // // There is a comment in glibc saying that "The MSB of got[1] of a // gnu object is set to identify gnu objects," and in GNU gold it // says "the second entry will be used by some runtime loaders". // But how this field is being used is unclear. // // We are not really willing to mimic other linkers behaviors // without understanding why they do that, but because all files // generated by GNU tools have this special GOT value, and because // we've been doing this for years, it is probably a safe bet to // keep doing this for now. We really need to revisit this to see // if we had to do this. writeUint(Buf + Config->Wordsize, (uint64_t)1 << (Config->Wordsize * 8 - 1)); Buf += HeaderEntriesNum * Config->Wordsize; // Write 'page address' entries to the local part of the GOT. for (std::pair<const OutputSection *, size_t> &L : PageIndexMap) { size_t PageCount = getMipsPageCount(L.first->Size); uint64_t FirstPageAddr = getMipsPageAddr(L.first->Addr); for (size_t PI = 0; PI < PageCount; ++PI) { uint8_t *Entry = Buf + (L.second + PI) * Config->Wordsize; writeUint(Entry, FirstPageAddr + PI * 0x10000); } } Buf += PageEntriesNum * Config->Wordsize; auto AddEntry = [&](const GotEntry &SA) { uint8_t *Entry = Buf; Buf += Config->Wordsize; const SymbolBody *Body = SA.first; uint64_t VA = Body->getVA(SA.second); writeUint(Entry, VA); }; std::for_each(std::begin(LocalEntries), std::end(LocalEntries), AddEntry); std::for_each(std::begin(LocalEntries32), std::end(LocalEntries32), AddEntry); std::for_each(std::begin(GlobalEntries), std::end(GlobalEntries), AddEntry); // Initialize TLS-related GOT entries. If the entry has a corresponding // dynamic relocations, leave it initialized by zero. Write down adjusted // TLS symbol's values otherwise. To calculate the adjustments use offsets // for thread-local storage. // https://www.linux-mips.org/wiki/NPTL if (TlsIndexOff != -1U && !Config->Pic) writeUint(Buf + TlsIndexOff, 1); for (const SymbolBody *B : TlsEntries) { if (!B || B->isPreemptible()) continue; uint64_t VA = B->getVA(); if (B->GotIndex != -1U) { uint8_t *Entry = Buf + B->GotIndex * Config->Wordsize; writeUint(Entry, VA - 0x7000); } if (B->GlobalDynIndex != -1U) { uint8_t *Entry = Buf + B->GlobalDynIndex * Config->Wordsize; writeUint(Entry, 1); Entry += Config->Wordsize; writeUint(Entry, VA - 0x8000); } } } GotPltSection::GotPltSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Target->GotPltEntrySize, ".got.plt") {} void GotPltSection::addEntry(SymbolBody &Sym) { Sym.GotPltIndex = Target->GotPltHeaderEntriesNum + Entries.size(); Entries.push_back(&Sym); } size_t GotPltSection::getSize() const { return (Target->GotPltHeaderEntriesNum + Entries.size()) * Target->GotPltEntrySize; } void GotPltSection::writeTo(uint8_t *Buf) { Target->writeGotPltHeader(Buf); Buf += Target->GotPltHeaderEntriesNum * Target->GotPltEntrySize; for (const SymbolBody *B : Entries) { Target->writeGotPlt(Buf, *B); Buf += Config->Wordsize; } } // On ARM the IgotPltSection is part of the GotSection, on other Targets it is // part of the .got.plt IgotPltSection::IgotPltSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Target->GotPltEntrySize, Config->EMachine == EM_ARM ? ".got" : ".got.plt") {} void IgotPltSection::addEntry(SymbolBody &Sym) { Sym.IsInIgot = true; Sym.GotPltIndex = Entries.size(); Entries.push_back(&Sym); } size_t IgotPltSection::getSize() const { return Entries.size() * Target->GotPltEntrySize; } void IgotPltSection::writeTo(uint8_t *Buf) { for (const SymbolBody *B : Entries) { Target->writeIgotPlt(Buf, *B); Buf += Config->Wordsize; } } StringTableSection::StringTableSection(StringRef Name, bool Dynamic) : SyntheticSection(Dynamic ? (uint64_t)SHF_ALLOC : 0, SHT_STRTAB, 1, Name), Dynamic(Dynamic) { // ELF string tables start with a NUL byte. addString(""); } // Adds a string to the string table. If HashIt is true we hash and check for // duplicates. It is optional because the name of global symbols are already // uniqued and hashing them again has a big cost for a small value: uniquing // them with some other string that happens to be the same. unsigned StringTableSection::addString(StringRef S, bool HashIt) { if (HashIt) { auto R = StringMap.insert(std::make_pair(S, this->Size)); if (!R.second) return R.first->second; } unsigned Ret = this->Size; this->Size = this->Size + S.size() + 1; Strings.push_back(S); return Ret; } void StringTableSection::writeTo(uint8_t *Buf) { for (StringRef S : Strings) { memcpy(Buf, S.data(), S.size()); Buf += S.size() + 1; } } // Returns the number of version definition entries. Because the first entry // is for the version definition itself, it is the number of versioned symbols // plus one. Note that we don't support multiple versions yet. static unsigned getVerDefNum() { return Config->VersionDefinitions.size() + 1; } template <class ELFT> DynamicSection<ELFT>::DynamicSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_DYNAMIC, Config->Wordsize, ".dynamic") { this->Entsize = ELFT::Is64Bits ? 16 : 8; // .dynamic section is not writable on MIPS. // See "Special Section" in Chapter 4 in the following document: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf if (Config->EMachine == EM_MIPS) this->Flags = SHF_ALLOC; addEntries(); } // There are some dynamic entries that don't depend on other sections. // Such entries can be set early. template <class ELFT> void DynamicSection<ELFT>::addEntries() { // Add strings to .dynstr early so that .dynstr's size will be // fixed early. for (StringRef S : Config->AuxiliaryList) add({DT_AUXILIARY, In<ELFT>::DynStrTab->addString(S)}); - if (!Config->RPath.empty()) + if (!Config->Rpath.empty()) add({Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, - In<ELFT>::DynStrTab->addString(Config->RPath)}); + In<ELFT>::DynStrTab->addString(Config->Rpath)}); for (SharedFile<ELFT> *F : Symtab<ELFT>::X->getSharedFiles()) if (F->isNeeded()) add({DT_NEEDED, In<ELFT>::DynStrTab->addString(F->SoName)}); if (!Config->SoName.empty()) add({DT_SONAME, In<ELFT>::DynStrTab->addString(Config->SoName)}); // Set DT_FLAGS and DT_FLAGS_1. uint32_t DtFlags = 0; uint32_t DtFlags1 = 0; if (Config->Bsymbolic) DtFlags |= DF_SYMBOLIC; if (Config->ZNodelete) DtFlags1 |= DF_1_NODELETE; if (Config->ZNodlopen) DtFlags1 |= DF_1_NOOPEN; if (Config->ZNow) { DtFlags |= DF_BIND_NOW; DtFlags1 |= DF_1_NOW; } if (Config->ZOrigin) { DtFlags |= DF_ORIGIN; DtFlags1 |= DF_1_ORIGIN; } if (DtFlags) add({DT_FLAGS, DtFlags}); if (DtFlags1) add({DT_FLAGS_1, DtFlags1}); if (!Config->Shared && !Config->Relocatable) add({DT_DEBUG, (uint64_t)0}); } // Add remaining entries to complete .dynamic contents. template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { if (this->Size) return; // Already finalized. this->Link = In<ELFT>::DynStrTab->OutSec->SectionIndex; if (In<ELFT>::RelaDyn->OutSec->Size > 0) { bool IsRela = Config->IsRela; add({IsRela ? DT_RELA : DT_REL, In<ELFT>::RelaDyn}); add({IsRela ? DT_RELASZ : DT_RELSZ, In<ELFT>::RelaDyn->OutSec->Size}); add({IsRela ? DT_RELAENT : DT_RELENT, uint64_t(IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel))}); // MIPS dynamic loader does not support RELCOUNT tag. // The problem is in the tight relation between dynamic // relocations and GOT. So do not emit this tag on MIPS. if (Config->EMachine != EM_MIPS) { size_t NumRelativeRels = In<ELFT>::RelaDyn->getRelativeRelocCount(); if (Config->ZCombreloc && NumRelativeRels) add({IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels}); } } if (In<ELFT>::RelaPlt->OutSec->Size > 0) { add({DT_JMPREL, In<ELFT>::RelaPlt}); add({DT_PLTRELSZ, In<ELFT>::RelaPlt->OutSec->Size}); add({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT, In<ELFT>::GotPlt}); add({DT_PLTREL, uint64_t(Config->IsRela ? DT_RELA : DT_REL)}); } add({DT_SYMTAB, In<ELFT>::DynSymTab}); add({DT_SYMENT, sizeof(Elf_Sym)}); add({DT_STRTAB, In<ELFT>::DynStrTab}); add({DT_STRSZ, In<ELFT>::DynStrTab->getSize()}); if (!Config->ZText) add({DT_TEXTREL, (uint64_t)0}); if (In<ELFT>::GnuHashTab) add({DT_GNU_HASH, In<ELFT>::GnuHashTab}); if (In<ELFT>::HashTab) add({DT_HASH, In<ELFT>::HashTab}); if (Out::PreinitArray) { add({DT_PREINIT_ARRAY, Out::PreinitArray}); add({DT_PREINIT_ARRAYSZ, Out::PreinitArray, Entry::SecSize}); } if (Out::InitArray) { add({DT_INIT_ARRAY, Out::InitArray}); add({DT_INIT_ARRAYSZ, Out::InitArray, Entry::SecSize}); } if (Out::FiniArray) { add({DT_FINI_ARRAY, Out::FiniArray}); add({DT_FINI_ARRAYSZ, Out::FiniArray, Entry::SecSize}); } if (SymbolBody *B = Symtab<ELFT>::X->findInCurrentDSO(Config->Init)) add({DT_INIT, B}); if (SymbolBody *B = Symtab<ELFT>::X->findInCurrentDSO(Config->Fini)) add({DT_FINI, B}); bool HasVerNeed = In<ELFT>::VerNeed->getNeedNum() != 0; if (HasVerNeed || In<ELFT>::VerDef) add({DT_VERSYM, In<ELFT>::VerSym}); if (In<ELFT>::VerDef) { add({DT_VERDEF, In<ELFT>::VerDef}); add({DT_VERDEFNUM, getVerDefNum()}); } if (HasVerNeed) { add({DT_VERNEED, In<ELFT>::VerNeed}); add({DT_VERNEEDNUM, In<ELFT>::VerNeed->getNeedNum()}); } if (Config->EMachine == EM_MIPS) { add({DT_MIPS_RLD_VERSION, 1}); add({DT_MIPS_FLAGS, RHF_NOTPOT}); add({DT_MIPS_BASE_ADDRESS, Config->ImageBase}); add({DT_MIPS_SYMTABNO, In<ELFT>::DynSymTab->getNumSymbols()}); add({DT_MIPS_LOCAL_GOTNO, In<ELFT>::MipsGot->getLocalEntriesNum()}); if (const SymbolBody *B = In<ELFT>::MipsGot->getFirstGlobalEntry()) add({DT_MIPS_GOTSYM, B->DynsymIndex}); else add({DT_MIPS_GOTSYM, In<ELFT>::DynSymTab->getNumSymbols()}); add({DT_PLTGOT, In<ELFT>::MipsGot}); if (In<ELFT>::MipsRldMap) add({DT_MIPS_RLD_MAP, In<ELFT>::MipsRldMap}); } this->OutSec->Link = this->Link; // +1 for DT_NULL this->Size = (Entries.size() + 1) * this->Entsize; } template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) { auto *P = reinterpret_cast<Elf_Dyn *>(Buf); for (const Entry &E : Entries) { P->d_tag = E.Tag; switch (E.Kind) { case Entry::SecAddr: P->d_un.d_ptr = E.OutSec->Addr; break; case Entry::InSecAddr: P->d_un.d_ptr = E.InSec->OutSec->Addr + E.InSec->OutSecOff; break; case Entry::SecSize: P->d_un.d_val = E.OutSec->Size; break; case Entry::SymAddr: P->d_un.d_ptr = E.Sym->getVA(); break; case Entry::PlainInt: P->d_un.d_val = E.Val; break; } ++P; } } uint64_t DynamicReloc::getOffset() const { return InputSec->OutSec->Addr + InputSec->getOffset(OffsetInSec); } int64_t DynamicReloc::getAddend() const { if (UseSymVA) return Sym->getVA(Addend); return Addend; } uint32_t DynamicReloc::getSymIndex() const { if (Sym && !UseSymVA) return Sym->DynsymIndex; return 0; } template <class ELFT> RelocationSection<ELFT>::RelocationSection(StringRef Name, bool Sort) : SyntheticSection(SHF_ALLOC, Config->IsRela ? SHT_RELA : SHT_REL, Config->Wordsize, Name), Sort(Sort) { this->Entsize = Config->IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); } template <class ELFT> void RelocationSection<ELFT>::addReloc(const DynamicReloc &Reloc) { if (Reloc.Type == Target->RelativeRel) ++NumRelativeRelocs; Relocs.push_back(Reloc); } template <class ELFT, class RelTy> static bool compRelocations(const RelTy &A, const RelTy &B) { bool AIsRel = A.getType(Config->IsMips64EL) == Target->RelativeRel; bool BIsRel = B.getType(Config->IsMips64EL) == Target->RelativeRel; if (AIsRel != BIsRel) return AIsRel; return A.getSymbol(Config->IsMips64EL) < B.getSymbol(Config->IsMips64EL); } template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { uint8_t *BufBegin = Buf; for (const DynamicReloc &Rel : Relocs) { auto *P = reinterpret_cast<Elf_Rela *>(Buf); Buf += Config->IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); if (Config->IsRela) P->r_addend = Rel.getAddend(); P->r_offset = Rel.getOffset(); if (Config->EMachine == EM_MIPS && Rel.getInputSec() == In<ELFT>::MipsGot) // Dynamic relocation against MIPS GOT section make deal TLS entries // allocated in the end of the GOT. We need to adjust the offset to take // in account 'local' and 'global' GOT entries. P->r_offset += In<ELFT>::MipsGot->getTlsOffset(); P->setSymbolAndType(Rel.getSymIndex(), Rel.Type, Config->IsMips64EL); } if (Sort) { if (Config->IsRela) std::stable_sort((Elf_Rela *)BufBegin, (Elf_Rela *)BufBegin + Relocs.size(), compRelocations<ELFT, Elf_Rela>); else std::stable_sort((Elf_Rel *)BufBegin, (Elf_Rel *)BufBegin + Relocs.size(), compRelocations<ELFT, Elf_Rel>); } } template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() { return this->Entsize * Relocs.size(); } template <class ELFT> void RelocationSection<ELFT>::finalizeContents() { this->Link = In<ELFT>::DynSymTab ? In<ELFT>::DynSymTab->OutSec->SectionIndex : In<ELFT>::SymTab->OutSec->SectionIndex; // Set required output section properties. this->OutSec->Link = this->Link; } template <class ELFT> SymbolTableSection<ELFT>::SymbolTableSection(StringTableSection &StrTabSec) : SyntheticSection(StrTabSec.isDynamic() ? (uint64_t)SHF_ALLOC : 0, StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB, Config->Wordsize, StrTabSec.isDynamic() ? ".dynsym" : ".symtab"), StrTabSec(StrTabSec) { this->Entsize = sizeof(Elf_Sym); } // Orders symbols according to their positions in the GOT, // in compliance with MIPS ABI rules. // See "Global Offset Table" in Chapter 5 in the following document // for detailed description: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf static bool sortMipsSymbols(const SymbolTableEntry &L, const SymbolTableEntry &R) { // Sort entries related to non-local preemptible symbols by GOT indexes. // All other entries go to the first part of GOT in arbitrary order. bool LIsInLocalGot = !L.Symbol->IsInGlobalMipsGot; bool RIsInLocalGot = !R.Symbol->IsInGlobalMipsGot; if (LIsInLocalGot || RIsInLocalGot) return !RIsInLocalGot; return L.Symbol->GotIndex < R.Symbol->GotIndex; } // Finalize a symbol table. The ELF spec requires that all local // symbols precede global symbols, so we sort symbol entries in this // function. (For .dynsym, we don't do that because symbols for // dynamic linking are inherently all globals.) template <class ELFT> void SymbolTableSection<ELFT>::finalizeContents() { this->OutSec->Link = StrTabSec.OutSec->SectionIndex; // If it is a .dynsym, there should be no local symbols, but we need // to do a few things for the dynamic linker. if (this->Type == SHT_DYNSYM) { // Section's Info field has the index of the first non-local symbol. // Because the first symbol entry is a null entry, 1 is the first. this->OutSec->Info = 1; if (In<ELFT>::GnuHashTab) { // NB: It also sorts Symbols to meet the GNU hash table requirements. In<ELFT>::GnuHashTab->addSymbols(Symbols); } else if (Config->EMachine == EM_MIPS) { std::stable_sort(Symbols.begin(), Symbols.end(), sortMipsSymbols); } size_t I = 0; for (const SymbolTableEntry &S : Symbols) S.Symbol->DynsymIndex = ++I; return; } } template <class ELFT> void SymbolTableSection<ELFT>::postThunkContents() { if (this->Type == SHT_DYNSYM) return; // move all local symbols before global symbols. auto It = std::stable_partition( Symbols.begin(), Symbols.end(), [](const SymbolTableEntry &S) { return S.Symbol->isLocal() || S.Symbol->symbol()->computeBinding() == STB_LOCAL; }); size_t NumLocals = It - Symbols.begin(); this->OutSec->Info = NumLocals + 1; } template <class ELFT> void SymbolTableSection<ELFT>::addSymbol(SymbolBody *B) { // Adding a local symbol to a .dynsym is a bug. assert(this->Type != SHT_DYNSYM || !B->isLocal()); bool HashIt = B->isLocal(); Symbols.push_back({B, StrTabSec.addString(B->getName(), HashIt)}); } template <class ELFT> size_t SymbolTableSection<ELFT>::getSymbolIndex(SymbolBody *Body) { auto I = llvm::find_if(Symbols, [&](const SymbolTableEntry &E) { if (E.Symbol == Body) return true; // This is used for -r, so we have to handle multiple section // symbols being combined. if (Body->Type == STT_SECTION && E.Symbol->Type == STT_SECTION) return cast<DefinedRegular>(Body)->Section->getOutputSection() == cast<DefinedRegular>(E.Symbol)->Section->getOutputSection(); return false; }); if (I == Symbols.end()) return 0; return I - Symbols.begin() + 1; } // Write the internal symbol table contents to the output symbol table. template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) { // The first entry is a null entry as per the ELF spec. Buf += sizeof(Elf_Sym); auto *ESym = reinterpret_cast<Elf_Sym *>(Buf); for (SymbolTableEntry &Ent : Symbols) { SymbolBody *Body = Ent.Symbol; // Set st_info and st_other. if (Body->isLocal()) { ESym->setBindingAndType(STB_LOCAL, Body->Type); } else { ESym->setBindingAndType(Body->symbol()->computeBinding(), Body->Type); ESym->setVisibility(Body->symbol()->Visibility); } ESym->st_name = Ent.StrTabOffset; ESym->st_size = Body->getSize<ELFT>(); // Set a section index. if (const OutputSection *OutSec = Body->getOutputSection()) ESym->st_shndx = OutSec->SectionIndex; else if (isa<DefinedRegular>(Body)) ESym->st_shndx = SHN_ABS; else if (isa<DefinedCommon>(Body)) ESym->st_shndx = SHN_COMMON; // st_value is usually an address of a symbol, but that has a // special meaining for uninstantiated common symbols (this can // occur if -r is given). if (!Config->DefineCommon && isa<DefinedCommon>(Body)) ESym->st_value = cast<DefinedCommon>(Body)->Alignment; else ESym->st_value = Body->getVA(); ++ESym; } // On MIPS we need to mark symbol which has a PLT entry and requires // pointer equality by STO_MIPS_PLT flag. That is necessary to help // dynamic linker distinguish such symbols and MIPS lazy-binding stubs. // https://sourceware.org/ml/binutils/2008-07/txt00000.txt if (Config->EMachine == EM_MIPS) { auto *ESym = reinterpret_cast<Elf_Sym *>(Buf); for (SymbolTableEntry &Ent : Symbols) { SymbolBody *Body = Ent.Symbol; if (Body->isInPlt() && Body->NeedsPltAddr) ESym->st_other |= STO_MIPS_PLT; if (Config->Relocatable) if (auto *D = dyn_cast<DefinedRegular>(Body)) if (D->isMipsPIC<ELFT>()) ESym->st_other |= STO_MIPS_PIC; ++ESym; } } } // .hash and .gnu.hash sections contain on-disk hash tables that map // symbol names to their dynamic symbol table indices. Their purpose // is to help the dynamic linker resolve symbols quickly. If ELF files // don't have them, the dynamic linker has to do linear search on all // dynamic symbols, which makes programs slower. Therefore, a .hash // section is added to a DSO by default. A .gnu.hash is added if you // give the -hash-style=gnu or -hash-style=both option. // // The Unix semantics of resolving dynamic symbols is somewhat expensive. // Each ELF file has a list of DSOs that the ELF file depends on and a // list of dynamic symbols that need to be resolved from any of the // DSOs. That means resolving all dynamic symbols takes O(m)*O(n) // where m is the number of DSOs and n is the number of dynamic // symbols. For modern large programs, both m and n are large. So // making each step faster by using hash tables substiantially // improves time to load programs. // // (Note that this is not the only way to design the shared library. // For instance, the Windows DLL takes a different approach. On // Windows, each dynamic symbol has a name of DLL from which the symbol // has to be resolved. That makes the cost of symbol resolution O(n). // This disables some hacky techniques you can use on Unix such as // LD_PRELOAD, but this is arguably better semantics than the Unix ones.) // // Due to historical reasons, we have two different hash tables, .hash // and .gnu.hash. They are for the same purpose, and .gnu.hash is a new // and better version of .hash. .hash is just an on-disk hash table, but // .gnu.hash has a bloom filter in addition to a hash table to skip // DSOs very quickly. If you are sure that your dynamic linker knows // about .gnu.hash, you want to specify -hash-style=gnu. Otherwise, a // safe bet is to specify -hash-style=both for backward compatibilty. template <class ELFT> GnuHashTableSection<ELFT>::GnuHashTableSection() : SyntheticSection(SHF_ALLOC, SHT_GNU_HASH, Config->Wordsize, ".gnu.hash") { } template <class ELFT> void GnuHashTableSection<ELFT>::finalizeContents() { this->OutSec->Link = In<ELFT>::DynSymTab->OutSec->SectionIndex; // Computes bloom filter size in word size. We want to allocate 8 // bits for each symbol. It must be a power of two. if (Symbols.empty()) MaskWords = 1; else MaskWords = NextPowerOf2((Symbols.size() - 1) / Config->Wordsize); Size = 16; // Header Size += Config->Wordsize * MaskWords; // Bloom filter Size += NBuckets * 4; // Hash buckets Size += Symbols.size() * 4; // Hash values } template <class ELFT> void GnuHashTableSection<ELFT>::writeTo(uint8_t *Buf) { // Write a header. write32(Buf, NBuckets, Config->Endianness); write32(Buf + 4, In<ELFT>::DynSymTab->getNumSymbols() - Symbols.size(), Config->Endianness); write32(Buf + 8, MaskWords, Config->Endianness); write32(Buf + 12, getShift2(), Config->Endianness); Buf += 16; // Write a bloom filter and a hash table. writeBloomFilter(Buf); Buf += Config->Wordsize * MaskWords; writeHashTable(Buf); } // This function writes a 2-bit bloom filter. This bloom filter alone // usually filters out 80% or more of all symbol lookups [1]. // The dynamic linker uses the hash table only when a symbol is not // filtered out by a bloom filter. // // [1] Ulrich Drepper (2011), "How To Write Shared Libraries" (Ver. 4.1.2), // p.9, https://www.akkadia.org/drepper/dsohowto.pdf template <class ELFT> void GnuHashTableSection<ELFT>::writeBloomFilter(uint8_t *Buf) { const unsigned C = Config->Wordsize * 8; for (const Entry &Sym : Symbols) { size_t I = (Sym.Hash / C) & (MaskWords - 1); uint64_t Val = readUint(Buf + I * Config->Wordsize); Val |= uint64_t(1) << (Sym.Hash % C); Val |= uint64_t(1) << ((Sym.Hash >> getShift2()) % C); writeUint(Buf + I * Config->Wordsize, Val); } } template <class ELFT> void GnuHashTableSection<ELFT>::writeHashTable(uint8_t *Buf) { // Group symbols by hash value. std::vector<std::vector<Entry>> Syms(NBuckets); for (const Entry &Ent : Symbols) Syms[Ent.Hash % NBuckets].push_back(Ent); // Write hash buckets. Hash buckets contain indices in the following // hash value table. uint32_t *Buckets = reinterpret_cast<uint32_t *>(Buf); for (size_t I = 0; I < NBuckets; ++I) if (!Syms[I].empty()) write32(Buckets + I, Syms[I][0].Body->DynsymIndex, Config->Endianness); // Write a hash value table. It represents a sequence of chains that // share the same hash modulo value. The last element of each chain // is terminated by LSB 1. uint32_t *Values = Buckets + NBuckets; size_t I = 0; for (std::vector<Entry> &Vec : Syms) { if (Vec.empty()) continue; for (const Entry &Ent : makeArrayRef(Vec).drop_back()) write32(Values + I++, Ent.Hash & ~1, Config->Endianness); write32(Values + I++, Vec.back().Hash | 1, Config->Endianness); } } static uint32_t hashGnu(StringRef Name) { uint32_t H = 5381; for (uint8_t C : Name) H = (H << 5) + H + C; return H; } // Returns a number of hash buckets to accomodate given number of elements. // We want to choose a moderate number that is not too small (which // causes too many hash collisions) and not too large (which wastes // disk space.) // // We return a prime number because it (is believed to) achieve good // hash distribution. static size_t getBucketSize(size_t NumSymbols) { // List of largest prime numbers that are not greater than 2^n + 1. for (size_t N : {131071, 65521, 32749, 16381, 8191, 4093, 2039, 1021, 509, 251, 127, 61, 31, 13, 7, 3, 1}) if (N <= NumSymbols) return N; return 0; } // Add symbols to this symbol hash table. Note that this function // destructively sort a given vector -- which is needed because // GNU-style hash table places some sorting requirements. template <class ELFT> void GnuHashTableSection<ELFT>::addSymbols(std::vector<SymbolTableEntry> &V) { // We cannot use 'auto' for Mid because GCC 6.1 cannot deduce // its type correctly. std::vector<SymbolTableEntry>::iterator Mid = std::stable_partition(V.begin(), V.end(), [](const SymbolTableEntry &S) { return S.Symbol->isUndefined(); }); if (Mid == V.end()) return; for (SymbolTableEntry &Ent : llvm::make_range(Mid, V.end())) { SymbolBody *B = Ent.Symbol; Symbols.push_back({B, Ent.StrTabOffset, hashGnu(B->getName())}); } NBuckets = getBucketSize(Symbols.size()); std::stable_sort(Symbols.begin(), Symbols.end(), [&](const Entry &L, const Entry &R) { return L.Hash % NBuckets < R.Hash % NBuckets; }); V.erase(Mid, V.end()); for (const Entry &Ent : Symbols) V.push_back({Ent.Body, Ent.StrTabOffset}); } template <class ELFT> HashTableSection<ELFT>::HashTableSection() : SyntheticSection(SHF_ALLOC, SHT_HASH, 4, ".hash") { this->Entsize = 4; } template <class ELFT> void HashTableSection<ELFT>::finalizeContents() { this->OutSec->Link = In<ELFT>::DynSymTab->OutSec->SectionIndex; unsigned NumEntries = 2; // nbucket and nchain. NumEntries += In<ELFT>::DynSymTab->getNumSymbols(); // The chain entries. // Create as many buckets as there are symbols. // FIXME: This is simplistic. We can try to optimize it, but implementing // support for SHT_GNU_HASH is probably even more profitable. NumEntries += In<ELFT>::DynSymTab->getNumSymbols(); this->Size = NumEntries * 4; } template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) { // A 32-bit integer type in the target endianness. typedef typename ELFT::Word Elf_Word; unsigned NumSymbols = In<ELFT>::DynSymTab->getNumSymbols(); auto *P = reinterpret_cast<Elf_Word *>(Buf); *P++ = NumSymbols; // nbucket *P++ = NumSymbols; // nchain Elf_Word *Buckets = P; Elf_Word *Chains = P + NumSymbols; for (const SymbolTableEntry &S : In<ELFT>::DynSymTab->getSymbols()) { SymbolBody *Body = S.Symbol; StringRef Name = Body->getName(); unsigned I = Body->DynsymIndex; uint32_t Hash = hashSysV(Name) % NumSymbols; Chains[I] = Buckets[Hash]; Buckets[Hash] = I; } } PltSection::PltSection(size_t S) : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, ".plt"), HeaderSize(S) {} void PltSection::writeTo(uint8_t *Buf) { // At beginning of PLT but not the IPLT, we have code to call the dynamic // linker to resolve dynsyms at runtime. Write such code. if (HeaderSize != 0) Target->writePltHeader(Buf); size_t Off = HeaderSize; // The IPlt is immediately after the Plt, account for this in RelOff unsigned PltOff = getPltRelocOff(); for (auto &I : Entries) { const SymbolBody *B = I.first; unsigned RelOff = I.second + PltOff; uint64_t Got = B->getGotPltVA(); uint64_t Plt = this->getVA() + Off; Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff); Off += Target->PltEntrySize; } } template <class ELFT> void PltSection::addEntry(SymbolBody &Sym) { Sym.PltIndex = Entries.size(); RelocationSection<ELFT> *PltRelocSection = In<ELFT>::RelaPlt; if (HeaderSize == 0) { PltRelocSection = In<ELFT>::RelaIplt; Sym.IsInIplt = true; } unsigned RelOff = PltRelocSection->getRelocOffset(); Entries.push_back(std::make_pair(&Sym, RelOff)); } size_t PltSection::getSize() const { return HeaderSize + Entries.size() * Target->PltEntrySize; } // Some architectures such as additional symbols in the PLT section. For // example ARM uses mapping symbols to aid disassembly void PltSection::addSymbols() { // The PLT may have symbols defined for the Header, the IPLT has no header if (HeaderSize != 0) Target->addPltHeaderSymbols(this); size_t Off = HeaderSize; for (size_t I = 0; I < Entries.size(); ++I) { Target->addPltSymbols(this, Off); Off += Target->PltEntrySize; } } unsigned PltSection::getPltRelocOff() const { return (HeaderSize == 0) ? InX::Plt->getSize() : 0; } GdbIndexSection::GdbIndexSection() : SyntheticSection(0, SHT_PROGBITS, 1, ".gdb_index"), StringPool(llvm::StringTableBuilder::ELF) {} // Iterative hash function for symbol's name is described in .gdb_index format // specification. Note that we use one for version 5 to 7 here, it is different // for version 4. static uint32_t hash(StringRef Str) { uint32_t R = 0; for (uint8_t C : Str) R = R * 67 + tolower(C) - 113; return R; } static std::vector<std::pair<uint64_t, uint64_t>> readCuList(DWARFContext &Dwarf, InputSection *Sec) { std::vector<std::pair<uint64_t, uint64_t>> Ret; for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf.compile_units()) Ret.push_back({Sec->OutSecOff + CU->getOffset(), CU->getLength() + 4}); return Ret; } static InputSectionBase *findSection(ArrayRef<InputSectionBase *> Arr, uint64_t Offset) { for (InputSectionBase *S : Arr) if (S && S != &InputSection::Discarded) if (Offset >= S->getOffsetInFile() && Offset < S->getOffsetInFile() + S->getSize()) return S; return nullptr; } static std::vector<AddressEntry> readAddressArea(DWARFContext &Dwarf, InputSection *Sec, size_t CurrentCU) { std::vector<AddressEntry> Ret; for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf.compile_units()) { DWARFAddressRangesVector Ranges; CU->collectAddressRanges(Ranges); ArrayRef<InputSectionBase *> Sections = Sec->File->getSections(); for (std::pair<uint64_t, uint64_t> &R : Ranges) if (InputSectionBase *S = findSection(Sections, R.first)) Ret.push_back({S, R.first - S->getOffsetInFile(), R.second - S->getOffsetInFile(), CurrentCU}); ++CurrentCU; } return Ret; } static std::vector<std::pair<StringRef, uint8_t>> readPubNamesAndTypes(DWARFContext &Dwarf, bool IsLE) { StringRef Data[] = {Dwarf.getGnuPubNamesSection(), Dwarf.getGnuPubTypesSection()}; std::vector<std::pair<StringRef, uint8_t>> Ret; for (StringRef D : Data) { DWARFDebugPubTable PubTable(D, IsLE, true); for (const DWARFDebugPubTable::Set &Set : PubTable.getData()) for (const DWARFDebugPubTable::Entry &Ent : Set.Entries) Ret.push_back({Ent.Name, Ent.Descriptor.toBits()}); } return Ret; } class ObjInfoTy : public llvm::LoadedObjectInfo { uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const override { auto &S = static_cast<const object::ELFSectionRef &>(Sec); if (S.getFlags() & ELF::SHF_ALLOC) return S.getOffset(); return 0; } std::unique_ptr<llvm::LoadedObjectInfo> clone() const override { return {}; } }; void GdbIndexSection::readDwarf(InputSection *Sec) { Expected<std::unique_ptr<object::ObjectFile>> Obj = object::ObjectFile::createObjectFile(Sec->File->MB); if (!Obj) { error(toString(Sec->File) + ": error creating DWARF context"); return; } ObjInfoTy ObjInfo; DWARFContextInMemory Dwarf(*Obj.get(), &ObjInfo); size_t CuId = CompilationUnits.size(); for (std::pair<uint64_t, uint64_t> &P : readCuList(Dwarf, Sec)) CompilationUnits.push_back(P); for (AddressEntry &Ent : readAddressArea(Dwarf, Sec, CuId)) AddressArea.push_back(Ent); std::vector<std::pair<StringRef, uint8_t>> NamesAndTypes = readPubNamesAndTypes(Dwarf, Config->IsLE); for (std::pair<StringRef, uint8_t> &Pair : NamesAndTypes) { uint32_t Hash = hash(Pair.first); size_t Offset = StringPool.add(Pair.first); bool IsNew; GdbSymbol *Sym; std::tie(IsNew, Sym) = SymbolTable.add(Hash, Offset); if (IsNew) { Sym->CuVectorIndex = CuVectors.size(); CuVectors.push_back({{CuId, Pair.second}}); continue; } CuVectors[Sym->CuVectorIndex].push_back({CuId, Pair.second}); } } void GdbIndexSection::finalizeContents() { if (Finalized) return; Finalized = true; for (InputSectionBase *S : InputSections) if (InputSection *IS = dyn_cast<InputSection>(S)) if (IS->OutSec && IS->Name == ".debug_info") readDwarf(IS); SymbolTable.finalizeContents(); // GdbIndex header consist from version fields // and 5 more fields with different kinds of offsets. CuTypesOffset = CuListOffset + CompilationUnits.size() * CompilationUnitSize; SymTabOffset = CuTypesOffset + AddressArea.size() * AddressEntrySize; ConstantPoolOffset = SymTabOffset + SymbolTable.getCapacity() * SymTabEntrySize; for (std::vector<std::pair<uint32_t, uint8_t>> &CuVec : CuVectors) { CuVectorsOffset.push_back(CuVectorsSize); CuVectorsSize += OffsetTypeSize * (CuVec.size() + 1); } StringPoolOffset = ConstantPoolOffset + CuVectorsSize; StringPool.finalizeInOrder(); } size_t GdbIndexSection::getSize() const { const_cast<GdbIndexSection *>(this)->finalizeContents(); return StringPoolOffset + StringPool.getSize(); } void GdbIndexSection::writeTo(uint8_t *Buf) { write32le(Buf, 7); // Write version. write32le(Buf + 4, CuListOffset); // CU list offset. write32le(Buf + 8, CuTypesOffset); // Types CU list offset. write32le(Buf + 12, CuTypesOffset); // Address area offset. write32le(Buf + 16, SymTabOffset); // Symbol table offset. write32le(Buf + 20, ConstantPoolOffset); // Constant pool offset. Buf += 24; // Write the CU list. for (std::pair<uint64_t, uint64_t> CU : CompilationUnits) { write64le(Buf, CU.first); write64le(Buf + 8, CU.second); Buf += 16; } // Write the address area. for (AddressEntry &E : AddressArea) { uint64_t BaseAddr = E.Section->OutSec->Addr + E.Section->getOffset(0); write64le(Buf, BaseAddr + E.LowAddress); write64le(Buf + 8, BaseAddr + E.HighAddress); write32le(Buf + 16, E.CuIndex); Buf += 20; } // Write the symbol table. for (size_t I = 0; I < SymbolTable.getCapacity(); ++I) { GdbSymbol *Sym = SymbolTable.getSymbol(I); if (Sym) { size_t NameOffset = Sym->NameOffset + StringPoolOffset - ConstantPoolOffset; size_t CuVectorOffset = CuVectorsOffset[Sym->CuVectorIndex]; write32le(Buf, NameOffset); write32le(Buf + 4, CuVectorOffset); } Buf += 8; } // Write the CU vectors into the constant pool. for (std::vector<std::pair<uint32_t, uint8_t>> &CuVec : CuVectors) { write32le(Buf, CuVec.size()); Buf += 4; for (std::pair<uint32_t, uint8_t> &P : CuVec) { uint32_t Index = P.first; uint8_t Flags = P.second; Index |= Flags << 24; write32le(Buf, Index); Buf += 4; } } StringPool.write(Buf); } bool GdbIndexSection::empty() const { return !Out::DebugInfo; } template <class ELFT> EhFrameHeader<ELFT>::EhFrameHeader() : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 1, ".eh_frame_hdr") {} // .eh_frame_hdr contains a binary search table of pointers to FDEs. // Each entry of the search table consists of two values, // the starting PC from where FDEs covers, and the FDE's address. // It is sorted by PC. template <class ELFT> void EhFrameHeader<ELFT>::writeTo(uint8_t *Buf) { const endianness E = ELFT::TargetEndianness; // Sort the FDE list by their PC and uniqueify. Usually there is only // one FDE for a PC (i.e. function), but if ICF merges two functions // into one, there can be more than one FDEs pointing to the address. auto Less = [](const FdeData &A, const FdeData &B) { return A.Pc < B.Pc; }; std::stable_sort(Fdes.begin(), Fdes.end(), Less); auto Eq = [](const FdeData &A, const FdeData &B) { return A.Pc == B.Pc; }; Fdes.erase(std::unique(Fdes.begin(), Fdes.end(), Eq), Fdes.end()); Buf[0] = 1; Buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4; Buf[2] = DW_EH_PE_udata4; Buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; write32<E>(Buf + 4, In<ELFT>::EhFrame->OutSec->Addr - this->getVA() - 4); write32<E>(Buf + 8, Fdes.size()); Buf += 12; uint64_t VA = this->getVA(); for (FdeData &Fde : Fdes) { write32<E>(Buf, Fde.Pc - VA); write32<E>(Buf + 4, Fde.FdeVA - VA); Buf += 8; } } template <class ELFT> size_t EhFrameHeader<ELFT>::getSize() const { // .eh_frame_hdr has a 12 bytes header followed by an array of FDEs. return 12 + In<ELFT>::EhFrame->NumFdes * 8; } template <class ELFT> void EhFrameHeader<ELFT>::addFde(uint32_t Pc, uint32_t FdeVA) { Fdes.push_back({Pc, FdeVA}); } template <class ELFT> bool EhFrameHeader<ELFT>::empty() const { return In<ELFT>::EhFrame->empty(); } template <class ELFT> VersionDefinitionSection<ELFT>::VersionDefinitionSection() : SyntheticSection(SHF_ALLOC, SHT_GNU_verdef, sizeof(uint32_t), ".gnu.version_d") {} static StringRef getFileDefName() { if (!Config->SoName.empty()) return Config->SoName; return Config->OutputFile; } template <class ELFT> void VersionDefinitionSection<ELFT>::finalizeContents() { FileDefNameOff = In<ELFT>::DynStrTab->addString(getFileDefName()); for (VersionDefinition &V : Config->VersionDefinitions) V.NameOff = In<ELFT>::DynStrTab->addString(V.Name); this->OutSec->Link = In<ELFT>::DynStrTab->OutSec->SectionIndex; // sh_info should be set to the number of definitions. This fact is missed in // documentation, but confirmed by binutils community: // https://sourceware.org/ml/binutils/2014-11/msg00355.html this->OutSec->Info = getVerDefNum(); } template <class ELFT> void VersionDefinitionSection<ELFT>::writeOne(uint8_t *Buf, uint32_t Index, StringRef Name, size_t NameOff) { auto *Verdef = reinterpret_cast<Elf_Verdef *>(Buf); Verdef->vd_version = 1; Verdef->vd_cnt = 1; Verdef->vd_aux = sizeof(Elf_Verdef); Verdef->vd_next = sizeof(Elf_Verdef) + sizeof(Elf_Verdaux); Verdef->vd_flags = (Index == 1 ? VER_FLG_BASE : 0); Verdef->vd_ndx = Index; Verdef->vd_hash = hashSysV(Name); auto *Verdaux = reinterpret_cast<Elf_Verdaux *>(Buf + sizeof(Elf_Verdef)); Verdaux->vda_name = NameOff; Verdaux->vda_next = 0; } template <class ELFT> void VersionDefinitionSection<ELFT>::writeTo(uint8_t *Buf) { writeOne(Buf, 1, getFileDefName(), FileDefNameOff); for (VersionDefinition &V : Config->VersionDefinitions) { Buf += sizeof(Elf_Verdef) + sizeof(Elf_Verdaux); writeOne(Buf, V.Id, V.Name, V.NameOff); } // Need to terminate the last version definition. Elf_Verdef *Verdef = reinterpret_cast<Elf_Verdef *>(Buf); Verdef->vd_next = 0; } template <class ELFT> size_t VersionDefinitionSection<ELFT>::getSize() const { return (sizeof(Elf_Verdef) + sizeof(Elf_Verdaux)) * getVerDefNum(); } template <class ELFT> VersionTableSection<ELFT>::VersionTableSection() : SyntheticSection(SHF_ALLOC, SHT_GNU_versym, sizeof(uint16_t), ".gnu.version") { this->Entsize = sizeof(Elf_Versym); } template <class ELFT> void VersionTableSection<ELFT>::finalizeContents() { // At the moment of june 2016 GNU docs does not mention that sh_link field // should be set, but Sun docs do. Also readelf relies on this field. this->OutSec->Link = In<ELFT>::DynSymTab->OutSec->SectionIndex; } template <class ELFT> size_t VersionTableSection<ELFT>::getSize() const { return sizeof(Elf_Versym) * (In<ELFT>::DynSymTab->getSymbols().size() + 1); } template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) { auto *OutVersym = reinterpret_cast<Elf_Versym *>(Buf) + 1; for (const SymbolTableEntry &S : In<ELFT>::DynSymTab->getSymbols()) { OutVersym->vs_index = S.Symbol->symbol()->VersionId; ++OutVersym; } } template <class ELFT> bool VersionTableSection<ELFT>::empty() const { return !In<ELFT>::VerDef && In<ELFT>::VerNeed->empty(); } template <class ELFT> VersionNeedSection<ELFT>::VersionNeedSection() : SyntheticSection(SHF_ALLOC, SHT_GNU_verneed, sizeof(uint32_t), ".gnu.version_r") { // Identifiers in verneed section start at 2 because 0 and 1 are reserved // for VER_NDX_LOCAL and VER_NDX_GLOBAL. // First identifiers are reserved by verdef section if it exist. NextIndex = getVerDefNum() + 1; } template <class ELFT> void VersionNeedSection<ELFT>::addSymbol(SharedSymbol *SS) { auto *Ver = reinterpret_cast<const typename ELFT::Verdef *>(SS->Verdef); if (!Ver) { SS->symbol()->VersionId = VER_NDX_GLOBAL; return; } auto *File = cast<SharedFile<ELFT>>(SS->File); // If we don't already know that we need an Elf_Verneed for this DSO, prepare // to create one by adding it to our needed list and creating a dynstr entry // for the soname. if (File->VerdefMap.empty()) Needed.push_back({File, In<ELFT>::DynStrTab->addString(File->SoName)}); typename SharedFile<ELFT>::NeededVer &NV = File->VerdefMap[Ver]; // If we don't already know that we need an Elf_Vernaux for this Elf_Verdef, // prepare to create one by allocating a version identifier and creating a // dynstr entry for the version name. if (NV.Index == 0) { NV.StrTab = In<ELFT>::DynStrTab->addString(File->getStringTable().data() + Ver->getAux()->vda_name); NV.Index = NextIndex++; } SS->symbol()->VersionId = NV.Index; } template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) { // The Elf_Verneeds need to appear first, followed by the Elf_Vernauxs. auto *Verneed = reinterpret_cast<Elf_Verneed *>(Buf); auto *Vernaux = reinterpret_cast<Elf_Vernaux *>(Verneed + Needed.size()); for (std::pair<SharedFile<ELFT> *, size_t> &P : Needed) { // Create an Elf_Verneed for this DSO. Verneed->vn_version = 1; Verneed->vn_cnt = P.first->VerdefMap.size(); Verneed->vn_file = P.second; Verneed->vn_aux = reinterpret_cast<char *>(Vernaux) - reinterpret_cast<char *>(Verneed); Verneed->vn_next = sizeof(Elf_Verneed); ++Verneed; // Create the Elf_Vernauxs for this Elf_Verneed. The loop iterates over // VerdefMap, which will only contain references to needed version // definitions. Each Elf_Vernaux is based on the information contained in // the Elf_Verdef in the source DSO. This loop iterates over a std::map of // pointers, but is deterministic because the pointers refer to Elf_Verdef // data structures within a single input file. for (auto &NV : P.first->VerdefMap) { Vernaux->vna_hash = NV.first->vd_hash; Vernaux->vna_flags = 0; Vernaux->vna_other = NV.second.Index; Vernaux->vna_name = NV.second.StrTab; Vernaux->vna_next = sizeof(Elf_Vernaux); ++Vernaux; } Vernaux[-1].vna_next = 0; } Verneed[-1].vn_next = 0; } template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() { this->OutSec->Link = In<ELFT>::DynStrTab->OutSec->SectionIndex; this->OutSec->Info = Needed.size(); } template <class ELFT> size_t VersionNeedSection<ELFT>::getSize() const { unsigned Size = Needed.size() * sizeof(Elf_Verneed); for (const std::pair<SharedFile<ELFT> *, size_t> &P : Needed) Size += P.first->VerdefMap.size() * sizeof(Elf_Vernaux); return Size; } template <class ELFT> bool VersionNeedSection<ELFT>::empty() const { return getNeedNum() == 0; } MergeSyntheticSection::MergeSyntheticSection(StringRef Name, uint32_t Type, uint64_t Flags, uint32_t Alignment) : SyntheticSection(Flags, Type, Alignment, Name), Builder(StringTableBuilder::RAW, Alignment) {} void MergeSyntheticSection::addSection(MergeInputSection *MS) { assert(!Finalized); MS->MergeSec = this; Sections.push_back(MS); } void MergeSyntheticSection::writeTo(uint8_t *Buf) { Builder.write(Buf); } bool MergeSyntheticSection::shouldTailMerge() const { return (this->Flags & SHF_STRINGS) && Config->Optimize >= 2; } void MergeSyntheticSection::finalizeTailMerge() { // Add all string pieces to the string table builder to create section // contents. for (MergeInputSection *Sec : Sections) for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I) if (Sec->Pieces[I].Live) Builder.add(Sec->getData(I)); // Fix the string table content. After this, the contents will never change. Builder.finalize(); // finalize() fixed tail-optimized strings, so we can now get // offsets of strings. Get an offset for each string and save it // to a corresponding StringPiece for easy access. for (MergeInputSection *Sec : Sections) for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I) if (Sec->Pieces[I].Live) Sec->Pieces[I].OutputOff = Builder.getOffset(Sec->getData(I)); } void MergeSyntheticSection::finalizeNoTailMerge() { // Add all string pieces to the string table builder to create section // contents. Because we are not tail-optimizing, offsets of strings are // fixed when they are added to the builder (string table builder contains // a hash table from strings to offsets). for (MergeInputSection *Sec : Sections) for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I) if (Sec->Pieces[I].Live) Sec->Pieces[I].OutputOff = Builder.add(Sec->getData(I)); Builder.finalizeInOrder(); } void MergeSyntheticSection::finalizeContents() { if (Finalized) return; Finalized = true; if (shouldTailMerge()) finalizeTailMerge(); else finalizeNoTailMerge(); } size_t MergeSyntheticSection::getSize() const { // We should finalize string builder to know the size. const_cast<MergeSyntheticSection *>(this)->finalizeContents(); return Builder.getSize(); } MipsRldMapSection::MipsRldMapSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Config->Wordsize, ".rld_map") {} void MipsRldMapSection::writeTo(uint8_t *Buf) { // Apply filler from linker script. Optional<uint32_t> Fill = Script->getFiller(this->Name); if (!Fill || *Fill == 0) return; uint64_t Filler = *Fill; Filler = (Filler << 32) | Filler; memcpy(Buf, &Filler, getSize()); } ARMExidxSentinelSection::ARMExidxSentinelSection() : SyntheticSection(SHF_ALLOC | SHF_LINK_ORDER, SHT_ARM_EXIDX, Config->Wordsize, ".ARM.exidx") {} // Write a terminating sentinel entry to the end of the .ARM.exidx table. // This section will have been sorted last in the .ARM.exidx table. // This table entry will have the form: // | PREL31 upper bound of code that has exception tables | EXIDX_CANTUNWIND | void ARMExidxSentinelSection::writeTo(uint8_t *Buf) { // Get the InputSection before us, we are by definition last auto RI = cast<OutputSection>(this->OutSec)->Sections.rbegin(); InputSection *LE = *(++RI); InputSection *LC = cast<InputSection>(LE->getLinkOrderDep()); uint64_t S = LC->OutSec->Addr + LC->getOffset(LC->getSize()); uint64_t P = this->getVA(); Target->relocateOne(Buf, R_ARM_PREL31, S - P); write32le(Buf + 4, 0x1); } ThunkSection::ThunkSection(OutputSection *OS, uint64_t Off) : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, Config->Wordsize, ".text.thunk") { this->OutSec = OS; this->OutSecOff = Off; } void ThunkSection::addThunk(Thunk *T) { uint64_t Off = alignTo(Size, T->alignment); T->Offset = Off; Thunks.push_back(T); T->addSymbols(*this); Size = Off + T->size(); } void ThunkSection::writeTo(uint8_t *Buf) { for (const Thunk *T : Thunks) T->writeTo(Buf + T->Offset, *this); } InputSection *ThunkSection::getTargetInputSection() const { const Thunk *T = Thunks.front(); return T->getTargetInputSection(); } InputSection *InX::ARMAttributes; BssSection *InX::Bss; BssSection *InX::BssRelRo; BuildIdSection *InX::BuildId; InputSection *InX::Common; StringTableSection *InX::DynStrTab; InputSection *InX::Interp; GdbIndexSection *InX::GdbIndex; GotPltSection *InX::GotPlt; IgotPltSection *InX::IgotPlt; MipsGotSection *InX::MipsGot; MipsRldMapSection *InX::MipsRldMap; PltSection *InX::Plt; PltSection *InX::Iplt; StringTableSection *InX::ShStrTab; StringTableSection *InX::StrTab; template void PltSection::addEntry<ELF32LE>(SymbolBody &Sym); template void PltSection::addEntry<ELF32BE>(SymbolBody &Sym); template void PltSection::addEntry<ELF64LE>(SymbolBody &Sym); template void PltSection::addEntry<ELF64BE>(SymbolBody &Sym); template InputSection *elf::createCommonSection<ELF32LE>(); template InputSection *elf::createCommonSection<ELF32BE>(); template InputSection *elf::createCommonSection<ELF64LE>(); template InputSection *elf::createCommonSection<ELF64BE>(); template MergeInputSection *elf::createCommentSection<ELF32LE>(); template MergeInputSection *elf::createCommentSection<ELF32BE>(); template MergeInputSection *elf::createCommentSection<ELF64LE>(); template MergeInputSection *elf::createCommentSection<ELF64BE>(); template SymbolBody *elf::addSyntheticLocal<ELF32LE>(StringRef, uint8_t, uint64_t, uint64_t, InputSectionBase *); template SymbolBody *elf::addSyntheticLocal<ELF32BE>(StringRef, uint8_t, uint64_t, uint64_t, InputSectionBase *); template SymbolBody *elf::addSyntheticLocal<ELF64LE>(StringRef, uint8_t, uint64_t, uint64_t, InputSectionBase *); template SymbolBody *elf::addSyntheticLocal<ELF64BE>(StringRef, uint8_t, uint64_t, uint64_t, InputSectionBase *); template class elf::MipsAbiFlagsSection<ELF32LE>; template class elf::MipsAbiFlagsSection<ELF32BE>; template class elf::MipsAbiFlagsSection<ELF64LE>; template class elf::MipsAbiFlagsSection<ELF64BE>; template class elf::MipsOptionsSection<ELF32LE>; template class elf::MipsOptionsSection<ELF32BE>; template class elf::MipsOptionsSection<ELF64LE>; template class elf::MipsOptionsSection<ELF64BE>; template class elf::MipsReginfoSection<ELF32LE>; template class elf::MipsReginfoSection<ELF32BE>; template class elf::MipsReginfoSection<ELF64LE>; template class elf::MipsReginfoSection<ELF64BE>; template class elf::GotSection<ELF32LE>; template class elf::GotSection<ELF32BE>; template class elf::GotSection<ELF64LE>; template class elf::GotSection<ELF64BE>; template class elf::DynamicSection<ELF32LE>; template class elf::DynamicSection<ELF32BE>; template class elf::DynamicSection<ELF64LE>; template class elf::DynamicSection<ELF64BE>; template class elf::RelocationSection<ELF32LE>; template class elf::RelocationSection<ELF32BE>; template class elf::RelocationSection<ELF64LE>; template class elf::RelocationSection<ELF64BE>; template class elf::SymbolTableSection<ELF32LE>; template class elf::SymbolTableSection<ELF32BE>; template class elf::SymbolTableSection<ELF64LE>; template class elf::SymbolTableSection<ELF64BE>; template class elf::GnuHashTableSection<ELF32LE>; template class elf::GnuHashTableSection<ELF32BE>; template class elf::GnuHashTableSection<ELF64LE>; template class elf::GnuHashTableSection<ELF64BE>; template class elf::HashTableSection<ELF32LE>; template class elf::HashTableSection<ELF32BE>; template class elf::HashTableSection<ELF64LE>; template class elf::HashTableSection<ELF64BE>; template class elf::EhFrameHeader<ELF32LE>; template class elf::EhFrameHeader<ELF32BE>; template class elf::EhFrameHeader<ELF64LE>; template class elf::EhFrameHeader<ELF64BE>; template class elf::VersionTableSection<ELF32LE>; template class elf::VersionTableSection<ELF32BE>; template class elf::VersionTableSection<ELF64LE>; template class elf::VersionTableSection<ELF64BE>; template class elf::VersionNeedSection<ELF32LE>; template class elf::VersionNeedSection<ELF32BE>; template class elf::VersionNeedSection<ELF64LE>; template class elf::VersionNeedSection<ELF64BE>; template class elf::VersionDefinitionSection<ELF32LE>; template class elf::VersionDefinitionSection<ELF32BE>; template class elf::VersionDefinitionSection<ELF64LE>; template class elf::VersionDefinitionSection<ELF64BE>; template class elf::EhFrameSection<ELF32LE>; template class elf::EhFrameSection<ELF32BE>; template class elf::EhFrameSection<ELF64LE>; template class elf::EhFrameSection<ELF64BE>; Index: vendor/lld/dist/ELF/Writer.cpp =================================================================== --- vendor/lld/dist/ELF/Writer.cpp (revision 317689) +++ vendor/lld/dist/ELF/Writer.cpp (revision 317690) @@ -1,1820 +1,1822 @@ //===- Writer.cpp ---------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "Writer.h" #include "Config.h" #include "Filesystem.h" #include "LinkerScript.h" #include "MapFile.h" #include "Memory.h" #include "OutputSections.h" #include "Relocations.h" #include "Strings.h" #include "SymbolTable.h" #include "SyntheticSections.h" #include "Target.h" #include "Threads.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/raw_ostream.h" #include <climits> using namespace llvm; using namespace llvm::ELF; using namespace llvm::object; using namespace llvm::support; using namespace llvm::support::endian; using namespace lld; using namespace lld::elf; namespace { // The writer writes a SymbolTable result to a file. template <class ELFT> class Writer { public: typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Ehdr Elf_Ehdr; typedef typename ELFT::Phdr Elf_Phdr; void run(); private: void createSyntheticSections(); void copyLocalSymbols(); void addSectionSymbols(); void addReservedSymbols(); void createSections(); void forEachRelSec(std::function<void(InputSectionBase &)> Fn); void sortSections(); void finalizeSections(); void addPredefinedSections(); std::vector<PhdrEntry> createPhdrs(); void removeEmptyPTLoad(); void addPtArmExid(std::vector<PhdrEntry> &Phdrs); void assignFileOffsets(); void assignFileOffsetsBinary(); void setPhdrs(); void fixHeaders(); void fixSectionAlignments(); void fixPredefinedSymbols(); void openFile(); void writeHeader(); void writeSections(); void writeSectionsBinary(); void writeBuildId(); std::unique_ptr<FileOutputBuffer> Buffer; std::vector<OutputSection *> OutputSections; OutputSectionFactory Factory{OutputSections}; void addRelIpltSymbols(); void addStartEndSymbols(); void addStartStopSymbols(OutputSection *Sec); uint64_t getEntryAddr(); OutputSection *findSection(StringRef Name); std::vector<PhdrEntry> Phdrs; uint64_t FileSize; uint64_t SectionHeaderOff; bool AllocateHeader = true; }; } // anonymous namespace StringRef elf::getOutputSectionName(StringRef Name) { if (Config->Relocatable) return Name; // If -emit-relocs is given (which is rare), we need to copy // relocation sections to the output. If input section .foo is // output as .bar, we want to rename .rel.foo .rel.bar as well. if (Config->EmitRelocs) { for (StringRef V : {".rel.", ".rela."}) { if (Name.startswith(V)) { StringRef Inner = getOutputSectionName(Name.substr(V.size() - 1)); - return Saver.save(Twine(V.drop_back()) + Inner); + return Saver.save(V.drop_back() + Inner); } } } for (StringRef V : {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.", ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.", ".gcc_except_table.", ".tdata.", ".ARM.exidx."}) { StringRef Prefix = V.drop_back(); if (Name.startswith(V) || Name == Prefix) return Prefix; } // CommonSection is identified as "COMMON" in linker scripts. // By default, it should go to .bss section. if (Name == "COMMON") return ".bss"; // ".zdebug_" is a prefix for ZLIB-compressed sections. // Because we decompressed input sections, we want to remove 'z'. if (Name.startswith(".zdebug_")) - return Saver.save(Twine(".") + Name.substr(2)); + return Saver.save("." + Name.substr(2)); return Name; } template <class ELFT> static bool needsInterpSection() { return !Symtab<ELFT>::X->getSharedFiles().empty() && !Config->DynamicLinker.empty() && !Script->ignoreInterpSection(); } template <class ELFT> void elf::writeResult() { Writer<ELFT>().run(); } template <class ELFT> void Writer<ELFT>::removeEmptyPTLoad() { auto I = std::remove_if(Phdrs.begin(), Phdrs.end(), [&](const PhdrEntry &P) { if (P.p_type != PT_LOAD) return false; if (!P.First) return true; uint64_t Size = P.Last->Addr + P.Last->Size - P.First->Addr; return Size == 0; }); Phdrs.erase(I, Phdrs.end()); } // This function scans over the input sections and creates mergeable // synthetic sections. It removes MergeInputSections from array and // adds new synthetic ones. Each synthetic section is added to the // location of the first input section it replaces. static void combineMergableSections() { std::vector<MergeSyntheticSection *> MergeSections; for (InputSectionBase *&S : InputSections) { MergeInputSection *MS = dyn_cast<MergeInputSection>(S); if (!MS) continue; // We do not want to handle sections that are not alive, so just remove // them instead of trying to merge. if (!MS->Live) continue; StringRef OutsecName = getOutputSectionName(MS->Name); uint64_t Flags = MS->Flags & ~(uint64_t)(SHF_GROUP | SHF_COMPRESSED); uint32_t Alignment = std::max<uint32_t>(MS->Alignment, MS->Entsize); auto I = llvm::find_if(MergeSections, [=](MergeSyntheticSection *Sec) { return Sec->Name == OutsecName && Sec->Flags == Flags && Sec->Alignment == Alignment; }); if (I == MergeSections.end()) { MergeSyntheticSection *Syn = make<MergeSyntheticSection>(OutsecName, MS->Type, Flags, Alignment); MergeSections.push_back(Syn); I = std::prev(MergeSections.end()); S = Syn; } else { S = nullptr; } (*I)->addSection(MS); } std::vector<InputSectionBase *> &V = InputSections; V.erase(std::remove(V.begin(), V.end(), nullptr), V.end()); } template <class ELFT> static void combineEhFrameSections() { for (InputSectionBase *&S : InputSections) { EhInputSection *ES = dyn_cast<EhInputSection>(S); if (!ES || !ES->Live) continue; In<ELFT>::EhFrame->addSection(ES); S = nullptr; } std::vector<InputSectionBase *> &V = InputSections; V.erase(std::remove(V.begin(), V.end(), nullptr), V.end()); } // The main function of the writer. template <class ELFT> void Writer<ELFT>::run() { // Create linker-synthesized sections such as .got or .plt. // Such sections are of type input section. createSyntheticSections(); combineMergableSections(); if (!Config->Relocatable) combineEhFrameSections<ELFT>(); // We need to create some reserved symbols such as _end. Create them. if (!Config->Relocatable) addReservedSymbols(); // Create output sections. Script->OutputSections = &OutputSections; if (Script->Opt.HasSections) { // If linker script contains SECTIONS commands, let it create sections. Script->processCommands(Factory); // Linker scripts may have left some input sections unassigned. // Assign such sections using the default rule. Script->addOrphanSections(Factory); } else { // If linker script does not contain SECTIONS commands, create // output sections by default rules. We still need to give the // linker script a chance to run, because it might contain // non-SECTIONS commands such as ASSERT. createSections(); Script->processCommands(Factory); } if (Config->Discard != DiscardPolicy::All) copyLocalSymbols(); if (Config->CopyRelocs) addSectionSymbols(); // Now that we have a complete set of output sections. This function // completes section contents. For example, we need to add strings // to the string table, and add entries to .got and .plt. // finalizeSections does that. finalizeSections(); if (ErrorCount) return; if (Config->Relocatable) { assignFileOffsets(); } else { if (!Script->Opt.HasSections) { fixSectionAlignments(); Script->fabricateDefaultCommands(Config->MaxPageSize); } + Script->synchronize(); Script->assignAddresses(Phdrs); // Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a // 0 sized region. This has to be done late since only after assignAddresses // we know the size of the sections. removeEmptyPTLoad(); if (!Config->OFormatBinary) assignFileOffsets(); else assignFileOffsetsBinary(); setPhdrs(); fixPredefinedSymbols(); } // It does not make sense try to open the file if we have error already. if (ErrorCount) return; // Write the result down to a file. openFile(); if (ErrorCount) return; if (!Config->OFormatBinary) { writeHeader(); writeSections(); } else { writeSectionsBinary(); } // Backfill .note.gnu.build-id section content. This is done at last // because the content is usually a hash value of the entire output file. writeBuildId(); if (ErrorCount) return; // Handle -Map option. writeMapFile<ELFT>(OutputSections); if (ErrorCount) return; if (auto EC = Buffer->commit()) error("failed to write to the output file: " + EC.message()); // Flush the output streams and exit immediately. A full shutdown // is a good test that we are keeping track of all allocated memory, // but actually freeing it is a waste of time in a regular linker run. if (Config->ExitEarly) exitLld(0); } // Initialize Out members. template <class ELFT> void Writer<ELFT>::createSyntheticSections() { // Initialize all pointers with NULL. This is needed because // you can call lld::elf::main more than once as a library. memset(&Out::First, 0, sizeof(Out)); auto Add = [](InputSectionBase *Sec) { InputSections.push_back(Sec); }; In<ELFT>::DynStrTab = make<StringTableSection>(".dynstr", true); In<ELFT>::Dynamic = make<DynamicSection<ELFT>>(); In<ELFT>::RelaDyn = make<RelocationSection<ELFT>>( Config->IsRela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc); In<ELFT>::ShStrTab = make<StringTableSection>(".shstrtab", false); Out::ElfHeader = make<OutputSection>("", 0, SHF_ALLOC); Out::ElfHeader->Size = sizeof(Elf_Ehdr); Out::ProgramHeaders = make<OutputSection>("", 0, SHF_ALLOC); Out::ProgramHeaders->updateAlignment(Config->Wordsize); if (needsInterpSection<ELFT>()) { In<ELFT>::Interp = createInterpSection(); Add(In<ELFT>::Interp); } else { In<ELFT>::Interp = nullptr; } if (!Config->Relocatable) Add(createCommentSection<ELFT>()); if (Config->Strip != StripPolicy::All) { In<ELFT>::StrTab = make<StringTableSection>(".strtab", false); In<ELFT>::SymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::StrTab); } if (Config->BuildId != BuildIdKind::None) { In<ELFT>::BuildId = make<BuildIdSection>(); Add(In<ELFT>::BuildId); } In<ELFT>::Common = createCommonSection<ELFT>(); if (In<ELFT>::Common) Add(InX::Common); In<ELFT>::Bss = make<BssSection>(".bss"); Add(In<ELFT>::Bss); In<ELFT>::BssRelRo = make<BssSection>(".bss.rel.ro"); Add(In<ELFT>::BssRelRo); // Add MIPS-specific sections. bool HasDynSymTab = !Symtab<ELFT>::X->getSharedFiles().empty() || Config->Pic || Config->ExportDynamic; if (Config->EMachine == EM_MIPS) { if (!Config->Shared && HasDynSymTab) { In<ELFT>::MipsRldMap = make<MipsRldMapSection>(); Add(In<ELFT>::MipsRldMap); } if (auto *Sec = MipsAbiFlagsSection<ELFT>::create()) Add(Sec); if (auto *Sec = MipsOptionsSection<ELFT>::create()) Add(Sec); if (auto *Sec = MipsReginfoSection<ELFT>::create()) Add(Sec); } if (HasDynSymTab) { In<ELFT>::DynSymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::DynStrTab); Add(In<ELFT>::DynSymTab); In<ELFT>::VerSym = make<VersionTableSection<ELFT>>(); Add(In<ELFT>::VerSym); if (!Config->VersionDefinitions.empty()) { In<ELFT>::VerDef = make<VersionDefinitionSection<ELFT>>(); Add(In<ELFT>::VerDef); } In<ELFT>::VerNeed = make<VersionNeedSection<ELFT>>(); Add(In<ELFT>::VerNeed); if (Config->GnuHash) { In<ELFT>::GnuHashTab = make<GnuHashTableSection<ELFT>>(); Add(In<ELFT>::GnuHashTab); } if (Config->SysvHash) { In<ELFT>::HashTab = make<HashTableSection<ELFT>>(); Add(In<ELFT>::HashTab); } Add(In<ELFT>::Dynamic); Add(In<ELFT>::DynStrTab); Add(In<ELFT>::RelaDyn); } // Add .got. MIPS' .got is so different from the other archs, // it has its own class. if (Config->EMachine == EM_MIPS) { In<ELFT>::MipsGot = make<MipsGotSection>(); Add(In<ELFT>::MipsGot); } else { In<ELFT>::Got = make<GotSection<ELFT>>(); Add(In<ELFT>::Got); } In<ELFT>::GotPlt = make<GotPltSection>(); Add(In<ELFT>::GotPlt); In<ELFT>::IgotPlt = make<IgotPltSection>(); Add(In<ELFT>::IgotPlt); if (Config->GdbIndex) { In<ELFT>::GdbIndex = make<GdbIndexSection>(); Add(In<ELFT>::GdbIndex); } // We always need to add rel[a].plt to output if it has entries. // Even for static linking it can contain R_[*]_IRELATIVE relocations. In<ELFT>::RelaPlt = make<RelocationSection<ELFT>>( Config->IsRela ? ".rela.plt" : ".rel.plt", false /*Sort*/); Add(In<ELFT>::RelaPlt); // The RelaIplt immediately follows .rel.plt (.rel.dyn for ARM) to ensure // that the IRelative relocations are processed last by the dynamic loader In<ELFT>::RelaIplt = make<RelocationSection<ELFT>>( (Config->EMachine == EM_ARM) ? ".rel.dyn" : In<ELFT>::RelaPlt->Name, false /*Sort*/); Add(In<ELFT>::RelaIplt); In<ELFT>::Plt = make<PltSection>(Target->PltHeaderSize); Add(In<ELFT>::Plt); In<ELFT>::Iplt = make<PltSection>(0); Add(In<ELFT>::Iplt); if (!Config->Relocatable) { if (Config->EhFrameHdr) { In<ELFT>::EhFrameHdr = make<EhFrameHeader<ELFT>>(); Add(In<ELFT>::EhFrameHdr); } In<ELFT>::EhFrame = make<EhFrameSection<ELFT>>(); Add(In<ELFT>::EhFrame); } if (In<ELFT>::SymTab) Add(In<ELFT>::SymTab); Add(In<ELFT>::ShStrTab); if (In<ELFT>::StrTab) Add(In<ELFT>::StrTab); } static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName, const SymbolBody &B) { if (B.isFile() || B.isSection()) return false; // If sym references a section in a discarded group, don't keep it. if (Sec == &InputSection::Discarded) return false; if (Config->Discard == DiscardPolicy::None) return true; // In ELF assembly .L symbols are normally discarded by the assembler. // If the assembler fails to do so, the linker discards them if // * --discard-locals is used. // * The symbol is in a SHF_MERGE section, which is normally the reason for // the assembler keeping the .L symbol. if (!SymName.startswith(".L") && !SymName.empty()) return true; if (Config->Discard == DiscardPolicy::Locals) return false; return !Sec || !(Sec->Flags & SHF_MERGE); } static bool includeInSymtab(const SymbolBody &B) { if (!B.isLocal() && !B.symbol()->IsUsedInRegularObj) return false; if (auto *D = dyn_cast<DefinedRegular>(&B)) { // Always include absolute symbols. SectionBase *Sec = D->Section; if (!Sec) return true; if (auto *IS = dyn_cast<InputSectionBase>(Sec)) { Sec = IS->Repl; IS = cast<InputSectionBase>(Sec); // Exclude symbols pointing to garbage-collected sections. if (!IS->Live) return false; } if (auto *S = dyn_cast<MergeInputSection>(Sec)) if (!S->getSectionPiece(D->Value)->Live) return false; } return true; } // Local symbols are not in the linker's symbol table. This function scans // each object file's symbol table to copy local symbols to the output. template <class ELFT> void Writer<ELFT>::copyLocalSymbols() { if (!In<ELFT>::SymTab) return; for (elf::ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles()) { for (SymbolBody *B : F->getLocalSymbols()) { if (!B->IsLocal) fatal(toString(F) + ": broken object: getLocalSymbols returns a non-local symbol"); auto *DR = dyn_cast<DefinedRegular>(B); // No reason to keep local undefined symbol in symtab. if (!DR) continue; if (!includeInSymtab(*B)) continue; SectionBase *Sec = DR->Section; if (!shouldKeepInSymtab(Sec, B->getName(), *B)) continue; In<ELFT>::SymTab->addSymbol(B); } } } template <class ELFT> void Writer<ELFT>::addSectionSymbols() { // Create one STT_SECTION symbol for each output section we might // have a relocation with. for (OutputSection *Sec : OutputSections) { if (Sec->Sections.empty()) continue; InputSection *IS = Sec->Sections[0]; if (isa<SyntheticSection>(IS) || IS->Type == SHT_REL || IS->Type == SHT_RELA) continue; auto *Sym = make<DefinedRegular>("", /*IsLocal=*/true, /*StOther=*/0, STT_SECTION, /*Value=*/0, /*Size=*/0, IS, nullptr); In<ELFT>::SymTab->addSymbol(Sym); } } // PPC64 has a number of special SHT_PROGBITS+SHF_ALLOC+SHF_WRITE sections that // we would like to make sure appear is a specific order to maximize their // coverage by a single signed 16-bit offset from the TOC base pointer. // Conversely, the special .tocbss section should be first among all SHT_NOBITS // sections. This will put it next to the loaded special PPC64 sections (and, // thus, within reach of the TOC base pointer). static int getPPC64SectionRank(StringRef SectionName) { return StringSwitch<int>(SectionName) .Case(".tocbss", 0) .Case(".branch_lt", 2) .Case(".toc", 3) .Case(".toc1", 4) .Case(".opd", 5) .Default(1); } // All sections with SHF_MIPS_GPREL flag should be grouped together // because data in these sections is addressable with a gp relative address. static int getMipsSectionRank(const OutputSection *S) { if ((S->Flags & SHF_MIPS_GPREL) == 0) return 0; if (S->Name == ".got") return 1; return 2; } // Today's loaders have a feature to make segments read-only after // processing dynamic relocations to enhance security. PT_GNU_RELRO // is defined for that. // // This function returns true if a section needs to be put into a // PT_GNU_RELRO segment. template <class ELFT> bool elf::isRelroSection(const OutputSection *Sec) { if (!Config->ZRelro) return false; uint64_t Flags = Sec->Flags; // Non-allocatable or non-writable sections don't need RELRO because // they are not writable or not even mapped to memory in the first place. // RELRO is for sections that are essentially read-only but need to // be writable only at process startup to allow dynamic linker to // apply relocations. if (!(Flags & SHF_ALLOC) || !(Flags & SHF_WRITE)) return false; // Once initialized, TLS data segments are used as data templates // for a thread-local storage. For each new thread, runtime // allocates memory for a TLS and copy templates there. No thread // are supposed to use templates directly. Thus, it can be in RELRO. if (Flags & SHF_TLS) return true; // .init_array, .preinit_array and .fini_array contain pointers to // functions that are executed on process startup or exit. These // pointers are set by the static linker, and they are not expected // to change at runtime. But if you are an attacker, you could do // interesting things by manipulating pointers in .fini_array, for // example. So they are put into RELRO. uint32_t Type = Sec->Type; if (Type == SHT_INIT_ARRAY || Type == SHT_FINI_ARRAY || Type == SHT_PREINIT_ARRAY) return true; // .got contains pointers to external symbols. They are resolved by // the dynamic linker when a module is loaded into memory, and after // that they are not expected to change. So, it can be in RELRO. if (In<ELFT>::Got && Sec == In<ELFT>::Got->OutSec) return true; // .got.plt contains pointers to external function symbols. They are // by default resolved lazily, so we usually cannot put it into RELRO. // However, if "-z now" is given, the lazy symbol resolution is // disabled, which enables us to put it into RELRO. if (Sec == In<ELFT>::GotPlt->OutSec) return Config->ZNow; // .dynamic section contains data for the dynamic linker, and // there's no need to write to it at runtime, so it's better to put // it into RELRO. if (Sec == In<ELFT>::Dynamic->OutSec) return true; // .bss.rel.ro is used for copy relocations for read-only symbols. // Since the dynamic linker needs to process copy relocations, the // section cannot be read-only, but once initialized, they shouldn't // change. if (Sec == In<ELFT>::BssRelRo->OutSec) return true; // Sections with some special names are put into RELRO. This is a // bit unfortunate because section names shouldn't be significant in // ELF in spirit. But in reality many linker features depend on // magic section names. StringRef S = Sec->Name; return S == ".data.rel.ro" || S == ".ctors" || S == ".dtors" || S == ".jcr" || S == ".eh_frame" || S == ".openbsd.randomdata"; } template <class ELFT> static bool compareSectionsNonScript(const OutputSection *A, const OutputSection *B) { // Put .interp first because some loaders want to see that section // on the first page of the executable file when loaded into memory. bool AIsInterp = A->Name == ".interp"; bool BIsInterp = B->Name == ".interp"; if (AIsInterp != BIsInterp) return AIsInterp; // Allocatable sections go first to reduce the total PT_LOAD size and // so debug info doesn't change addresses in actual code. bool AIsAlloc = A->Flags & SHF_ALLOC; bool BIsAlloc = B->Flags & SHF_ALLOC; if (AIsAlloc != BIsAlloc) return AIsAlloc; // We don't have any special requirements for the relative order of two non // allocatable sections. if (!AIsAlloc) return false; // We want to put section specified by -T option first, so we // can start assigning VA starting from them later. auto AAddrSetI = Config->SectionStartMap.find(A->Name); auto BAddrSetI = Config->SectionStartMap.find(B->Name); bool AHasAddrSet = AAddrSetI != Config->SectionStartMap.end(); bool BHasAddrSet = BAddrSetI != Config->SectionStartMap.end(); if (AHasAddrSet != BHasAddrSet) return AHasAddrSet; if (AHasAddrSet) return AAddrSetI->second < BAddrSetI->second; // We want the read only sections first so that they go in the PT_LOAD // covering the program headers at the start of the file. bool AIsWritable = A->Flags & SHF_WRITE; bool BIsWritable = B->Flags & SHF_WRITE; if (AIsWritable != BIsWritable) return BIsWritable; if (!Config->SingleRoRx) { // For a corresponding reason, put non exec sections first (the program // header PT_LOAD is not executable). // We only do that if we are not using linker scripts, since with linker // scripts ro and rx sections are in the same PT_LOAD, so their relative // order is not important. The same applies for -no-rosegment. bool AIsExec = A->Flags & SHF_EXECINSTR; bool BIsExec = B->Flags & SHF_EXECINSTR; if (AIsExec != BIsExec) return BIsExec; } // If we got here we know that both A and B are in the same PT_LOAD. bool AIsTls = A->Flags & SHF_TLS; bool BIsTls = B->Flags & SHF_TLS; bool AIsNoBits = A->Type == SHT_NOBITS; bool BIsNoBits = B->Type == SHT_NOBITS; // The first requirement we have is to put (non-TLS) nobits sections last. The // reason is that the only thing the dynamic linker will see about them is a // p_memsz that is larger than p_filesz. Seeing that it zeros the end of the // PT_LOAD, so that has to correspond to the nobits sections. bool AIsNonTlsNoBits = AIsNoBits && !AIsTls; bool BIsNonTlsNoBits = BIsNoBits && !BIsTls; if (AIsNonTlsNoBits != BIsNonTlsNoBits) return BIsNonTlsNoBits; // We place nobits RelRo sections before plain r/w ones, and non-nobits RelRo // sections after r/w ones, so that the RelRo sections are contiguous. bool AIsRelRo = isRelroSection<ELFT>(A); bool BIsRelRo = isRelroSection<ELFT>(B); if (AIsRelRo != BIsRelRo) return AIsNonTlsNoBits ? AIsRelRo : BIsRelRo; // The TLS initialization block needs to be a single contiguous block in a R/W // PT_LOAD, so stick TLS sections directly before the other RelRo R/W // sections. The TLS NOBITS sections are placed here as they don't take up // virtual address space in the PT_LOAD. if (AIsTls != BIsTls) return AIsTls; // Within the TLS initialization block, the non-nobits sections need to appear // first. if (AIsNoBits != BIsNoBits) return BIsNoBits; // Some architectures have additional ordering restrictions for sections // within the same PT_LOAD. if (Config->EMachine == EM_PPC64) return getPPC64SectionRank(A->Name) < getPPC64SectionRank(B->Name); if (Config->EMachine == EM_MIPS) return getMipsSectionRank(A) < getMipsSectionRank(B); return false; } // Output section ordering is determined by this function. template <class ELFT> static bool compareSections(const OutputSection *A, const OutputSection *B) { // For now, put sections mentioned in a linker script first. int AIndex = Script->getSectionIndex(A->Name); int BIndex = Script->getSectionIndex(B->Name); bool AInScript = AIndex != INT_MAX; bool BInScript = BIndex != INT_MAX; if (AInScript != BInScript) return AInScript; // If both are in the script, use that order. if (AInScript) return AIndex < BIndex; return compareSectionsNonScript<ELFT>(A, B); } // Program header entry PhdrEntry::PhdrEntry(unsigned Type, unsigned Flags) { p_type = Type; p_flags = Flags; } void PhdrEntry::add(OutputSection *Sec) { Last = Sec; if (!First) First = Sec; p_align = std::max(p_align, Sec->Alignment); if (p_type == PT_LOAD) Sec->FirstInPtLoad = First; } template <class ELFT> static Symbol *addRegular(StringRef Name, SectionBase *Sec, uint64_t Value, uint8_t StOther = STV_HIDDEN, uint8_t Binding = STB_WEAK) { // The linker generated symbols are added as STB_WEAK to allow user defined // ones to override them. return Symtab<ELFT>::X->addRegular(Name, StOther, STT_NOTYPE, Value, /*Size=*/0, Binding, Sec, /*File=*/nullptr); } template <class ELFT> static DefinedRegular * addOptionalRegular(StringRef Name, SectionBase *Sec, uint64_t Val, uint8_t StOther = STV_HIDDEN, uint8_t Binding = STB_GLOBAL) { SymbolBody *S = Symtab<ELFT>::X->find(Name); if (!S) return nullptr; if (S->isInCurrentDSO()) return nullptr; return cast<DefinedRegular>( addRegular<ELFT>(Name, Sec, Val, StOther, Binding)->body()); } // The beginning and the ending of .rel[a].plt section are marked // with __rel[a]_iplt_{start,end} symbols if it is a statically linked // executable. The runtime needs these symbols in order to resolve // all IRELATIVE relocs on startup. For dynamic executables, we don't // need these symbols, since IRELATIVE relocs are resolved through GOT // and PLT. For details, see http://www.airs.com/blog/archives/403. template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() { if (In<ELFT>::DynSymTab) return; StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start"; addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, 0, STV_HIDDEN, STB_WEAK); S = Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end"; addOptionalRegular<ELFT>(S, In<ELFT>::RelaIplt, -1, STV_HIDDEN, STB_WEAK); } // The linker is expected to define some symbols depending on // the linking result. This function defines such symbols. template <class ELFT> void Writer<ELFT>::addReservedSymbols() { if (Config->EMachine == EM_MIPS) { // Define _gp for MIPS. st_value of _gp symbol will be updated by Writer // so that it points to an absolute address which by default is relative // to GOT. Default offset is 0x7ff0. // See "Global Data Symbols" in Chapter 6 in the following document: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf ElfSym::MipsGp = Symtab<ELFT>::X->addAbsolute("_gp", STV_HIDDEN, STB_LOCAL); // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between // start of function and 'gp' pointer into GOT. if (Symtab<ELFT>::X->find("_gp_disp")) ElfSym::MipsGpDisp = Symtab<ELFT>::X->addAbsolute("_gp_disp", STV_HIDDEN, STB_LOCAL); // The __gnu_local_gp is a magic symbol equal to the current value of 'gp' // pointer. This symbol is used in the code generated by .cpload pseudo-op // in case of using -mno-shared option. // https://sourceware.org/ml/binutils/2004-12/msg00094.html if (Symtab<ELFT>::X->find("__gnu_local_gp")) ElfSym::MipsLocalGp = Symtab<ELFT>::X->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_LOCAL); } // In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol // is magical and is used to produce a R_386_GOTPC relocation. // The R_386_GOTPC relocation value doesn't actually depend on the // symbol value, so it could use an index of STN_UNDEF which, according // to the spec, means the symbol value is 0. // Unfortunately both gas and MC keep the _GLOBAL_OFFSET_TABLE_ symbol in // the object file. // The situation is even stranger on x86_64 where the assembly doesn't // need the magical symbol, but gas still puts _GLOBAL_OFFSET_TABLE_ as // an undefined symbol in the .o files. // Given that the symbol is effectively unused, we just create a dummy // hidden one to avoid the undefined symbol error. Symtab<ELFT>::X->addIgnored("_GLOBAL_OFFSET_TABLE_"); // __tls_get_addr is defined by the dynamic linker for dynamic ELFs. For // static linking the linker is required to optimize away any references to // __tls_get_addr, so it's not defined anywhere. Create a hidden definition // to avoid the undefined symbol error. if (!In<ELFT>::DynSymTab) Symtab<ELFT>::X->addIgnored("__tls_get_addr"); // If linker script do layout we do not need to create any standart symbols. if (Script->Opt.HasSections) return; // __ehdr_start is the location of ELF file headers. addOptionalRegular<ELFT>("__ehdr_start", Out::ElfHeader, 0, STV_HIDDEN); auto Add = [](StringRef S) { return addOptionalRegular<ELFT>(S, Out::ElfHeader, 0, STV_DEFAULT); }; ElfSym::Bss = Add("__bss_start"); ElfSym::End1 = Add("end"); ElfSym::End2 = Add("_end"); ElfSym::Etext1 = Add("etext"); ElfSym::Etext2 = Add("_etext"); ElfSym::Edata1 = Add("edata"); ElfSym::Edata2 = Add("_edata"); } // Sort input sections by section name suffixes for // __attribute__((init_priority(N))). static void sortInitFini(OutputSection *S) { if (S) reinterpret_cast<OutputSection *>(S)->sortInitFini(); } // Sort input sections by the special rule for .ctors and .dtors. static void sortCtorsDtors(OutputSection *S) { if (S) reinterpret_cast<OutputSection *>(S)->sortCtorsDtors(); } // Sort input sections using the list provided by --symbol-ordering-file. template <class ELFT> static void sortBySymbolsOrder(ArrayRef<OutputSection *> OutputSections) { if (Config->SymbolOrderingFile.empty()) return; // Build a map from symbols to their priorities. Symbols that didn't // appear in the symbol ordering file have the lowest priority 0. // All explicitly mentioned symbols have negative (higher) priorities. DenseMap<StringRef, int> SymbolOrder; int Priority = -Config->SymbolOrderingFile.size(); for (StringRef S : Config->SymbolOrderingFile) SymbolOrder.insert({S, Priority++}); // Build a map from sections to their priorities. DenseMap<SectionBase *, int> SectionOrder; for (elf::ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) { for (SymbolBody *Body : File->getSymbols()) { auto *D = dyn_cast<DefinedRegular>(Body); if (!D || !D->Section) continue; int &Priority = SectionOrder[D->Section]; Priority = std::min(Priority, SymbolOrder.lookup(D->getName())); } } // Sort sections by priority. for (OutputSection *Base : OutputSections) if (auto *Sec = dyn_cast<OutputSection>(Base)) Sec->sort([&](InputSectionBase *S) { return SectionOrder.lookup(S); }); } template <class ELFT> void Writer<ELFT>::forEachRelSec(std::function<void(InputSectionBase &)> Fn) { for (InputSectionBase *IS : InputSections) { if (!IS->Live) continue; // Scan all relocations. Each relocation goes through a series // of tests to determine if it needs special treatment, such as // creating GOT, PLT, copy relocations, etc. // Note that relocations for non-alloc sections are directly // processed by InputSection::relocateNonAlloc. if (!(IS->Flags & SHF_ALLOC)) continue; if (isa<InputSection>(IS) || isa<EhInputSection>(IS)) Fn(*IS); } if (!Config->Relocatable) { for (EhInputSection *ES : In<ELFT>::EhFrame->Sections) Fn(*ES); } } template <class ELFT> void Writer<ELFT>::createSections() { for (InputSectionBase *IS : InputSections) if (IS) Factory.addInputSec(IS, getOutputSectionName(IS->Name)); sortBySymbolsOrder<ELFT>(OutputSections); sortInitFini(findSection(".init_array")); sortInitFini(findSection(".fini_array")); sortCtorsDtors(findSection(".ctors")); sortCtorsDtors(findSection(".dtors")); for (OutputSection *Sec : OutputSections) Sec->assignOffsets(); } static bool canSharePtLoad(const OutputSection &S1, const OutputSection &S2) { if (!(S1.Flags & SHF_ALLOC) || !(S2.Flags & SHF_ALLOC)) return false; bool S1IsWrite = S1.Flags & SHF_WRITE; bool S2IsWrite = S2.Flags & SHF_WRITE; if (S1IsWrite != S2IsWrite) return false; if (!S1IsWrite) return true; // RO and RX share a PT_LOAD with linker scripts. return (S1.Flags & SHF_EXECINSTR) == (S2.Flags & SHF_EXECINSTR); } template <class ELFT> void Writer<ELFT>::sortSections() { // Don't sort if using -r. It is not necessary and we want to preserve the // relative order for SHF_LINK_ORDER sections. if (Config->Relocatable) return; if (!Script->Opt.HasSections) { std::stable_sort(OutputSections.begin(), OutputSections.end(), compareSectionsNonScript<ELFT>); return; } Script->adjustSectionsBeforeSorting(); // The order of the sections in the script is arbitrary and may not agree with // compareSectionsNonScript. This means that we cannot easily define a // strict weak ordering. To see why, consider a comparison of a section in the // script and one not in the script. We have a two simple options: // * Make them equivalent (a is not less than b, and b is not less than a). // The problem is then that equivalence has to be transitive and we can // have sections a, b and c with only b in a script and a less than c // which breaks this property. // * Use compareSectionsNonScript. Given that the script order doesn't have // to match, we can end up with sections a, b, c, d where b and c are in the // script and c is compareSectionsNonScript less than b. In which case d // can be equivalent to c, a to b and d < a. As a concrete example: // .a (rx) # not in script // .b (rx) # in script // .c (ro) # in script // .d (ro) # not in script // // The way we define an order then is: // * First put script sections at the start and sort the script and // non-script sections independently. // * Move each non-script section to its preferred position. We try // to put each section in the last position where it it can share // a PT_LOAD. std::stable_sort(OutputSections.begin(), OutputSections.end(), compareSections<ELFT>); auto I = OutputSections.begin(); auto E = OutputSections.end(); auto NonScriptI = std::find_if(OutputSections.begin(), E, [](OutputSection *S) { return Script->getSectionIndex(S->Name) == INT_MAX; }); while (NonScriptI != E) { auto BestPos = std::max_element( I, NonScriptI, [&](OutputSection *&A, OutputSection *&B) { bool ACanSharePtLoad = canSharePtLoad(**NonScriptI, *A); bool BCanSharePtLoad = canSharePtLoad(**NonScriptI, *B); if (ACanSharePtLoad != BCanSharePtLoad) return BCanSharePtLoad; bool ACmp = compareSectionsNonScript<ELFT>(*NonScriptI, A); bool BCmp = compareSectionsNonScript<ELFT>(*NonScriptI, B); if (ACmp != BCmp) return BCmp; // FIXME: missing test size_t PosA = &A - &OutputSections[0]; size_t PosB = &B - &OutputSections[0]; return ACmp ? PosA > PosB : PosA < PosB; }); // max_element only returns NonScriptI if the range is empty. If the range // is not empty we should consider moving the the element forward one // position. if (BestPos != NonScriptI && !compareSectionsNonScript<ELFT>(*NonScriptI, *BestPos)) ++BestPos; std::rotate(BestPos, NonScriptI, NonScriptI + 1); ++NonScriptI; } Script->adjustSectionsAfterSorting(); } static void applySynthetic(const std::vector<SyntheticSection *> &Sections, std::function<void(SyntheticSection *)> Fn) { for (SyntheticSection *SS : Sections) if (SS && SS->OutSec && !SS->empty()) { Fn(SS); SS->OutSec->assignOffsets(); } } // We need to add input synthetic sections early in createSyntheticSections() // to make them visible from linkescript side. But not all sections are always // required to be in output. For example we don't need dynamic section content // sometimes. This function filters out such unused sections from the output. static void removeUnusedSyntheticSections(std::vector<OutputSection *> &V) { // All input synthetic sections that can be empty are placed after // all regular ones. We iterate over them all and exit at first // non-synthetic. for (InputSectionBase *S : llvm::reverse(InputSections)) { SyntheticSection *SS = dyn_cast<SyntheticSection>(S); if (!SS) return; if (!SS->empty() || !SS->OutSec) continue; SS->OutSec->Sections.erase(std::find(SS->OutSec->Sections.begin(), SS->OutSec->Sections.end(), SS)); + SS->Live = false; // If there are no other sections in the output section, remove it from the // output. if (SS->OutSec->Sections.empty()) V.erase(std::find(V.begin(), V.end(), SS->OutSec)); } } // Create output section objects and add them to OutputSections. template <class ELFT> void Writer<ELFT>::finalizeSections() { Out::DebugInfo = findSection(".debug_info"); Out::PreinitArray = findSection(".preinit_array"); Out::InitArray = findSection(".init_array"); Out::FiniArray = findSection(".fini_array"); // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop // symbols for sections, so that the runtime can get the start and end // addresses of each section by section name. Add such symbols. if (!Config->Relocatable) { addStartEndSymbols(); for (OutputSection *Sec : OutputSections) addStartStopSymbols(Sec); } // Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type. // It should be okay as no one seems to care about the type. // Even the author of gold doesn't remember why gold behaves that way. // https://sourceware.org/ml/binutils/2002-03/msg00360.html if (In<ELFT>::DynSymTab) addRegular<ELFT>("_DYNAMIC", In<ELFT>::Dynamic, 0); // Define __rel[a]_iplt_{start,end} symbols if needed. addRelIpltSymbols(); // This responsible for splitting up .eh_frame section into // pieces. The relocation scan uses those pieces, so this has to be // earlier. applySynthetic({In<ELFT>::EhFrame}, [](SyntheticSection *SS) { SS->finalizeContents(); }); // Scan relocations. This must be done after every symbol is declared so that // we can correctly decide if a dynamic relocation is needed. forEachRelSec(scanRelocations<ELFT>); if (In<ELFT>::Plt && !In<ELFT>::Plt->empty()) In<ELFT>::Plt->addSymbols(); if (In<ELFT>::Iplt && !In<ELFT>::Iplt->empty()) In<ELFT>::Iplt->addSymbols(); // Now that we have defined all possible global symbols including linker- // synthesized ones. Visit all symbols to give the finishing touches. for (Symbol *S : Symtab<ELFT>::X->getSymbols()) { SymbolBody *Body = S->body(); if (!includeInSymtab(*Body)) continue; if (In<ELFT>::SymTab) In<ELFT>::SymTab->addSymbol(Body); if (In<ELFT>::DynSymTab && S->includeInDynsym()) { In<ELFT>::DynSymTab->addSymbol(Body); if (auto *SS = dyn_cast<SharedSymbol>(Body)) if (cast<SharedFile<ELFT>>(SS->File)->isNeeded()) In<ELFT>::VerNeed->addSymbol(SS); } } // Do not proceed if there was an undefined symbol. if (ErrorCount) return; // So far we have added sections from input object files. // This function adds linker-created Out::* sections. addPredefinedSections(); removeUnusedSyntheticSections(OutputSections); sortSections(); // This is a bit of a hack. A value of 0 means undef, so we set it // to 1 t make __ehdr_start defined. The section number is not // particularly relevant. Out::ElfHeader->SectionIndex = 1; unsigned I = 1; for (OutputSection *Sec : OutputSections) { Sec->SectionIndex = I++; Sec->ShName = In<ELFT>::ShStrTab->addString(Sec->Name); } // Binary and relocatable output does not have PHDRS. // The headers have to be created before finalize as that can influence the // image base and the dynamic section on mips includes the image base. if (!Config->Relocatable && !Config->OFormatBinary) { Phdrs = Script->hasPhdrsCommands() ? Script->createPhdrs() : createPhdrs(); addPtArmExid(Phdrs); fixHeaders(); } // Dynamic section must be the last one in this list and dynamic // symbol table section (DynSymTab) must be the first one. applySynthetic({In<ELFT>::DynSymTab, In<ELFT>::Bss, In<ELFT>::BssRelRo, In<ELFT>::GnuHashTab, In<ELFT>::HashTab, In<ELFT>::SymTab, In<ELFT>::ShStrTab, In<ELFT>::StrTab, In<ELFT>::VerDef, In<ELFT>::DynStrTab, In<ELFT>::GdbIndex, In<ELFT>::Got, In<ELFT>::MipsGot, In<ELFT>::IgotPlt, In<ELFT>::GotPlt, In<ELFT>::RelaDyn, In<ELFT>::RelaIplt, In<ELFT>::RelaPlt, In<ELFT>::Plt, In<ELFT>::Iplt, In<ELFT>::Plt, In<ELFT>::EhFrameHdr, In<ELFT>::VerSym, In<ELFT>::VerNeed, In<ELFT>::Dynamic}, [](SyntheticSection *SS) { SS->finalizeContents(); }); // Some architectures use small displacements for jump instructions. // It is linker's responsibility to create thunks containing long // jump instructions if jump targets are too far. Create thunks. if (Target->NeedsThunks) { // FIXME: only ARM Interworking and Mips LA25 Thunks are implemented, // these // do not require address information. To support range extension Thunks // we need to assign addresses so that we can tell if jump instructions // are out of range. This will need to turn into a loop that converges // when no more Thunks are added ThunkCreator<ELFT> TC; if (TC.createThunks(OutputSections)) applySynthetic({In<ELFT>::MipsGot}, [](SyntheticSection *SS) { SS->updateAllocSize(); }); } // Fill other section headers. The dynamic table is finalized // at the end because some tags like RELSZ depend on result // of finalizing other sections. for (OutputSection *Sec : OutputSections) Sec->finalize<ELFT>(); // If -compressed-debug-sections is specified, we need to compress // .debug_* sections. Do it right now because it changes the size of // output sections. parallelForEach(OutputSections.begin(), OutputSections.end(), [](OutputSection *S) { S->maybeCompress<ELFT>(); }); // createThunks may have added local symbols to the static symbol table applySynthetic({In<ELFT>::SymTab, In<ELFT>::ShStrTab, In<ELFT>::StrTab}, [](SyntheticSection *SS) { SS->postThunkContents(); }); } template <class ELFT> void Writer<ELFT>::addPredefinedSections() { // ARM ABI requires .ARM.exidx to be terminated by some piece of data. // We have the terminater synthetic section class. Add that at the end. auto *OS = dyn_cast_or_null<OutputSection>(findSection(".ARM.exidx")); if (OS && !OS->Sections.empty() && !Config->Relocatable) OS->addSection(make<ARMExidxSentinelSection>()); } // The linker is expected to define SECNAME_start and SECNAME_end // symbols for a few sections. This function defines them. template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { auto Define = [&](StringRef Start, StringRef End, OutputSection *OS) { // These symbols resolve to the image base if the section does not exist. // A special value -1 indicates end of the section. if (OS) { addOptionalRegular<ELFT>(Start, OS, 0); addOptionalRegular<ELFT>(End, OS, -1); } else { if (Config->Pic) OS = Out::ElfHeader; addOptionalRegular<ELFT>(Start, OS, 0); addOptionalRegular<ELFT>(End, OS, 0); } }; Define("__preinit_array_start", "__preinit_array_end", Out::PreinitArray); Define("__init_array_start", "__init_array_end", Out::InitArray); Define("__fini_array_start", "__fini_array_end", Out::FiniArray); if (OutputSection *Sec = findSection(".ARM.exidx")) Define("__exidx_start", "__exidx_end", Sec); } // If a section name is valid as a C identifier (which is rare because of // the leading '.'), linkers are expected to define __start_<secname> and // __stop_<secname> symbols. They are at beginning and end of the section, // respectively. This is not requested by the ELF standard, but GNU ld and // gold provide the feature, and used by many programs. template <class ELFT> void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) { StringRef S = Sec->Name; if (!isValidCIdentifier(S)) return; addOptionalRegular<ELFT>(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT); addOptionalRegular<ELFT>(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT); } template <class ELFT> OutputSection *Writer<ELFT>::findSection(StringRef Name) { for (OutputSection *Sec : OutputSections) if (Sec->Name == Name) return Sec; return nullptr; } static bool needsPtLoad(OutputSection *Sec) { if (!(Sec->Flags & SHF_ALLOC)) return false; // Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is // responsible for allocating space for them, not the PT_LOAD that // contains the TLS initialization image. if (Sec->Flags & SHF_TLS && Sec->Type == SHT_NOBITS) return false; return true; } // Linker scripts are responsible for aligning addresses. Unfortunately, most // linker scripts are designed for creating two PT_LOADs only, one RX and one // RW. This means that there is no alignment in the RO to RX transition and we // cannot create a PT_LOAD there. static uint64_t computeFlags(uint64_t Flags) { if (Config->Omagic) return PF_R | PF_W | PF_X; if (Config->SingleRoRx && !(Flags & PF_W)) return Flags | PF_X; return Flags; } // Decide which program headers to create and which sections to include in each // one. template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() { std::vector<PhdrEntry> Ret; auto AddHdr = [&](unsigned Type, unsigned Flags) -> PhdrEntry * { Ret.emplace_back(Type, Flags); return &Ret.back(); }; // The first phdr entry is PT_PHDR which describes the program header itself. AddHdr(PT_PHDR, PF_R)->add(Out::ProgramHeaders); // PT_INTERP must be the second entry if exists. if (OutputSection *Sec = findSection(".interp")) AddHdr(PT_INTERP, Sec->getPhdrFlags())->add(Sec); // Add the first PT_LOAD segment for regular output sections. uint64_t Flags = computeFlags(PF_R); PhdrEntry *Load = AddHdr(PT_LOAD, Flags); for (OutputSection *Sec : OutputSections) { if (!(Sec->Flags & SHF_ALLOC)) break; if (!needsPtLoad(Sec)) continue; // Segments are contiguous memory regions that has the same attributes // (e.g. executable or writable). There is one phdr for each segment. // Therefore, we need to create a new phdr when the next section has // different flags or is loaded at a discontiguous address using AT linker // script command. uint64_t NewFlags = computeFlags(Sec->getPhdrFlags()); if (Script->hasLMA(Sec->Name) || Flags != NewFlags) { Load = AddHdr(PT_LOAD, NewFlags); Flags = NewFlags; } Load->add(Sec); } // Add a TLS segment if any. PhdrEntry TlsHdr(PT_TLS, PF_R); for (OutputSection *Sec : OutputSections) if (Sec->Flags & SHF_TLS) TlsHdr.add(Sec); if (TlsHdr.First) Ret.push_back(std::move(TlsHdr)); // Add an entry for .dynamic. if (In<ELFT>::DynSymTab) AddHdr(PT_DYNAMIC, In<ELFT>::Dynamic->OutSec->getPhdrFlags()) ->add(In<ELFT>::Dynamic->OutSec); // PT_GNU_RELRO includes all sections that should be marked as // read-only by dynamic linker after proccessing relocations. PhdrEntry RelRo(PT_GNU_RELRO, PF_R); for (OutputSection *Sec : OutputSections) if (needsPtLoad(Sec) && isRelroSection<ELFT>(Sec)) RelRo.add(Sec); if (RelRo.First) Ret.push_back(std::move(RelRo)); // PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr. if (!In<ELFT>::EhFrame->empty() && In<ELFT>::EhFrameHdr && In<ELFT>::EhFrame->OutSec && In<ELFT>::EhFrameHdr->OutSec) AddHdr(PT_GNU_EH_FRAME, In<ELFT>::EhFrameHdr->OutSec->getPhdrFlags()) ->add(In<ELFT>::EhFrameHdr->OutSec); // PT_OPENBSD_RANDOMIZE is an OpenBSD-specific feature. That makes // the dynamic linker fill the segment with random data. if (OutputSection *Sec = findSection(".openbsd.randomdata")) AddHdr(PT_OPENBSD_RANDOMIZE, Sec->getPhdrFlags())->add(Sec); // PT_GNU_STACK is a special section to tell the loader to make the // pages for the stack non-executable. If you really want an executable // stack, you can pass -z execstack, but that's not recommended for // security reasons. unsigned Perm; if (Config->ZExecstack) Perm = PF_R | PF_W | PF_X; else Perm = PF_R | PF_W; AddHdr(PT_GNU_STACK, Perm)->p_memsz = Config->ZStackSize; // PT_OPENBSD_WXNEEDED is a OpenBSD-specific header to mark the executable // is expected to perform W^X violations, such as calling mprotect(2) or // mmap(2) with PROT_WRITE | PROT_EXEC, which is prohibited by default on // OpenBSD. if (Config->ZWxneeded) AddHdr(PT_OPENBSD_WXNEEDED, PF_X); // Create one PT_NOTE per a group of contiguous .note sections. PhdrEntry *Note = nullptr; for (OutputSection *Sec : OutputSections) { if (Sec->Type == SHT_NOTE) { if (!Note || Script->hasLMA(Sec->Name)) Note = AddHdr(PT_NOTE, PF_R); Note->add(Sec); } else { Note = nullptr; } } return Ret; } template <class ELFT> void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry> &Phdrs) { if (Config->EMachine != EM_ARM) return; auto I = std::find_if( OutputSections.begin(), OutputSections.end(), [](OutputSection *Sec) { return Sec->Type == SHT_ARM_EXIDX; }); if (I == OutputSections.end()) return; // PT_ARM_EXIDX is the ARM EHABI equivalent of PT_GNU_EH_FRAME PhdrEntry ARMExidx(PT_ARM_EXIDX, PF_R); ARMExidx.add(*I); Phdrs.push_back(ARMExidx); } // The first section of each PT_LOAD, the first section in PT_GNU_RELRO and the // first section after PT_GNU_RELRO have to be page aligned so that the dynamic // linker can set the permissions. template <class ELFT> void Writer<ELFT>::fixSectionAlignments() { for (const PhdrEntry &P : Phdrs) if (P.p_type == PT_LOAD && P.First) P.First->PageAlign = true; for (const PhdrEntry &P : Phdrs) { if (P.p_type != PT_GNU_RELRO) continue; if (P.First) P.First->PageAlign = true; // Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we // have to align it to a page. auto End = OutputSections.end(); auto I = std::find(OutputSections.begin(), End, P.Last); if (I == End || (I + 1) == End) continue; OutputSection *Sec = *(I + 1); if (needsPtLoad(Sec)) Sec->PageAlign = true; } } bool elf::allocateHeaders(std::vector<PhdrEntry> &Phdrs, ArrayRef<OutputSection *> OutputSections, uint64_t Min) { auto FirstPTLoad = std::find_if(Phdrs.begin(), Phdrs.end(), [](const PhdrEntry &E) { return E.p_type == PT_LOAD; }); if (FirstPTLoad == Phdrs.end()) return false; uint64_t HeaderSize = getHeaderSize(); if (HeaderSize > Min) { auto PhdrI = std::find_if(Phdrs.begin(), Phdrs.end(), [](const PhdrEntry &E) { return E.p_type == PT_PHDR; }); if (PhdrI != Phdrs.end()) Phdrs.erase(PhdrI); return false; } Min = alignDown(Min - HeaderSize, Config->MaxPageSize); if (!Script->Opt.HasSections) Config->ImageBase = Min = std::min(Min, Config->ImageBase); Out::ElfHeader->Addr = Min; Out::ProgramHeaders->Addr = Min + Out::ElfHeader->Size; if (Script->hasPhdrsCommands()) return true; if (FirstPTLoad->First) for (OutputSection *Sec : OutputSections) if (Sec->FirstInPtLoad == FirstPTLoad->First) Sec->FirstInPtLoad = Out::ElfHeader; FirstPTLoad->First = Out::ElfHeader; if (!FirstPTLoad->Last) FirstPTLoad->Last = Out::ProgramHeaders; return true; } // We should set file offsets and VAs for elf header and program headers // sections. These are special, we do not include them into output sections // list, but have them to simplify the code. template <class ELFT> void Writer<ELFT>::fixHeaders() { Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size(); // If the script has SECTIONS, assignAddresses will compute the values. if (Script->Opt.HasSections) return; // When -T<section> option is specified, lower the base to make room for those // sections. uint64_t Min = -1; if (!Config->SectionStartMap.empty()) for (const auto &P : Config->SectionStartMap) Min = std::min(Min, P.second); AllocateHeader = allocateHeaders(Phdrs, OutputSections, Min); } // Adjusts the file alignment for a given output section and returns // its new file offset. The file offset must be the same with its // virtual address (modulo the page size) so that the loader can load // executables without any address adjustment. static uint64_t getFileAlignment(uint64_t Off, OutputSection *Sec) { OutputSection *First = Sec->FirstInPtLoad; // If the section is not in a PT_LOAD, we just have to align it. if (!First) return alignTo(Off, Sec->Alignment); // The first section in a PT_LOAD has to have congruent offset and address // module the page size. if (Sec == First) return alignTo(Off, Config->MaxPageSize, Sec->Addr); // If two sections share the same PT_LOAD the file offset is calculated // using this formula: Off2 = Off1 + (VA2 - VA1). return First->Offset + Sec->Addr - First->Addr; } static uint64_t setOffset(OutputSection *Sec, uint64_t Off) { if (Sec->Type == SHT_NOBITS) { Sec->Offset = Off; return Off; } Off = getFileAlignment(Off, Sec); Sec->Offset = Off; return Off + Sec->Size; } template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() { uint64_t Off = 0; for (OutputSection *Sec : OutputSections) if (Sec->Flags & SHF_ALLOC) Off = setOffset(Sec, Off); FileSize = alignTo(Off, Config->Wordsize); } // Assign file offsets to output sections. template <class ELFT> void Writer<ELFT>::assignFileOffsets() { uint64_t Off = 0; Off = setOffset(Out::ElfHeader, Off); Off = setOffset(Out::ProgramHeaders, Off); for (OutputSection *Sec : OutputSections) Off = setOffset(Sec, Off); SectionHeaderOff = alignTo(Off, Config->Wordsize); FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr); } // Finalize the program headers. We call this function after we assign // file offsets and VAs to all sections. template <class ELFT> void Writer<ELFT>::setPhdrs() { for (PhdrEntry &P : Phdrs) { OutputSection *First = P.First; OutputSection *Last = P.Last; if (First) { P.p_filesz = Last->Offset - First->Offset; if (Last->Type != SHT_NOBITS) P.p_filesz += Last->Size; P.p_memsz = Last->Addr + Last->Size - First->Addr; P.p_offset = First->Offset; P.p_vaddr = First->Addr; if (!P.HasLMA) P.p_paddr = First->getLMA(); } if (P.p_type == PT_LOAD) P.p_align = Config->MaxPageSize; else if (P.p_type == PT_GNU_RELRO) { P.p_align = 1; // The glibc dynamic loader rounds the size down, so we need to round up // to protect the last page. This is a no-op on FreeBSD which always // rounds up. P.p_memsz = alignTo(P.p_memsz, Target->PageSize); } // The TLS pointer goes after PT_TLS. At least glibc will align it, // so round up the size to make sure the offsets are correct. if (P.p_type == PT_TLS) { Out::TlsPhdr = &P; if (P.p_memsz) P.p_memsz = alignTo(P.p_memsz, P.p_align); } } } // The entry point address is chosen in the following ways. // // 1. the '-e' entry command-line option; // 2. the ENTRY(symbol) command in a linker control script; // 3. the value of the symbol start, if present; // 4. the address of the first byte of the .text section, if present; // 5. the address 0. template <class ELFT> uint64_t Writer<ELFT>::getEntryAddr() { // Case 1, 2 or 3. As a special case, if the symbol is actually // a number, we'll use that number as an address. if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Entry)) return B->getVA(); uint64_t Addr; if (!Config->Entry.getAsInteger(0, Addr)) return Addr; // Case 4 if (OutputSection *Sec = findSection(".text")) { if (Config->WarnMissingEntry) warn("cannot find entry symbol " + Config->Entry + "; defaulting to 0x" + utohexstr(Sec->Addr)); return Sec->Addr; } // Case 5 if (Config->WarnMissingEntry) warn("cannot find entry symbol " + Config->Entry + "; not setting start address"); return 0; } static uint16_t getELFType() { if (Config->Pic) return ET_DYN; if (Config->Relocatable) return ET_REL; return ET_EXEC; } // This function is called after we have assigned address and size // to each section. This function fixes some predefined // symbol values that depend on section address and size. template <class ELFT> void Writer<ELFT>::fixPredefinedSymbols() { auto Set = [](DefinedRegular *S1, DefinedRegular *S2, OutputSection *Sec, uint64_t Value) { if (S1) { S1->Section = Sec; S1->Value = Value; } if (S2) { S2->Section = Sec; S2->Value = Value; } }; // _etext is the first location after the last read-only loadable segment. // _edata is the first location after the last read-write loadable segment. // _end is the first location after the uninitialized data region. PhdrEntry *Last = nullptr; PhdrEntry *LastRO = nullptr; PhdrEntry *LastRW = nullptr; for (PhdrEntry &P : Phdrs) { if (P.p_type != PT_LOAD) continue; Last = &P; if (P.p_flags & PF_W) LastRW = &P; else LastRO = &P; } if (Last) Set(ElfSym::End1, ElfSym::End2, Last->First, Last->p_memsz); if (LastRO) Set(ElfSym::Etext1, ElfSym::Etext2, LastRO->First, LastRO->p_filesz); if (LastRW) Set(ElfSym::Edata1, ElfSym::Edata2, LastRW->First, LastRW->p_filesz); if (ElfSym::Bss) ElfSym::Bss->Section = findSection(".bss"); // Setup MIPS _gp_disp/__gnu_local_gp symbols which should // be equal to the _gp symbol's value. if (Config->EMachine == EM_MIPS) { if (!ElfSym::MipsGp->Value) { // Find GP-relative section with the lowest address // and use this address to calculate default _gp value. uint64_t Gp = -1; for (const OutputSection *OS : OutputSections) if ((OS->Flags & SHF_MIPS_GPREL) && OS->Addr < Gp) Gp = OS->Addr; if (Gp != (uint64_t)-1) ElfSym::MipsGp->Value = Gp + 0x7ff0; } } } template <class ELFT> void Writer<ELFT>::writeHeader() { uint8_t *Buf = Buffer->getBufferStart(); memcpy(Buf, "\177ELF", 4); // Write the ELF header. auto *EHdr = reinterpret_cast<Elf_Ehdr *>(Buf); EHdr->e_ident[EI_CLASS] = Config->Is64 ? ELFCLASS64 : ELFCLASS32; EHdr->e_ident[EI_DATA] = Config->IsLE ? ELFDATA2LSB : ELFDATA2MSB; EHdr->e_ident[EI_VERSION] = EV_CURRENT; EHdr->e_ident[EI_OSABI] = Config->OSABI; EHdr->e_type = getELFType(); EHdr->e_machine = Config->EMachine; EHdr->e_version = EV_CURRENT; EHdr->e_entry = getEntryAddr(); EHdr->e_shoff = SectionHeaderOff; EHdr->e_ehsize = sizeof(Elf_Ehdr); EHdr->e_phnum = Phdrs.size(); EHdr->e_shentsize = sizeof(Elf_Shdr); EHdr->e_shnum = OutputSections.size() + 1; EHdr->e_shstrndx = In<ELFT>::ShStrTab->OutSec->SectionIndex; if (Config->EMachine == EM_ARM) // We don't currently use any features incompatible with EF_ARM_EABI_VER5, // but we don't have any firm guarantees of conformance. Linux AArch64 // kernels (as of 2016) require an EABI version to be set. EHdr->e_flags = EF_ARM_EABI_VER5; else if (Config->EMachine == EM_MIPS) EHdr->e_flags = getMipsEFlags<ELFT>(); if (!Config->Relocatable) { EHdr->e_phoff = sizeof(Elf_Ehdr); EHdr->e_phentsize = sizeof(Elf_Phdr); } // Write the program header table. auto *HBuf = reinterpret_cast<Elf_Phdr *>(Buf + EHdr->e_phoff); for (PhdrEntry &P : Phdrs) { HBuf->p_type = P.p_type; HBuf->p_flags = P.p_flags; HBuf->p_offset = P.p_offset; HBuf->p_vaddr = P.p_vaddr; HBuf->p_paddr = P.p_paddr; HBuf->p_filesz = P.p_filesz; HBuf->p_memsz = P.p_memsz; HBuf->p_align = P.p_align; ++HBuf; } // Write the section header table. Note that the first table entry is null. auto *SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff); for (OutputSection *Sec : OutputSections) Sec->writeHeaderTo<ELFT>(++SHdrs); } // Open a result file. template <class ELFT> void Writer<ELFT>::openFile() { if (!Config->Is64 && FileSize > UINT32_MAX) { error("output file too large: " + Twine(FileSize) + " bytes"); return; } unlinkAsync(Config->OutputFile); ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr = FileOutputBuffer::create(Config->OutputFile, FileSize, FileOutputBuffer::F_executable); if (auto EC = BufferOrErr.getError()) error("failed to open " + Config->OutputFile + ": " + EC.message()); else Buffer = std::move(*BufferOrErr); } template <class ELFT> void Writer<ELFT>::writeSectionsBinary() { uint8_t *Buf = Buffer->getBufferStart(); for (OutputSection *Sec : OutputSections) if (Sec->Flags & SHF_ALLOC) Sec->writeTo<ELFT>(Buf + Sec->Offset); } // Write section contents to a mmap'ed file. template <class ELFT> void Writer<ELFT>::writeSections() { uint8_t *Buf = Buffer->getBufferStart(); // PPC64 needs to process relocations in the .opd section // before processing relocations in code-containing sections. Out::Opd = findSection(".opd"); if (Out::Opd) { Out::OpdBuf = Buf + Out::Opd->Offset; Out::Opd->template writeTo<ELFT>(Buf + Out::Opd->Offset); } OutputSection *EhFrameHdr = In<ELFT>::EhFrameHdr ? In<ELFT>::EhFrameHdr->OutSec : nullptr; // In -r or -emit-relocs mode, write the relocation sections first as in // ELf_Rel targets we might find out that we need to modify the relocated // section while doing it. for (OutputSection *Sec : OutputSections) if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA) Sec->writeTo<ELFT>(Buf + Sec->Offset); for (OutputSection *Sec : OutputSections) if (Sec != Out::Opd && Sec != EhFrameHdr && Sec->Type != SHT_REL && Sec->Type != SHT_RELA) Sec->writeTo<ELFT>(Buf + Sec->Offset); // The .eh_frame_hdr depends on .eh_frame section contents, therefore // it should be written after .eh_frame is written. if (EhFrameHdr && !EhFrameHdr->Sections.empty()) EhFrameHdr->writeTo<ELFT>(Buf + EhFrameHdr->Offset); } template <class ELFT> void Writer<ELFT>::writeBuildId() { if (!In<ELFT>::BuildId || !In<ELFT>::BuildId->OutSec) return; // Compute a hash of all sections of the output file. uint8_t *Start = Buffer->getBufferStart(); uint8_t *End = Start + FileSize; In<ELFT>::BuildId->writeBuildId({Start, End}); } template void elf::writeResult<ELF32LE>(); template void elf::writeResult<ELF32BE>(); template void elf::writeResult<ELF64LE>(); template void elf::writeResult<ELF64BE>(); template bool elf::isRelroSection<ELF32LE>(const OutputSection *); template bool elf::isRelroSection<ELF32BE>(const OutputSection *); template bool elf::isRelroSection<ELF64LE>(const OutputSection *); template bool elf::isRelroSection<ELF64BE>(const OutputSection *); Index: vendor/lld/dist/docs/index.rst =================================================================== --- vendor/lld/dist/docs/index.rst (revision 317689) +++ vendor/lld/dist/docs/index.rst (revision 317690) @@ -1,179 +1,179 @@ LLD - The LLVM Linker ===================== LLD is a linker from the LLVM project. That is a drop-in replacement for system linkers and runs much faster than them. It also provides features that are useful for toolchain developers. The linker supports ELF (Unix), PE/COFF (Windows) and Mach-O (macOS) in descending order of completeness. Internally, LLD consists of three different linkers. The ELF port is the one that will be described in this document. The PE/COFF port is almost complete except the lack of the Windows debug info (PDB) support. The Mach-O port is built based on a different architecture than the ELF or COFF ports. For the details about Mach-O, please read :doc:`AtomLLD`. Features -------- - LLD is a drop-in replacement for the GNU linkers. That accepts the same command line arguments and linker scripts as GNU. We are currently working closely with the FreeBSD project to make LLD default system linker in future versions of the operating system, so we are serious about addressing compatibility issues. As of February 2017, LLD is able to link the entire FreeBSD/amd64 base system including the kernel. With a few work-in-progress patches it can link approximately 95% of the ports collection on AMD64. For the details, see `FreeBSD quarterly status report <https://www.freebsd.org/news/status/report-2016-10-2016-12.html#Using-LLVM%27s-LLD-Linker-as-FreeBSD%27s-System-Linker>`_. - LLD is very fast. When you link a large program on a multicore machine, you can expect that LLD runs more than twice as fast as GNU gold linker. Your milage may vary, though. - It supports various CPUs/ABIs including x86-64, x86, x32, AArch64, ARM, MIPS 32/64 big/little-endian, PowerPC, PowerPC 64 and AMDGPU. Among these, x86-64 is the most well-supported target and have reached production quality. AArch64 and MIPS seem decent too. x86 should be OK but not well tested yet. ARM support is being developed actively. - It is always a cross-linker, meaning that it always supports all the above targets however it was built. In fact, we don't provide a build-time option to enable/disable each target. This should make it easy to use our linker as part of a cross-compile toolchain. - You can embed LLD to your program to eliminate dependency to external linkers. All you have to do is to construct object files and command line arguments just like you would do to invoke an external linker and then call the linker's main function, ``lld::elf::link``, from your code. - It is small. We are using LLVM libObject library to read from object files, so it is not completely a fair comparison, but as of February 2017, LLD/ELF consists only of 21k lines of C++ code while GNU gold consists of 198k lines of C++ code. - Link-time optimization (LTO) is supported by default. Essentially, all you have to do to do LTO is to pass the ``-flto`` option to clang. Then clang creates object files not in the native object file format but in LLVM bitcode format. LLD reads bitcode object files, compile them using LLVM and emit an output file. Because in this way LLD can see the entire program, it can do the whole program optimization. - Some very old features for ancient Unix systems (pre-90s or even before that) have been removed. Some default settings have been tuned for the 21st century. For example, the stack is marked as non-executable by default to tighten security. Performance ----------- This is a link time comparison on a 2-socket 20-core 40-thread Xeon E5-2680 2.80 GHz machine with an SSD drive. LLD is much faster than the GNU linkers for large programs. That's fast for small programs too, but because the link time is short anyway, the difference is not very noticeable in that case. Note that this is just a benchmark result of our environment. Depending on number of available cores, available amount of memory or disk latency/throughput, your results may vary. ============ =========== ============ ============= ====== Program Output size GNU ld GNU gold [1]_ LLD ffmpeg dbg 91 MiB 1.59s 1.15s 0.78s mysqld dbg 157 MiB 7.09s 2.49s 1.31s clang dbg 1.45 GiB 86.76s 21.93s 8.38s chromium dbg 1.52 GiB 142.30s [2]_ 40.86s 12.69s ============ =========== ============ ============= ====== .. [1] With the ``--threads`` option to enable multi-threading support. .. [2] Since GNU ld doesn't support the ``-icf=all`` option, we removed that from the command line for GNU ld. GNU ld would be slower than this if it had that option support. For gold and LLD, we use ``-icf=all``. Build ----- If you have already checked out LLVM using SVN, you can check out LLD under ``tools`` directory just like you probably did for clang. For the details, see `Getting Started with the LLVM System <http://llvm.org/docs/GettingStarted.html>`_. If you haven't checkout out LLVM, the easiest way to build LLD is to checkout the entire LLVM projects/sub-projects from a git mirror and build that tree. You need `cmake` and of course a C++ compiler. .. code-block:: console $ git clone https://github.com/llvm-project/llvm-project/ $ mkdir build $ cd build $ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS=lld -DCMAKE_INSTALL_PREFIX=/usr/local ../llvm-project/llvm $ make install Using LLD --------- LLD is installed as ``ld.lld``. On Unix, linkers are invoked by compiler drivers, so you are not expected to use that command directly. There are a few ways to tell compiler drivers to use ld.lld instead of the default linker. The easiest way to do that is to overwrite the default linker. After installing LLD to somewhere on your disk, you can create a symbolic link by doing ``ln -s /path/to/ld.lld /usr/bin/ld`` so that ``/usr/bin/ld`` is resolved to LLD. If you don't want to change the system setting, you can use clang's ``-fuse-ld`` option. In this way, you want to set ``-fuse-ld=lld`` to LDFLAGS when building your programs. LLD leaves its name and version number to a ``.comment`` section in an output. If you are in doubt whether you are successfully using LLD or -not, run ``objdump -s -j .comment <output-file>`` and examine the +not, run ``readelf --string-dump .comment <output-file>`` and examine the output. If the string "Linker: LLD" is included in the output, you are using LLD. History ------- Here is a brief project history of the ELF and COFF ports. - May 2015: We decided to rewrite the COFF linker and did that. Noticed that the new linker is much faster than the MSVC linker. - July 2015: The new ELF port was developed based on the COFF linker architecture. - September 2015: The first patches to support MIPS and AArch64 landed. - October 2015: Succeeded to self-host the ELF port. We have noticed that the linker was faster than the GNU linkers, but we weren't sure at the time if we would be able to keep the gap as we would add more features to the linker. - July 2016: Started working on improving the linker script support. - December 2016: Succeeded to build the entire FreeBSD base system including the kernel. We had widen the performance gap against the GNU linkers. Internals --------- For the internals of the linker, please read :doc:`NewLLD`. It is a bit outdated but the fundamental concepts remain valid. We'll update the document soon. .. toctree:: :maxdepth: 1 NewLLD AtomLLD windows_support ReleaseNotes Index: vendor/lld/dist/test/COFF/Inputs/constant-import.s =================================================================== --- vendor/lld/dist/test/COFF/Inputs/constant-import.s (nonexistent) +++ vendor/lld/dist/test/COFF/Inputs/constant-import.s (revision 317690) @@ -0,0 +1,21 @@ + + .def __DllMainCRTStartup@12 + .type 32 + .scl 2 + .endef + .global __DllMainCRTStartup@12 +__DllMainCRTStartup@12: + ret + + .data + .def _Data + .type 0 + .scl 2 + .endef + .global _Data +_Data: + .long ___CFConstantStringClassReference + + .section .drectve + .ascii " -export:_Data" + Property changes on: vendor/lld/dist/test/COFF/Inputs/constant-import.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/COFF/constant.test =================================================================== --- vendor/lld/dist/test/COFF/constant.test (nonexistent) +++ vendor/lld/dist/test/COFF/constant.test (revision 317690) @@ -0,0 +1,5 @@ +RUN: mkdir -p %t +RUN: llvm-mc -triple i686-unknown-windows-msvc -filetype obj -o %t/import.o %S/Inputs/constant-import.s +RUN: llc -mtriple i686-unknown-windows-msvc -filetype obj -o %t/export.o %S/Inputs/constant-export.ll +RUN: lld-link -machine:x86 -dll -out:%t/export.dll %t/export.o -entry:__CFConstantStringClassReference +RUN: lld-link -machine:x86 -dll -out:%t/import.dll %t/import.o %t/export.lib Index: vendor/lld/dist/test/COFF/icf-data.test =================================================================== --- vendor/lld/dist/test/COFF/icf-data.test (nonexistent) +++ vendor/lld/dist/test/COFF/icf-data.test (revision 317690) @@ -0,0 +1,61 @@ +# RUN: yaml2obj < %s > %t.obj +# RUN: lld-link /entry:foo /out:%t.exe /subsystem:console /include:bar \ +# RUN: /verbose %t.obj > %t.log 2>&1 +# RUN: FileCheck %s < %t.log + +# CHECK-NOT: Removed foo +# CHECK-NOT: Removed bar + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [] +sections: + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 4883EC28E8000000004883C428C3 + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 4883EC28E8000000004883C428C3 +symbols: + - Name: '.text$mn' + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 14 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 1682752513 + Number: 0 + Selection: IMAGE_COMDAT_SELECT_NODUPLICATES + - Name: '.text$mn' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 14 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 1682752513 + Number: 0 + Selection: IMAGE_COMDAT_SELECT_NODUPLICATES + - Name: foo + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: bar + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... Index: vendor/lld/dist/test/COFF/lldmap.test =================================================================== --- vendor/lld/dist/test/COFF/lldmap.test (revision 317689) +++ vendor/lld/dist/test/COFF/lldmap.test (revision 317690) @@ -1,11 +1,10 @@ # RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj # RUN: lld-link /out:%t.exe /entry:main /lldmap:%T/foo.map %t.obj -# RUN: FileCheck %s < %T/foo.map +# RUN: FileCheck -strict-whitespace %s < %T/foo.map # RUN: lld-link /out:%T/bar.exe /entry:main /lldmap %t.obj -# RUN: FileCheck %s < %T/bar.map +# RUN: FileCheck -strict-whitespace %s < %T/bar.map -# CHECK: Address Size Align Out In File Symbol +# CHECK: Address Size Align Out In Symbol # CHECK-NEXT: 00001000 00000006 4096 .text -# CHECK-NEXT: 00001000 00000006 16 .text$mn -# CHECK-NEXT: 00001000 00000006 16 {{.*}}lldmap.test.tmp.obj -# CHECK-NEXT: 00001000 00000006 0 main +# CHECK-NEXT: 00001000 00000006 16 {{.*}}lldmap.test.tmp.obj:(.text$mn) +# CHECK-NEXT: 00001000 00000000 0 main Index: vendor/lld/dist/test/ELF/Inputs/eh-frame-end.s =================================================================== --- vendor/lld/dist/test/ELF/Inputs/eh-frame-end.s (nonexistent) +++ vendor/lld/dist/test/ELF/Inputs/eh-frame-end.s (revision 317690) @@ -0,0 +1,2 @@ + .section ".eh_frame", "a", @progbits + .long 0 Property changes on: vendor/lld/dist/test/ELF/Inputs/eh-frame-end.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/abs-conflict.s =================================================================== --- vendor/lld/dist/test/ELF/abs-conflict.s (revision 317689) +++ vendor/lld/dist/test/ELF/abs-conflict.s (revision 317690) @@ -1,18 +1,18 @@ // REQUIRES: x86 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o // RUN: ld.lld %t.o %t.o -o %t.so -shared // RUN: llvm-readobj --dyn-symbols %t.so | FileCheck %s // CHECK: Name: foo // CHECK-NEXT: Value: 0x123 .global foo foo = 0x123 // RUN: echo ".global foo; foo = 0x124" > %t2.s // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t2.s -o %t2.o // RUN: not ld.lld %t.o %t2.o -o %t.so -shared 2>&1 | FileCheck --check-prefix=DUP %s // DUP: duplicate symbol: foo // DUP-NEXT: >>> defined in {{.*}}.o -// DUP-NEXT: >>> defined in (internal) +// DUP-NEXT: >>> defined in <internal> Index: vendor/lld/dist/test/ELF/debug-gnu-pubnames.s =================================================================== --- vendor/lld/dist/test/ELF/debug-gnu-pubnames.s (nonexistent) +++ vendor/lld/dist/test/ELF/debug-gnu-pubnames.s (revision 317690) @@ -0,0 +1,10 @@ +# REQUIRES: x86 +# RUN: ld.lld -e main %p/Inputs/gdb-index-a.elf %p/Inputs/gdb-index-b.elf -o %t1.exe +# RUN: llvm-readobj -sections %t1.exe | FileCheck -check-prefix=CHECK1 %s +# CHECK1: Name: .debug_gnu_pubnames +# CHECK1: Name: .debug_gnu_pubtypes + +# RUN: ld.lld -gdb-index -e main %p/Inputs/gdb-index-a.elf %p/Inputs/gdb-index-b.elf -o %t2.exe +# RUN: llvm-readobj -sections %t2.exe | FileCheck -check-prefix=CHECK2 %s +# CHECK2-NOT: Name: .debug_gnu_pubnames +# CHECK2-NOT: Name: .debug_gnu_pubtypes Property changes on: vendor/lld/dist/test/ELF/debug-gnu-pubnames.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/driver-access.test =================================================================== --- vendor/lld/dist/test/ELF/driver-access.test (revision 317689) +++ vendor/lld/dist/test/ELF/driver-access.test (revision 317690) @@ -1,14 +1,15 @@ # REQUIRES: x86, shell # Make sure that LLD works even if the current directory is not writable. # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o # RUN: ld.lld %t.o -o %t.exe # RUN: mkdir -p %t.dir # RUN: chmod 100 %t.dir # RUN: cd %t.dir # RUN: ld.lld %t.o -o %t.exe +# RUN: chmod 755 %t.dir .globl _start _start: nop Index: vendor/lld/dist/test/ELF/eh-frame-begin-end.s =================================================================== --- vendor/lld/dist/test/ELF/eh-frame-begin-end.s (nonexistent) +++ vendor/lld/dist/test/ELF/eh-frame-begin-end.s (revision 317690) @@ -0,0 +1,17 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=amd64-unknown-openbsd %s -o %t.o +// RUN: llvm-mc -filetype=obj -triple=amd64-unknown-openbsd %p/Inputs/eh-frame-end.s -o %t2.o +// RUN: ld.lld %t.o %t2.o -o %t +// RUN: llvm-readobj -sections %t | FileCheck %s + +// CHECK: Name: .eh_frame +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_ALLOC +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x200120 +// CHECK-NEXT: Offset: 0x120 +// CHECK-NEXT: Size: 4 + + .section ".eh_frame", "a", @progbits +__EH_FRAME_BEGIN__: Property changes on: vendor/lld/dist/test/ELF/eh-frame-begin-end.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/gdb-index.s =================================================================== --- vendor/lld/dist/test/ELF/gdb-index.s (revision 317689) +++ vendor/lld/dist/test/ELF/gdb-index.s (revision 317690) @@ -1,49 +1,49 @@ ## gdb-index-a.elf and gdb-index-b.elf are a test.o and test2.o renamed, ## were generated in this way: ## test.cpp: ## int main() { return 0; } ## test2.cpp: ## int main2() { return 0; } ## Compiled with: ## gcc -gsplit-dwarf -c test.cpp test2.cpp ## gcc version 5.3.1 20160413 ## Info about gdb-index: https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html # REQUIRES: x86 # RUN: ld.lld --gdb-index -e main %p/Inputs/gdb-index-a.elf %p/Inputs/gdb-index-b.elf -o %t # RUN: llvm-dwarfdump -debug-dump=gdb_index %t | FileCheck %s # RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=DISASM # DISASM: Disassembly of section .text: # DISASM: main: # DISASM-CHECK: 11000: 55 pushq %rbp # DISASM-CHECK: 11001: 48 89 e5 movq %rsp, %rbp # DISASM-CHECK: 11004: b8 00 00 00 00 movl $0, %eax # DISASM-CHECK: 11009: 5d popq %rbp # DISASM-CHECK: 1100a: c3 retq # DISASM: _Z5main2v: # DISASM-CHECK: 1100b: 55 pushq %rbp # DISASM-CHECK: 1100c: 48 89 e5 movq %rsp, %rbp # DISASM-CHECK: 1100f: b8 00 00 00 00 movl $0, %eax # DISASM-CHECK: 11014: 5d popq %rbp # DISASM-CHECK: 11015: c3 retq # CHECK: .gnu_index contents: # CHECK-NEXT: Version = 7 # CHECK: CU list offset = 0x18, has 2 entries: # CHECK-NEXT: 0: Offset = 0x0, Length = 0x34 # CHECK-NEXT: 1: Offset = 0x34, Length = 0x34 # CHECK: Address area offset = 0x38, has 2 entries: -# CHECK-NEXT: Low address = 0x201000, High address = 0x20100b, CU index = 0 -# CHECK-NEXT: Low address = 0x20100b, High address = 0x201016, CU index = 1 +# CHECK-NEXT: Low/High address = [0x201000, 0x20100b) (Size: 0xb), CU id = 0 +# CHECK-NEXT: Low/High address = [0x20100b, 0x201016) (Size: 0xb), CU id = 1 # CHECK: Symbol table offset = 0x60, size = 1024, filled slots: # CHECK-NEXT: 489: Name offset = 0x1d, CU vector offset = 0x0 # CHECK-NEXT: String name: main, CU vector index: 0 # CHECK-NEXT: 754: Name offset = 0x22, CU vector offset = 0x8 # CHECK-NEXT: String name: int, CU vector index: 1 # CHECK-NEXT: 956: Name offset = 0x26, CU vector offset = 0x14 # CHECK-NEXT: String name: main2, CU vector index: 2 # CHECK: Constant pool offset = 0x2060, has 3 CU vectors: # CHECK-NEXT: 0(0x0): 0x30000000 # CHECK-NEXT: 1(0x8): 0x90000000 0x90000001 # CHECK-NEXT: 2(0x14): 0x30000001 Index: vendor/lld/dist/test/ELF/linkerscript/section-metadata.s =================================================================== --- vendor/lld/dist/test/ELF/linkerscript/section-metadata.s (nonexistent) +++ vendor/lld/dist/test/ELF/linkerscript/section-metadata.s (revision 317690) @@ -0,0 +1,33 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o + +# RUN: echo "SECTIONS { .text : { *(.text.bar) *(.text.foo) } }" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o +# RUN: llvm-objdump -s %t | FileCheck %s + +# RUN: echo "SECTIONS { .text : { *(.text.foo) *(.text.bar) } }" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o +# RUN: llvm-objdump -s %t | FileCheck --check-prefix=INV %s + + +# CHECK: Contents of section .text: +# CHECK-NEXT: 02000000 00000000 01000000 00000000 +# CHECK: Contents of section .rodata: +# CHECK-NEXT: 02000000 00000000 01000000 00000000 + +# INV: Contents of section .text: +# INV-NEXT: 01000000 00000000 02000000 00000000 +# INV: Contents of section .rodata: +# INV-NEXT: 01000000 00000000 02000000 00000000 + +.global _start +_start: + +.section .text.bar,"a",@progbits +.quad 2 +.section .text.foo,"a",@progbits +.quad 1 +.section .rodata.foo,"ao",@progbits,.text.foo +.quad 1 +.section .rodata.bar,"ao",@progbits,.text.bar +.quad 2 Property changes on: vendor/lld/dist/test/ELF/linkerscript/section-metadata.s ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lld/dist/test/ELF/linkerscript/sections.s =================================================================== --- vendor/lld/dist/test/ELF/linkerscript/sections.s (revision 317689) +++ vendor/lld/dist/test/ELF/linkerscript/sections.s (revision 317690) @@ -1,112 +1,113 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t # Empty SECTIONS command. # RUN: echo "SECTIONS {}" > %t.script # RUN: ld.lld -o %t1 --script %t.script %t # RUN: llvm-objdump -section-headers %t1 | \ # RUN: FileCheck -check-prefix=SEC-DEFAULT %s # SECTIONS command with the same order as default. # RUN: echo "SECTIONS { \ # RUN: .text : { *(.text) } \ # RUN: .data : { *(.data) } }" > %t.script # RUN: ld.lld -o %t2 --script %t.script %t # RUN: llvm-objdump -section-headers %t2 | \ # RUN: FileCheck -check-prefix=SEC-DEFAULT %s # Idx Name Size # SEC-DEFAULT: 1 .text 0000000e {{[0-9a-f]*}} TEXT DATA # SEC-DEFAULT: 2 .data 00000020 {{[0-9a-f]*}} DATA # SEC-DEFAULT: 3 other 00000003 {{[0-9a-f]*}} DATA # SEC-DEFAULT: 4 .bss 00000002 {{[0-9a-f]*}} BSS # SEC-DEFAULT: 5 .comment 00000008 {{[0-9a-f]*}} # SEC-DEFAULT: 6 .symtab 00000030 {{[0-9a-f]*}} # SEC-DEFAULT: 7 .shstrtab 0000003b {{[0-9a-f]*}} # SEC-DEFAULT: 8 .strtab 00000008 {{[0-9a-f]*}} # Sections are put in order specified in linker script, other than alloc # sections going first. # RUN: echo "SECTIONS { \ # RUN: .bss : { *(.bss) } \ # RUN: other : { *(other) } \ # RUN: .shstrtab : { *(.shstrtab) } \ # RUN: .symtab : { *(.symtab) } \ # RUN: .strtab : { *(.strtab) } \ # RUN: .data : { *(.data) } \ # RUN: .text : { *(.text) } }" > %t.script # RUN: ld.lld -o %t3 --script %t.script %t # RUN: llvm-objdump -section-headers %t3 | \ # RUN: FileCheck -check-prefix=SEC-ORDER %s # Idx Name Size # SEC-ORDER: 1 .bss 00000002 {{[0-9a-f]*}} BSS # SEC-ORDER: 2 other 00000003 {{[0-9a-f]*}} DATA # SEC-ORDER: 3 .shstrtab 0000003b {{[0-9a-f]*}} # SEC-ORDER: 4 .symtab 00000030 {{[0-9a-f]*}} # SEC-ORDER: 5 .strtab 00000008 {{[0-9a-f]*}} # SEC-ORDER: 6 .data 00000020 {{[0-9a-f]*}} DATA # SEC-ORDER: 7 .text 0000000e {{[0-9a-f]*}} TEXT DATA # .text and .data have swapped names but proper sizes and types. # RUN: echo "SECTIONS { \ # RUN: .data : { *(.text) } \ # RUN: .text : { *(.data) } }" > %t.script # RUN: ld.lld -o %t4 --script %t.script %t # RUN: llvm-objdump -section-headers %t4 | \ # RUN: FileCheck -check-prefix=SEC-SWAP-NAMES %s # Idx Name Size # SEC-SWAP-NAMES: 1 .data 0000000e {{[0-9a-f]*}} TEXT DATA # SEC-SWAP-NAMES: 2 .text 00000020 {{[0-9a-f]*}} DATA # SEC-SWAP-NAMES: 3 other 00000003 {{[0-9a-f]*}} DATA # SEC-SWAP-NAMES: 4 .bss 00000002 {{[0-9a-f]*}} BSS # SEC-SWAP-NAMES: 5 .comment 00000008 {{[0-9a-f]*}} # SEC-SWAP-NAMES: 6 .symtab 00000030 {{[0-9a-f]*}} # SEC-SWAP-NAMES: 7 .shstrtab 0000003b {{[0-9a-f]*}} # SEC-SWAP-NAMES: 8 .strtab 00000008 {{[0-9a-f]*}} # Attemp to discard .shstrtab section. # RUN: echo "SECTIONS { /DISCARD/ : { *(.shstrtab) } }" > %t.script # RUN: not ld.lld -o %t5 --script %t.script %t 2>&1 | \ # RUN: FileCheck -check-prefix=SEC-DISCARD %s # SEC-DISCARD: discarding .shstrtab section is not allowed # Multiple SECTIONS command specifying additional input section descriptions # for the same output section description - input sections are merged into # one output section. # RUN: echo "SECTIONS { \ # RUN: .text : { *(.text) } \ # RUN: .data : { *(.data) } } \ # RUN: SECTIONS { \ # RUN: .data : { *(other) } }" > %t.script # RUN: ld.lld -o %t6 --script %t.script %t # RUN: llvm-objdump -section-headers %t6 | \ # RUN: FileCheck -check-prefix=SEC-MULTI %s # Idx Name Size # SEC-MULTI: 1 .text 0000000e {{[0-9a-f]*}} TEXT DATA -# SEC-MULTI-NEXT: .data 00000023 {{[0-9a-f]*}} DATA +# SEC-MULTI-NEXT: .data 00000020 {{[0-9a-f]*}} DATA +# SEC-MULTI-NEXT: .data 00000003 {{[0-9a-f]*}} DATA # SEC-MULTI-NEXT: .bss 00000002 {{[0-9a-f]*}} BSS # SEC-MULTI-NEXT: .comment 00000008 {{[0-9a-f]*}} # SEC-MULTI-NEXT: .symtab 00000030 {{[0-9a-f]*}} # SEC-MULTI-NEXT: .shstrtab 00000035 {{[0-9a-f]*}} # SEC-MULTI-NEXT: .strtab 00000008 {{[0-9a-f]*}} # Input section pattern contains additional semicolon. # Case found in linux kernel script. Check we are able to parse it. # RUN: echo "SECTIONS { .text : { ;;*(.text);;S = 0;; } }" > %t.script # RUN: ld.lld -o /dev/null --script %t.script %t .globl _start _start: mov $60, %rax mov $42, %rdi .section .data,"aw" .quad 10, 10, 20, 20 .section other,"aw" .short 10 .byte 20 .section .bss,"",@nobits .short 0 Index: vendor/lld/dist/test/ELF/map-file.s =================================================================== --- vendor/lld/dist/test/ELF/map-file.s (revision 317689) +++ vendor/lld/dist/test/ELF/map-file.s (revision 317690) @@ -1,62 +1,59 @@ // REQUIRES: x86 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/map-file2.s -o %t2.o // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/map-file3.s -o %t3.o // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/map-file4.s -o %t4.o // RUN: rm -f %t4.a // RUN: llvm-ar rc %t4.a %t4.o -// RUN: ld.lld %t1.o %t2.o %t3.o %t4.a -o %t -M | FileCheck %s -// RUN: ld.lld %t1.o %t2.o %t3.o %t4.a -o %t -print-map | FileCheck %s +// RUN: ld.lld %t1.o %t2.o %t3.o %t4.a -o %t -M | FileCheck -strict-whitespace %s +// RUN: ld.lld %t1.o %t2.o %t3.o %t4.a -o %t -print-map | FileCheck -strict-whitespace %s // RUN: ld.lld %t1.o %t2.o %t3.o %t4.a -o %t -Map=%t.map -// RUN: FileCheck %s < %t.map +// RUN: FileCheck -strict-whitespace %s < %t.map .global _start _start: call baz .global _Z1fi _Z1fi: .cfi_startproc .cfi_endproc nop .weak bar bar: .long bar - . .long zed - . local: .comm common,4,16 -// CHECK: Address Size Align Out In File Symbol +// CHECK: Address Size Align Out In Symbol // CHECK-NEXT: 0000000000200158 0000000000000030 8 .eh_frame -// CHECK-NEXT: 0000000000200158 0000000000000030 8 .eh_frame +// CHECK-NEXT: 0000000000200158 0000000000000030 8 <internal>:(.eh_frame) // CHECK-NEXT: 0000000000201000 0000000000000015 4 .text -// CHECK-NEXT: 0000000000201000 000000000000000e 4 .text -// CHECK-NEXT: 0000000000201000 000000000000000e 4 {{.*}}{{/|\\}}map-file.s.tmp1.o -// CHECK-NEXT: 000000000020100e 0000000000000000 0 local -// CHECK-NEXT: 0000000000201005 0000000000000000 0 f(int) -// CHECK-NEXT: 0000000000201000 0000000000000000 0 _start -// CHECK-NEXT: 0000000000201010 0000000000000002 4 {{.*}}{{/|\\}}map-file.s.tmp2.o -// CHECK-NEXT: 0000000000201010 0000000000000000 0 foo -// CHECK-NEXT: 0000000000201011 0000000000000000 0 bar -// CHECK-NEXT: 0000000000201012 0000000000000000 1 .text.zed -// CHECK-NEXT: 0000000000201012 0000000000000000 1 {{.*}}{{/|\\}}map-file.s.tmp2.o -// CHECK-NEXT: 0000000000201012 0000000000000000 0 zed -// CHECK-NEXT: 0000000000201014 0000000000000000 4 .text -// CHECK-NEXT: 0000000000201014 0000000000000000 4 {{.*}}{{/|\\}}map-file.s.tmp3.o -// CHECK-NEXT: 0000000000201014 0000000000000000 0 bah -// CHECK-NEXT: 0000000000201014 0000000000000001 4 {{.*}}{{/|\\}}map-file.s.tmp4.a(map-file.s.tmp4.o) -// CHECK-NEXT: 0000000000201014 0000000000000000 0 baz +// CHECK-NEXT: 0000000000201000 000000000000000e 4 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.text) +// CHECK-NEXT: 0000000000201000 0000000000000000 0 _start +// CHECK-NEXT: 0000000000201005 0000000000000000 0 f(int) +// CHECK-NEXT: 000000000020100e 0000000000000000 0 local +// CHECK-NEXT: 0000000000201010 0000000000000002 4 {{.*}}{{/|\\}}map-file.s.tmp2.o:(.text) +// CHECK-NEXT: 0000000000201010 0000000000000000 0 foo +// CHECK-NEXT: 0000000000201011 0000000000000000 0 bar +// CHECK-NEXT: 0000000000201012 0000000000000000 1 {{.*}}{{/|\\}}map-file.s.tmp2.o:(.text.zed) +// CHECK-NEXT: 0000000000201012 0000000000000000 0 zed +// CHECK-NEXT: 0000000000201014 0000000000000000 4 {{.*}}{{/|\\}}map-file.s.tmp3.o:(.text) +// CHECK-NEXT: 0000000000201014 0000000000000000 0 bah +// CHECK-NEXT: 0000000000201014 0000000000000001 4 {{.*}}{{/|\\}}map-file.s.tmp4.a(map-file.s.tmp4.o):(.text) +// CHECK-NEXT: 0000000000201014 0000000000000000 0 baz // CHECK-NEXT: 0000000000202000 0000000000000004 16 .bss -// CHECK-NEXT: 0000000000202000 0000000000000004 16 COMMON +// CHECK-NEXT: 0000000000202000 0000000000000004 16 <internal>:(COMMON) // CHECK-NEXT: 0000000000000000 0000000000000008 1 .comment -// CHECK-NEXT: 0000000000000000 0000000000000008 1 .comment +// CHECK-NEXT: 0000000000000000 0000000000000008 1 <internal>:(.comment) // CHECK-NEXT: 0000000000000000 00000000000000f0 8 .symtab -// CHECK-NEXT: 0000000000000000 00000000000000f0 8 .symtab +// CHECK-NEXT: 0000000000000000 00000000000000f0 8 <internal>:(.symtab) // CHECK-NEXT: 0000000000000000 0000000000000039 1 .shstrtab -// CHECK-NEXT: 0000000000000000 0000000000000039 1 .shstrtab +// CHECK-NEXT: 0000000000000000 0000000000000039 1 <internal>:(.shstrtab) // CHECK-NEXT: 0000000000000000 000000000000002f 1 .strtab -// CHECK-NEXT: 0000000000000000 000000000000002f 1 .strtab +// CHECK-NEXT: 0000000000000000 000000000000002f 1 <internal>:(.strtab) // RUN: not ld.lld %t1.o %t2.o %t3.o %t4.a -o %t -Map=/ 2>&1 \ // RUN: | FileCheck -check-prefix=FAIL %s // FAIL: cannot open map file / Index: vendor/lld/dist/test/ELF/relocation-in-merge.s =================================================================== --- vendor/lld/dist/test/ELF/relocation-in-merge.s (revision 317689) +++ vendor/lld/dist/test/ELF/relocation-in-merge.s (revision 317690) @@ -1,7 +1,12 @@ // REQUIRES: x86 // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux -// RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s -// CHECK: relocations pointing to SHF_MERGE are not supported +// RUN: ld.lld %t.o -o %t -shared +// RUN: llvm-objdump -section-headers %t | FileCheck %s - .section .foo,"aM",@progbits,4 - .long bar +// Test that we accept this by just not merging the section. +// CHECK: .foo 00000008 + +bar: + .section .foo,"aM",@progbits,8 + .long bar - . + .long bar - .