forked from OSchip/llvm-project
[PECOFF] Implement IMAGE_REL_I386_{SECTION,SECREL} relocations.
These relocations are used in .debug section. llvm-svn: 196262
This commit is contained in:
parent
14b02848a3
commit
fac7332d71
|
@ -180,6 +180,8 @@ PECOFFLinkingContext::relocKindFromString(StringRef str) const {
|
|||
LLD_CASE(IMAGE_REL_I386_ABSOLUTE)
|
||||
LLD_CASE(IMAGE_REL_I386_DIR32)
|
||||
LLD_CASE(IMAGE_REL_I386_DIR32NB)
|
||||
LLD_CASE(IMAGE_REL_I386_SECTION)
|
||||
LLD_CASE(IMAGE_REL_I386_SECREL)
|
||||
LLD_CASE(IMAGE_REL_I386_REL32)
|
||||
.Default(-1);
|
||||
#undef LLD_CASE
|
||||
|
@ -198,6 +200,8 @@ PECOFFLinkingContext::stringFromRelocKind(Reference::Kind kind) const {
|
|||
LLD_CASE(IMAGE_REL_I386_ABSOLUTE)
|
||||
LLD_CASE(IMAGE_REL_I386_DIR32)
|
||||
LLD_CASE(IMAGE_REL_I386_DIR32NB)
|
||||
LLD_CASE(IMAGE_REL_I386_SECTION)
|
||||
LLD_CASE(IMAGE_REL_I386_SECREL)
|
||||
LLD_CASE(IMAGE_REL_I386_REL32)
|
||||
#undef LLD_CASE
|
||||
}
|
||||
|
|
|
@ -195,6 +195,7 @@ public:
|
|||
|
||||
void applyRelocations(uint8_t *fileBuffer,
|
||||
std::map<const Atom *, uint64_t> &atomRva,
|
||||
std::vector<uint64_t> §ionRva,
|
||||
uint64_t imageBaseAddress);
|
||||
void printAtomAddresses(uint64_t baseAddr);
|
||||
void addBaseRelocations(std::vector<uint64_t> &relocSites);
|
||||
|
@ -505,16 +506,18 @@ void AtomChunk::write(uint8_t *fileBuffer) {
|
|||
|
||||
void AtomChunk::applyRelocations(uint8_t *fileBuffer,
|
||||
std::map<const Atom *, uint64_t> &atomRva,
|
||||
std::vector<uint64_t> §ionRva,
|
||||
uint64_t imageBaseAddress) {
|
||||
for (const auto *layout : _atomLayouts) {
|
||||
const DefinedAtom *atom = cast<DefinedAtom>(layout->_atom);
|
||||
for (const Reference *ref : *atom) {
|
||||
auto relocSite = reinterpret_cast<ulittle32_t *>(
|
||||
auto relocSite32 = reinterpret_cast<ulittle32_t *>(
|
||||
fileBuffer + layout->_fileOffset + ref->offsetInAtom());
|
||||
auto relocSite16 = reinterpret_cast<ulittle16_t *>(relocSite32);
|
||||
uint64_t targetAddr = atomRva[ref->target()];
|
||||
// Also account for whatever offset is already stored at the relocation
|
||||
// site.
|
||||
targetAddr += *relocSite;
|
||||
targetAddr += *relocSite32;
|
||||
|
||||
// Skip if this reference is not for relocation.
|
||||
if (ref->kind() < lld::Reference::kindTargetLow)
|
||||
|
@ -526,19 +529,42 @@ void AtomChunk::applyRelocations(uint8_t *fileBuffer,
|
|||
break;
|
||||
case llvm::COFF::IMAGE_REL_I386_DIR32:
|
||||
// Set target's 32-bit VA.
|
||||
*relocSite = targetAddr + imageBaseAddress;
|
||||
*relocSite32 = targetAddr + imageBaseAddress;
|
||||
break;
|
||||
case llvm::COFF::IMAGE_REL_I386_DIR32NB:
|
||||
// Set target's 32-bit RVA.
|
||||
*relocSite = targetAddr;
|
||||
*relocSite32 = targetAddr;
|
||||
break;
|
||||
case llvm::COFF::IMAGE_REL_I386_REL32: {
|
||||
// Set 32-bit relative address of the target. This relocation is
|
||||
// usually used for relative branch or call instruction.
|
||||
uint32_t disp = atomRva[atom] + ref->offsetInAtom() + 4;
|
||||
*relocSite = targetAddr - disp;
|
||||
*relocSite32 = targetAddr - disp;
|
||||
break;
|
||||
}
|
||||
case llvm::COFF::IMAGE_REL_I386_SECTION: {
|
||||
// The 16-bit section index that contains the target symbol.
|
||||
uint16_t i = 1;
|
||||
for (uint64_t rva : sectionRva) {
|
||||
if (targetAddr < rva) {
|
||||
*relocSite16 = i;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case llvm::COFF::IMAGE_REL_I386_SECREL:
|
||||
// The 32-bit relative address from the beginning of the section that
|
||||
// contains the target symbol.
|
||||
for (int i = 0, e = sectionRva.size(); i < e; ++i) {
|
||||
if (i == e - 1 ||
|
||||
(sectionRva[i] <= targetAddr && targetAddr <= sectionRva[i + 1])) {
|
||||
*relocSite32 = targetAddr - sectionRva[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Unsupported relocation kind");
|
||||
}
|
||||
|
@ -860,6 +886,9 @@ private:
|
|||
|
||||
// The map from defined atoms to its RVAs. Will be used for relocation.
|
||||
std::map<const Atom *, uint64_t> atomRva;
|
||||
|
||||
// List of section RVAs. Will be used for relocation.
|
||||
std::vector<uint64_t> sectionRva;
|
||||
};
|
||||
|
||||
StringRef customSectionName(const DefinedAtom *atom) {
|
||||
|
@ -930,11 +959,13 @@ void ExecutableWriter::build(const File &linkedFile) {
|
|||
|
||||
SectionChunk *text = nullptr;
|
||||
SectionChunk *data = nullptr;
|
||||
std::vector<SectionChunk *> sectionChunks;
|
||||
for (auto i : atoms) {
|
||||
StringRef sectionName = i.first;
|
||||
std::vector<const DefinedAtom *> &contents = i.second;
|
||||
auto *section = new GenericSectionChunk(_PECOFFLinkingContext, sectionName,
|
||||
contents);
|
||||
sectionChunks.push_back(section);
|
||||
addSectionChunk(section, sectionTable);
|
||||
|
||||
if (!text && sectionName == ".text")
|
||||
|
@ -961,6 +992,9 @@ void ExecutableWriter::build(const File &linkedFile) {
|
|||
|
||||
setImageSizeOnDisk();
|
||||
|
||||
for (SectionChunk *p : sectionChunks)
|
||||
sectionRva.push_back(p->getVirtualAddress());
|
||||
|
||||
// Now that we know the size and file offset of sections. Set the file
|
||||
// header accordingly.
|
||||
peHeader->setSizeOfCode(calcSizeOfCode());
|
||||
|
@ -1005,7 +1039,7 @@ error_code ExecutableWriter::writeFile(const File &linkedFile, StringRef path) {
|
|||
void ExecutableWriter::applyAllRelocations(uint8_t *bufferStart) {
|
||||
for (auto &cp : _chunks)
|
||||
if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp))
|
||||
chunk->applyRelocations(bufferStart, atomRva,
|
||||
chunk->applyRelocations(bufferStart, atomRva, sectionRva,
|
||||
_PECOFFLinkingContext.getBaseAddress());
|
||||
}
|
||||
|
||||
|
|
|
@ -6,15 +6,21 @@ sections:
|
|||
- Name: .text
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 16
|
||||
SectionData: 5589E583EC14C745FC00000000C744240C00000000C744240807000000C744240400000000C7042400000000FF150000000083EC1031C083C4145DC3
|
||||
SectionData: 68000000006800000000680000000068000000006800000000
|
||||
Relocations:
|
||||
- VirtualAddress: 25
|
||||
- VirtualAddress: 1
|
||||
SymbolName: _message
|
||||
Type: IMAGE_REL_I386_SECTION
|
||||
- VirtualAddress: 6
|
||||
SymbolName: _message
|
||||
Type: IMAGE_REL_I386_SECREL
|
||||
- VirtualAddress: 11
|
||||
SymbolName: .data
|
||||
Type: IMAGE_REL_I386_DIR32
|
||||
- VirtualAddress: 33
|
||||
- VirtualAddress: 16
|
||||
SymbolName: .data
|
||||
Type: IMAGE_REL_I386_DIR32
|
||||
- VirtualAddress: 46
|
||||
- VirtualAddress: 21
|
||||
SymbolName: __imp__MessageBoxA@16
|
||||
Type: IMAGE_REL_I386_DIR32
|
||||
- Name: .data
|
||||
|
@ -44,6 +50,12 @@ symbols:
|
|||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
- Name: _message
|
||||
Value: 5
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
- Name: __imp__MessageBoxA@16
|
||||
Value: 0
|
||||
SectionNumber: 0
|
||||
|
|
|
@ -1,40 +1,11 @@
|
|||
# RUN: yaml2obj %p/Inputs/reloc.obj.yaml > %t.obj
|
||||
#
|
||||
# RUN: llvm-objdump -d %t.obj | FileCheck -check-prefix=BEFORE %s
|
||||
#
|
||||
# RUN: lld -flavor link /out:%t1 /subsystem:console /force /opt:noref \
|
||||
# RUN: -- %t.obj && llvm-objdump -d %t1 | FileCheck -check-prefix=AFTER %s
|
||||
# RUN: -- %t.obj && llvm-objdump -d %t1 | FileCheck %s
|
||||
|
||||
BEFORE: Disassembly of section .text:
|
||||
BEFORE: _main:
|
||||
BEFORE: 0: 55
|
||||
BEFORE: 1: 89 e5
|
||||
BEFORE: 3: 83 ec 14
|
||||
BEFORE: 6: c7 45 fc 00 00 00 00
|
||||
BEFORE: d: c7 44 24 0c 00 00 00 00
|
||||
BEFORE: 15: c7 44 24 08 07 00 00 00
|
||||
BEFORE: 1d: c7 44 24 04 00 00 00 00
|
||||
BEFORE: 25: c7 04 24 00 00 00 00
|
||||
BEFORE: 2c: ff 15 00 00 00 00
|
||||
BEFORE: 32: 83 ec 10
|
||||
BEFORE: 35: 31 c0
|
||||
BEFORE: 37: 83 c4 14
|
||||
BEFORE: 3a: 5d
|
||||
BEFORE: 3b: c3
|
||||
|
||||
AFTER: Disassembly of section .text:
|
||||
AFTER: .text:
|
||||
AFTER: pushl %ebp
|
||||
AFTER: movl %esp, %ebp
|
||||
AFTER: subl $20, %esp
|
||||
AFTER: movl $0, -4(%ebp)
|
||||
AFTER: movl $0, 12(%esp)
|
||||
AFTER: movl $4198407, 8(%esp)
|
||||
AFTER: movl $4198400, 4(%esp)
|
||||
AFTER: movl $0, (%esp)
|
||||
AFTER: calll *4194304
|
||||
AFTER: subl $16, %esp
|
||||
AFTER: xorl %eax, %eax
|
||||
AFTER: addl $20, %esp
|
||||
AFTER: popl %ebp
|
||||
AFTER: ret
|
||||
CHECK: .text:
|
||||
CHECK: 2000: 68 02 00 00 00
|
||||
CHECK: 2005: 68 05 00 00 00
|
||||
CHECK: 200a: 68 00 10 40 00
|
||||
CHECK: 200f: 68 00 10 40 00
|
||||
CHECK: 2014: 68 00 00 40 00
|
||||
|
|
Loading…
Reference in New Issue