[COFF] Fix SECTION and SECREL relocation handling for absolute symbols

Summary:
For SECTION relocations against absolute symbols, MSVC emits the largest
output section index plus one. I've implemented that by threading a
global variable through DefinedAbsolute that is filled in by the Writer.
A more library-oriented approach would be to thread the Writer through
Chunk::writeTo and SectionChunk::applyRel*, but Rui seems to prefer
doing it this way.

MSVC rejects SECREL relocations against absolute symbols, but only when
the relocation is in a real output section. When the relocation is in a
CodeView debug info section destined for the PDB, it seems that this
relocation error is suppressed, and absolute symbols become zeros in the
object file. This is easily implemented by checking the input section
from which we're applying relocations.

This should fix errors about __safe_se_handler_table and
__guard_fids_table when linking the CRT and generating a PDB.

Reviewers: ruiu

Subscribers: aprantl, llvm-commits

Differential Revision: https://reviews.llvm.org/D34541

llvm-svn: 306071
This commit is contained in:
Reid Kleckner 2017-06-22 23:33:04 +00:00
parent d49711996f
commit 8456411e3b
7 changed files with 156 additions and 3 deletions

View File

@ -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));
}

View File

@ -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);

View File

@ -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;
};

View File

@ -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();

View File

@ -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
...

View File

@ -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: ]

View File

@ -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