[lld] r239710 - COFF: Support base relocations.
Rui Ueyama
ruiu at google.com
Sun Jun 14 18:23:58 PDT 2015
Author: ruiu
Date: Sun Jun 14 20:23:58 2015
New Revision: 239710
URL: http://llvm.org/viewvc/llvm-project?rev=239710&view=rev
Log:
COFF: Support base relocations.
PE/COFF executables/DLLs usually contain data which is called
base relocations. Base relocations are a list of addresses that
need to be fixed by the loader if load-time relocation is needed.
Base relocations are in .reloc section.
We emit one base relocation entry for each IMAGE_REL_AMD64_ADDR64
relocation.
In order to save disk space, base relocations are grouped by page.
Each group is called a block. A block starts with a 32-bit page
address followed by 16-bit offsets in the page. That is more
efficient representation of addresses than just an array of 32-bit
addresses.
Added:
lld/trunk/test/COFF/Inputs/baserel.obj.yaml
lld/trunk/test/COFF/baserel.test
Modified:
lld/trunk/COFF/Chunks.cpp
lld/trunk/COFF/Chunks.h
lld/trunk/COFF/Config.h
lld/trunk/COFF/Driver.cpp
lld/trunk/COFF/README.md
lld/trunk/COFF/Writer.cpp
lld/trunk/COFF/Writer.h
Modified: lld/trunk/COFF/Chunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.cpp?rev=239710&r1=239709&r2=239710&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.cpp (original)
+++ lld/trunk/COFF/Chunks.cpp Sun Jun 14 20:23:58 2015
@@ -21,7 +21,6 @@ using namespace llvm;
using namespace llvm::object;
using namespace llvm::support::endian;
using namespace llvm::COFF;
-using llvm::RoundUpToAlignment;
namespace lld {
namespace coff {
@@ -114,6 +113,25 @@ void SectionChunk::applyReloc(uint8_t *B
}
}
+// Windows-specific.
+// Collect all locations that contain absolute 64-bit addresses,
+// which need to be fixed by the loader if load-time relocation is needed.
+// Only called when base relocation is enabled.
+void SectionChunk::getBaserels(std::vector<uint32_t> *Res, Defined *ImageBase) {
+ for (const auto &I : getSectionRef().relocations()) {
+ // ADDR64 relocations contain absolute addresses.
+ // Symbol __ImageBase is special -- it's an absolute symbol, but its
+ // address never changes even if image is relocated.
+ const coff_relocation *Rel = File->getCOFFObj()->getCOFFRelocation(I);
+ if (Rel->Type != IMAGE_REL_AMD64_ADDR64)
+ continue;
+ SymbolBody *Body = File->getSymbolBody(Rel->SymbolTableIndex);
+ if (Body == ImageBase)
+ continue;
+ Res->push_back(RVA + Rel->VirtualAddress);
+ }
+}
+
bool SectionChunk::hasData() const {
return !(Header->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA);
}
@@ -173,5 +191,25 @@ void ImportThunkChunk::writeTo(uint8_t *
write32le(Buf + FileOff + 2, Operand);
}
+// Windows-specific.
+// This class represents a block in .reloc section.
+BaserelChunk::BaserelChunk(uint32_t Page, uint32_t *Begin, uint32_t *End) {
+ // Block header consists of 4 byte page RVA and 4 byte block size.
+ // Each entry is 2 byte. Last entry may be padding.
+ Data.resize(RoundUpToAlignment((End - Begin) * 2 + 8, 4));
+ uint8_t *P = Data.data();
+ write32le(P, Page);
+ write32le(P + 4, Data.size());
+ P += 8;
+ for (uint32_t *I = Begin; I != End; ++I) {
+ write16le(P, (IMAGE_REL_BASED_DIR64 << 12) | (*I - Page));
+ P += 2;
+ }
+}
+
+void BaserelChunk::writeTo(uint8_t *Buf) {
+ memcpy(Buf + FileOff, Data.data(), Data.size());
+}
+
} // namespace coff
} // namespace lld
Modified: lld/trunk/COFF/Chunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.h?rev=239710&r1=239709&r2=239710&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.h (original)
+++ lld/trunk/COFF/Chunks.h Sun Jun 14 20:23:58 2015
@@ -92,6 +92,10 @@ public:
void setOutputSection(OutputSection *O) { Out = O; }
OutputSection *getOutputSection() { return Out; }
+ // Windows-specific.
+ // Collect all locations that contain absolute addresses for base relocations.
+ virtual void getBaserels(std::vector<uint32_t> *Res, Defined *ImageBase) {}
+
protected:
// The RVA of this chunk in the output. The writer sets a value.
uint64_t RVA = 0;
@@ -123,6 +127,7 @@ public:
StringRef getSectionName() const override { return SectionName; }
void printDiscardedMessage() override;
bool isCOMDAT() const override;
+ void getBaserels(std::vector<uint32_t> *Res, Defined *ImageBase) override;
// Adds COMDAT associative sections to this COMDAT section. A chunk
// and its children are treated as a group by the garbage collector.
@@ -183,6 +188,19 @@ private:
Defined *ImpSymbol;
};
+// Windows-specific.
+// This class represents a block in .reloc section.
+// See the PE/COFF spec 5.6 for details.
+class BaserelChunk : public Chunk {
+public:
+ BaserelChunk(uint32_t Page, uint32_t *Begin, uint32_t *End);
+ size_t getSize() const override { return Data.size(); }
+ void writeTo(uint8_t *Buf) override;
+
+private:
+ std::vector<uint8_t> Data;
+};
+
} // namespace coff
} // namespace lld
Modified: lld/trunk/COFF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Config.h?rev=239710&r1=239709&r2=239710&view=diff
==============================================================================
--- lld/trunk/COFF/Config.h (original)
+++ lld/trunk/COFF/Config.h Sun Jun 14 20:23:58 2015
@@ -31,6 +31,7 @@ public:
StringRef EntryName;
std::string OutputFile;
bool DoGC = true;
+ bool Relocatable = true;
// Symbols in this set are considered as live by the garbage collector.
std::set<StringRef> GCRoots;
Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=239710&r1=239709&r2=239710&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Sun Jun 14 20:23:58 2015
@@ -225,6 +225,10 @@ bool LinkerDriver::link(int Argc, const
if (auto *Arg = Args->getLastArg(OPT_entry))
Config->EntryName = Arg->getValue();
+ // Handle /fixed
+ if (Args->hasArg(OPT_fixed))
+ Config->Relocatable = false;
+
// Handle /machine
auto MTOrErr = getMachineType(Args.get());
if (auto EC = MTOrErr.getError()) {
Modified: lld/trunk/COFF/README.md
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/README.md?rev=239710&r1=239709&r2=239710&view=diff
==============================================================================
--- lld/trunk/COFF/README.md (original)
+++ lld/trunk/COFF/README.md Sun Jun 14 20:23:58 2015
@@ -222,12 +222,8 @@ Glossary
locations containing addresses. The loader adds a difference between
RVA and actual load address to all locations listed there.
- Note 1: This run-time relocation mechanism is very simple compared
- to ELF. There's no PLT or GOT. Images are relocated as a whole just
+ Note that this run-time relocation mechanism is much simpler than ELF.
+ There's no PLT or GOT. Images are relocated as a whole just
by shifting entire images in memory by some offsets. Although doing
this breaks text sharing, I think this mechanism is not actually bad
on today's computers.
-
- Note 2: We do not support base relocations yet. But if you were
- wondering how Windows manages to load two images having conflicting
- addresses into the same memory space, this is how it works.
Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=239710&r1=239709&r2=239710&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Sun Jun 14 20:23:58 2015
@@ -42,6 +42,8 @@ std::error_code Writer::write(StringRef
markLive();
createSections();
createImportTables();
+ if (Config->Relocatable)
+ createSection(".reloc");
assignAddresses();
removeEmptySections();
if (auto EC = openFile(OutputPath))
@@ -192,6 +194,8 @@ void Writer::assignAddresses() {
uint64_t RVA = 0x1000; // The first page is kept unmapped.
uint64_t FileOff = SizeOfHeaders;
for (OutputSection *Sec : OutputSections) {
+ if (Sec->getName() == ".reloc")
+ addBaserels(Sec);
Sec->setRVA(RVA);
Sec->setFileOffset(FileOff);
RVA += RoundUpToAlignment(Sec->getVirtualSize(), PageSize);
@@ -238,8 +242,9 @@ void Writer::writeHeader() {
COFF->Machine = MachineType;
COFF->NumberOfSections = OutputSections.size();
COFF->Characteristics =
- (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_RELOCS_STRIPPED |
- IMAGE_FILE_LARGE_ADDRESS_AWARE);
+ (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LARGE_ADDRESS_AWARE);
+ if (!Config->Relocatable)
+ COFF->Characteristics = COFF->Characteristics | IMAGE_FILE_RELOCS_STRIPPED;
COFF->SizeOfOptionalHeader =
sizeof(pe32plus_header) + sizeof(data_directory) * NumberfOfDataDirectory;
@@ -265,6 +270,8 @@ void Writer::writeHeader() {
PE->SizeOfStackCommit = Config->StackCommit;
PE->SizeOfHeapReserve = Config->HeapReserve;
PE->SizeOfHeapCommit = Config->HeapCommit;
+ if (Config->Relocatable)
+ PE->DLLCharacteristics = IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;
PE->NumberOfRvaAndSize = NumberfOfDataDirectory;
if (OutputSection *Text = findSection(".text")) {
PE->BaseOfCode = Text->getRVA();
@@ -285,6 +292,10 @@ void Writer::writeHeader() {
DataDirectory[RESOURCE_TABLE].RelativeVirtualAddress = Sec->getRVA();
DataDirectory[RESOURCE_TABLE].Size = Sec->getRawSize();
}
+ if (OutputSection *Sec = findSection(".reloc")) {
+ DataDirectory[BASE_RELOCATION_TABLE].RelativeVirtualAddress = Sec->getRVA();
+ DataDirectory[BASE_RELOCATION_TABLE].Size = Sec->getVirtualSize();
+ }
// Section table
// Name field in the section table is 8 byte long. Longer names need
@@ -368,6 +379,7 @@ OutputSection *Writer::createSection(Str
const auto DATA = IMAGE_SCN_CNT_INITIALIZED_DATA;
const auto BSS = IMAGE_SCN_CNT_UNINITIALIZED_DATA;
const auto CODE = IMAGE_SCN_CNT_CODE;
+ const auto DISCARDABLE = IMAGE_SCN_MEM_DISCARDABLE;
const auto R = IMAGE_SCN_MEM_READ;
const auto W = IMAGE_SCN_MEM_WRITE;
const auto X = IMAGE_SCN_MEM_EXECUTE;
@@ -377,6 +389,7 @@ OutputSection *Writer::createSection(Str
.Case(".didat", DATA | R)
.Case(".idata", DATA | R)
.Case(".rdata", DATA | R)
+ .Case(".reloc", DATA | DISCARDABLE | R)
.Case(".text", CODE | R | X)
.Default(0);
if (!Perms)
@@ -388,5 +401,42 @@ OutputSection *Writer::createSection(Str
return Sec;
}
+// Dest is .reloc section. Add contents to that section.
+void Writer::addBaserels(OutputSection *Dest) {
+ std::vector<uint32_t> V;
+ Defined *ImageBase = cast<Defined>(Symtab->find("__ImageBase"));
+ for (OutputSection *Sec : OutputSections) {
+ if (Sec == Dest)
+ continue;
+ // Collect all locations for base relocations.
+ for (Chunk *C : Sec->getChunks())
+ C->getBaserels(&V, ImageBase);
+ // Add the addresses to .reloc section.
+ if (!V.empty())
+ addBaserelBlocks(Dest, V);
+ V.clear();
+ }
+}
+
+// Add addresses to .reloc section. Note that addresses are grouped by page.
+void Writer::addBaserelBlocks(OutputSection *Dest, std::vector<uint32_t> &V) {
+ const uint32_t Mask = ~uint32_t(PageSize - 1);
+ uint32_t Page = V[0] & Mask;
+ size_t I = 0, J = 1;
+ for (size_t E = V.size(); J < E; ++J) {
+ uint32_t P = V[J] & Mask;
+ if (P == Page)
+ continue;
+ BaserelChunk *Buf = BAlloc.Allocate();
+ Dest->addChunk(new (Buf) BaserelChunk(Page, &V[I], &V[0] + J));
+ I = J;
+ Page = P;
+ }
+ if (I == J)
+ return;
+ BaserelChunk *Buf = BAlloc.Allocate();
+ Dest->addChunk(new (Buf) BaserelChunk(Page, &V[I], &V[0] + J));
+}
+
} // namespace coff
} // namespace lld
Modified: lld/trunk/COFF/Writer.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.h?rev=239710&r1=239709&r2=239710&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.h (original)
+++ lld/trunk/COFF/Writer.h Sun Jun 14 20:23:58 2015
@@ -87,6 +87,8 @@ private:
OutputSection *findSection(StringRef Name);
OutputSection *createSection(StringRef Name);
+ void addBaserels(OutputSection *Dest);
+ void addBaserelBlocks(OutputSection *Dest, std::vector<uint32_t> &V);
uint32_t getSizeOfInitializedData();
std::map<StringRef, std::vector<DefinedImportData *>> binImports();
@@ -94,6 +96,7 @@ private:
SymbolTable *Symtab;
std::unique_ptr<llvm::FileOutputBuffer> Buffer;
llvm::SpecificBumpPtrAllocator<OutputSection> CAlloc;
+ llvm::SpecificBumpPtrAllocator<BaserelChunk> BAlloc;
std::vector<OutputSection *> OutputSections;
std::unique_ptr<IdataContents> Idata;
Added: lld/trunk/test/COFF/Inputs/baserel.obj.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/Inputs/baserel.obj.yaml?rev=239710&view=auto
==============================================================================
--- lld/trunk/test/COFF/Inputs/baserel.obj.yaml (added)
+++ lld/trunk/test/COFF/Inputs/baserel.obj.yaml Sun Jun 14 20:23:58 2015
@@ -0,0 +1,164 @@
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4096
+ SectionData: B800000000000000005068000000000000000068000000000000000050E8000000000000000050E8000000000000000050E80000000000000000
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: abs_symbol
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 7
+ SymbolName: caption
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 12
+ SymbolName: message
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 18
+ SymbolName: MessageBoxA
+ Type: IMAGE_REL_AMD64_REL32
+ - VirtualAddress: 24
+ SymbolName: ExitProcess
+ Type: IMAGE_REL_AMD64_REL32
+ - VirtualAddress: 30
+ SymbolName: __ImageBase
+ Type: IMAGE_REL_AMD64_ADDR64
+ - Name: .text2
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4096
+ SectionData: B800000000000000005068000000000000000068000000000000000050E8000000000000000050E8000000000000000050E80000000000000000
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: abs_symbol
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 7
+ SymbolName: caption
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 12
+ SymbolName: message
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 18
+ SymbolName: MessageBoxA
+ Type: IMAGE_REL_AMD64_REL32
+ - VirtualAddress: 24
+ SymbolName: ExitProcess
+ Type: IMAGE_REL_AMD64_REL32
+ - VirtualAddress: 30
+ SymbolName: __ImageBase
+ Type: IMAGE_REL_AMD64_ADDR64
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: 48656C6C6F0048656C6C6F20576F726C6400
+ - Name: .drectve
+ Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 2147483648
+ SectionData: 2F454E5452593A6D61696E20
+symbols:
+ - Name: "@comp.id"
+ Value: 10394907
+ SectionNumber: 65535
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 28
+ NumberOfRelocations: 6
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: .text2
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 28
+ NumberOfRelocations: 6
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: .data
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 18
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: MessageBoxA
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: ExitProcess
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: message
+ Value: 6
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: mainCRTStartup
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: caption
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: .drectve
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 12
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: .file
+ Value: 0
+ SectionNumber: 65534
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ File: "hello.c"
+ - Name: abs_symbol
+ Value: 0xDEADBEEF
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __ImageBase
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
Added: lld/trunk/test/COFF/baserel.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/baserel.test?rev=239710&view=auto
==============================================================================
--- lld/trunk/test/COFF/baserel.test (added)
+++ lld/trunk/test/COFF/baserel.test Sun Jun 14 20:23:58 2015
@@ -0,0 +1,72 @@
+# RUN: yaml2obj %p/Inputs/baserel.obj.yaml > %t.obj
+#
+# RUN: lld -flavor link2 /out:%t.exe %t.obj %p/Inputs/std64.lib
+# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck %s --check-prefix=BASEREL
+#
+# RUN: lld -flavor link2 /out:%t.exe /fixed %t.obj %p/Inputs/std64.lib
+# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck %s --check-prefix=NOBASEREL
+
+BASEREL: BaseReloc [
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: DIR64
+BASEREL-NEXT: Address: 0x2000
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: DIR64
+BASEREL-NEXT: Address: 0x2007
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: DIR64
+BASEREL-NEXT: Address: 0x200C
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: ABSOLUTE
+BASEREL-NEXT: Address: 0x2000
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: DIR64
+BASEREL-NEXT: Address: 0x3000
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: DIR64
+BASEREL-NEXT: Address: 0x3007
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: DIR64
+BASEREL-NEXT: Address: 0x300C
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: ABSOLUTE
+BASEREL-NEXT: Address: 0x3000
+BASEREL-NEXT: }
+
+NOBASEREL: BaseReloc [
+NOBASEREL-NEXT: ]
+
+# RUN: lld -flavor link2 /out:%t.exe %t.obj %p/Inputs/std64.lib
+# RUN: llvm-readobj -file-headers -sections %t.exe | FileCheck %s \
+# RUN: --check-prefix=BASEREL-HEADER
+#
+# RN: lld -flavor link2 /out:%t.exe /fixed %t.obj %p/Inputs/std64.lib
+# RN: llvm-readobj -file-headers %t.exe | FileCheck %s \
+# RN: --check-prefix=NOBASEREL-HEADER
+
+BASEREL-HEADER-NOT: IMAGE_FILE_RELOCS_STRIPPED
+
+NOBASEREL-HEADER: IMAGE_FILE_RELOCS_STRIPPED
+
+BASEREL-HEADER: BaseRelocationTableRVA: 0x5000
+BASEREL-HEADER: BaseRelocationTableSize: 0x20
+BASEREL-HEADER: Name: .reloc (2E 72 65 6C 6F 63 00 00)
+BASEREL-HEADER-NEXT: VirtualSize: 0x20
+BASEREL-HEADER-NEXT: VirtualAddress: 0x5000
+BASEREL-HEADER-NEXT: RawDataSize: 512
+BASEREL-HEADER-NEXT: PointerToRawData: 0x1800
+BASEREL-HEADER-NEXT: PointerToRelocations: 0x0
+BASEREL-HEADER-NEXT: PointerToLineNumbers: 0x0
+BASEREL-HEADER-NEXT: RelocationCount: 0
+BASEREL-HEADER-NEXT: LineNumberCount: 0
+BASEREL-HEADER-NEXT: Characteristics [ (0x40000040)
+BASEREL-HEADER-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
+BASEREL-HEADER-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
+BASEREL-HEADER-NEXT: ]
More information about the llvm-commits
mailing list