From 3d371bd84bf7af139c961c7d8363776e0b322987 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 8 Oct 2014 06:38:50 +0000 Subject: [PATCH] llvm-dwarfdump: Add support for some COFF relocations DWARF in COFF utilizes several relocations. Implement support for them in RelocVisitor to support llvm-dwarfdump. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219280 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/ELFObjectFile.h | 2 + include/llvm/Object/RelocVisitor.h | 106 ++++++++++++++------ lib/DebugInfo/DWARFContext.cpp | 9 +- test/DebugInfo/X86/processes-relocations.ll | 6 +- 4 files changed, 87 insertions(+), 36 deletions(-) diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 2c9c07a48d2..9e18a204b21 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -47,6 +47,8 @@ public: virtual std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, bool &IsDefault) const = 0; + + static inline bool classof(const Binary *v) { return v->isELF(); } }; template class ELFObjectFile : public ELFObjectFileBase { diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index 9eb768daa0a..4fffd7eec28 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -17,6 +17,7 @@ #define LLVM_OBJECT_RELOCVISITOR_H #include "llvm/ADT/StringRef.h" +#include "llvm/Object/COFF.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" @@ -46,8 +47,23 @@ public: // TODO: Should handle multiple applied relocations via either passing in the // previously computed value or just count paired relocations as a single // visit. - RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t SecAddr = 0, - uint64_t Value = 0) { + RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t Value = 0) { + if (isa(ObjToVisit)) + return visitELF(RelocType, R, Value); + if (isa(ObjToVisit)) + return visitCOFF(RelocType, R, Value); + + HasError = true; + return RelocToApply(); + } + + bool error() { return HasError; } + +private: + ObjectFile &ObjToVisit; + bool HasError; + + RelocToApply visitELF(uint32_t RelocType, RelocationRef R, uint64_t Value) { if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file switch (ObjToVisit.getArch()) { case Triple::x86_64: @@ -57,7 +73,7 @@ public: case llvm::ELF::R_X86_64_64: return visitELF_X86_64_64(R, Value); case llvm::ELF::R_X86_64_PC32: - return visitELF_X86_64_PC32(R, Value, SecAddr); + return visitELF_X86_64_PC32(R, Value); case llvm::ELF::R_X86_64_32: return visitELF_X86_64_32(R, Value); case llvm::ELF::R_X86_64_32S: @@ -133,7 +149,7 @@ public: case llvm::ELF::R_386_32: return visitELF_386_32(R, Value); case llvm::ELF::R_386_PC32: - return visitELF_386_PC32(R, Value, SecAddr); + return visitELF_386_PC32(R, Value); default: HasError = true; return RelocToApply(); @@ -182,13 +198,30 @@ public: } } - bool error() { return HasError; } - -private: - ObjectFile &ObjToVisit; - bool HasError; + RelocToApply visitCOFF(uint32_t RelocType, RelocationRef R, uint64_t Value) { + switch (ObjToVisit.getArch()) { + case Triple::x86: + switch (RelocType) { + case COFF::IMAGE_REL_I386_SECREL: + return visitCOFF_I386_SECREL(R, Value); + case COFF::IMAGE_REL_I386_DIR32: + return visitCOFF_I386_DIR32(R, Value); + } + break; + case Triple::x86_64: + switch (RelocType) { + case COFF::IMAGE_REL_AMD64_SECREL: + return visitCOFF_AMD64_SECREL(R, Value); + case COFF::IMAGE_REL_AMD64_ADDR64: + return visitCOFF_AMD64_ADDR64(R, Value); + } + break; + } + HasError = true; + return RelocToApply(); + } - int64_t getAddend32LE(RelocationRef R) { + int64_t getELFAddend32LE(RelocationRef R) { const ELF32LEObjectFile *Obj = cast(R.getObjectFile()); DataRefImpl DRI = R.getRawDataRefImpl(); int64_t Addend; @@ -196,7 +229,7 @@ private: return Addend; } - int64_t getAddend64LE(RelocationRef R) { + int64_t getELFAddend64LE(RelocationRef R) { const ELF64LEObjectFile *Obj = cast(R.getObjectFile()); DataRefImpl DRI = R.getRawDataRefImpl(); int64_t Addend; @@ -204,7 +237,7 @@ private: return Addend; } - int64_t getAddend32BE(RelocationRef R) { + int64_t getELFAddend32BE(RelocationRef R) { const ELF32BEObjectFile *Obj = cast(R.getObjectFile()); DataRefImpl DRI = R.getRawDataRefImpl(); int64_t Addend; @@ -212,7 +245,7 @@ private: return Addend; } - int64_t getAddend64BE(RelocationRef R) { + int64_t getELFAddend64BE(RelocationRef R) { const ELF64BEObjectFile *Obj = cast(R.getObjectFile()); DataRefImpl DRI = R.getRawDataRefImpl(); int64_t Addend; @@ -229,13 +262,12 @@ private: // Ideally the Addend here will be the addend in the data for // the relocation. It's not actually the case for Rel relocations. RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend32LE(R); + int64_t Addend = getELFAddend32LE(R); return RelocToApply(Value + Addend, 4); } - RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value, - uint64_t SecAddr) { - int64_t Addend = getAddend32LE(R); + RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value) { + int64_t Addend = getELFAddend32LE(R); uint64_t Address; R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); @@ -246,23 +278,22 @@ private: return RelocToApply(0, 0); } RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend = getELFAddend64LE(R); return RelocToApply(Value + Addend, 8); } - RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value, - uint64_t SecAddr) { - int64_t Addend = getAddend64LE(R); + RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) { + int64_t Addend = getELFAddend64LE(R); uint64_t Address; R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); } RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend = getELFAddend64LE(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend = getELFAddend64LE(R); int32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } @@ -282,7 +313,7 @@ private: /// PPC32 ELF RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend32BE(R); + int64_t Addend = getELFAddend32BE(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } @@ -323,7 +354,7 @@ private: // SystemZ ELF RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64BE(R); + int64_t Addend = getELFAddend64BE(R); int64_t Res = Value + Addend; // Overflow check allows for both signed and unsigned interpretation. @@ -334,22 +365,22 @@ private: } RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64BE(R); + int64_t Addend = getELFAddend64BE(R); return RelocToApply(Value + Addend, 8); } RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) { - int32_t Addend = getAddend32BE(R); + int32_t Addend = getELFAddend32BE(R); return RelocToApply(Value + Addend, 4); } RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) { - int32_t Addend = getAddend64BE(R); + int32_t Addend = getELFAddend64BE(R); return RelocToApply(Value + Addend, 4); } RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64BE(R); + int64_t Addend = getELFAddend64BE(R); return RelocToApply(Value + Addend, 8); } @@ -365,6 +396,23 @@ private: return RelocToApply(static_cast(Res), 4); } + /// I386 COFF + RelocToApply visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) { + return RelocToApply(static_cast(Value), /*Width=*/4); + } + + RelocToApply visitCOFF_I386_DIR32(RelocationRef R, uint64_t Value) { + return RelocToApply(static_cast(Value), /*Width=*/4); + } + + /// AMD64 COFF + RelocToApply visitCOFF_AMD64_SECREL(RelocationRef R, uint64_t Value) { + return RelocToApply(static_cast(Value), /*Width=*/4); + } + + RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) { + return RelocToApply(Value, /*Width=*/8); + } }; } diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp index 2cacfd9b949..a1216391bd9 100644 --- a/lib/DebugInfo/DWARFContext.cpp +++ b/lib/DebugInfo/DWARFContext.cpp @@ -620,15 +620,12 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile &Obj) uint64_t Type; Reloc.getType(Type); uint64_t SymAddr = 0; - // ELF relocations may need the symbol address - if (Obj.isELF()) { - object::symbol_iterator Sym = Reloc.getSymbol(); + object::symbol_iterator Sym = Reloc.getSymbol(); + if (Sym != Obj.symbol_end()) Sym->getAddress(SymAddr); - } object::RelocVisitor V(Obj); - // The section address is always 0 for debug sections. - object::RelocToApply R(V.visit(Type, Reloc, 0, SymAddr)); + object::RelocToApply R(V.visit(Type, Reloc, SymAddr)); if (V.error()) { SmallString<32> Name; std::error_code ec(Reloc.getTypeName(Name)); diff --git a/test/DebugInfo/X86/processes-relocations.ll b/test/DebugInfo/X86/processes-relocations.ll index f9a31ebd6bf..2a29be4310d 100644 --- a/test/DebugInfo/X86/processes-relocations.ll +++ b/test/DebugInfo/X86/processes-relocations.ll @@ -2,6 +2,10 @@ ; RUN: llvm-dwarfdump - 2>&1 | FileCheck %s ; RUN: llc -filetype=obj -O0 < %s -mtriple i386-none-linux | \ ; RUN: llvm-dwarfdump - 2>&1 | FileCheck %s +; RUN: llc -filetype=obj -O0 < %s -mtriple x86_64-none-mingw32 | \ +; RUN: llvm-dwarfdump - 2>&1 | FileCheck %s +; RUN: llc -filetype=obj -O0 < %s -mtriple i386-none-mingw32 | \ +; RUN: llvm-dwarfdump - 2>&1 | FileCheck %s ; CHECK-NOT: failed to compute relocation @@ -13,5 +17,5 @@ !1 = metadata !{metadata !"empty.c", metadata !"/a"} !2 = metadata !{} !3 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!4 = metadata !{i32 2, metadata !"Debug Info Version", i32 1} +!4 = metadata !{i32 2, metadata !"Debug Info Version", i32 2} !5 = metadata !{metadata !"clang version 3.6.0 "} -- 2.34.1