COFF: Fix SECREL and SECTION relocations.

SECREL should sets the 32-bit offset of the target from the beginning
of *target's* output section. Previously, the offset from the beginning
of source's output section was used instead.

SECTION means the target section's index, and not the source section's
index. This patch fixes that issue too.

llvm-svn: 243535
This commit is contained in:
Rui Ueyama 2015-07-29 16:30:45 +00:00
parent b4731a5847
commit eb26e1d03c
6 changed files with 116 additions and 48 deletions

View File

@ -50,8 +50,9 @@ 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); }
void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, uint64_t S,
void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym,
uint64_t P) {
uint64_t S = Sym->getRVA();
switch (Type) {
case IMAGE_REL_AMD64_ADDR32: add32(Off, S + Config->ImageBase); break;
case IMAGE_REL_AMD64_ADDR64: add64(Off, S + Config->ImageBase); break;
@ -62,22 +63,23 @@ void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, uint64_t S,
case IMAGE_REL_AMD64_REL32_3: add32(Off, S - P - 7); break;
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, Out->SectionIndex); break;
case IMAGE_REL_AMD64_SECREL: add32(Off, S - Out->getRVA()); break;
case IMAGE_REL_AMD64_SECTION: add16(Off, Sym->getSectionIndex()); break;
case IMAGE_REL_AMD64_SECREL: add32(Off, Sym->getSecrel()); break;
default:
llvm::report_fatal_error("Unsupported relocation type");
}
}
void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, uint64_t S,
void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, Defined *Sym,
uint64_t P) {
uint64_t S = Sym->getRVA();
switch (Type) {
case IMAGE_REL_I386_ABSOLUTE: break;
case IMAGE_REL_I386_DIR32: add32(Off, S + Config->ImageBase); break;
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, Out->SectionIndex); break;
case IMAGE_REL_I386_SECREL: add32(Off, S - Out->getRVA()); break;
case IMAGE_REL_I386_SECTION: add16(Off, Sym->getSectionIndex()); break;
case IMAGE_REL_I386_SECREL: add32(Off, Sym->getSecrel()); break;
default:
llvm::report_fatal_error("Unsupported relocation type");
}
@ -100,8 +102,9 @@ static void applyBranchImm(uint8_t *Off, int32_t V) {
or16(Off + 2, ((V >> 1) & 0x7ff) | (J2 << 11) | (J1 << 13));
}
void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, uint64_t S,
void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, Defined *Sym,
uint64_t P) {
uint64_t S = Sym->getRVA();
switch (Type) {
case IMAGE_REL_ARM_ADDR32: add32(Off, S + Config->ImageBase); break;
case IMAGE_REL_ARM_ADDR32NB: add32(Off, S); break;
@ -124,17 +127,17 @@ void SectionChunk::writeTo(uint8_t *Buf) {
for (const coff_relocation &Rel : Relocs) {
uint8_t *Off = Buf + FileOff + Rel.VirtualAddress;
SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex)->repl();
uint64_t S = cast<Defined>(Body)->getRVA();
Defined *Sym = cast<Defined>(Body);
uint64_t P = RVA + Rel.VirtualAddress;
switch (Config->Machine) {
case AMD64:
applyRelX64(Off, Rel.Type, S, P);
applyRelX64(Off, Rel.Type, Sym, P);
break;
case I386:
applyRelX86(Off, Rel.Type, S, P);
applyRelX86(Off, Rel.Type, Sym, P);
break;
case ARMNT:
applyRelARM(Off, Rel.Type, S, P);
applyRelARM(Off, Rel.Type, Sym, P);
break;
default:
llvm_unreachable("unknown machine type");

View File

@ -137,9 +137,9 @@ public:
StringRef getSectionName() const override { return SectionName; }
void getBaserels(std::vector<Baserel> *Res) override;
bool isCOMDAT() const;
void applyRelX64(uint8_t *Off, uint16_t Type, uint64_t S, uint64_t P);
void applyRelX86(uint8_t *Off, uint16_t Type, uint64_t S, uint64_t P);
void applyRelARM(uint8_t *Off, uint16_t Type, uint64_t S, uint64_t P);
void applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym, uint64_t P);
void applyRelX86(uint8_t *Off, uint16_t Type, Defined *Sym, uint64_t P);
void applyRelARM(uint8_t *Off, uint16_t Type, Defined *Sym, uint64_t P);
// Called if the garbage collector decides to not include this chunk
// in a final output. It's supposed to print out a log message to stdout.

View File

@ -130,6 +130,14 @@ public:
// Returns the file offset of this symbol in the final executable.
// The writer uses this information to apply relocations.
uint64_t getFileOff();
// Returns the RVA relative to the beginning of the output section.
// Used to implement SECREL relocation type.
uint64_t getSecrel();
// Returns the output section index.
// Used to implement SECTION relocation type.
uint64_t getSectionIndex();
};
// Symbols defined via a COFF object file.

View File

@ -678,5 +678,17 @@ void Writer::addBaserelBlocks(OutputSection *Dest, std::vector<Baserel> &V) {
Dest->addChunk(new (Buf) BaserelChunk(Page, &V[I], &V[0] + J));
}
uint64_t Defined::getSecrel() {
if (auto *D = dyn_cast<DefinedRegular>(this))
return getRVA() - D->getChunk()->getOutputSection()->getRVA();
llvm::report_fatal_error("SECREL relocation points to a non-regular symbol");
}
uint64_t Defined::getSectionIndex() {
if (auto *D = dyn_cast<DefinedRegular>(this))
return D->getChunk()->getOutputSection()->SectionIndex;
llvm::report_fatal_error("SECTION relocation points to a non-regular symbol");
}
} // namespace coff
} // namespace lld

View File

@ -3,16 +3,17 @@
# RUN: llvm-objdump -d %t.exe | FileCheck %s
# CHECK: .text:
# CHECK: 1000: a1 00 10 00 40 00 00 00 00
# CHECK: 1009: a1 00 10 00 40 01 00 00 00
# CHECK: 1012: a1 00 10 00 00 00 00 00 00
# CHECK: 101b: a1 e0 ff ff ff 00 00 00 00
# CHECK: 1024: a1 d6 ff ff ff 00 00 00 00
# CHECK: 102d: a1 cc ff ff ff 00 00 00 00
# CHECK: 1036: a1 c2 ff ff ff 00 00 00 00
# CHECK: 103f: a1 b8 ff ff ff 00 00 00 00
# CHECK: 1048: a1 ae ff ff ff 00 00 00 00
# CHECK: 1051: a1 01 00 00 00 00 00 00 00
# CHECK: 1000: a1 03 20 00 40 00 00 00 00
# CHECK: 1009: a1 03 20 00 40 01 00 00 00
# CHECK: 1012: a1 03 20 00 00 00 00 00 00
# CHECK: 101b: a1 e3 0f 00 00 00 00 00 00
# CHECK: 1024: a1 d9 0f 00 00 00 00 00 00
# CHECK: 102d: a1 cf 0f 00 00 00 00 00 00
# CHECK: 1036: a1 c5 0f 00 00 00 00 00 00
# CHECK: 103f: a1 bb 0f 00 00 00 00 00 00
# CHECK: 1048: a1 b1 0f 00 00 00 00 00 00
# CHECK: 1051: a1 02 00 00 00 00 00 00 00
# CHECK: 105a: a1 03 00 00 00 00 00 00 00
---
header:
@ -22,41 +23,45 @@ sections:
- Name: .text
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
Alignment: 4096
SectionData: A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000
SectionData: A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000
Relocations:
- VirtualAddress: 1
SymbolName: main
SymbolName: foo
Type: IMAGE_REL_AMD64_ADDR32
- VirtualAddress: 10
SymbolName: main
SymbolName: foo
Type: IMAGE_REL_AMD64_ADDR64
- VirtualAddress: 19
SymbolName: main
SymbolName: foo
Type: IMAGE_REL_AMD64_ADDR32NB
- VirtualAddress: 28
SymbolName: main
SymbolName: foo
Type: IMAGE_REL_AMD64_REL32
- VirtualAddress: 37
SymbolName: main
SymbolName: foo
Type: IMAGE_REL_AMD64_REL32_1
- VirtualAddress: 46
SymbolName: main
SymbolName: foo
Type: IMAGE_REL_AMD64_REL32_2
- VirtualAddress: 55
SymbolName: main
SymbolName: foo
Type: IMAGE_REL_AMD64_REL32_3
- VirtualAddress: 64
SymbolName: main
SymbolName: foo
Type: IMAGE_REL_AMD64_REL32_4
- VirtualAddress: 73
SymbolName: main
SymbolName: foo
Type: IMAGE_REL_AMD64_REL32_5
- VirtualAddress: 82
SymbolName: main
SymbolName: foo
Type: IMAGE_REL_AMD64_SECTION
- VirtualAddress: 91
SymbolName: main
SymbolName: foo
Type: IMAGE_REL_AMD64_SECREL
- Name: .zzz
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
Alignment: 4096
SectionData: 0000000000000000
symbols:
- Name: .text
Value: 0
@ -70,10 +75,28 @@ symbols:
NumberOfLinenumbers: 0
CheckSum: 0
Number: 0
- Name: .zzz
Value: 0
SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 8
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 0
Number: 0
- Name: main
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- Name: foo
Value: 3
SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
...

View File

@ -3,12 +3,12 @@
# RUN: llvm-objdump -d %t.exe | FileCheck %s
# CHECK: .text:
# CHECK: 1000: a1 00 00 00 00
# CHECK: 1005: a1 00 10 40 00
# CHECK: 100a: a1 00 10 00 00
# CHECK: 100f: a1 ec ff ff ff
# CHECK: 1014: a1 00 00 01 00
# CHECK: 1019: a1 00 00 00 00
# CHECK: 1000: a1 00 00 00 00
# CHECK: 1005: a1 03 20 40 00
# CHECK: 100a: a1 03 20 00 00
# CHECK: 100f: a1 ef 0f 00 00
# CHECK: 1014: a1 00 00 02 00
# CHECK: 1019: a1 03 00 00 00
---
header:
@ -21,23 +21,27 @@ sections:
SectionData: A100000000A100000000A100000000A100000000A100000000A100000000
Relocations:
- VirtualAddress: 1
SymbolName: _main
SymbolName: _foo
Type: IMAGE_REL_I386_ABSOLUTE
- VirtualAddress: 6
SymbolName: _main
SymbolName: _foo
Type: IMAGE_REL_I386_DIR32
- VirtualAddress: 11
SymbolName: _main
SymbolName: _foo
Type: IMAGE_REL_I386_DIR32NB
- VirtualAddress: 16
SymbolName: _main
SymbolName: _foo
Type: IMAGE_REL_I386_REL32
- VirtualAddress: 23
SymbolName: _main
SymbolName: _foo
Type: IMAGE_REL_I386_SECTION
- VirtualAddress: 26
SymbolName: _main
SymbolName: _foo
Type: IMAGE_REL_I386_SECREL
- Name: .zzz
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
Alignment: 4096
SectionData: 0000000000000000
symbols:
- Name: .text
Value: 0
@ -51,10 +55,28 @@ symbols:
NumberOfLinenumbers: 0
CheckSum: 0
Number: 0
- Name: .zzz
Value: 0
SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 8
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 0
Number: 0
- Name: _main
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- Name: _foo
Value: 3
SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
...