public:
PDBContext(const object::COFFObjectFile &Object,
- std::unique_ptr<IPDBSession> PDBSession,
- bool RelativeAddress);
+ std::unique_ptr<IPDBSession> PDBSession);
static bool classof(const DIContext *DICtx) {
return DICtx->getKind() == CK_PDB;
std::error_code getSectionContents(const coff_section *Sec,
ArrayRef<uint8_t> &Res) const;
+ ErrorOr<uint64_t> getImageBase() const;
std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const;
std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const;
std::error_code getHintName(uint32_t Rva, uint16_t &Hint,
using namespace llvm::object;
PDBContext::PDBContext(const COFFObjectFile &Object,
- std::unique_ptr<IPDBSession> PDBSession,
- bool RelativeAddress)
+ std::unique_ptr<IPDBSession> PDBSession)
: DIContext(CK_PDB), Session(std::move(PDBSession)) {
- if (!RelativeAddress) {
- uint64_t ImageBase = 0;
- if (Object.is64()) {
- const pe32plus_header *Header = nullptr;
- Object.getPE32PlusHeader(Header);
- if (Header)
- ImageBase = Header->ImageBase;
- } else {
- const pe32_header *Header = nullptr;
- Object.getPE32Header(Header);
- if (Header)
- ImageBase = static_cast<uint64_t>(Header->ImageBase);
- }
- Session->setLoadAddress(ImageBase);
- }
+ ErrorOr<uint64_t> ImageBase = Object.getImageBase();
+ if (ImageBase)
+ Session->setLoadAddress(ImageBase.get());
}
void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType) {}
// The section VirtualAddress does not include ImageBase, and we want to
// return virtual addresses.
- if (PE32Header)
- Result += PE32Header->ImageBase;
- else if (PE32PlusHeader)
- Result += PE32PlusHeader->ImageBase;
+ Result += getImageBase().get();
return Result;
}
// The section VirtualAddress does not include ImageBase, and we want to
// return virtual addresses.
- if (PE32Header)
- Result += PE32Header->ImageBase;
- else if (PE32PlusHeader)
- Result += PE32PlusHeader->ImageBase;
+ Result += getImageBase().get();
return Result;
}
return std::error_code();
}
+ErrorOr<uint64_t> COFFObjectFile::getImageBase() const {
+ if (PE32Header)
+ return uint64_t(PE32Header->ImageBase);
+ else if (PE32PlusHeader)
+ return uint64_t(PE32PlusHeader->ImageBase);
+ return object_error::parse_failed;
+}
+
// Returns the file offset for the given VA.
std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
- uint64_t ImageBase = PE32Header ? (uint64_t)PE32Header->ImageBase
- : (uint64_t)PE32PlusHeader->ImageBase;
+ uint64_t ImageBase = getImageBase().get();
uint64_t Rva = Addr - ImageBase;
assert(Rva <= UINT32_MAX);
return getRvaPtr((uint32_t)Rva, Res);
--- /dev/null
+// To generate the corresponding EXE, run:
+// clang-cl -O2 -gdwarf -c coff-dwarf.cpp && lld-link -debug coff-dwarf.obj
+
+extern "C" int puts(const char *str);
+
+void __declspec(noinline) foo() {
+ puts("foo1");
+ puts("foo2");
+}
+
+// LLVM should inline this into main.
+static void bar() {
+ foo();
+}
+
+int main() {
+ bar();
+ return 0;
+}
--- /dev/null
+0x5009
+0x5038
--- /dev/null
+RUN: llvm-symbolizer --inlining --relative-address -obj="%p/Inputs/coff-dwarf.exe" \
+RUN: < %p/Inputs/coff-dwarf.input | FileCheck %s
+
+CHECK: foo(void)
+CHECK: coff-dwarf.cpp:7
+CHECK: bar(void)
+CHECK: coff-dwarf.cpp:13
+CHECK: main
+CHECK: coff-dwarf.cpp:17
RUN: llvm-symbolizer -obj="%p/Inputs/test.exe" < "%p/Inputs/test.exe.input" | \
RUN: FileCheck %s --check-prefix=CHECK
+RUN: llvm-symbolizer -obj="%p/Inputs/test.exe" < "%p/Inputs/test.exe.input" | \
+RUN: FileCheck %s --check-prefix=CHECK
RUN: llvm-symbolizer -obj="%p/Inputs/test.exe" -demangle=false < \
RUN: "%p/Inputs/test.exe.input" | FileCheck %s --check-prefix=CHECK-NO-DEMANGLE
+Subtract ImageBase from all the offsets and run the test again with
+--relative-address.
+
+RUN: python -c 'import sys;print "\n".join([hex(int(x, 16) - 0x400000) for x in sys.stdin])' \
+RUN: < %p/Inputs/test.exe.input \
+RUN: | llvm-symbolizer -obj="%p/Inputs/test.exe" -demangle=false --relative-address \
+RUN: | FileCheck %s --check-prefix=CHECK-NO-DEMANGLE
+
CHECK: foo(void)
CHECK-NEXT: test.cpp:10
CHECK: main
return CoffObject && CoffObject->getMachine() == COFF::IMAGE_FILE_MACHINE_I386;
}
+uint64_t ModuleInfo::getModulePreferredBase() const {
+ if (auto *CoffObject = dyn_cast<COFFObjectFile>(Module))
+ if (auto Base = CoffObject->getImageBase())
+ return Base.get();
+ return 0;
+}
+
bool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
std::string &Name, uint64_t &Addr,
uint64_t &Size) const {
ModuleInfo *Info = getOrCreateModuleInfo(ModuleName);
if (!Info)
return printDILineInfo(DILineInfo(), Info);
+
+ // If the user is giving us relative addresses, add the preferred base of the
+ // object to the offset before we do the query. It's what DIContext expects.
+ if (Opts.RelativeAddresses)
+ ModuleOffset += Info->getModulePreferredBase();
+
if (Opts.PrintInlining) {
DIInliningInfo InlinedContext =
Info->symbolizeInlinedCode(ModuleOffset, Opts);
uint64_t Size = 0;
if (Opts.UseSymbolTable) {
if (ModuleInfo *Info = getOrCreateModuleInfo(ModuleName)) {
+ // If the user is giving us relative addresses, add the preferred base of the
+ // object to the offset before we do the query. It's what DIContext expects.
+ if (Opts.RelativeAddresses)
+ ModuleOffset += Info->getModulePreferredBase();
if (Info->symbolizeData(ModuleOffset, Name, Start, Size) && Opts.Demangle)
Name = DemangleName(Name, Info);
}
PDB_ErrorCode Error = loadDataForEXE(PDB_ReaderType::DIA,
Objects.first->getFileName(), Session);
if (Error == PDB_ErrorCode::Success) {
- Context = new PDBContext(*CoffObject, std::move(Session),
- Opts.RelativeAddresses);
+ Context = new PDBContext(*CoffObject, std::move(Session));
}
}
if (!Context)
// Return true if this is a 32-bit x86 PE COFF module.
bool isWin32Module() const;
+ // Returns the preferred base of the module, i.e. where the loader would place
+ // it in memory assuming there were no conflicts.
+ uint64_t getModulePreferredBase() const;
+
private:
bool getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
std::string &Name, uint64_t &Addr,