svn commit: r320382 - in vendor/lld/dist: . COFF ELF ELF/Arch docs lib/Driver lib/ReaderWriter/MachO test test/COFF test/COFF/Inputs test/ELF test/ELF/Inputs test/ELF/linkerscript test/ELF/lto test...
Dimitry Andric
dim at FreeBSD.org
Mon Jun 26 20:33:48 UTC 2017
Author: dim
Date: Mon Jun 26 20:33:45 2017
New Revision: 320382
URL: https://svnweb.freebsd.org/changeset/base/320382
Log:
Vendor import of lld trunk r306325:
https://llvm.org/svn/llvm-project/lld/trunk@306325
Added:
vendor/lld/dist/ELF/Arch/MipsArchTree.cpp (contents, props changed)
vendor/lld/dist/test/COFF/Inputs/associative-comdat-2.s (contents, props changed)
vendor/lld/dist/test/COFF/Inputs/pdb_comdat_bar.yaml
vendor/lld/dist/test/COFF/Inputs/pdb_comdat_main.yaml
vendor/lld/dist/test/COFF/Inputs/pdb_lines_1.yaml
vendor/lld/dist/test/COFF/Inputs/pdb_lines_2.yaml
vendor/lld/dist/test/COFF/associative-comdat.s (contents, props changed)
vendor/lld/dist/test/COFF/guardcf.test
vendor/lld/dist/test/COFF/pdb-comdat.test
vendor/lld/dist/test/COFF/pdb-safeseh.yaml
vendor/lld/dist/test/COFF/pdb-secrel-absolute.yaml
vendor/lld/dist/test/COFF/pdb-source-lines.test
vendor/lld/dist/test/COFF/pdb-symbol-types.yaml
vendor/lld/dist/test/COFF/safeseh-diag-feat.test
vendor/lld/dist/test/COFF/safeseh.s (contents, props changed)
vendor/lld/dist/test/COFF/secidx-absolute.s (contents, props changed)
vendor/lld/dist/test/COFF/secrel-absolute.s (contents, props changed)
vendor/lld/dist/test/COFF/secrel-common.s (contents, props changed)
vendor/lld/dist/test/ELF/Inputs/exclude-libs.s (contents, props changed)
vendor/lld/dist/test/ELF/exclude-libs.s (contents, props changed)
vendor/lld/dist/test/ELF/global-offset-table-position-aarch64.s (contents, props changed)
vendor/lld/dist/test/ELF/global-offset-table-position-arm.s (contents, props changed)
vendor/lld/dist/test/ELF/global-offset-table-position-i386.s (contents, props changed)
vendor/lld/dist/test/ELF/global-offset-table-position-mips.s (contents, props changed)
vendor/lld/dist/test/ELF/global-offset-table-position.s (contents, props changed)
vendor/lld/dist/test/ELF/invalid-z.s (contents, props changed)
vendor/lld/dist/test/ELF/linkerscript/discard-section-err.s (contents, props changed)
vendor/lld/dist/test/ELF/linkerscript/segment-none.s (contents, props changed)
vendor/lld/dist/test/ELF/linkerscript/ttext-script.s (contents, props changed)
Deleted:
vendor/lld/dist/ELF/Mips.cpp
vendor/lld/dist/test/COFF/safeseh.test
Modified:
vendor/lld/dist/COFF/Chunks.cpp
vendor/lld/dist/COFF/Chunks.h
vendor/lld/dist/COFF/Config.h
vendor/lld/dist/COFF/Driver.cpp
vendor/lld/dist/COFF/Driver.h
vendor/lld/dist/COFF/DriverUtils.cpp
vendor/lld/dist/COFF/InputFiles.cpp
vendor/lld/dist/COFF/Options.td
vendor/lld/dist/COFF/PDB.cpp
vendor/lld/dist/COFF/Strings.cpp
vendor/lld/dist/COFF/SymbolTable.cpp
vendor/lld/dist/COFF/SymbolTable.h
vendor/lld/dist/COFF/Symbols.cpp
vendor/lld/dist/COFF/Symbols.h
vendor/lld/dist/COFF/Writer.cpp
vendor/lld/dist/ELF/Arch/AArch64.cpp
vendor/lld/dist/ELF/Arch/AMDGPU.cpp
vendor/lld/dist/ELF/Arch/ARM.cpp
vendor/lld/dist/ELF/Arch/AVR.cpp
vendor/lld/dist/ELF/Arch/Mips.cpp
vendor/lld/dist/ELF/Arch/PPC.cpp
vendor/lld/dist/ELF/Arch/PPC64.cpp
vendor/lld/dist/ELF/Arch/X86.cpp
vendor/lld/dist/ELF/Arch/X86_64.cpp
vendor/lld/dist/ELF/CMakeLists.txt
vendor/lld/dist/ELF/Config.h
vendor/lld/dist/ELF/Driver.cpp
vendor/lld/dist/ELF/Driver.h
vendor/lld/dist/ELF/DriverUtils.cpp
vendor/lld/dist/ELF/InputFiles.cpp
vendor/lld/dist/ELF/InputFiles.h
vendor/lld/dist/ELF/InputSection.cpp
vendor/lld/dist/ELF/LinkerScript.cpp
vendor/lld/dist/ELF/MarkLive.cpp
vendor/lld/dist/ELF/Options.td
vendor/lld/dist/ELF/OutputSections.cpp
vendor/lld/dist/ELF/Relocations.cpp
vendor/lld/dist/ELF/SymbolTable.cpp
vendor/lld/dist/ELF/SymbolTable.h
vendor/lld/dist/ELF/Symbols.cpp
vendor/lld/dist/ELF/Symbols.h
vendor/lld/dist/ELF/Target.cpp
vendor/lld/dist/ELF/Target.h
vendor/lld/dist/ELF/Writer.cpp
vendor/lld/dist/README.md
vendor/lld/dist/docs/windows_support.rst
vendor/lld/dist/lib/Driver/DarwinLdDriver.cpp
vendor/lld/dist/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
vendor/lld/dist/test/COFF/Inputs/pdb1.yaml
vendor/lld/dist/test/COFF/def-name.test
vendor/lld/dist/test/COFF/dll.test
vendor/lld/dist/test/COFF/dllimport-gc.test
vendor/lld/dist/test/COFF/hello32.test
vendor/lld/dist/test/COFF/icf-associative.test
vendor/lld/dist/test/COFF/manifestinput.test
vendor/lld/dist/test/COFF/noentry.test
vendor/lld/dist/test/COFF/out.test
vendor/lld/dist/test/COFF/pdb-lib.s
vendor/lld/dist/test/COFF/pdb.test
vendor/lld/dist/test/COFF/resource.test
vendor/lld/dist/test/ELF/arm-gnu-ifunc-plt.s
vendor/lld/dist/test/ELF/arm-got-relative.s
vendor/lld/dist/test/ELF/arm-thumb-branch.s
vendor/lld/dist/test/ELF/arm-thumb-plt-reloc.s
vendor/lld/dist/test/ELF/defsym.s
vendor/lld/dist/test/ELF/global_offset_table_shared.s
vendor/lld/dist/test/ELF/linkerscript/sections.s
vendor/lld/dist/test/ELF/lto/cache.ll
vendor/lld/dist/test/ELF/lto/wrap-2.ll
vendor/lld/dist/test/ELF/mips-got16-relocatable.s
vendor/lld/dist/test/ELF/mips-npic-call-pic-os.s
vendor/lld/dist/test/ELF/mips-npic-call-pic-script.s
vendor/lld/dist/test/ELF/mips-npic-call-pic.s
vendor/lld/dist/test/ELF/mips-plt-r6.s
vendor/lld/dist/test/ELF/wrap.s
vendor/lld/dist/test/lit.cfg
vendor/lld/dist/test/mach-o/executable-exports.yaml
Modified: vendor/lld/dist/COFF/Chunks.cpp
==============================================================================
--- vendor/lld/dist/COFF/Chunks.cpp Mon Jun 26 20:33:41 2017 (r320381)
+++ vendor/lld/dist/COFF/Chunks.cpp Mon Jun 26 20:33:45 2017 (r320382)
@@ -37,8 +37,14 @@ SectionChunk::SectionChunk(ObjectFile *F, const coff_s
Align = Header->getAlignment();
- // Only COMDAT sections are subject of dead-stripping.
- Live = !isCOMDAT();
+ // Chunks may be discarded during comdat merging.
+ Discarded = false;
+
+ // If linker GC is disabled, every chunk starts out alive. If linker GC is
+ // enabled, treat non-comdat sections as roots. Generally optimized object
+ // files will be built with -ffunction-sections or /Gy, so most things worth
+ // stripping will be in a comdat.
+ Live = !Config->DoGC || !isCOMDAT();
}
static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); }
@@ -46,6 +52,15 @@ static void add32(uint8_t *P, int32_t V) { write32le(P
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); }
+static void applySecRel(const SectionChunk *Sec, uint8_t *Off, Defined *Sym) {
+ // Don't apply section relative relocations to absolute symbols in codeview
+ // debug info sections. MSVC does not treat such relocations as fatal errors,
+ // and they can be found in the standard library for linker-provided symbols
+ // like __guard_fids_table and __safe_se_handler_table.
+ if (!(isa<DefinedAbsolute>(Sym) && Sec->isCodeView()))
+ add32(Off, Sym->getSecrel());
+}
+
void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym,
uint64_t P) const {
uint64_t S = Sym->getRVA();
@@ -60,7 +75,7 @@ void SectionChunk::applyRelX64(uint8_t *Off, uint16_t
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;
+ case IMAGE_REL_AMD64_SECREL: applySecRel(this, Off, Sym); break;
default:
fatal("unsupported relocation type 0x" + Twine::utohexstr(Type));
}
@@ -75,7 +90,7 @@ void SectionChunk::applyRelX86(uint8_t *Off, uint16_t
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;
+ case IMAGE_REL_I386_SECREL: applySecRel(this, Off, Sym); break;
default:
fatal("unsupported relocation type 0x" + Twine::utohexstr(Type));
}
@@ -135,7 +150,7 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t
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;
+ case IMAGE_REL_ARM_SECREL: applySecRel(this, Off, Sym); break;
default:
fatal("unsupported relocation type 0x" + Twine::utohexstr(Type));
}
@@ -226,8 +241,12 @@ bool SectionChunk::isCOMDAT() const {
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());
+ if (Sym && this == Repl) {
+ if (Discarded)
+ message("Discarded comdat symbol " + Sym->getName());
+ else if (!Live)
+ message("Discarded " + Sym->getName());
+ }
}
StringRef SectionChunk::getDebugName() {
Modified: vendor/lld/dist/COFF/Chunks.h
==============================================================================
--- vendor/lld/dist/COFF/Chunks.h Mon Jun 26 20:33:41 2017 (r320381)
+++ vendor/lld/dist/COFF/Chunks.h Mon Jun 26 20:33:45 2017 (r320382)
@@ -64,7 +64,6 @@ class Chunk { (public)
uint64_t getRVA() const { return RVA; }
uint32_t getAlign() const { return Align; }
void setRVA(uint64_t V) { RVA = V; }
- void setOutputSectionOff(uint64_t V) { OutputSectionOff = V; }
// Returns true if this has non-zero data. BSS chunks return
// false. If false is returned, the space occupied by this chunk
@@ -97,17 +96,19 @@ class Chunk { (public)
Chunk(Kind K = OtherKind) : ChunkKind(K) {}
const Kind ChunkKind;
+ // The alignment of this chunk. The writer uses the value.
+ uint32_t Align = 1;
+
// The RVA of this chunk in the output. The writer sets a value.
uint64_t RVA = 0;
+public:
// The offset from beginning of the output section. The writer sets a value.
uint64_t OutputSectionOff = 0;
+protected:
// The output section for this chunk.
OutputSection *Out = nullptr;
-
- // The alignment of this chunk. The writer uses the value.
- uint32_t Align = 1;
};
// A chunk corresponding a section of an input file.
@@ -159,13 +160,29 @@ class SectionChunk : public Chunk { (public)
StringRef getDebugName() override;
void setSymbol(DefinedRegular *S) { if (!Sym) Sym = S; }
+ // Returns true if the chunk was not dropped by GC or COMDAT deduplication.
+ bool isLive() { return Live && !Discarded; }
+
// Used by the garbage collector.
- bool isLive() { return !Config->DoGC || Live; }
void markLive() {
+ assert(Config->DoGC && "should only mark things live from GC");
assert(!isLive() && "Cannot mark an already live section!");
Live = true;
}
+ // Returns true if this chunk was dropped by COMDAT deduplication.
+ bool isDiscarded() const { return Discarded; }
+
+ // Used by the SymbolTable when discarding unused comdat sections. This is
+ // redundant when GC is enabled, as all comdat sections will start out dead.
+ void markDiscarded() { Discarded = true; }
+
+ // True if this is a codeview debug info chunk. These will not be laid out in
+ // the image. Instead they will end up in the PDB, if one is requested.
+ bool isCodeView() const {
+ return SectionName == ".debug" || SectionName.startswith(".debug$");
+ }
+
// Allow iteration over the bodies of this chunk's relocated symbols.
llvm::iterator_range<symbol_iterator> symbols() const {
return llvm::make_range(symbol_iterator(File, Relocs.begin()),
@@ -195,6 +212,9 @@ class SectionChunk : public Chunk { (public)
std::vector<SectionChunk *> AssocChildren;
llvm::iterator_range<const coff_relocation *> Relocs;
size_t NumRelocs;
+
+ // True if this chunk was discarded because it was a duplicate comdat section.
+ bool Discarded;
// Used by the garbage collector.
bool Live;
Modified: vendor/lld/dist/COFF/Config.h
==============================================================================
--- vendor/lld/dist/COFF/Config.h Mon Jun 26 20:33:41 2017 (r320381)
+++ vendor/lld/dist/COFF/Config.h Mon Jun 26 20:33:45 2017 (r320382)
@@ -161,9 +161,6 @@ struct Configuration {
bool LargeAddressAware = false;
bool HighEntropyVA = false;
bool AppContainer = false;
-
- // This is for debugging.
- bool DumpPdb = false;
};
extern Configuration *Config;
Modified: vendor/lld/dist/COFF/Driver.cpp
==============================================================================
--- vendor/lld/dist/COFF/Driver.cpp Mon Jun 26 20:33:41 2017 (r320381)
+++ vendor/lld/dist/COFF/Driver.cpp Mon Jun 26 20:33:45 2017 (r320382)
@@ -905,7 +905,6 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr
Config->TerminalServerAware = false;
if (Args.hasArg(OPT_nosymtab))
Config->WriteSymtab = false;
- Config->DumpPdb = Args.hasArg(OPT_dumppdb);
Config->MapFile = getMapFile(Args);
@@ -936,9 +935,9 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr
Config->Machine = AMD64;
}
- // Windows specific -- Input files can be Windows resource files (.res files).
- // We invoke cvtres.exe to convert resource files to a regular COFF file
- // then link the result file normally.
+ // Input files can be Windows resource files (.res files). We use
+ // WindowsResource to convert resource files to a regular COFF file,
+ // then link the resulting file normally.
if (!Resources.empty())
addBuffer(convertResToCOFF(Resources));
@@ -1027,17 +1026,21 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr
if (Config->ImageBase == uint64_t(-1))
Config->ImageBase = getDefaultImageBase();
- Symtab.addRelative(mangle("__ImageBase"), 0);
+ Symtab.addSynthetic(mangle("__ImageBase"), nullptr);
if (Config->Machine == I386) {
- Config->SEHTable = Symtab.addRelative("___safe_se_handler_table", 0);
- Config->SEHCount = Symtab.addAbsolute("___safe_se_handler_count", 0);
+ Symtab.addAbsolute("___safe_se_handler_table", 0);
+ Symtab.addAbsolute("___safe_se_handler_count", 0);
}
// We do not support /guard:cf (control flow protection) yet.
// Define CFG symbols anyway so that we can link MSVC 2015 CRT.
- Symtab.addAbsolute(mangle("__guard_fids_table"), 0);
Symtab.addAbsolute(mangle("__guard_fids_count"), 0);
+ Symtab.addAbsolute(mangle("__guard_fids_table"), 0);
Symtab.addAbsolute(mangle("__guard_flags"), 0x100);
+ Symtab.addAbsolute(mangle("__guard_iat_count"), 0);
+ Symtab.addAbsolute(mangle("__guard_iat_table"), 0);
+ Symtab.addAbsolute(mangle("__guard_longjmp_count"), 0);
+ Symtab.addAbsolute(mangle("__guard_longjmp_table"), 0);
// This code may add new undefined symbols to the link, which may enqueue more
// symbol resolution tasks, so we need to continue executing tasks until we
Modified: vendor/lld/dist/COFF/Driver.h
==============================================================================
--- vendor/lld/dist/COFF/Driver.h Mon Jun 26 20:33:41 2017 (r320381)
+++ vendor/lld/dist/COFF/Driver.h Mon Jun 26 20:33:45 2017 (r320382)
@@ -178,7 +178,7 @@ void runMSVCLinker(std::string Rsp, ArrayRef<StringRef
// 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,
+#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID,
#include "Options.inc"
#undef OPTION
};
Modified: vendor/lld/dist/COFF/DriverUtils.cpp
==============================================================================
--- vendor/lld/dist/COFF/DriverUtils.cpp Mon Jun 26 20:33:41 2017 (r320381)
+++ vendor/lld/dist/COFF/DriverUtils.cpp Mon Jun 26 20:33:45 2017 (r320382)
@@ -20,12 +20,15 @@
#include "Symbols.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/BinaryFormat/COFF.h"
#include "llvm/Object/COFF.h"
+#include "llvm/Object/WindowsResource.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
@@ -41,6 +44,9 @@ namespace lld {
namespace coff {
namespace {
+const uint16_t SUBLANG_ENGLISH_US = 0x0409;
+const uint16_t RT_MANIFEST = 24;
+
class Executor {
public:
explicit Executor(StringRef S) : Prog(Saver.save(S)) {}
@@ -257,26 +263,6 @@ void parseManifestUAC(StringRef Arg) {
}
}
-// Quote each line with "". Existing double-quote is converted
-// to two double-quotes.
-static void quoteAndPrint(raw_ostream &Out, StringRef S) {
- while (!S.empty()) {
- StringRef Line;
- std::tie(Line, S) = S.split("\n");
- if (Line.empty())
- continue;
- Out << '\"';
- for (int I = 0, E = Line.size(); I != E; ++I) {
- if (Line[I] == '\"') {
- Out << "\"\"";
- } else {
- Out << Line[I];
- }
- }
- Out << "\"\n";
- }
-}
-
// An RAII temporary file class that automatically removes a temporary file.
namespace {
class TemporaryFile {
@@ -390,38 +376,64 @@ static std::string createManifestXml() {
return readFile(File2.Path);
}
+static std::unique_ptr<MemoryBuffer>
+createMemoryBufferForManifestRes(size_t ManifestSize) {
+ size_t ResSize = alignTo(object::WIN_RES_MAGIC_SIZE +
+ object::WIN_RES_NULL_ENTRY_SIZE +
+ sizeof(object::WinResHeaderPrefix) +
+ sizeof(object::WinResIDs) +
+ sizeof(object::WinResHeaderSuffix) +
+ ManifestSize,
+ object::WIN_RES_DATA_ALIGNMENT);
+ return MemoryBuffer::getNewMemBuffer(ResSize);
+}
+
+static void writeResFileHeader(char *&Buf) {
+ memcpy(Buf, COFF::WinResMagic, sizeof(COFF::WinResMagic));
+ Buf += sizeof(COFF::WinResMagic);
+ memset(Buf, 0, object::WIN_RES_NULL_ENTRY_SIZE);
+ Buf += object::WIN_RES_NULL_ENTRY_SIZE;
+}
+
+static void writeResEntryHeader(char *&Buf, size_t ManifestSize) {
+ // Write the prefix.
+ auto *Prefix = reinterpret_cast<object::WinResHeaderPrefix *>(Buf);
+ Prefix->DataSize = ManifestSize;
+ Prefix->HeaderSize = sizeof(object::WinResHeaderPrefix) +
+ sizeof(object::WinResIDs) +
+ sizeof(object::WinResHeaderSuffix);
+ Buf += sizeof(object::WinResHeaderPrefix);
+
+ // Write the Type/Name IDs.
+ auto *IDs = reinterpret_cast<object::WinResIDs *>(Buf);
+ IDs->setType(RT_MANIFEST);
+ IDs->setName(Config->ManifestID);
+ Buf += sizeof(object::WinResIDs);
+
+ // Write the suffix.
+ auto *Suffix = reinterpret_cast<object::WinResHeaderSuffix *>(Buf);
+ Suffix->DataVersion = 0;
+ Suffix->MemoryFlags = object::WIN_RES_PURE_MOVEABLE;
+ Suffix->Language = SUBLANG_ENGLISH_US;
+ Suffix->Version = 0;
+ Suffix->Characteristics = 0;
+ Buf += sizeof(object::WinResHeaderSuffix);
+}
+
// Create a resource file containing a manifest XML.
std::unique_ptr<MemoryBuffer> createManifestRes() {
- // Create a temporary file for the resource script file.
- TemporaryFile RCFile("manifest", "rc");
+ std::string Manifest = createManifestXml();
- // Open the temporary file for writing.
- std::error_code EC;
- raw_fd_ostream Out(RCFile.Path, EC, sys::fs::F_Text);
- if (EC)
- fatal(EC, "failed to open " + RCFile.Path);
+ std::unique_ptr<MemoryBuffer> Res =
+ createMemoryBufferForManifestRes(Manifest.size());
- // Write resource script to the RC file.
- Out << "#define LANG_ENGLISH 9\n"
- << "#define SUBLANG_DEFAULT 1\n"
- << "#define APP_MANIFEST " << Config->ManifestID << "\n"
- << "#define RT_MANIFEST 24\n"
- << "LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT\n"
- << "APP_MANIFEST RT_MANIFEST {\n";
- quoteAndPrint(Out, createManifestXml());
- Out << "}\n";
- Out.close();
+ char *Buf = const_cast<char *>(Res->getBufferStart());
+ writeResFileHeader(Buf);
+ writeResEntryHeader(Buf, Manifest.size());
- // Create output resource file.
- TemporaryFile ResFile("output-resource", "res");
-
- Executor E("rc.exe");
- E.add("/fo");
- E.add(ResFile.Path);
- E.add("/nologo");
- E.add(RCFile.Path);
- E.run();
- return ResFile.getMemoryBuffer();
+ // Copy the manifest data into the .res file.
+ std::copy(Manifest.begin(), Manifest.end(), Buf);
+ return Res;
}
void createSideBySideManifest() {
@@ -592,40 +604,22 @@ void checkFailIfMismatch(StringRef Arg) {
// using cvtres.exe.
std::unique_ptr<MemoryBuffer>
convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) {
- // Create an output file path.
- TemporaryFile File("resource-file", "obj");
+ object::WindowsResourceParser Parser;
- // Execute cvtres.exe.
- Executor E("cvtres.exe");
- E.add("/machine:" + machineToStr(Config->Machine));
- E.add("/readonly");
- E.add("/nologo");
- E.add("/out:" + Twine(File.Path));
-
- // We must create new files because the memory buffers we have may have no
- // underlying file still existing on the disk.
- // It happens if it was created from a TemporaryFile, which usually delete
- // the file just after creating the MemoryBuffer.
- std::vector<TemporaryFile> ResFiles;
- ResFiles.reserve(MBs.size());
for (MemoryBufferRef MB : MBs) {
- // We store the temporary file in a vector to avoid deletion
- // before running cvtres
- ResFiles.emplace_back("resource-file", "res");
- TemporaryFile& ResFile = ResFiles.back();
- // Write the content of the resource in a temporary file
- std::error_code EC;
- raw_fd_ostream OS(ResFile.Path, EC, sys::fs::F_None);
- if (EC)
- fatal(EC, "failed to open " + ResFile.Path);
- OS << MB.getBuffer();
- OS.close();
-
- E.add(ResFile.Path);
+ std::unique_ptr<object::Binary> Bin = check(object::createBinary(MB));
+ object::WindowsResource *RF = dyn_cast<object::WindowsResource>(Bin.get());
+ if (!RF)
+ fatal("cannot compile non-resource file as resource");
+ if (auto EC = Parser.parse(RF))
+ fatal(EC, "failed to parse .res file");
}
- E.run();
- return File.getMemoryBuffer();
+ Expected<std::unique_ptr<MemoryBuffer>> E =
+ llvm::object::writeWindowsResourceCOFF(Config->Machine, Parser);
+ if (!E)
+ fatal(errorToErrorCode(E.takeError()), "failed to write .res to COFF");
+ return std::move(E.get());
}
// Run MSVC link.exe for given in-memory object files.
@@ -657,11 +651,9 @@ void runMSVCLinker(std::string Rsp, ArrayRef<StringRef
// Create table mapping all options defined in Options.td
static const llvm::opt::OptTable::Info infoTable[] = {
-#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \
- { \
- X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \
- OPT_##GROUP, OPT_##ALIAS, X6 \
- },
+#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \
+ {X1, X2, X10, X11, OPT_##ID, llvm::opt::Option::KIND##Class, \
+ X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12},
#include "Options.inc"
#undef OPTION
};
Modified: vendor/lld/dist/COFF/InputFiles.cpp
==============================================================================
--- vendor/lld/dist/COFF/InputFiles.cpp Mon Jun 26 20:33:41 2017 (r320381)
+++ vendor/lld/dist/COFF/InputFiles.cpp Mon Jun 26 20:33:45 2017 (r320382)
@@ -132,17 +132,17 @@ void ObjectFile::initializeChunks() {
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(make<SectionChunk>(this, Sec));
- continue;
- }
-
if (Sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE)
continue;
auto *C = make<SectionChunk>(this, Sec);
- Chunks.push_back(C);
+
+ // CodeView sections are stored to a different vector because they are not
+ // linked in the regular manner.
+ if (C->isCodeView())
+ DebugChunks.push_back(C);
+ else
+ Chunks.push_back(C);
+
SparseChunks[I] = C;
}
}
@@ -249,8 +249,12 @@ SymbolBody *ObjectFile::createDefined(COFFSymbolRef Sy
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())]))
+ SparseChunks[Aux->getNumber(Sym.isBigObj())])) {
ParentSC->addAssociative(SC);
+ // If we already discarded the parent, discard the child.
+ if (ParentSC->isDiscarded())
+ SC->markDiscarded();
+ }
SC->Checksum = Aux->CheckSum;
}
Modified: vendor/lld/dist/COFF/Options.td
==============================================================================
--- vendor/lld/dist/COFF/Options.td Mon Jun 26 20:33:41 2017 (r320381)
+++ vendor/lld/dist/COFF/Options.td Mon Jun 26 20:33:45 2017 (r320382)
@@ -102,7 +102,6 @@ def nosymtab : F<"nosymtab">;
def msvclto : F<"msvclto">;
// Flags for debugging
-def dumppdb : Joined<["/", "-"], "dumppdb">;
def lldmap : F<"lldmap">;
def lldmap_file : Joined<["/", "-"], "lldmap:">;
Modified: vendor/lld/dist/COFF/PDB.cpp
==============================================================================
--- vendor/lld/dist/COFF/PDB.cpp Mon Jun 26 20:33:41 2017 (r320381)
+++ vendor/lld/dist/COFF/PDB.cpp Mon Jun 26 20:33:45 2017 (r320382)
@@ -15,10 +15,11 @@
#include "Symbols.h"
#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
-#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
-#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
@@ -46,8 +47,6 @@ using namespace lld;
using namespace lld::coff;
using namespace llvm;
using namespace llvm::codeview;
-using namespace llvm::support;
-using namespace llvm::support::endian;
using llvm::object::coff_section;
@@ -68,22 +67,24 @@ static SectionChunk *findByName(std::vector<SectionChu
return nullptr;
}
-static ArrayRef<uint8_t> getDebugSection(ObjectFile *File, StringRef SecName) {
- SectionChunk *Sec = findByName(File->getDebugChunks(), SecName);
- if (!Sec)
- return {};
-
+static ArrayRef<uint8_t> consumeDebugMagic(ArrayRef<uint8_t> Data,
+ StringRef SecName) {
// First 4 bytes are section magic.
- ArrayRef<uint8_t> Data = Sec->getContents();
if (Data.size() < 4)
fatal(SecName + " too short");
- if (read32le(Data.data()) != COFF::DEBUG_SECTION_MAGIC)
+ if (support::endian::read32le(Data.data()) != COFF::DEBUG_SECTION_MAGIC)
fatal(SecName + " has an invalid magic");
return Data.slice(4);
}
+static ArrayRef<uint8_t> getDebugSection(ObjectFile *File, StringRef SecName) {
+ if (SectionChunk *Sec = findByName(File->getDebugChunks(), SecName))
+ return consumeDebugMagic(Sec->getContents(), SecName);
+ return {};
+}
+
static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,
- codeview::TypeTableBuilder &TypeTable) {
+ TypeTableBuilder &TypeTable) {
// Start the TPI or IPI stream header.
TpiBuilder.setVersionHeader(pdb::PdbTpiV80);
@@ -94,17 +95,148 @@ static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuil
});
}
+static void mergeDebugT(ObjectFile *File,
+ TypeTableBuilder &IDTable,
+ TypeTableBuilder &TypeTable,
+ SmallVectorImpl<TypeIndex> &TypeIndexMap,
+ pdb::PDBTypeServerHandler &Handler) {
+ ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
+ if (Data.empty())
+ return;
+
+ BinaryByteStream Stream(Data, support::little);
+ CVTypeArray Types;
+ BinaryStreamReader Reader(Stream);
+ Handler.addSearchPath(sys::path::parent_path(File->getName()));
+ if (auto EC = Reader.readArray(Types, Reader.getLength()))
+ fatal(EC, "Reader::readArray failed");
+ if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable,
+ TypeIndexMap, &Handler, Types))
+ fatal(Err, "codeview::mergeTypeStreams failed");
+}
+
+static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) {
+ if (TI.isSimple())
+ return true;
+ if (TI.toArrayIndex() >= TypeIndexMap.size())
+ return false;
+ TI = TypeIndexMap[TI.toArrayIndex()];
+ return true;
+}
+
+static bool remapTypesInSymbolRecord(ObjectFile *File,
+ MutableArrayRef<uint8_t> Contents,
+ ArrayRef<TypeIndex> TypeIndexMap,
+ ArrayRef<TiReference> TypeRefs) {
+ for (const TiReference &Ref : TypeRefs) {
+ unsigned ByteSize = Ref.Count * sizeof(TypeIndex);
+ if (Contents.size() < Ref.Offset + ByteSize) {
+ log("ignoring short symbol record");
+ return false;
+ }
+ MutableArrayRef<TypeIndex> TIs(
+ reinterpret_cast<TypeIndex *>(Contents.data() + Ref.Offset), Ref.Count);
+ for (TypeIndex &TI : TIs)
+ if (!remapTypeIndex(TI, TypeIndexMap)) {
+ log("ignoring symbol record in " + File->getName() +
+ " with bad type index 0x" + utohexstr(TI.getIndex()));
+ return false;
+ }
+ }
+ return true;
+}
+
+/// MSVC translates S_PROC_ID_END to S_END.
+uint16_t canonicalizeSymbolKind(SymbolKind Kind) {
+ if (Kind == SymbolKind::S_PROC_ID_END)
+ return SymbolKind::S_END;
+ return Kind;
+}
+
+/// Copy the symbol record. In a PDB, symbol records must be 4 byte aligned.
+/// The object file may not be aligned.
+static MutableArrayRef<uint8_t> copySymbolForPdb(const CVSymbol &Sym,
+ BumpPtrAllocator &Alloc) {
+ size_t Size = alignTo(Sym.length(), alignOf(CodeViewContainer::Pdb));
+ assert(Size >= 4 && "record too short");
+ assert(Size <= MaxRecordLength && "record too long");
+ void *Mem = Alloc.Allocate(Size, 4);
+
+ // Copy the symbol record and zero out any padding bytes.
+ MutableArrayRef<uint8_t> NewData(reinterpret_cast<uint8_t *>(Mem), Size);
+ memcpy(NewData.data(), Sym.data().data(), Sym.length());
+ memset(NewData.data() + Sym.length(), 0, Size - Sym.length());
+
+ // Update the record prefix length. It should point to the beginning of the
+ // next record. MSVC does some canonicalization of the record kind, so we do
+ // that as well.
+ auto *Prefix = reinterpret_cast<RecordPrefix *>(Mem);
+ Prefix->RecordKind = canonicalizeSymbolKind(Sym.kind());
+ Prefix->RecordLen = Size - 2;
+ return NewData;
+}
+
+static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File,
+ ArrayRef<TypeIndex> TypeIndexMap,
+ BinaryStreamRef SymData) {
+ // FIXME: Improve error recovery by warning and skipping records when
+ // possible.
+ CVSymbolArray Syms;
+ BinaryStreamReader Reader(SymData);
+ ExitOnErr(Reader.readArray(Syms, Reader.getLength()));
+ for (const CVSymbol &Sym : Syms) {
+ // Discover type index references in the record. Skip it if we don't know
+ // where they are.
+ SmallVector<TiReference, 32> TypeRefs;
+ if (!discoverTypeIndices(Sym, TypeRefs)) {
+ log("ignoring unknown symbol record with kind 0x" + utohexstr(Sym.kind()));
+ continue;
+ }
+
+ // Copy the symbol record so we can mutate it.
+ MutableArrayRef<uint8_t> NewData = copySymbolForPdb(Sym, Alloc);
+
+ // Re-map all the type index references.
+ MutableArrayRef<uint8_t> Contents =
+ NewData.drop_front(sizeof(RecordPrefix));
+ if (!remapTypesInSymbolRecord(File, Contents, TypeIndexMap, TypeRefs))
+ continue;
+
+ // FIXME: Fill in "Parent" and "End" fields by maintaining a stack of
+ // scopes.
+
+ // Add the symbol to the module.
+ File->ModuleDBI->addSymbol(CVSymbol(Sym.kind(), NewData));
+ }
+}
+
+// Allocate memory for a .debug$S section and relocate it.
+static ArrayRef<uint8_t> relocateDebugChunk(BumpPtrAllocator &Alloc,
+ SectionChunk *DebugChunk) {
+ uint8_t *Buffer = Alloc.Allocate<uint8_t>(DebugChunk->getSize());
+ assert(DebugChunk->OutputSectionOff == 0 &&
+ "debug sections should not be in output sections");
+ DebugChunk->writeTo(Buffer);
+ return consumeDebugMagic(makeArrayRef(Buffer, DebugChunk->getSize()),
+ ".debug$S");
+}
+
// Add all object files to the PDB. Merge .debug$T sections into IpiData and
// TpiData.
-static void addObjectsToPDB(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder,
- codeview::TypeTableBuilder &TypeTable,
- codeview::TypeTableBuilder &IDTable) {
+static void addObjectsToPDB(BumpPtrAllocator &Alloc, SymbolTable *Symtab,
+ pdb::PDBFileBuilder &Builder,
+ TypeTableBuilder &TypeTable,
+ TypeTableBuilder &IDTable) {
// Follow type servers. If the same type server is encountered more than
// once for this instance of `PDBTypeServerHandler` (for example if many
// object files reference the same TypeServer), the types from the
// TypeServer will only be visited once.
pdb::PDBTypeServerHandler Handler;
+ // PDBs use a single global string table for filenames in the file checksum
+ // table.
+ auto PDBStrTab = std::make_shared<DebugStringTableSubsection>();
+
// Visit all .debug$T sections to add them to Builder.
for (ObjectFile *File : Symtab->ObjectFiles) {
// Add a module descriptor for every object file. We need to put an absolute
@@ -118,25 +250,74 @@ static void addObjectsToPDB(SymbolTable *Symtab, pdb::
File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name));
File->ModuleDBI->setObjFileName(Path);
- // FIXME: Walk the .debug$S sections and add them. Do things like recording
- // source files.
+ // Before we can process symbol substreams from .debug$S, we need to process
+ // type information, file checksums, and the string table. Add type info to
+ // the PDB first, so that we can get the map from object file type and item
+ // indices to PDB type and item indices.
+ SmallVector<TypeIndex, 128> TypeIndexMap;
+ mergeDebugT(File, IDTable, TypeTable, TypeIndexMap, Handler);
- ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
- if (Data.empty())
- continue;
+ // Now do all line info.
+ for (SectionChunk *DebugChunk : File->getDebugChunks()) {
+ if (!DebugChunk->isLive() || DebugChunk->getSectionName() != ".debug$S")
+ continue;
- BinaryByteStream Stream(Data, support::little);
- codeview::CVTypeArray Types;
- BinaryStreamReader Reader(Stream);
- SmallVector<TypeIndex, 128> SourceToDest;
- Handler.addSearchPath(llvm::sys::path::parent_path(File->getName()));
- if (auto EC = Reader.readArray(Types, Reader.getLength()))
- fatal(EC, "Reader::readArray failed");
- if (auto Err = codeview::mergeTypeAndIdRecords(
- IDTable, TypeTable, SourceToDest, &Handler, Types))
- fatal(Err, "codeview::mergeTypeStreams failed");
+ ArrayRef<uint8_t> RelocatedDebugContents =
+ relocateDebugChunk(Alloc, DebugChunk);
+ if (RelocatedDebugContents.empty())
+ continue;
+
+ DebugSubsectionArray Subsections;
+ BinaryStreamReader Reader(RelocatedDebugContents, support::little);
+ ExitOnErr(Reader.readArray(Subsections, RelocatedDebugContents.size()));
+
+ DebugStringTableSubsectionRef CVStrTab;
+ DebugChecksumsSubsectionRef Checksums;
+ for (const DebugSubsectionRecord &SS : Subsections) {
+ switch (SS.kind()) {
+ case DebugSubsectionKind::StringTable:
+ ExitOnErr(CVStrTab.initialize(SS.getRecordData()));
+ break;
+ case DebugSubsectionKind::FileChecksums:
+ ExitOnErr(Checksums.initialize(SS.getRecordData()));
+ break;
+ case DebugSubsectionKind::Lines:
+ // We can add the relocated line table directly to the PDB without
+ // modification because the file checksum offsets will stay the same.
+ File->ModuleDBI->addDebugSubsection(SS);
+ break;
+ case DebugSubsectionKind::Symbols:
+ mergeSymbolRecords(Alloc, File, TypeIndexMap, SS.getRecordData());
+ break;
+ default:
+ // FIXME: Process the rest of the subsections.
+ break;
+ }
+ }
+
+ if (Checksums.valid()) {
+ // Make a new file checksum table that refers to offsets in the PDB-wide
+ // string table. Generally the string table subsection appears after the
+ // checksum table, so we have to do this after looping over all the
+ // subsections.
+ if (!CVStrTab.valid())
+ fatal(".debug$S sections must have both a string table subsection "
+ "and a checksum subsection table or neither");
+ auto NewChecksums =
+ make_unique<DebugChecksumsSubsection>(*PDBStrTab);
+ for (FileChecksumEntry &FC : Checksums) {
+ StringRef FileName = ExitOnErr(CVStrTab.getString(FC.FileNameOffset));
+ ExitOnErr(Builder.getDbiBuilder().addModuleSourceFile(
+ *File->ModuleDBI, FileName));
+ NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum);
+ }
+ File->ModuleDBI->addDebugSubsection(std::move(NewChecksums));
+ }
+ }
}
+ Builder.getStringTableBuilder().setStrings(*PDBStrTab);
+
// Construct TPI stream contents.
addTypeInfo(Builder.getTpiBuilder(), TypeTable);
@@ -144,56 +325,10 @@ static void addObjectsToPDB(SymbolTable *Symtab, pdb::
addTypeInfo(Builder.getIpiBuilder(), IDTable);
}
-static void dumpDebugT(ScopedPrinter &W, ObjectFile *File) {
- ListScope LS(W, "DebugT");
- ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
- if (Data.empty())
- return;
-
- LazyRandomTypeCollection Types(Data, 100);
- TypeDumpVisitor TDV(Types, &W, false);
- // Use a default implementation that does not follow type servers and instead
- // just dumps the contents of the TypeServer2 record.
- if (auto EC = codeview::visitTypeStream(Types, TDV))
- fatal(EC, "CVTypeDumper::dump failed");
-}
-
-static void dumpDebugS(ScopedPrinter &W, ObjectFile *File) {
- ListScope LS(W, "DebugS");
- ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$S");
- if (Data.empty())
- return;
-
- BinaryByteStream Stream(Data, llvm::support::little);
- CVSymbolArray Symbols;
- BinaryStreamReader Reader(Stream);
- if (auto EC = Reader.readArray(Symbols, Reader.getLength()))
- fatal(EC, "StreamReader.readArray<CVSymbolArray> failed");
-
- TypeDatabase TDB(0);
- CVSymbolDumper SymbolDumper(W, TDB, CodeViewContainer::ObjectFile, nullptr,
- false);
- if (auto EC = SymbolDumper.dump(Symbols))
- fatal(EC, "CVSymbolDumper::dump failed");
-}
-
-// Dump CodeView debug info. This is for debugging.
-static void dumpCodeView(SymbolTable *Symtab) {
- ScopedPrinter W(outs());
-
- for (ObjectFile *File : Symtab->ObjectFiles) {
- dumpDebugT(W, File);
- dumpDebugS(W, File);
- }
-}
-
// Creates a PDB file.
void coff::createPDB(StringRef Path, SymbolTable *Symtab,
ArrayRef<uint8_t> SectionTable,
const llvm::codeview::DebugInfo *DI) {
- if (Config->DumpPdb)
- dumpCodeView(Symtab);
-
BumpPtrAllocator Alloc;
pdb::PDBFileBuilder Builder(Alloc);
ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize
@@ -219,9 +354,9 @@ void coff::createPDB(StringRef Path, SymbolTable *Symt
pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
DbiBuilder.setVersionHeader(pdb::PdbDbiV110);
- codeview::TypeTableBuilder TypeTable(BAlloc);
- codeview::TypeTableBuilder IDTable(BAlloc);
- addObjectsToPDB(Symtab, Builder, TypeTable, IDTable);
+ TypeTableBuilder TypeTable(BAlloc);
+ TypeTableBuilder IDTable(BAlloc);
+ addObjectsToPDB(Alloc, Symtab, Builder, TypeTable, IDTable);
// Add Section Contributions.
addSectionContribs(Symtab, DbiBuilder);
Modified: vendor/lld/dist/COFF/Strings.cpp
==============================================================================
--- vendor/lld/dist/COFF/Strings.cpp Mon Jun 26 20:33:41 2017 (r320381)
+++ vendor/lld/dist/COFF/Strings.cpp Mon Jun 26 20:33:45 2017 (r320382)
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "Strings.h"
+#include <mutex>
#if defined(_MSC_VER)
#include <Windows.h>
@@ -21,6 +22,10 @@ using namespace llvm;
Optional<std::string> coff::demangle(StringRef S) {
#if defined(_MSC_VER)
+ // UnDecorateSymbolName is not thread-safe, so we need a mutex.
+ static std::mutex Mu;
+ std::lock_guard<std::mutex> Lock(Mu);
+
char Buf[4096];
if (S.startswith("?"))
if (size_t Len = UnDecorateSymbolName(S.str().c_str(), Buf, sizeof(Buf), 0))
Modified: vendor/lld/dist/COFF/SymbolTable.cpp
==============================================================================
--- vendor/lld/dist/COFF/SymbolTable.cpp Mon Jun 26 20:33:41 2017 (r320381)
+++ vendor/lld/dist/COFF/SymbolTable.cpp Mon Jun 26 20:33:45 2017 (r320382)
@@ -219,13 +219,13 @@ Symbol *SymbolTable::addAbsolute(StringRef N, uint64_t
return S;
}
-Symbol *SymbolTable::addRelative(StringRef N, uint64_t VA) {
+Symbol *SymbolTable::addSynthetic(StringRef N, Chunk *C) {
Symbol *S;
bool WasInserted;
std::tie(S, WasInserted) = insert(N);
S->IsUsedInRegularObj = true;
if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body()))
- replaceBody<DefinedRelative>(S, N, VA);
+ replaceBody<DefinedSynthetic>(S, N, C);
else if (!isa<DefinedCOFF>(S->body()))
reportDuplicate(S, nullptr);
return S;
@@ -244,6 +244,12 @@ Symbol *SymbolTable::addRegular(InputFile *F, StringRe
reportDuplicate(S, F);
} else if (SP == SP_NEW) {
replaceBody<DefinedRegular>(S, F, N, IsCOMDAT, /*IsExternal*/ true, Sym, C);
+ } else if (SP == SP_EXISTING && IsCOMDAT && C) {
+ C->markDiscarded();
+ // Discard associative chunks that we've parsed so far. No need to recurse
+ // because an associative section cannot have children.
+ for (SectionChunk *Child : C->children())
+ Child->markDiscarded();
}
return S;
}
Modified: vendor/lld/dist/COFF/SymbolTable.h
==============================================================================
--- vendor/lld/dist/COFF/SymbolTable.h Mon Jun 26 20:33:41 2017 (r320381)
+++ vendor/lld/dist/COFF/SymbolTable.h Mon Jun 26 20:33:45 2017 (r320382)
@@ -85,7 +85,7 @@ class SymbolTable { (public)
// Creates an Undefined symbol for a given name.
SymbolBody *addUndefined(StringRef Name);
- Symbol *addRelative(StringRef N, uint64_t VA);
+ Symbol *addSynthetic(StringRef N, Chunk *C);
Symbol *addAbsolute(StringRef N, uint64_t VA);
Symbol *addUndefined(StringRef Name, InputFile *F, bool IsWeakAlias);
Modified: vendor/lld/dist/COFF/Symbols.cpp
==============================================================================
--- vendor/lld/dist/COFF/Symbols.cpp Mon Jun 26 20:33:41 2017 (r320381)
+++ vendor/lld/dist/COFF/Symbols.cpp Mon Jun 26 20:33:45 2017 (r320382)
@@ -61,6 +61,8 @@ COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(Sym));
}
+uint16_t DefinedAbsolute::OutputSectionIndex = 0;
+
static Chunk *makeImportThunk(DefinedImportData *S, uint16_t Machine) {
if (Machine == AMD64)
return make<ImportThunkChunkX64>(S);
Modified: vendor/lld/dist/COFF/Symbols.h
==============================================================================
--- vendor/lld/dist/COFF/Symbols.h Mon Jun 26 20:33:41 2017 (r320381)
+++ vendor/lld/dist/COFF/Symbols.h Mon Jun 26 20:33:45 2017 (r320382)
@@ -50,13 +50,13 @@ class SymbolBody { (public)
DefinedImportThunkKind,
DefinedImportDataKind,
DefinedAbsoluteKind,
- DefinedRelativeKind,
+ DefinedSyntheticKind,
UndefinedKind,
LazyKind,
LastDefinedCOFFKind = DefinedCommonKind,
- LastDefinedKind = DefinedRelativeKind,
+ LastDefinedKind = DefinedSyntheticKind,
};
Kind kind() const { return static_cast<Kind>(SymbolKind); }
@@ -112,11 +112,11 @@ class Defined : public SymbolBody { (public)
// Returns the RVA relative to the beginning of the output section.
// Used to implement SECREL relocation type.
- uint64_t getSecrel();
+ uint32_t getSecrel();
// Returns the output section index.
// Used to implement SECTION relocation type.
- uint64_t getSectionIndex();
+ uint16_t getSectionIndex();
// Returns true if this symbol points to an executable (e.g. .text) section.
// Used to implement ARM relocations.
@@ -167,6 +167,7 @@ class DefinedRegular : public DefinedCOFF { (public)
bool isCOMDAT() { return IsCOMDAT; }
SectionChunk *getChunk() { return *Data; }
uint32_t getValue() { return Sym->Value; }
+ uint32_t getSecrel();
private:
SectionChunk **Data;
@@ -186,6 +187,8 @@ class DefinedCommon : public DefinedCOFF { (public)
}
uint64_t getRVA() { return Data->getRVA(); }
+ uint32_t getSecrel() { return Data->OutputSectionOff; }
+ uint16_t getSectionIndex();
private:
friend SymbolTable;
@@ -212,28 +215,34 @@ class DefinedAbsolute : public Defined { (public)
uint64_t getRVA() { return VA - Config->ImageBase; }
void setVA(uint64_t V) { VA = V; }
+ // The sentinel absolute symbol section index. Section index relocations
+ // against absolute symbols resolve to this 16 bit number, and it is the
+ // largest valid section index plus one. This is written by the Writer.
+ static uint16_t OutputSectionIndex;
+
private:
uint64_t VA;
};
-// This is a kind of absolute symbol but relative to the image base.
-// Unlike absolute symbols, relocations referring this kind of symbols
-// are subject of the base relocation. This type is used rarely --
-// mainly for __ImageBase.
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-vendor
mailing list