summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/COFF/Chunks.cpp15
-rw-r--r--lld/COFF/Symbols.cpp2
-rw-r--r--lld/COFF/Symbols.h5
-rw-r--r--lld/COFF/Writer.cpp6
-rw-r--r--lld/test/COFF/pdb-secrel-absolute.yaml84
-rw-r--r--lld/test/COFF/secidx-absolute.s33
-rw-r--r--lld/test/COFF/secrel-absolute.s14
7 files changed, 156 insertions, 3 deletions
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index 1d5ae5571d2..56124acaf9a 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -52,6 +52,15 @@ static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); }
static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); }
static void or16(uint8_t *P, uint16_t V) { write16le(P, read16le(P) | V); }
+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();
@@ -66,7 +75,7 @@ void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym,
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));
}
@@ -81,7 +90,7 @@ void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, Defined *Sym,
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));
}
@@ -141,7 +150,7 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, Defined *Sym,
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));
}
diff --git a/lld/COFF/Symbols.cpp b/lld/COFF/Symbols.cpp
index 5c185a511dd..1cf2934a355 100644
--- a/lld/COFF/Symbols.cpp
+++ b/lld/COFF/Symbols.cpp
@@ -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);
diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h
index 801fc87f91d..828744b8ff3 100644
--- a/lld/COFF/Symbols.h
+++ b/lld/COFF/Symbols.h
@@ -212,6 +212,11 @@ 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;
};
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index d31f0c3d57a..c67fac59f92 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -219,6 +219,8 @@ uint64_t Defined::getSecrel() {
uint64_t Defined::getSectionIndex() {
if (auto *D = dyn_cast<DefinedRegular>(this))
return D->getChunk()->getOutputSection()->SectionIndex;
+ if (auto *D = dyn_cast<DefinedAbsolute>(this))
+ return DefinedAbsolute::OutputSectionIndex;
fatal("SECTION relocation points to a non-regular symbol: " +
toString(*this));
}
@@ -775,6 +777,10 @@ void Writer::setSectionPermissions() {
// Write section contents to a mmap'ed file.
void Writer::writeSections() {
+ // Record the section index that should be used when resolving a section
+ // relocation against an absolute symbol.
+ DefinedAbsolute::OutputSectionIndex = OutputSections.size() + 1;
+
uint8_t *Buf = Buffer->getBufferStart();
for (OutputSection *Sec : OutputSections) {
uint8_t *SecBuf = Buf + Sec->getFileOff();
diff --git a/lld/test/COFF/pdb-secrel-absolute.yaml b/lld/test/COFF/pdb-secrel-absolute.yaml
new file mode 100644
index 00000000000..61bcd562766
--- /dev/null
+++ b/lld/test/COFF/pdb-secrel-absolute.yaml
@@ -0,0 +1,84 @@
+# RUN: yaml2obj %s -o %t.obj
+# RUN: lld-link -debug -entry:main -out:%t.exe -pdb:%t.pdb %t.obj
+# RUN: llvm-pdbutil raw -symbols %t.pdb | FileCheck %s
+
+# There is an S_GDATA32 symbol record with .secrel32 and .secidx relocations in
+# it in this debug info. This is similar to the relocations in the loadcfg.obj
+# file in the MSVC CRT. We need to make sure that our relocation logic matches
+# MSVC's for these absolute, linker-provided symbols.
+
+# CHECK: Mod 0000 |
+# CHECK-NEXT: - S_GDATA32 [size = 36] `__guard_fids_table`
+# CHECK-NEXT: type = 0x0022 (unsigned long), addr = 0003:0000
+# CHECK-NEXT: Mod 0001 | `* Linker *`:
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: '.debug$S'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 1
+ Subsections:
+ - !Symbols
+ Records:
+ - Kind: S_GDATA32
+ DataSym:
+ Type: 34
+ DisplayName: __guard_fids_table
+ - !StringTable
+ Strings:
+ Relocations:
+ - VirtualAddress: 20
+ SymbolName: __guard_fids_table
+ Type: IMAGE_REL_AMD64_SECREL
+ - VirtualAddress: 24
+ SymbolName: __guard_fids_table
+ Type: IMAGE_REL_AMD64_SECTION
+ - Name: '.text$mn'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 488D0500000000C3
+ Relocations:
+ - VirtualAddress: 3
+ SymbolName: __guard_fids_table
+ Type: IMAGE_REL_AMD64_REL32
+symbols:
+ - Name: '.debug$S'
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 372
+ NumberOfRelocations: 6
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: '.text$mn'
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 8
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 1092178131
+ Number: 0
+ - Name: main
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __guard_fids_table
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/secidx-absolute.s b/lld/test/COFF/secidx-absolute.s
new file mode 100644
index 00000000000..bfe7136b31d
--- /dev/null
+++ b/lld/test/COFF/secidx-absolute.s
@@ -0,0 +1,33 @@
+# RUN: llvm-mc %s -filetype=obj -triple=x86_64-windows-msvc -o %t.obj
+# RUN: lld-link -entry:main -nodefaultlib %t.obj -out:%t.exe
+# RUN: llvm-readobj %t.exe -sections -section-data | FileCheck %s
+
+# Section relocations against absolute symbols resolve to the last real ouput
+# section index plus one.
+
+.text
+.global main
+main:
+ret
+
+.section .rdata,"dr"
+.secidx __guard_fids_table
+
+# CHECK: Sections [
+# CHECK: Section {
+# CHECK: Number: 1
+# CHECK: Name: .rdata (2E 72 64 61 74 61 00 00)
+# CHECK: SectionData (
+# CHECK: 0000: 0300 |..|
+# CHECK: )
+# CHECK: }
+# CHECK: Section {
+# CHECK: Number: 2
+# CHECK: Name: .text (2E 74 65 78 74 00 00 00)
+# CHECK: VirtualSize: 0x1
+# CHECK: SectionData (
+# CHECK: 0000: C3 |.|
+# CHECK: )
+# CHECK: }
+# CHECK-NOT: Section
+# CHECK: ]
diff --git a/lld/test/COFF/secrel-absolute.s b/lld/test/COFF/secrel-absolute.s
new file mode 100644
index 00000000000..69b5ab92991
--- /dev/null
+++ b/lld/test/COFF/secrel-absolute.s
@@ -0,0 +1,14 @@
+# RUN: llvm-mc %s -filetype=obj -triple=x86_64-windows-msvc -o %t.obj
+# RUN: not lld-link -entry:main -nodefaultlib %t.obj -out:%t.exe 2>&1 | FileCheck %s
+
+# secrel relocations against absolute symbols are errors.
+
+# CHECK: SECREL relocation points to a non-regular symbol: __guard_fids_table
+
+.text
+.global main
+main:
+ret
+
+.section .rdata,"dr"
+.secrel32 __guard_fids_table
OpenPOWER on IntegriCloud