Index: llvm/trunk/lib/XRay/InstrumentationMap.cpp =================================================================== --- llvm/trunk/lib/XRay/InstrumentationMap.cpp +++ llvm/trunk/lib/XRay/InstrumentationMap.cpp @@ -12,12 +12,14 @@ //===----------------------------------------------------------------------===// #include "llvm/XRay/InstrumentationMap.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" #include "llvm/Object/Binary.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Error.h" @@ -46,6 +48,8 @@ return None; } +using RelocMap = DenseMap; + static Error loadObj(StringRef Filename, object::OwningBinary &ObjFile, InstrumentationMap::SledContainer &Sleds, @@ -79,6 +83,31 @@ return errorCodeToError( std::make_error_code(std::errc::executable_format_error)); + RelocMap Relocs; + if (ObjFile.getBinary()->isELF()) { + uint32_t RelrRelocationType = [](object::ObjectFile *ObjFile) { + if (const auto *ELFObj = dyn_cast(ObjFile)) + return ELFObj->getELFFile()->getRelrRelocationType(); + else if (const auto *ELFObj = dyn_cast(ObjFile)) + return ELFObj->getELFFile()->getRelrRelocationType(); + else if (const auto *ELFObj = dyn_cast(ObjFile)) + return ELFObj->getELFFile()->getRelrRelocationType(); + else if (const auto *ELFObj = dyn_cast(ObjFile)) + return ELFObj->getELFFile()->getRelrRelocationType(); + else + return static_cast(0); + }(ObjFile.getBinary()); + + for (const object::SectionRef &Section : Sections) { + for (const object::RelocationRef &Reloc : Section.relocations()) { + if (Reloc.getType() != RelrRelocationType) + continue; + if (auto AddendOrErr = object::ELFRelocationRef(Reloc).getAddend()) + Relocs.insert({Reloc.getOffset(), *AddendOrErr}); + } + } + } + // Copy the instrumentation map data into the Sleds data structure. auto C = Contents.bytes_begin(); static constexpr size_t ELF64SledEntrySize = 32; @@ -89,6 +118,16 @@ "an XRay sled entry in ELF64."), std::make_error_code(std::errc::executable_format_error)); + auto RelocateOrElse = [&](uint32_t Offset, uint64_t Address) { + if (!Address) { + uint64_t A = I->getAddress() + C - Contents.bytes_begin() + Offset; + RelocMap::const_iterator R = Relocs.find(A); + if (R != Relocs.end()) + return R->second; + } + return Address; + }; + int32_t FuncId = 1; uint64_t CurFn = 0; for (; C != Contents.bytes_end(); C += ELF64SledEntrySize) { @@ -98,8 +137,8 @@ Sleds.push_back({}); auto &Entry = Sleds.back(); uint32_t OffsetPtr = 0; - Entry.Address = Extractor.getU64(&OffsetPtr); - Entry.Function = Extractor.getU64(&OffsetPtr); + Entry.Address = RelocateOrElse(OffsetPtr, Extractor.getU64(&OffsetPtr)); + Entry.Function = RelocateOrElse(OffsetPtr, Extractor.getU64(&OffsetPtr)); auto Kind = Extractor.getU8(&OffsetPtr); static constexpr SledEntry::FunctionKinds Kinds[] = { SledEntry::FunctionKinds::ENTRY, SledEntry::FunctionKinds::EXIT, Index: llvm/trunk/test/tools/llvm-xray/X86/extract-instrmap-pie.ll =================================================================== --- llvm/trunk/test/tools/llvm-xray/X86/extract-instrmap-pie.ll +++ llvm/trunk/test/tools/llvm-xray/X86/extract-instrmap-pie.ll @@ -0,0 +1,11 @@ +; This test makes sure we can extract the instrumentation map from an +; XRay-instrumented PIE file. +; +; RUN: llvm-xray extract %S/Inputs/elf64-pie.bin -s | FileCheck %s + +; CHECK: --- +; CHECK-NEXT: - { id: 1, address: 0x00000000000299C0, function: 0x00000000000299C0, kind: function-enter, always-instrument: true, function-name: {{.*foo.*}} } +; CHECK-NEXT: - { id: 1, address: 0x00000000000299D0, function: 0x00000000000299C0, kind: function-exit, always-instrument: true, function-name: {{.*foo.*}} } +; CHECK-NEXT: - { id: 2, address: 0x00000000000299E0, function: 0x00000000000299E0, kind: function-enter, always-instrument: true, function-name: {{.*bar.*}} } +; CHECK-NEXT: - { id: 2, address: 0x00000000000299F6, function: 0x00000000000299E0, kind: function-exit, always-instrument: true, function-name: {{.*bar.*}} } +; CHECK-NEXT: ...