diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-01-06 20:07:13 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-01-06 20:07:13 +0000 |
commit | fba2c04f31e119eacf142fcbbaabd5a9e63a39ed (patch) | |
tree | 59eba88ea527759edb2c98d294ae369f95f57e33 | |
parent | 5a5c549fe9a3fef595297bd21d36bed8409dc37d (diff) |
Vendor import of lld trunk r256945:vendor/lld/lld-trunk-r256945
Notes
Notes:
svn path=/vendor/lld/dist/; revision=293258
svn path=/vendor/lld/lld-trunk-r256945/; revision=293259; tag=vendor/lld/lld-trunk-r256945
33 files changed, 446 insertions, 344 deletions
diff --git a/ELF/Config.h b/ELF/Config.h index 7b820f18b8c7..c279b99b43c1 100644 --- a/ELF/Config.h +++ b/ELF/Config.h @@ -30,6 +30,10 @@ enum ELFKind { ELF64BEKind }; +// 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 { SymbolBody *EntrySym = nullptr; SymbolBody *MipsGpDisp = nullptr; @@ -76,6 +80,7 @@ struct Configuration { unsigned Optimize = 0; }; +// The only instance of Configuration struct. extern Configuration *Config; } // namespace elf2 diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp index 6d881373b303..2a3ecfa61586 100644 --- a/ELF/Driver.cpp +++ b/ELF/Driver.cpp @@ -57,6 +57,24 @@ static std::pair<ELFKind, uint16_t> parseEmulation(StringRef S) { error("Unknown emulation: " + S); } +// Returns slices of MB by parsing MB as an archive file. +// Each slice consists of a member file in the archive. +static std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef MB) { + ErrorOr<std::unique_ptr<Archive>> FileOrErr = Archive::create(MB); + error(FileOrErr, "Failed to parse archive"); + std::unique_ptr<Archive> File = std::move(*FileOrErr); + + std::vector<MemoryBufferRef> V; + for (const ErrorOr<Archive::Child> &C : File->children()) { + error(C, "Could not get the child of the archive " + File->getFileName()); + ErrorOr<MemoryBufferRef> MbOrErr = C->getMemoryBufferRef(); + error(MbOrErr, "Could not get the buffer for a child of the archive " + + File->getFileName()); + V.push_back(*MbOrErr); + } + 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) { @@ -75,19 +93,17 @@ void LinkerDriver::addFile(StringRef Path) { return; case file_magic::archive: if (WholeArchive) { - auto File = make_unique<ArchiveFile>(MBRef); - for (MemoryBufferRef &MB : File->getMembers()) - Files.push_back(createELFFile<ObjectFile>(MB)); - OwningArchives.emplace_back(std::move(File)); + for (MemoryBufferRef MB : getArchiveMembers(MBRef)) + Files.push_back(createObjectFile(MB)); return; } Files.push_back(make_unique<ArchiveFile>(MBRef)); return; case file_magic::elf_shared_object: - Files.push_back(createELFFile<SharedFile>(MBRef)); + Files.push_back(createSharedFile(MBRef)); return; default: - Files.push_back(createELFFile<ObjectFile>(MBRef)); + Files.push_back(createObjectFile(MBRef)); } } diff --git a/ELF/Driver.h b/ELF/Driver.h index 2641155104dc..bfae2b3f4dfa 100644 --- a/ELF/Driver.h +++ b/ELF/Driver.h @@ -38,7 +38,6 @@ private: llvm::BumpPtrAllocator Alloc; bool WholeArchive = false; std::vector<std::unique_ptr<InputFile>> Files; - std::vector<std::unique_ptr<ArchiveFile>> OwningArchives; std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs; }; diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp index e0827a3ee43d..d9df6abbf233 100644 --- a/ELF/InputFiles.cpp +++ b/ELF/InputFiles.cpp @@ -37,10 +37,9 @@ ELFFileBase<ELFT>::ELFFileBase(Kind K, MemoryBufferRef M) template <class ELFT> ELFKind ELFFileBase<ELFT>::getELFKind() { - using llvm::support::little; - if (ELFT::Is64Bits) - return ELFT::TargetEndianness == little ? ELF64LEKind : ELF64BEKind; - return ELFT::TargetEndianness == little ? ELF32LEKind : ELF32BEKind; + if (ELFT::TargetEndianness == support::little) + return ELFT::Is64Bits ? ELF64LEKind : ELF32LEKind; + return ELFT::Is64Bits ? ELF64BEKind : ELF32BEKind; } template <class ELFT> @@ -63,8 +62,7 @@ template <class ELFT> uint32_t ELFFileBase<ELFT>::getSectionIndex(const Elf_Sym &Sym) const { uint32_t I = Sym.st_shndx; if (I == ELF::SHN_XINDEX) - return this->ELFObj.getExtendedSymbolTableIndex(&Sym, this->Symtab, - SymtabSHNDX); + return ELFObj.getExtendedSymbolTableIndex(&Sym, Symtab, SymtabSHNDX); if (I >= ELF::SHN_LORESERVE || I == ELF::SHN_ABS) return 0; return I; @@ -74,7 +72,7 @@ template <class ELFT> void ELFFileBase<ELFT>::initStringTable() { if (!Symtab) return; ErrorOr<StringRef> StringTableOrErr = ELFObj.getStringTableForSymtab(*Symtab); - error(StringTableOrErr.getError()); + error(StringTableOrErr); StringTable = *StringTableOrErr; } @@ -108,9 +106,9 @@ ObjectFile<ELFT>::getLocalSymbol(uintX_t SymIndex) { } template <class ELFT> -void elf2::ObjectFile<ELFT>::parse(DenseSet<StringRef> &Comdats) { +void ObjectFile<ELFT>::parse(DenseSet<StringRef> &ComdatGroups) { // Read section and symbol tables. - initializeSections(Comdats); + initializeSections(ComdatGroups); initializeSymbols(); } @@ -139,7 +137,7 @@ ObjectFile<ELFT>::getShtGroupEntries(const Elf_Shdr &Sec) { const ELFFile<ELFT> &Obj = this->ELFObj; ErrorOr<ArrayRef<GroupEntryType>> EntriesOrErr = Obj.template getSectionContentsAsArray<GroupEntryType>(&Sec); - error(EntriesOrErr.getError()); + error(EntriesOrErr); ArrayRef<GroupEntryType> Entries = *EntriesOrErr; if (Entries.empty() || Entries[0] != GRP_COMDAT) error("Unsupported SHT_GROUP format"); @@ -174,7 +172,7 @@ static bool shouldMerge(const typename ELFFile<ELFT>::Elf_Shdr &Sec) { } template <class ELFT> -void elf2::ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &Comdats) { +void ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &ComdatGroups) { uint64_t Size = this->ELFObj.getNumSections(); Sections.resize(Size); unsigned I = -1; @@ -187,7 +185,7 @@ void elf2::ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &Comdats) { switch (Sec.sh_type) { case SHT_GROUP: Sections[I] = &InputSection<ELFT>::Discarded; - if (Comdats.insert(getShtGroupSignature(Sec)).second) + if (ComdatGroups.insert(getShtGroupSignature(Sec)).second) continue; for (GroupEntryType E : getShtGroupEntries(Sec)) { uint32_t SecIndex = E; @@ -235,7 +233,7 @@ void elf2::ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &Comdats) { } template <class ELFT> InputSectionBase<ELFT> * -elf2::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { +ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { ErrorOr<StringRef> NameOrErr = this->ELFObj.getSectionName(&Sec); error(NameOrErr); StringRef Name = *NameOrErr; @@ -250,29 +248,29 @@ elf2::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { // A MIPS object file has a special section that contains register // usage info, which needs to be handled by the linker specially. if (Config->EMachine == EM_MIPS && Name == ".reginfo") { - MipsReginfo = new (this->Alloc) MipsReginfoInputSection<ELFT>(this, &Sec); + MipsReginfo = new (Alloc) MipsReginfoInputSection<ELFT>(this, &Sec); return MipsReginfo; } if (Name == ".eh_frame") - return new (this->EHAlloc.Allocate()) EHInputSection<ELFT>(this, &Sec); + return new (EHAlloc.Allocate()) EHInputSection<ELFT>(this, &Sec); if (shouldMerge<ELFT>(Sec)) - return new (this->MAlloc.Allocate()) MergeInputSection<ELFT>(this, &Sec); - return new (this->Alloc) InputSection<ELFT>(this, &Sec); + return new (MAlloc.Allocate()) MergeInputSection<ELFT>(this, &Sec); + return new (Alloc) InputSection<ELFT>(this, &Sec); } -template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSymbols() { +template <class ELFT> void ObjectFile<ELFT>::initializeSymbols() { this->initStringTable(); Elf_Sym_Range Syms = this->getNonLocalSymbols(); uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end()); - this->SymbolBodies.reserve(NumSymbols); + SymbolBodies.reserve(NumSymbols); for (const Elf_Sym &Sym : Syms) - this->SymbolBodies.push_back(createSymbolBody(this->StringTable, &Sym)); + SymbolBodies.push_back(createSymbolBody(this->StringTable, &Sym)); } template <class ELFT> InputSectionBase<ELFT> * -elf2::ObjectFile<ELFT>::getSection(const Elf_Sym &Sym) const { +ObjectFile<ELFT>::getSection(const Elf_Sym &Sym) const { uint32_t Index = this->getSectionIndex(Sym); if (Index == 0) return nullptr; @@ -282,19 +280,19 @@ elf2::ObjectFile<ELFT>::getSection(const Elf_Sym &Sym) const { } template <class ELFT> -SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable, +SymbolBody *ObjectFile<ELFT>::createSymbolBody(StringRef StringTable, const Elf_Sym *Sym) { ErrorOr<StringRef> NameOrErr = Sym->getName(StringTable); - error(NameOrErr.getError()); + error(NameOrErr); StringRef Name = *NameOrErr; switch (Sym->st_shndx) { case SHN_UNDEF: - return new (this->Alloc) UndefinedElf<ELFT>(Name, *Sym); + return new (Alloc) UndefinedElf<ELFT>(Name, *Sym); case SHN_COMMON: - return new (this->Alloc) DefinedCommon( - Name, Sym->st_size, Sym->st_value, - Sym->getBinding() == llvm::ELF::STB_WEAK, Sym->getVisibility()); + return new (Alloc) DefinedCommon(Name, Sym->st_size, Sym->st_value, + Sym->getBinding() == llvm::ELF::STB_WEAK, + Sym->getVisibility()); } switch (Sym->getBinding()) { @@ -305,20 +303,16 @@ SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable, case STB_GNU_UNIQUE: { InputSectionBase<ELFT> *Sec = getSection(*Sym); if (Sec == &InputSection<ELFT>::Discarded) - return new (this->Alloc) UndefinedElf<ELFT>(Name, *Sym); - return new (this->Alloc) DefinedRegular<ELFT>(Name, *Sym, Sec); + return new (Alloc) UndefinedElf<ELFT>(Name, *Sym); + return new (Alloc) DefinedRegular<ELFT>(Name, *Sym, Sec); } } } -static std::unique_ptr<Archive> openArchive(MemoryBufferRef MB) { - ErrorOr<std::unique_ptr<Archive>> ArchiveOrErr = Archive::create(MB); - error(ArchiveOrErr, "Failed to parse archive"); - return std::move(*ArchiveOrErr); -} - void ArchiveFile::parse() { - File = openArchive(MB); + ErrorOr<std::unique_ptr<Archive>> FileOrErr = Archive::create(MB); + error(FileOrErr, "Failed to parse archive"); + File = std::move(*FileOrErr); // Allocate a buffer for Lazy objects. size_t NumSyms = File->getNumberOfSymbols(); @@ -345,28 +339,9 @@ MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) { return *RefOrErr; } -std::vector<MemoryBufferRef> ArchiveFile::getMembers() { - File = openArchive(MB); - - std::vector<MemoryBufferRef> Result; - for (auto &ChildOrErr : File->children()) { - error(ChildOrErr, - "Could not get the child of the archive " + File->getFileName()); - const Archive::Child Child(*ChildOrErr); - ErrorOr<MemoryBufferRef> MbOrErr = Child.getMemoryBufferRef(); - if (!MbOrErr) - error(MbOrErr, "Could not get the buffer for a child of the archive " + - File->getFileName()); - Result.push_back(MbOrErr.get()); - } - return Result; -} - template <class ELFT> SharedFile<ELFT>::SharedFile(MemoryBufferRef M) - : ELFFileBase<ELFT>(Base::SharedKind, M) { - AsNeeded = Config->AsNeeded; -} + : ELFFileBase<ELFT>(Base::SharedKind, M), AsNeeded(Config->AsNeeded) {} template <class ELFT> const typename ELFFile<ELFT>::Elf_Shdr * @@ -379,6 +354,8 @@ SharedFile<ELFT>::getSection(const Elf_Sym &Sym) const { return *Ret; } +// Partially parse the shared object file so that we can call +// getSoName on this object. template <class ELFT> void SharedFile<ELFT>::parseSoName() { typedef typename ELFFile<ELFT>::Elf_Dyn Elf_Dyn; typedef typename ELFFile<ELFT>::uintX_t uintX_t; @@ -405,7 +382,7 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() { } this->initStringTable(); - this->SoName = this->getName(); + SoName = this->getName(); if (!DynamicSec) return; @@ -418,13 +395,14 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() { uintX_t Val = Dyn.getVal(); if (Val >= this->StringTable.size()) error("Invalid DT_SONAME entry"); - this->SoName = StringRef(this->StringTable.data() + Val); + SoName = StringRef(this->StringTable.data() + Val); return; } } } -template <class ELFT> void SharedFile<ELFT>::parse() { +// Fully parse the shared object file. This must be called after parseSoName(). +template <class ELFT> void SharedFile<ELFT>::parseRest() { Elf_Sym_Range Syms = this->getNonLocalSymbols(); uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end()); SymbolBodies.reserve(NumSymbols); @@ -456,7 +434,7 @@ static std::unique_ptr<InputFile> createELFFileAux(MemoryBufferRef MB) { } template <template <class> class T> -std::unique_ptr<InputFile> lld::elf2::createELFFile(MemoryBufferRef MB) { +static std::unique_ptr<InputFile> createELFFile(MemoryBufferRef MB) { std::pair<unsigned char, unsigned char> Type = getElfArchType(MB.getBuffer()); if (Type.second != ELF::ELFDATA2LSB && Type.second != ELF::ELFDATA2MSB) error("Invalid data encoding: " + MB.getBufferIdentifier()); @@ -474,6 +452,14 @@ std::unique_ptr<InputFile> lld::elf2::createELFFile(MemoryBufferRef MB) { error("Invalid file class: " + MB.getBufferIdentifier()); } +std::unique_ptr<InputFile> elf2::createObjectFile(MemoryBufferRef MB) { + return createELFFile<ObjectFile>(MB); +} + +std::unique_ptr<InputFile> elf2::createSharedFile(MemoryBufferRef MB) { + return createELFFile<SharedFile>(MB); +} + template class elf2::ELFFileBase<ELF32LE>; template class elf2::ELFFileBase<ELF32BE>; template class elf2::ELFFileBase<ELF64LE>; @@ -488,9 +474,3 @@ template class elf2::SharedFile<ELF32LE>; template class elf2::SharedFile<ELF32BE>; template class elf2::SharedFile<ELF64LE>; template class elf2::SharedFile<ELF64BE>; - -template std::unique_ptr<InputFile> -elf2::createELFFile<ObjectFile>(MemoryBufferRef); - -template std::unique_ptr<InputFile> -elf2::createELFFile<SharedFile>(MemoryBufferRef); diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h index 4e529c558cf5..9c54a9328f80 100644 --- a/ELF/InputFiles.h +++ b/ELF/InputFiles.h @@ -101,10 +101,10 @@ public: return F->kind() == Base::ObjectKind; } - ArrayRef<SymbolBody *> getSymbols() { return this->SymbolBodies; } + ArrayRef<SymbolBody *> getSymbols() { return SymbolBodies; } explicit ObjectFile(MemoryBufferRef M); - void parse(llvm::DenseSet<StringRef> &Comdats); + void parse(llvm::DenseSet<StringRef> &ComdatGroups); ArrayRef<InputSectionBase<ELFT> *> getSections() const { return Sections; } InputSectionBase<ELFT> *getSection(const Elf_Sym &Sym) const; @@ -113,7 +113,7 @@ public: uint32_t FirstNonLocal = this->Symtab->sh_info; if (SymbolIndex < FirstNonLocal) return nullptr; - return this->SymbolBodies[SymbolIndex - FirstNonLocal]; + return SymbolBodies[SymbolIndex - FirstNonLocal]; } Elf_Sym_Range getLocalSymbols(); @@ -127,7 +127,7 @@ public: uint32_t getMipsGp0() const; private: - void initializeSections(llvm::DenseSet<StringRef> &Comdats); + void initializeSections(llvm::DenseSet<StringRef> &ComdatGroups); void initializeSymbols(); InputSectionBase<ELFT> *createInputSection(const Elf_Shdr &Sec); @@ -159,7 +159,6 @@ public: MemoryBufferRef getMember(const Archive::Symbol *Sym); llvm::MutableArrayRef<Lazy> getLazySymbols() { return LazySymbols; } - std::vector<MemoryBufferRef> getMembers(); private: std::unique_ptr<Archive> File; @@ -194,7 +193,7 @@ public: explicit SharedFile(MemoryBufferRef M); void parseSoName(); - void parse(); + void parseRest(); // Used for --as-needed bool AsNeeded = false; @@ -202,8 +201,8 @@ public: bool isNeeded() const { return !AsNeeded || IsUsed; } }; -template <template <class> class T> -std::unique_ptr<InputFile> createELFFile(MemoryBufferRef MB); +std::unique_ptr<InputFile> createObjectFile(MemoryBufferRef MB); +std::unique_ptr<InputFile> createSharedFile(MemoryBufferRef MB); } // namespace elf2 } // namespace lld diff --git a/ELF/InputSection.h b/ELF/InputSection.h index d4dc9864ae91..24491a2e17c0 100644 --- a/ELF/InputSection.h +++ b/ELF/InputSection.h @@ -93,6 +93,10 @@ InputSectionBase<ELFT> InputSectionBase<ELFT>::Discarded(nullptr, nullptr, InputSectionBase<ELFT>::Regular); +// Usually sections are copied to the output as atomic chunks of data, +// but some special types of sections are split into small pieces of data +// and each piece is copied to a different place in the output. +// This class represents such special sections. template <class ELFT> class SplitInputSection : public InputSectionBase<ELFT> { typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr; typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t; @@ -100,7 +104,11 @@ template <class ELFT> class SplitInputSection : public InputSectionBase<ELFT> { public: SplitInputSection(ObjectFile<ELFT> *File, const Elf_Shdr *Header, typename InputSectionBase<ELFT>::Kind SectionKind); + + // For each piece of data, we maintain the offsets in the input section and + // in the output section. The latter may be -1 if it is not assigned yet. std::vector<std::pair<uintX_t, uintX_t>> Offsets; + std::pair<std::pair<uintX_t, uintX_t> *, uintX_t> getRangeAndSize(uintX_t Offset); }; diff --git a/ELF/MarkLive.cpp b/ELF/MarkLive.cpp index 1ad9b01af4e8..b719b1a09c25 100644 --- a/ELF/MarkLive.cpp +++ b/ELF/MarkLive.cpp @@ -16,7 +16,7 @@ // by default. Starting with GC-root symbols or sections, markLive function // defined in this file visits all reachable sections to set their Live // bits. Writer will then ignore sections whose Live bits are off, so that -// such sections are removed from output. +// such sections are not included into output. // //===----------------------------------------------------------------------===// @@ -37,7 +37,7 @@ using namespace llvm::object; using namespace lld; using namespace lld::elf2; -// Calls Fn for each section that Sec refers to. +// Calls Fn for each section that Sec refers to via relocations. template <class ELFT> static void forEachSuccessor(InputSection<ELFT> *Sec, std::function<void(InputSectionBase<ELFT> *)> Fn) { @@ -104,7 +104,7 @@ template <class ELFT> void lld::elf2::markLive(SymbolTable<ELFT> *Symtab) { MarkSymbol(Symtab->find(S)); // Preserve externally-visible symbols if the symbols defined by this - // file could override other ELF file's symbols at runtime. + // file can interrupt other ELF file's symbols at runtime. if (Config->Shared || Config->ExportDynamic) { for (const std::pair<StringRef, Symbol *> &P : Symtab->getSymbols()) { SymbolBody *B = P.second->Body; diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp index 8bdc2b0e5c4f..30ec83f4d3b1 100644 --- a/ELF/OutputSections.cpp +++ b/ELF/OutputSections.cpp @@ -239,14 +239,13 @@ bool RelocationSection<ELFT>::applyTlsDynamicReloc(SymbolBody *Body, } template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { - const unsigned EntrySize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); for (const DynamicReloc<ELFT> &Rel : Relocs) { auto *P = reinterpret_cast<Elf_Rel *>(Buf); - Buf += EntrySize; + Buf += IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); // Skip placeholder for global dynamic TLS relocation pair. It was already // handled by the previous relocation. - if (!Rel.C || !Rel.RI) + if (!Rel.C) continue; InputSectionBase<ELFT> &C = *Rel.C; @@ -262,16 +261,16 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { continue; bool NeedsCopy = Body && Target->needsCopyRel(Type, *Body); bool NeedsGot = Body && Target->relocNeedsGot(Type, *Body); - bool CanBePreempted = canBePreempted(Body, NeedsGot); + bool CBP = canBePreempted(Body, NeedsGot); bool LazyReloc = Body && Target->supportsLazyRelocations() && Target->relocNeedsPlt(Type, *Body); bool IsDynRelative = Type == Target->getRelativeReloc(); - unsigned Sym = CanBePreempted ? Body->DynamicSymbolTableIndex : 0; + unsigned Sym = CBP ? Body->DynamicSymbolTableIndex : 0; unsigned Reloc; - if (!CanBePreempted && Body && isGnuIFunc<ELFT>(*Body)) + if (!CBP && Body && isGnuIFunc<ELFT>(*Body)) Reloc = Target->getIRelativeReloc(); - else if (!CanBePreempted || IsDynRelative) + else if (!CBP || IsDynRelative) Reloc = Target->getRelativeReloc(); else if (LazyReloc) Reloc = Target->getPltReloc(); @@ -289,7 +288,7 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body); else if (NeedsCopy) P->r_offset = Out<ELFT>::Bss->getVA() + - dyn_cast<SharedSymbol<ELFT>>(Body)->OffsetInBSS; + cast<SharedSymbol<ELFT>>(Body)->OffsetInBss; else P->r_offset = C.getOffset(RI.r_offset) + C.OutSec->getVA(); @@ -300,7 +299,7 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { uintX_t Addend; if (NeedsCopy) Addend = 0; - else if (CanBePreempted || IsDynRelative) + else if (CBP || IsDynRelative) Addend = OrigAddend; else if (Body) Addend = getSymVA<ELFT>(*Body) + OrigAddend; @@ -640,6 +639,9 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() { if (DtFlags1) ++NumEntries; // DT_FLAGS_1 + if (!Config->Entry.empty()) + ++NumEntries; // DT_DEBUG + if (Config->EMachine == EM_MIPS) { ++NumEntries; // DT_MIPS_RLD_VERSION ++NumEntries; // DT_MIPS_FLAGS @@ -738,6 +740,8 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) { WriteVal(DT_FLAGS, DtFlags); if (DtFlags1) WriteVal(DT_FLAGS_1, DtFlags1); + if (!Config->Entry.empty()) + WriteVal(DT_DEBUG, 0); // See "Dynamic Section" in Chapter 5 in the following document // for detailed description: @@ -799,11 +803,11 @@ typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const SymbolBody &S) { return SC->OutSec->getVA() + SC->getOffset(DR.Sym); } case SymbolBody::DefinedCommonKind: - return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(S).OffsetInBSS; + return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(S).OffsetInBss; case SymbolBody::SharedKind: { auto &SS = cast<SharedSymbol<ELFT>>(S); if (SS.NeedsCopy) - return Out<ELFT>::Bss->getVA() + SS.OffsetInBSS; + return Out<ELFT>::Bss->getVA() + SS.OffsetInBss; return 0; } case SymbolBody::UndefinedElfKind: @@ -1119,9 +1123,9 @@ void MergeOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) { ArrayRef<uint8_t> D = S->getSectionData(); StringRef Data((const char *)D.data(), D.size()); uintX_t EntSize = S->getSectionHdr()->sh_entsize; - uintX_t Offset = 0; if (this->Header.sh_flags & SHF_STRINGS) { + uintX_t Offset = 0; while (!Data.empty()) { size_t End = findNull(Data, EntSize); if (End == StringRef::npos) @@ -1139,8 +1143,7 @@ void MergeOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) { for (unsigned I = 0, N = Data.size(); I != N; I += EntSize) { StringRef Entry = Data.substr(I, EntSize); size_t OutputOffset = Builder.add(Entry); - S->Offsets.push_back(std::make_pair(Offset, OutputOffset)); - Offset += EntSize; + S->Offsets.push_back(std::make_pair(I, OutputOffset)); } } } diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp index e022ecd2e90d..74951bad410f 100644 --- a/ELF/SymbolTable.cpp +++ b/ELF/SymbolTable.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // 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 +// 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. // @@ -28,6 +28,9 @@ using namespace lld::elf2; template <class ELFT> SymbolTable<ELFT>::SymbolTable() {} +// 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 void checkCompatibility(InputFile *FileP) { auto *F = dyn_cast<ELFFileBase<ELFT>>(FileP); @@ -42,6 +45,7 @@ static void checkCompatibility(InputFile *FileP) { error(A + " is incompatible with " + B); } +// Add symbols in File to the symbol table. template <class ELFT> void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) { InputFile *FileP = File.get(); @@ -64,7 +68,7 @@ void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) { return; SharedFiles.emplace_back(cast<SharedFile<ELFT>>(File.release())); - F->parse(); + F->parseRest(); for (SharedSymbol<ELFT> &B : F->getSharedSymbols()) resolve(&B); return; @@ -73,7 +77,7 @@ void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) { // .o file auto *F = cast<ObjectFile<ELFT>>(FileP); ObjectFiles.emplace_back(cast<ObjectFile<ELFT>>(File.release())); - F->parse(Comdats); + F->parse(ComdatGroups); for (SymbolBody *B : F->getSymbols()) resolve(B); } @@ -109,6 +113,9 @@ void SymbolTable<ELFT>::addSynthetic(StringRef Name, resolve(Sym); } +// Add Name as an "ignored" symbol. An ignored symbol is a regular +// linker-synthesized defined symbol, but it is not recorded to the output +// file's symbol table. Such symbols are useful for some linker-defined symbols. template <class ELFT> SymbolBody *SymbolTable<ELFT>::addIgnored(StringRef Name) { auto *Sym = new (Alloc) @@ -117,18 +124,10 @@ SymbolBody *SymbolTable<ELFT>::addIgnored(StringRef Name) { return Sym; } -template <class ELFT> bool SymbolTable<ELFT>::isUndefined(StringRef Name) { - if (SymbolBody *Sym = find(Name)) - return Sym->isUndefined(); - return false; -} - // Returns a file from which symbol B was created. -// If B does not belong to any file in ObjectFiles, returns a nullptr. +// If B does not belong to any file, returns a nullptr. template <class ELFT> -ELFFileBase<ELFT> * -elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles, - const SymbolBody *B) { +ELFFileBase<ELFT> *SymbolTable<ELFT>::findFile(SymbolBody *B) { for (const std::unique_ptr<ObjectFile<ELFT>> &F : ObjectFiles) { ArrayRef<SymbolBody *> Syms = F->getSymbols(); if (std::find(Syms.begin(), Syms.end(), B) != Syms.end()) @@ -139,8 +138,8 @@ elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles, template <class ELFT> std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Old, SymbolBody *New) { - ELFFileBase<ELFT> *OldFile = findFile<ELFT>(ObjectFiles, Old); - ELFFileBase<ELFT> *NewFile = findFile<ELFT>(ObjectFiles, New); + ELFFileBase<ELFT> *OldFile = findFile(Old); + ELFFileBase<ELFT> *NewFile = findFile(New); StringRef Sym = Old->getName(); StringRef F1 = OldFile ? OldFile->getName() : "(internal)"; @@ -173,15 +172,15 @@ template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) { // compare() returns -1, 0, or 1 if the lhs symbol is less preferable, // equivalent (conflicting), or more preferable, respectively. - int comp = Existing->compare<ELFT>(New); - if (comp == 0) { + int Comp = Existing->compare<ELFT>(New); + if (Comp == 0) { std::string S = "duplicate symbol: " + conflictMsg(Existing, New); if (!Config->AllowMultipleDefinition) error(S); warning(S); return; } - if (comp < 0) + if (Comp < 0) Sym->Body = New; } @@ -248,20 +247,7 @@ template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() { Sym->setUsedInDynamicReloc(); } -template class lld::elf2::SymbolTable<ELF32LE>; -template class lld::elf2::SymbolTable<ELF32BE>; -template class lld::elf2::SymbolTable<ELF64LE>; -template class lld::elf2::SymbolTable<ELF64BE>; - -template ELFFileBase<ELF32LE> * -lld::elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELF32LE>>>, - const SymbolBody *); -template ELFFileBase<ELF32BE> * -lld::elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELF32BE>>>, - const SymbolBody *); -template ELFFileBase<ELF64LE> * -lld::elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELF64LE>>>, - const SymbolBody *); -template ELFFileBase<ELF64BE> * -lld::elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELF64BE>>>, - const SymbolBody *); +template class elf2::SymbolTable<ELF32LE>; +template class elf2::SymbolTable<ELF32BE>; +template class elf2::SymbolTable<ELF64LE>; +template class elf2::SymbolTable<ELF64BE>; diff --git a/ELF/SymbolTable.h b/ELF/SymbolTable.h index aa905e027d48..4f8f5afa420a 100644 --- a/ELF/SymbolTable.h +++ b/ELF/SymbolTable.h @@ -55,9 +55,9 @@ public: void addSynthetic(StringRef Name, OutputSectionBase<ELFT> &Section, typename llvm::object::ELFFile<ELFT>::uintX_t Value); SymbolBody *addIgnored(StringRef Name); - bool isUndefined(StringRef Name); void scanShlibUndefined(); SymbolBody *find(StringRef Name); + ELFFileBase<ELFT> *findFile(SymbolBody *B); private: Symbol *insert(SymbolBody *New); @@ -78,7 +78,7 @@ private: llvm::MapVector<StringRef, Symbol *> Symtab; llvm::BumpPtrAllocator Alloc; - llvm::DenseSet<StringRef> Comdats; + llvm::DenseSet<StringRef> ComdatGroups; // The writer needs to infer the machine type from the object files. std::vector<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles; @@ -87,11 +87,6 @@ private: llvm::DenseSet<StringRef> IncludedSoNames; }; -template <class ELFT> -ELFFileBase<ELFT> * -findFile(ArrayRef<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles, - const SymbolBody *B); - } // namespace elf2 } // namespace lld diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp index f8d585242a86..4af1b88e79ad 100644 --- a/ELF/Symbols.cpp +++ b/ELF/Symbols.cpp @@ -115,8 +115,7 @@ std::unique_ptr<InputFile> Lazy::getMember() { // read from the library. if (MBRef.getBuffer().empty()) return std::unique_ptr<InputFile>(nullptr); - - return createELFFile<ObjectFile>(MBRef); + return createObjectFile(MBRef); } template <class ELFT> static void doInitSymbols() { diff --git a/ELF/Symbols.h b/ELF/Symbols.h index 8556452dbb13..16a3b338b3cd 100644 --- a/ELF/Symbols.h +++ b/ELF/Symbols.h @@ -173,7 +173,7 @@ public: // The output offset of this common symbol in the output bss. Computed by the // writer. - uint64_t OffsetInBSS; + uint64_t OffsetInBss; // The maximum alignment we have seen for this symbol. uint64_t MaxAlignment; @@ -262,9 +262,9 @@ public: SharedFile<ELFT> *File; // True if the linker has to generate a copy relocation for this shared - // symbol. OffsetInBSS is significant only when NeedsCopy is true. + // symbol. OffsetInBss is significant only when NeedsCopy is true. bool NeedsCopy = false; - uintX_t OffsetInBSS = 0; + uintX_t OffsetInBss = 0; }; // This class represents a symbol defined in an archive file. It is diff --git a/ELF/Target.cpp b/ELF/Target.cpp index 8d848d040c61..8d54c93570fa 100644 --- a/ELF/Target.cpp +++ b/ELF/Target.cpp @@ -320,7 +320,7 @@ void X86TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, // separate procedure linkage tables. if (Config->Shared) { const uint8_t V[] = { - 0xff, 0xb3, 0x04, 0x00, 0x00, 0x00, // pushl 4(%ebx + 0xff, 0xb3, 0x04, 0x00, 0x00, 0x00, // pushl 4(%ebx) 0xff, 0xa3, 0x08, 0x00, 0x00, 0x00, // jmp *8(%ebx) 0x90, 0x90, 0x90, 0x90 // nop;nop;nop;nop }; diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp index bdcb720a8a48..2437a435657c 100644 --- a/ELF/Writer.cpp +++ b/ELF/Writer.cpp @@ -69,7 +69,7 @@ private: } int getPhdrsNum() const; - OutputSection<ELFT> *getBSS(); + OutputSection<ELFT> *getBss(); void addCommonSymbols(std::vector<DefinedCommon *> &Syms); void addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms); @@ -330,18 +330,17 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &S, } template <class ELFT> -static void reportUndefined(const SymbolTable<ELFT> &S, const SymbolBody &Sym) { +static void reportUndefined(SymbolTable<ELFT> &Symtab, SymbolBody *Sym) { if (Config->Shared && !Config->NoUndefined) return; - ELFFileBase<ELFT> *SymFile = findFile<ELFT>(S.getObjectFiles(), &Sym); - std::string Message = "undefined symbol: " + Sym.getName().str(); - if (SymFile) - Message += " in " + SymFile->getName().str(); + std::string Msg = "undefined symbol: " + Sym->getName().str(); + if (ELFFileBase<ELFT> *File = Symtab.findFile(Sym)) + Msg += " in " + File->getName().str(); if (Config->NoInhibitExec) - warning(Message); + warning(Msg); else - error(Message); + error(Msg); } // Local symbols are not in the linker's symbol table. This function scans @@ -466,7 +465,7 @@ static bool compareOutputSections(OutputSectionBase<ELFT> *A, return false; } -template <class ELFT> OutputSection<ELFT> *Writer<ELFT>::getBSS() { +template <class ELFT> OutputSection<ELFT> *Writer<ELFT>::getBss() { if (!Out<ELFT>::Bss) { Out<ELFT>::Bss = new OutputSection<ELFT>(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); @@ -480,8 +479,6 @@ template <class ELFT> OutputSection<ELFT> *Writer<ELFT>::getBSS() { // This function adds them to end of BSS section. template <class ELFT> void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon *> &Syms) { - typedef typename ELFFile<ELFT>::uintX_t uintX_t; - if (Syms.empty()) return; @@ -491,11 +488,11 @@ void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon *> &Syms) { return A->MaxAlignment > B->MaxAlignment; }); - uintX_t Off = getBSS()->getSize(); + uintX_t Off = getBss()->getSize(); for (DefinedCommon *C : Syms) { uintX_t Align = C->MaxAlignment; Off = RoundUpToAlignment(Off, Align); - C->OffsetInBSS = Off; + C->OffsetInBss = Off; Off += C->Size; } @@ -507,7 +504,7 @@ template <class ELFT> void Writer<ELFT>::addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms) { if (Syms.empty()) return; - uintX_t Off = getBSS()->getSize(); + uintX_t Off = getBss()->getSize(); for (SharedSymbol<ELFT> *C : Syms) { const Elf_Sym &Sym = C->Sym; const Elf_Shdr *Sec = C->File->getSection(Sym); @@ -518,7 +515,7 @@ void Writer<ELFT>::addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms) { uintX_t Align = 1 << TrailingZeros; Out<ELFT>::Bss->updateAlign(Align); Off = RoundUpToAlignment(Off, Align); - C->OffsetInBSS = Off; + C->OffsetInBss = Off; Off += Sym.st_size; } Out<ELFT>::Bss->setSize(Off); @@ -803,7 +800,7 @@ template <class ELFT> void Writer<ELFT>::createSections() { SymbolBody *Body = P.second->Body; if (auto *U = dyn_cast<Undefined>(Body)) if (!U->isWeak() && !U->canKeepUndefined()) - reportUndefined<ELFT>(Symtab, *Body); + reportUndefined<ELFT>(Symtab, Body); if (auto *C = dyn_cast<DefinedCommon>(Body)) CommonSymbols.push_back(C); @@ -958,10 +955,12 @@ void Writer<ELFT>::addStartStopSymbols(OutputSectionBase<ELFT> *Sec) { StringSaver Saver(Alloc); StringRef Start = Saver.save("__start_" + S); StringRef Stop = Saver.save("__stop_" + S); - if (Symtab.isUndefined(Start)) - Symtab.addSynthetic(Start, *Sec, 0); - if (Symtab.isUndefined(Stop)) - Symtab.addSynthetic(Stop, *Sec, Sec->getSize()); + if (SymbolBody *B = Symtab.find(Start)) + if (B->isUndefined()) + Symtab.addSynthetic(Start, *Sec, 0); + if (SymbolBody *B = Symtab.find(Stop)) + if (B->isUndefined()) + Symtab.addSynthetic(Stop, *Sec, Sec->getSize()); } template <class ELFT> static bool needsPhdr(OutputSectionBase<ELFT> *Sec) { @@ -1016,7 +1015,7 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() { Elf_Phdr GnuRelroPhdr = {}; Elf_Phdr TlsPhdr{}; bool RelroAligned = false; - uintX_t ThreadBSSOffset = 0; + uintX_t ThreadBssOffset = 0; // Create phdrs as we assign VAs and file offsets to all output sections. for (OutputSectionBase<ELFT> *Sec : OutputSections) { Elf_Phdr *PH = &Phdrs[PhdrIdx]; @@ -1042,11 +1041,11 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() { setPhdr(&TlsPhdr, PT_TLS, PF_R, FileOff, VA, 0, Sec->getAlign()); if (Sec->getType() != SHT_NOBITS) VA = RoundUpToAlignment(VA, Sec->getAlign()); - uintX_t TVA = RoundUpToAlignment(VA + ThreadBSSOffset, Sec->getAlign()); + uintX_t TVA = RoundUpToAlignment(VA + ThreadBssOffset, Sec->getAlign()); Sec->setVA(TVA); TlsPhdr.p_memsz += Sec->getSize(); if (Sec->getType() == SHT_NOBITS) { - ThreadBSSOffset = TVA - VA + Sec->getSize(); + ThreadBssOffset = TVA - VA + Sec->getSize(); } else { TlsPhdr.p_filesz += Sec->getSize(); VA += Sec->getSize(); diff --git a/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp b/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp index 5e5a426b310b..0ba590cc6422 100644 --- a/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp +++ b/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp @@ -507,6 +507,23 @@ void ArchHandler_arm64::generateAtomContent( // Copy raw bytes. memcpy(atomContentBuffer, atom.rawContent().data(), atom.size()); // Apply fix-ups. +#ifndef NDEBUG + if (atom.begin() != atom.end()) { + DEBUG_WITH_TYPE("atom-content", llvm::dbgs() + << "Applying fixups to atom:\n" + << " address=" + << llvm::format(" 0x%09lX", &atom) + << ", file=#" + << atom.file().ordinal() + << ", atom=#" + << atom.ordinal() + << ", name=" + << atom.name() + << ", type=" + << atom.contentType() + << "\n"); + } +#endif for (const Reference *ref : atom) { uint32_t offset = ref->offsetInAtom(); const Atom *target = ref->target(); diff --git a/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp b/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp index c57a00359e33..8b4d1cf38cba 100644 --- a/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp +++ b/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp @@ -647,13 +647,33 @@ void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref, *loc32 = ref.addend() + inAtomAddress - fixupAddress; return; case delta32Anon: - *loc32 = (targetAddress - fixupAddress) + ref.addend(); + // The value we write here should be the the delta to the target + // after taking in to account the difference from the fixup back to the + // last defined label + // ie, if we have: + // _base: ... + // Lfixup: .quad Ltarget - . + // ... + // Ltarget: + // + // Then we want to encode the value (Ltarget + addend) - (LFixup - _base) + *loc32 = (targetAddress + ref.addend()) - (fixupAddress - inAtomAddress); return; case delta64: *loc64 = ref.addend() + inAtomAddress - fixupAddress; return; case delta64Anon: - *loc64 = (targetAddress - fixupAddress) + ref.addend(); + // The value we write here should be the the delta to the target + // after taking in to account the difference from the fixup back to the + // last defined label + // ie, if we have: + // _base: ... + // Lfixup: .quad Ltarget - . + // ... + // Ltarget: + // + // Then we want to encode the value (Ltarget + addend) - (LFixup - _base) + *loc64 = (targetAddress + ref.addend()) - (fixupAddress - inAtomAddress); return; case negDelta32: *loc32 = fixupAddress - targetAddress + ref.addend(); diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp index f80e2ac467fc..e830db9fcc7b 100644 --- a/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp +++ b/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp @@ -406,14 +406,8 @@ bool Util::TextSectionSorter::operator()(const SectionInfo *left, } void Util::organizeSections() { - if (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT) { - // Leave sections ordered as normalized file specified. - uint32_t sectionIndex = 1; - for (SectionInfo *si : _sectionInfos) { - si->finalSectionIndex = sectionIndex++; - } - } else { - switch (_ctx.outputMachOType()) { + // NOTE!: Keep this in sync with assignAddressesToSections. + switch (_ctx.outputMachOType()) { case llvm::MachO::MH_EXECUTE: // Main executables, need a zero-page segment segmentForName("__PAGEZERO"); @@ -425,32 +419,30 @@ void Util::organizeSections() { break; default: break; + } + // Group sections into segments. + for (SectionInfo *si : _sectionInfos) { + SegmentInfo *seg = segmentForName(si->segmentName); + seg->sections.push_back(si); + } + // Sort segments. + std::sort(_segmentInfos.begin(), _segmentInfos.end(), SegmentSorter()); + + // Sort sections within segments. + for (SegmentInfo *seg : _segmentInfos) { + if (seg->name.equals("__TEXT")) { + std::sort(seg->sections.begin(), seg->sections.end(), + TextSectionSorter()); } - // Group sections into segments. - for (SectionInfo *si : _sectionInfos) { - SegmentInfo *seg = segmentForName(si->segmentName); - seg->sections.push_back(si); - } - // Sort segments. - std::sort(_segmentInfos.begin(), _segmentInfos.end(), SegmentSorter()); - - // Sort sections within segments. - for (SegmentInfo *seg : _segmentInfos) { - if (seg->name.equals("__TEXT")) { - std::sort(seg->sections.begin(), seg->sections.end(), - TextSectionSorter()); - } - } + } - // Record final section indexes. - uint32_t segmentIndex = 0; - uint32_t sectionIndex = 1; - for (SegmentInfo *seg : _segmentInfos) { - seg->normalizedSegmentIndex = segmentIndex++; - for (SectionInfo *sect : seg->sections) { - sect->finalSectionIndex = sectionIndex++; - } - } + // Record final section indexes. + uint32_t segmentIndex = 0; + uint32_t sectionIndex = 1; + for (SegmentInfo *seg : _segmentInfos) { + seg->normalizedSegmentIndex = segmentIndex++; + for (SectionInfo *sect : seg->sections) + sect->finalSectionIndex = sectionIndex++; } } @@ -487,54 +479,39 @@ void Util::layoutSectionsInTextSegment(size_t hlcSize, SegmentInfo *seg, } void Util::assignAddressesToSections(const NormalizedFile &file) { + // NOTE!: Keep this in sync with organizeSections. size_t hlcSize = headerAndLoadCommandsSize(file); uint64_t address = 0; - if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT) { - for (SegmentInfo *seg : _segmentInfos) { - if (seg->name.equals("__PAGEZERO")) { - seg->size = _ctx.pageZeroSize(); - address += seg->size; - } - else if (seg->name.equals("__TEXT")) { - // _ctx.baseAddress() == 0 implies it was either unspecified or - // pageZeroSize is also 0. In either case resetting address is safe. - address = _ctx.baseAddress() ? _ctx.baseAddress() : address; - layoutSectionsInTextSegment(hlcSize, seg, address); - } else - layoutSectionsInSegment(seg, address); - - address = llvm::RoundUpToAlignment(address, _ctx.pageSize()); + for (SegmentInfo *seg : _segmentInfos) { + if (seg->name.equals("__PAGEZERO")) { + seg->size = _ctx.pageZeroSize(); + address += seg->size; } - DEBUG_WITH_TYPE("WriterMachO-norm", - llvm::dbgs() << "assignAddressesToSections()\n"; - for (SegmentInfo *sgi : _segmentInfos) { - llvm::dbgs() << " address=" << llvm::format("0x%08llX", sgi->address) - << ", size=" << llvm::format("0x%08llX", sgi->size) - << ", segment-name='" << sgi->name - << "'\n"; - for (SectionInfo *si : sgi->sections) { - llvm::dbgs()<< " addr=" << llvm::format("0x%08llX", si->address) - << ", size=" << llvm::format("0x%08llX", si->size) - << ", section-name='" << si->sectionName - << "\n"; - } + else if (seg->name.equals("__TEXT")) { + // _ctx.baseAddress() == 0 implies it was either unspecified or + // pageZeroSize is also 0. In either case resetting address is safe. + address = _ctx.baseAddress() ? _ctx.baseAddress() : address; + layoutSectionsInTextSegment(hlcSize, seg, address); + } else + layoutSectionsInSegment(seg, address); + + address = llvm::RoundUpToAlignment(address, _ctx.pageSize()); + } + DEBUG_WITH_TYPE("WriterMachO-norm", + llvm::dbgs() << "assignAddressesToSections()\n"; + for (SegmentInfo *sgi : _segmentInfos) { + llvm::dbgs() << " address=" << llvm::format("0x%08llX", sgi->address) + << ", size=" << llvm::format("0x%08llX", sgi->size) + << ", segment-name='" << sgi->name + << "'\n"; + for (SectionInfo *si : sgi->sections) { + llvm::dbgs()<< " addr=" << llvm::format("0x%08llX", si->address) + << ", size=" << llvm::format("0x%08llX", si->size) + << ", section-name='" << si->sectionName + << "\n"; } - ); - } else { - for (SectionInfo *sect : _sectionInfos) { - sect->address = llvm::RoundUpToAlignment(address, sect->alignment); - address = sect->address + sect->size; } - DEBUG_WITH_TYPE("WriterMachO-norm", - llvm::dbgs() << "assignAddressesToSections()\n"; - for (SectionInfo *si : _sectionInfos) { - llvm::dbgs() << " section=" << si->sectionName - << " address= " << llvm::format("0x%08X", si->address) - << " size= " << llvm::format("0x%08X", si->size) - << "\n"; - } - ); - } + ); } void Util::copySegmentInfo(NormalizedFile &file) { @@ -604,16 +581,9 @@ void Util::copySectionContent(NormalizedFile &file) { void Util::copySectionInfo(NormalizedFile &file) { file.sections.reserve(_sectionInfos.size()); - // For final linked images, write sections grouped by segment. - if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT) { - for (SegmentInfo *sgi : _segmentInfos) { - for (SectionInfo *si : sgi->sections) { - appendSection(si, file); - } - } - } else { - // Object files write sections in default order. - for (SectionInfo *si : _sectionInfos) { + // Write sections grouped by segment. + for (SegmentInfo *sgi : _segmentInfos) { + for (SectionInfo *si : sgi->sections) { appendSection(si, file); } } @@ -621,20 +591,12 @@ void Util::copySectionInfo(NormalizedFile &file) { void Util::updateSectionInfo(NormalizedFile &file) { file.sections.reserve(_sectionInfos.size()); - if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT) { - // For final linked images, sections grouped by segment. - for (SegmentInfo *sgi : _segmentInfos) { - Segment *normSeg = &file.segments[sgi->normalizedSegmentIndex]; - normSeg->address = sgi->address; - normSeg->size = sgi->size; - for (SectionInfo *si : sgi->sections) { - Section *normSect = &file.sections[si->normalizedSectionIndex]; - normSect->address = si->address; - } - } - } else { - // Object files write sections in default order. - for (SectionInfo *si : _sectionInfos) { + // sections grouped by segment. + for (SegmentInfo *sgi : _segmentInfos) { + Segment *normSeg = &file.segments[sgi->normalizedSegmentIndex]; + normSeg->address = sgi->address; + normSeg->size = sgi->size; + for (SectionInfo *si : sgi->sections) { Section *normSect = &file.sections[si->normalizedSectionIndex]; normSect->address = si->address; } @@ -663,19 +625,47 @@ void Util::buildAtomToAddressMap() { _entryAtom = info.atom; } DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() - << " address=" - << llvm::format("0x%016X", _atomToAddress[info.atom]) - << " atom=" << info.atom - << " name=" << info.atom->name() << "\n"); + << " address=" + << llvm::format("0x%016X", _atomToAddress[info.atom]) + << llvm::format(" 0x%09lX", info.atom) + << ", file=#" + << info.atom->file().ordinal() + << ", atom=#" + << info.atom->ordinal() + << ", name=" + << info.atom->name() + << ", type=" + << info.atom->contentType() + << "\n"); } } + DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() + << "assign header alias atom addresses:\n"); for (const Atom *atom : _machHeaderAliasAtoms) { _atomToAddress[atom] = _ctx.baseAddress(); - DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() - << " address=" - << llvm::format("0x%016X", _atomToAddress[atom]) - << " atom=" << atom - << " name=" << atom->name() << "\n"); +#ifndef NDEBUG + if (auto *definedAtom = dyn_cast<DefinedAtom>(atom)) { + DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() + << " address=" + << llvm::format("0x%016X", _atomToAddress[atom]) + << llvm::format(" 0x%09lX", atom) + << ", file=#" + << definedAtom->file().ordinal() + << ", atom=#" + << definedAtom->ordinal() + << ", name=" + << definedAtom->name() + << ", type=" + << definedAtom->contentType() + << "\n"); + } else { + DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() + << " address=" + << llvm::format("0x%016X", _atomToAddress[atom]) + << " atom=" << atom + << " name=" << atom->name() << "\n"); + } +#endif } } @@ -999,11 +989,9 @@ void Util::segIndexForSection(const SectionInfo *sect, uint8_t &segmentIndex, uint32_t Util::sectionIndexForAtom(const Atom *atom) { uint64_t address = _atomToAddress[atom]; - uint32_t index = 1; for (const SectionInfo *si : _sectionInfos) { if ((si->address <= address) && (address < si->address+si->size)) - return index; - ++index; + return si->finalSectionIndex; } llvm_unreachable("atom not in any section"); } diff --git a/test/ELF/dt_tags.s b/test/ELF/dt_tags.s new file mode 100644 index 000000000000..f2759d6ef204 --- /dev/null +++ b/test/ELF/dt_tags.s @@ -0,0 +1,18 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t +# RUN: ld.lld -shared %t -o %t.so +# RUN: ld.lld %t %t.so -o %t.exe +# RUN: llvm-readobj -dynamic-table %t.so | FileCheck -check-prefix=DSO %s +# RUN: llvm-readobj -dynamic-table %t.exe | FileCheck -check-prefix=EXE %s + +# EXE: DynamicSection [ +# EXE: 0x0000000000000015 DEBUG 0x0 +# EXE: ] + +# DSO: DynamicSection [ +# DSO-NOT: 0x0000000000000015 DEBUG 0x0 +# DSO: ] + +.globl _start +_start: diff --git a/test/ELF/dynamic-reloc.s b/test/ELF/dynamic-reloc.s index ab2a2405726b..295396006543 100644 --- a/test/ELF/dynamic-reloc.s +++ b/test/ELF/dynamic-reloc.s @@ -53,6 +53,7 @@ // CHECK-NEXT: 0x000000000000000A STRSZ // CHECK-NEXT: 0x0000000000000004 HASH // CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so) +// CHECK-NEXT: 0x0000000000000015 DEBUG 0x0 // CHECK-NEXT: 0x0000000000000000 NULL 0x0 // CHECK-NEXT: ] diff --git a/test/ELF/got.s b/test/ELF/got.s index 5fa1c2a7251f..600377ded2f7 100644 --- a/test/ELF/got.s +++ b/test/ELF/got.s @@ -12,7 +12,7 @@ // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: SHF_WRITE // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x120A0 +// CHECK-NEXT: Address: 0x120B0 // CHECK-NEXT: Offset: // CHECK-NEXT: Size: 16 // CHECK-NEXT: Link: 0 @@ -21,22 +21,22 @@ // CHECK: Relocations [ // CHECK-NEXT: Section ({{.*}}) .rela.dyn { -// CHECK-NEXT: 0x120A0 R_X86_64_GLOB_DAT bar 0x0 -// CHECK-NEXT: 0x120A8 R_X86_64_GLOB_DAT zed 0x0 +// CHECK-NEXT: 0x120B0 R_X86_64_GLOB_DAT bar 0x0 +// CHECK-NEXT: 0x120B8 R_X86_64_GLOB_DAT zed 0x0 // CHECK-NEXT: } // CHECK-NEXT: ] // Unfortunately FileCheck can't do math, so we have to check for explicit // values: -// 0x120A0 - (0x11000 + 2) - 4 = 4250 -// 0x120A0 - (0x11006 + 2) - 4 = 4244 -// 0x120A8 - (0x1100c + 2) - 4 = 4246 +// 0x120B0 - (0x11000 + 2) - 4 = 4266 +// 0x120B0 - (0x11006 + 2) - 4 = 4260 +// 0x120A8 - (0x1100c + 2) - 4 = 4262 // DISASM: _start: -// DISASM-NEXT: 11000: {{.*}} jmpq *4250(%rip) -// DISASM-NEXT: 11006: {{.*}} jmpq *4244(%rip) -// DISASM-NEXT: 1100c: {{.*}} jmpq *4246(%rip) +// DISASM-NEXT: 11000: {{.*}} jmpq *4266(%rip) +// DISASM-NEXT: 11006: {{.*}} jmpq *4260(%rip) +// DISASM-NEXT: 1100c: {{.*}} jmpq *4262(%rip) .global _start _start: diff --git a/test/ELF/local-got.s b/test/ELF/local-got.s index 015c058e2eb9..1a8fa0dfd253 100644 --- a/test/ELF/local-got.s +++ b/test/ELF/local-got.s @@ -14,11 +14,11 @@ _start: foo: nop -// 0x120A0 - 0x11000 - 5 = 4251 -// 0x120A8 - 0x11005 - 5 = 4254 +// 0x120B0 - 0x11000 - 5 = 4251 +// 0x120B8 - 0x11005 - 5 = 4254 // DISASM: _start: -// DISASM-NEXT: 11000: {{.*}} callq 4251 -// DISASM-NEXT: 11005: {{.*}} callq 4254 +// DISASM-NEXT: 11000: {{.*}} callq 4267 +// DISASM-NEXT: 11005: {{.*}} callq 4270 // DISASM: foo: // DISASM-NEXT: 1100a: {{.*}} nop @@ -29,7 +29,7 @@ foo: // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: SHF_WRITE // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x120A0 +// CHECK-NEXT: Address: 0x120B0 // CHECK-NEXT: Offset: // CHECK-NEXT: Size: 16 // CHECK-NEXT: Link: 0 @@ -43,6 +43,6 @@ foo: // CHECK: Relocations [ // CHECK-NEXT: Section ({{.*}}) .rela.dyn { -// CHECK-NEXT: 0x120A0 R_X86_64_GLOB_DAT bar 0x0 +// CHECK-NEXT: 0x120B0 R_X86_64_GLOB_DAT bar 0x0 // CHECK-NEXT: } // CHECK-NEXT: ] diff --git a/test/ELF/relocation-i686.s b/test/ELF/relocation-i686.s index f66cad20a074..529a35765f9e 100644 --- a/test/ELF/relocation-i686.s +++ b/test/ELF/relocation-i686.s @@ -55,7 +55,7 @@ movl bar@GOT, %eax // ADDR-NEXT: SHF_ALLOC // ADDR-NEXT: SHF_WRITE // ADDR-NEXT: ] -// ADDR-NEXT: Address: 0x12070 +// ADDR-NEXT: Address: 0x12078 .section .R_386_GOTPC,"ax",@progbits R_386_GOTPC: @@ -65,7 +65,7 @@ R_386_GOTPC: // CHECK: Disassembly of section .R_386_GOTPC: // CHECK-NEXT: R_386_GOTPC: -// CHECK-NEXT: 11014: {{.*}} movl $4188, %eax +// CHECK-NEXT: 11014: {{.*}} movl $4196, %eax .section .dynamic_reloc, "ax",@progbits call bar diff --git a/test/ELF/relocation.s b/test/ELF/relocation.s index a6dd1d1ef5d6..33b0e23ee972 100644 --- a/test/ELF/relocation.s +++ b/test/ELF/relocation.s @@ -22,7 +22,7 @@ // SEC-NEXT: SHF_ALLOC // SEC-NEXT: SHF_WRITE // SEC-NEXT: ] -// SEC-NEXT: Address: 0x120E0 +// SEC-NEXT: Address: 0x120F0 // SEC-NEXT: Offset: // SEC-NEXT: Size: 8 // SEC-NEXT: Link: 0 @@ -111,7 +111,7 @@ R_X86_64_64: R_X86_64_GOTPCREL: .long zed@gotpcrel -// 0x120E8 - 0x101D8 = 7952 +// 0x120F8 - 0x101D8 = 7952 // 7952 = 0x101f0000 in little endian // CHECK: Contents of section .R_X86_64_GOTPCREL -// CHECK-NEXT: 101d0 101f0000 +// CHECK-NEXT: 101d0 201f0000 diff --git a/test/ELF/relro.s b/test/ELF/relro.s index 7a225a269075..692d6b271cf8 100644 --- a/test/ELF/relro.s +++ b/test/ELF/relro.s @@ -17,8 +17,8 @@ // FULLRELRO-NEXT: SHF_ALLOC // FULLRELRO-NEXT: SHF_WRITE // FULLRELRO-NEXT: ] -// FULLRELRO-NEXT: Address: 0x12100 -// FULLRELRO-NEXT: Offset: 0x2100 +// FULLRELRO-NEXT: Address: 0x12110 +// FULLRELRO-NEXT: Offset: 0x2110 // FULLRELRO-NEXT: Size: 8 // FULLRELRO-NEXT: Link: 0 // FULLRELRO-NEXT: Info: 0 @@ -36,8 +36,8 @@ // FULLRELRO-NEXT: SHF_ALLOC // FULLRELRO-NEXT: SHF_WRITE // FULLRELRO-NEXT: ] -// FULLRELRO-NEXT: Address: 0x12108 -// FULLRELRO-NEXT: Offset: 0x2108 +// FULLRELRO-NEXT: Address: 0x12118 +// FULLRELRO-NEXT: Offset: 0x2118 // FULLRELRO-NEXT: Size: 32 // FULLRELRO-NEXT: Link: 0 // FULLRELRO-NEXT: Info: 0 @@ -103,8 +103,8 @@ // FULLRELRO-NEXT: Offset: 0x // FULLRELRO-NEXT: VirtualAddress: [[RWADDR]] // FULLRELRO-NEXT: PhysicalAddress: -// FULLRELRO-NEXT: FileSize: 296 -// FULLRELRO-NEXT: MemSize: 296 +// FULLRELRO-NEXT: FileSize: 312 +// FULLRELRO-NEXT: MemSize: 312 // FULLRELRO-NEXT: Flags [ // FULLRELRO-NEXT: PF_R // FULLRELRO-NEXT: ] @@ -119,8 +119,8 @@ // PARTRELRO-NEXT: SHF_ALLOC // PARTRELRO-NEXT: SHF_WRITE // PARTRELRO-NEXT: ] -// PARTRELRO-NEXT: Address: 0x120E0 -// PARTRELRO-NEXT: Offset: 0x20E0 +// PARTRELRO-NEXT: Address: 0x120F0 +// PARTRELRO-NEXT: Offset: 0x20F0 // PARTRELRO-NEXT: Size: 8 // PARTRELRO-NEXT: Link: 0 // PARTRELRO-NEXT: Info: 0 @@ -219,8 +219,8 @@ // PARTRELRO-NEXT: Offset: 0x2000 // PARTRELRO-NEXT: VirtualAddress: [[RWADDR]] // PARTRELRO-NEXT: PhysicalAddress: -// PARTRELRO-NEXT: FileSize: 232 -// PARTRELRO-NEXT: MemSize: 232 +// PARTRELRO-NEXT: FileSize: 248 +// PARTRELRO-NEXT: MemSize: 248 // PARTRELRO-NEXT: Flags [ // PARTRELRO-NEXT: PF_R // PARTRELRO-NEXT: ] diff --git a/test/ELF/shared-be.s b/test/ELF/shared-be.s index 1524d48b2ed6..0f57a4b7f0c3 100644 --- a/test/ELF/shared-be.s +++ b/test/ELF/shared-be.s @@ -25,6 +25,7 @@ // CHECK-NEXT: 0x0000000000000009 RELAENT [[RELENT]] (bytes) // CHECK: 0x000000000000001D RUNPATH foo:bar // CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so) +// CHECK-NEXT: 0x0000000000000015 DEBUG 0x0 // CHECK-NEXT: 0x0000000000000000 NULL 0x0 // CHECK-NEXT: ] diff --git a/test/ELF/shared.s b/test/ELF/shared.s index f76495d960af..1bf5bd1795bc 100644 --- a/test/ELF/shared.s +++ b/test/ELF/shared.s @@ -253,6 +253,7 @@ // CHECK-NEXT: 0x00000004 HASH [[HASHADDR]] // CHECK-NEXT: 0x0000001D RUNPATH foo:bar // CHECK-NEXT: 0x00000001 NEEDED SharedLibrary ({{.*}}2.so) +// CHECK-NEXT: 0x00000015 DEBUG 0x0 // CHECK-NEXT: 0x00000000 NULL 0x0 // CHECK-NEXT: ] diff --git a/test/ELF/tls-got.s b/test/ELF/tls-got.s index 10b9cf994579..aa024519a64a 100644 --- a/test/ELF/tls-got.s +++ b/test/ELF/tls-got.s @@ -14,7 +14,7 @@ // CHECK-NEXT: SHF_WRITE // CHECK-NEXT: ] // CHECK-NEXT: Address: [[ADDR:.*]] -// CHECK-NEXT: Offset: 0x20A0 +// CHECK-NEXT: Offset: 0x20B0 // CHECK-NEXT: Size: 16 // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 @@ -25,20 +25,20 @@ // CHECK: Relocations [ // CHECK-NEXT: Section (4) .rela.dyn { // CHECK-NEXT: [[ADDR]] R_X86_64_TPOFF64 tls1 0x0 -// CHECK-NEXT: 0x120A8 R_X86_64_TPOFF64 tls0 0x0 +// CHECK-NEXT: 0x120B8 R_X86_64_TPOFF64 tls0 0x0 // CHECK-NEXT: } // CHECK-NEXT: ] -//0x11000 + 4249 + 7 = 0x120A0 -//0x1100A + 4247 + 7 = 0x120A8 -//0x11014 + 4237 + 7 = 0x120A8 +//0x11000 + 4249 + 7 = 0x120B0 +//0x1100A + 4247 + 7 = 0x120B8 +//0x11014 + 4237 + 7 = 0x120B8 //DISASM: Disassembly of section .text: //DISASM-NEXT: main: -//DISASM-NEXT: 11000: 48 8b 05 99 10 00 00 movq 4249(%rip), %rax +//DISASM-NEXT: 11000: 48 8b 05 a9 10 00 00 movq 4265(%rip), %rax //DISASM-NEXT: 11007: 64 8b 00 movl %fs:(%rax), %eax -//DISASM-NEXT: 1100a: 48 8b 05 97 10 00 00 movq 4247(%rip), %rax +//DISASM-NEXT: 1100a: 48 8b 05 a7 10 00 00 movq 4263(%rip), %rax //DISASM-NEXT: 11011: 64 8b 00 movl %fs:(%rax), %eax -//DISASM-NEXT: 11014: 48 8b 05 8d 10 00 00 movq 4237(%rip), %rax +//DISASM-NEXT: 11014: 48 8b 05 9d 10 00 00 movq 4253(%rip), %rax //DISASM-NEXT: 1101b: 64 8b 00 movl %fs:(%rax), %eax //DISASM-NEXT: 1101e: c3 retq diff --git a/test/ELF/tls-opt-gdie.s b/test/ELF/tls-opt-gdie.s index a6c68686c57b..3f83157086e7 100644 --- a/test/ELF/tls-opt-gdie.s +++ b/test/ELF/tls-opt-gdie.s @@ -13,8 +13,8 @@ //RELOC-NEXT: SHF_ALLOC //RELOC-NEXT: SHF_WRITE //RELOC-NEXT: ] -//RELOC-NEXT: Address: 0x120E0 -//RELOC-NEXT: Offset: 0x20E0 +//RELOC-NEXT: Address: 0x120F0 +//RELOC-NEXT: Offset: 0x20F0 //RELOC-NEXT: Size: 16 //RELOC-NEXT: Link: 0 //RELOC-NEXT: Info: 0 @@ -23,22 +23,22 @@ //RELOC-NEXT: } //RELOC: Relocations [ //RELOC-NEXT: Section (4) .rela.dyn { -//RELOC-NEXT: 0x120E0 R_X86_64_TPOFF64 tlsshared0 0x0 -//RELOC-NEXT: 0x120E8 R_X86_64_TPOFF64 tlsshared1 0x0 +//RELOC-NEXT: 0x120F0 R_X86_64_TPOFF64 tlsshared0 0x0 +//RELOC-NEXT: 0x120F8 R_X86_64_TPOFF64 tlsshared1 0x0 //RELOC-NEXT: } //RELOC-NEXT: Section (5) .rela.plt { //RELOC-NEXT: 0x13018 R_X86_64_JUMP_SLOT __tls_get_addr 0x0 //RELOC-NEXT: } //RELOC-NEXT: ] -//0x11009 + (4304 + 7) = 0x120E0 -//0x11019 + (4296 + 7) = 0x120E8 +//0x11009 + (4304 + 7) = 0x120F0 +//0x11019 + (4296 + 7) = 0x120F8 // DISASM: Disassembly of section .text: // DISASM-NEXT: _start: // DISASM-NEXT: 11000: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax -// DISASM-NEXT: 11009: 48 03 05 d0 10 00 00 addq 4304(%rip), %rax +// DISASM-NEXT: 11009: 48 03 05 e0 10 00 00 addq 4320(%rip), %rax // DISASM-NEXT: 11010: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax -// DISASM-NEXT: 11019: 48 03 05 c8 10 00 00 addq 4296(%rip), %rax +// DISASM-NEXT: 11019: 48 03 05 d8 10 00 00 addq 4312(%rip), %rax .section .text .globl _start diff --git a/test/ELF/tls-opt-gdiele-i686.s b/test/ELF/tls-opt-gdiele-i686.s index 94630bbc0df2..1432a9607da9 100644 --- a/test/ELF/tls-opt-gdiele-i686.s +++ b/test/ELF/tls-opt-gdiele-i686.s @@ -7,8 +7,8 @@ // NORELOC: Relocations [ // NORELOC-NEXT: Section ({{.*}}) .rel.dyn { -// NORELOC-NEXT: 0x12050 R_386_TLS_TPOFF tlsshared0 0x0 -// NORELOC-NEXT: 0x12054 R_386_TLS_TPOFF tlsshared1 0x0 +// NORELOC-NEXT: 0x12058 R_386_TLS_TPOFF tlsshared0 0x0 +// NORELOC-NEXT: 0x1205C R_386_TLS_TPOFF tlsshared1 0x0 // NORELOC-NEXT: } // NORELOC-NEXT: ] diff --git a/test/ELF/tls-opt-iele-i686-nopic.s b/test/ELF/tls-opt-iele-i686-nopic.s index bc6c6bed7b44..50ade0fc76cc 100644 --- a/test/ELF/tls-opt-iele-i686-nopic.s +++ b/test/ELF/tls-opt-iele-i686-nopic.s @@ -16,8 +16,8 @@ // GOTREL-NEXT: SHF_ALLOC // GOTREL-NEXT: SHF_WRITE // GOTREL-NEXT: ] -// GOTREL-NEXT: Address: 0x12050 -// GOTREL-NEXT: Offset: 0x2050 +// GOTREL-NEXT: Address: 0x12058 +// GOTREL-NEXT: Offset: 0x2058 // GOTREL-NEXT: Size: 8 // GOTREL-NEXT: Link: 0 // GOTREL-NEXT: Info: 0 @@ -26,8 +26,8 @@ // GOTREL-NEXT: } // GOTREL: Relocations [ // GOTREL-NEXT: Section ({{.*}}) .rel.dyn { -// GOTREL-NEXT: 0x12050 R_386_TLS_TPOFF tlsshared0 0x0 -// GOTREL-NEXT: 0x12054 R_386_TLS_TPOFF tlsshared1 0x0 +// GOTREL-NEXT: 0x12058 R_386_TLS_TPOFF tlsshared0 0x0 +// GOTREL-NEXT: 0x1205C R_386_TLS_TPOFF tlsshared1 0x0 // GOTREL-NEXT: } // GOTREL-NEXT: ] @@ -35,8 +35,8 @@ // DISASM-NEXT: _start: // 4294967288 = 0xFFFFFFF8 // 4294967292 = 0xFFFFFFFC -// 73808 = (.got)[0] = 0x12050 -// 73812 = (.got)[1] = 0x12054 +// 73808 = (.got)[0] = 0x12058 +// 73812 = (.got)[1] = 0x1205C // DISASM-NEXT: 11000: c7 c1 f8 ff ff ff movl $4294967288, %ecx // DISASM-NEXT: 11006: 65 8b 01 movl %gs:(%ecx), %eax // DISASM-NEXT: 11009: b8 f8 ff ff ff movl $4294967288, %eax @@ -49,9 +49,9 @@ // DISASM-NEXT: 11028: 65 8b 00 movl %gs:(%eax), %eax // DISASM-NEXT: 1102b: 81 c1 fc ff ff ff addl $4294967292, %ecx // DISASM-NEXT: 11031: 65 8b 01 movl %gs:(%ecx), %eax -// DISASM-NEXT: 11034: 8b 0d 50 20 01 00 movl 73808, %ecx +// DISASM-NEXT: 11034: 8b 0d 58 20 01 00 movl 73816, %ecx // DISASM-NEXT: 1103a: 65 8b 01 movl %gs:(%ecx), %eax -// DISASM-NEXT: 1103d: 03 0d 54 20 01 00 addl 73812, %ecx +// DISASM-NEXT: 1103d: 03 0d 5c 20 01 00 addl 73820, %ecx // DISASM-NEXT: 11043: 65 8b 01 movl %gs:(%ecx), %eax // GOTRELSHARED: Section { diff --git a/test/mach-o/arm64-reloc-negDelta32-fixup.yaml b/test/mach-o/arm64-reloc-negDelta32-fixup.yaml index 87708a0db12b..8beab2841dc3 100644 --- a/test/mach-o/arm64-reloc-negDelta32-fixup.yaml +++ b/test/mach-o/arm64-reloc-negDelta32-fixup.yaml @@ -6,12 +6,12 @@ # The reference from FDE->CIE is implicitly created as a negDelta32. # We don't emit these in to the binary as relocations, so we need to # make sure that the offset in the FDE to the CIE is the correct value. -# CHECK: 0010 10000000 00000000 017a5200 01781e01 -# CHECK: 0020 100c1f00 20000000 18000000 e4ffffff -# Note, this one that matters ^~~~~~~~ +# CHECK: {{[0-9abcdef]*}} 10000000 00000000 017a5200 01781e01 +# CHECK: {{[0-9abcdef]*}} 100c1f00 20000000 18000000 e4ffffff +# Note, this one that matters ^~~~~~~~ # It needs to be 0x18 as that is the offset back to 0 where the CIE is. -# CHECK: 0030 ffffffff 20000000 00000000 00480e10 -# CHECK: 0040 9e019d02 00000000 +# CHECK: {{[0-9abcdef]*}} ffffffff 20000000 00000000 00480e10 +# CHECK: {{[0-9abcdef]*}} 9e019d02 00000000 --- !mach-o arch: arm64 diff --git a/test/mach-o/arm64-section-order.yaml b/test/mach-o/arm64-section-order.yaml new file mode 100644 index 000000000000..50d684668a52 --- /dev/null +++ b/test/mach-o/arm64-section-order.yaml @@ -0,0 +1,67 @@ +# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %s -o %t +# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %t -o %t2 +# RUN: llvm-objdump -section-headers %t | FileCheck %s +# RUN: llvm-objdump -section-headers %t2 | FileCheck %s + +# Make sure that the sections are sorted. Currently we want this order: +# __text, __unwind_info + +# CHECK: Sections: +# CHECK: 0 __text {{.*}} TEXT +# CHECK: 1 __compact_unwind {{.*}} + + +--- !mach-o +arch: arm64 +file-type: MH_OBJECT +flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ] +compat-version: 0.0 +current-version: 0.0 +has-UUID: false +OS: unknown +sections: + - segment: __TEXT + section: __text + type: S_REGULAR + attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ] + alignment: 8 + address: 0x0000000000000000 + content: [ 0xC0, 0x03, 0x5F, 0xD6, 0xC0, 0x03, 0x5F, 0xD6 ] + - segment: __LD + section: __compact_unwind + type: S_REGULAR + attributes: [ ] + alignment: 8 + address: 0x0000000000000008 + content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] + relocations: + - offset: 0x00000020 + type: ARM64_RELOC_UNSIGNED + length: 3 + pc-rel: false + extern: false + symbol: 1 + - offset: 0x00000000 + type: ARM64_RELOC_UNSIGNED + length: 3 + pc-rel: false + extern: false + symbol: 1 +global-symbols: + - name: __Z3fooi + type: N_SECT + scope: [ N_EXT ] + sect: 1 + value: 0x0000000000000000 + - name: __Z4foo2i + type: N_SECT + scope: [ N_EXT ] + sect: 1 + value: 0x0000000000000004 diff --git a/test/mach-o/parse-data-relocs-x86_64.yaml b/test/mach-o/parse-data-relocs-x86_64.yaml index b6f38f5d10e4..6b05e26372b8 100644 --- a/test/mach-o/parse-data-relocs-x86_64.yaml +++ b/test/mach-o/parse-data-relocs-x86_64.yaml @@ -268,7 +268,7 @@ page-size: 0x00000000 # CHECK: type: data # CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00, 04, 00, 00, 00, # CHECK: 00, 00, 00, 00, F0, FF, FF, FF, FF, FF, FF, FF, -# CHECK: {{..}}, 00, 00, 00, 00, 00, 00, 00, {{..}}, 00, 00, 00, +# CHECK: {{..}}, {{..}}, 00, 00, 00, 00, 00, 00, {{..}}, {{..}}, 00, 00, # CHECK: 00, 00, 00, 00, D8, FF, FF, FF, FF, FF, FF, FF, # CHECK: D4, FF, FF, FF, FF, FF, FF, FF, {{..}}, {{..}}, {{..}}, {{..}}, # CHECK: {{..}}, {{..}}, {{..}}, {{..}}, C0, FF, FF, FF, C0, FF, FF, FF, |