COFF: Use COFFObjectFile::getRelocations(). NFC.

llvm-svn: 240614
This commit is contained in:
Rui Ueyama 2015-06-25 00:33:38 +00:00
parent e9247ab6d6
commit 42aa00b34b
2 changed files with 38 additions and 63 deletions

View File

@ -28,7 +28,8 @@ namespace lld {
namespace coff {
SectionChunk::SectionChunk(ObjectFile *F, const coff_section *H)
: File(F), Ptr(this), Header(H) {
: File(F), Ptr(this), Header(H),
Relocs(File->getCOFFObj()->getRelocations(Header)) {
// Initialize SectionName.
File->getCOFFObj()->getSectionName(Header, SectionName);
@ -49,6 +50,10 @@ SectionChunk::SectionChunk(ObjectFile *F, const coff_section *H)
Root = true;
}
static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); }
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); }
void SectionChunk::writeTo(uint8_t *Buf) {
if (!hasData())
return;
@ -58,8 +63,27 @@ void SectionChunk::writeTo(uint8_t *Buf) {
memcpy(Buf + FileOff, Data.data(), Data.size());
// Apply relocations.
for (const coff_relocation *Rel = relBegin(), *E = relEnd(); Rel != E; ++Rel)
applyReloc(Buf, Rel);
for (const coff_relocation &Rel : Relocs) {
uint8_t *Off = Buf + FileOff + Rel.VirtualAddress;
SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex);
uint64_t S = cast<Defined>(Body)->getRVA();
uint64_t P = RVA + Rel.VirtualAddress;
switch (Rel.Type) {
case IMAGE_REL_AMD64_ADDR32: add32(Off, S + Config->ImageBase); break;
case IMAGE_REL_AMD64_ADDR64: add64(Off, S + Config->ImageBase); break;
case IMAGE_REL_AMD64_ADDR32NB: add32(Off, S); break;
case IMAGE_REL_AMD64_REL32: add32(Off, S - P - 4); break;
case IMAGE_REL_AMD64_REL32_1: add32(Off, S - P - 5); break;
case IMAGE_REL_AMD64_REL32_2: add32(Off, S - P - 6); break;
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->getSectionIndex()); break;
case IMAGE_REL_AMD64_SECREL: add32(Off, S - Out->getRVA()); break;
default:
llvm::report_fatal_error("Unsupported relocation type");
}
}
}
void SectionChunk::mark() {
@ -67,9 +91,8 @@ void SectionChunk::mark() {
Live = true;
// Mark all symbols listed in the relocation table for this section.
for (const coff_relocation *Rel = relBegin(), *E = relEnd(); Rel != E;
++Rel) {
SymbolBody *B = File->getSymbolBody(Rel->SymbolTableIndex);
for (const coff_relocation &Rel : Relocs) {
SymbolBody *B = File->getSymbolBody(Rel.SymbolTableIndex);
if (auto *Def = dyn_cast<Defined>(B))
Def->markLive();
}
@ -86,49 +109,21 @@ void SectionChunk::addAssociative(SectionChunk *Child) {
Child->Root = false;
}
static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); }
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); }
// Implements x64 PE/COFF relocations.
void SectionChunk::applyReloc(uint8_t *Buf, const coff_relocation *Rel) {
uint8_t *Off = Buf + FileOff + Rel->VirtualAddress;
SymbolBody *Body = File->getSymbolBody(Rel->SymbolTableIndex);
uint64_t S = cast<Defined>(Body)->getRVA();
uint64_t P = RVA + Rel->VirtualAddress;
switch (Rel->Type) {
case IMAGE_REL_AMD64_ADDR32: add32(Off, S + Config->ImageBase); break;
case IMAGE_REL_AMD64_ADDR64: add64(Off, S + Config->ImageBase); break;
case IMAGE_REL_AMD64_ADDR32NB: add32(Off, S); break;
case IMAGE_REL_AMD64_REL32: add32(Off, S - P - 4); break;
case IMAGE_REL_AMD64_REL32_1: add32(Off, S - P - 5); break;
case IMAGE_REL_AMD64_REL32_2: add32(Off, S - P - 6); break;
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->getSectionIndex()); break;
case IMAGE_REL_AMD64_SECREL: add32(Off, S - Out->getRVA()); break;
default:
llvm::report_fatal_error("Unsupported relocation type");
}
}
// 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 coff_relocation *Rel = relBegin(), *E = relEnd(); Rel != E;
++Rel) {
for (const coff_relocation &Rel : Relocs) {
// ADDR64 relocations contain absolute addresses.
// Symbol __ImageBase is special -- it's an absolute symbol, but its
// address never changes even if image is relocated.
if (Rel->Type != IMAGE_REL_AMD64_ADDR64)
if (Rel.Type != IMAGE_REL_AMD64_ADDR64)
continue;
SymbolBody *Body = File->getSymbolBody(Rel->SymbolTableIndex);
SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex);
if (Body == ImageBase)
continue;
Res->push_back(RVA + Rel->VirtualAddress);
Res->push_back(RVA + Rel.VirtualAddress);
}
}
@ -188,9 +183,9 @@ bool SectionChunk::equals(const SectionChunk *X) const {
return false;
// Compare relocations
const coff_relocation *Rel1 = relBegin();
const coff_relocation *End = relEnd();
const coff_relocation *Rel2 = X->relBegin();
const coff_relocation *Rel1 = Relocs.begin();
const coff_relocation *End = Relocs.end();
const coff_relocation *Rel2 = X->Relocs.begin();
for (; Rel1 != End; ++Rel1, ++Rel2) {
if (Rel1->Type != Rel2->Type)
return false;
@ -220,22 +215,6 @@ void SectionChunk::replaceWith(SectionChunk *Other) {
Live = false;
}
const coff_relocation *SectionChunk::relBegin() const {
if (!Reloc) {
DataRefImpl Ref;
Ref.p = uintptr_t(Header);
SectionRef Sref(Ref, File->getCOFFObj());
relocation_iterator It = Sref.relocation_begin();
Reloc = File->getCOFFObj()->getCOFFRelocation(*It);
}
return Reloc;
}
const coff_relocation *SectionChunk::relEnd() const {
const coff_relocation *I = relBegin();
return I + Header->NumberOfRelocations;
}
CommonChunk::CommonChunk(const COFFSymbolRef S) : Sym(S) {
// Common symbols are aligned on natural boundaries up to 32 bytes.
// This is what MSVC link.exe does.

View File

@ -12,6 +12,7 @@
#include "lld/Core/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Object/COFF.h"
#include <map>
#include <vector>
@ -149,16 +150,10 @@ public:
private:
void mark() override;
void applyReloc(uint8_t *Buf, const coff_relocation *Rel);
// A file this chunk was created from.
ObjectFile *File;
// A raw pointer to the relocation table.
mutable const coff_relocation *Reloc = nullptr;
const coff_relocation *relBegin() const;
const coff_relocation *relEnd() const;
// A pointer pointing to a replacement for this chunk.
// Initially it points to "this" object. If this chunk is merged
// with other chunk by ICF, it points to another chunk,
@ -168,6 +163,7 @@ private:
const coff_section *Header;
StringRef SectionName;
std::vector<Chunk *> AssocChildren;
llvm::iterator_range<const coff_relocation *> Relocs;
// Chunks are basically unnamed chunks of bytes.
// Symbols are associated for debugging and logging purposs only.