diff options
Diffstat (limited to 'llvm/lib/XRay/InstrumentationMap.cpp')
-rw-r--r-- | llvm/lib/XRay/InstrumentationMap.cpp | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/llvm/lib/XRay/InstrumentationMap.cpp b/llvm/lib/XRay/InstrumentationMap.cpp index 84317708d3f..d33fb4a2b80 100644 --- a/llvm/lib/XRay/InstrumentationMap.cpp +++ b/llvm/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 @@ Optional<uint64_t> InstrumentationMap::getFunctionAddr(int32_t FuncId) const { return None; } +using RelocMap = DenseMap<uint64_t, uint64_t>; + static Error loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile, InstrumentationMap::SledContainer &Sleds, @@ -79,6 +83,31 @@ loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile, 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<object::ELF32LEObjectFile>(ObjFile)) + return ELFObj->getELFFile()->getRelrRelocationType(); + else if (const auto *ELFObj = dyn_cast<object::ELF32BEObjectFile>(ObjFile)) + return ELFObj->getELFFile()->getRelrRelocationType(); + else if (const auto *ELFObj = dyn_cast<object::ELF64LEObjectFile>(ObjFile)) + return ELFObj->getELFFile()->getRelrRelocationType(); + else if (const auto *ELFObj = dyn_cast<object::ELF64BEObjectFile>(ObjFile)) + return ELFObj->getELFFile()->getRelrRelocationType(); + else + return static_cast<uint32_t>(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 @@ loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile, "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 @@ loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile, 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, |