mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
[llvm-xray] Support for PIE
When the instrumented binary is linked as PIE, we need to apply the relative relocations to sleds. This is handled by the dynamic linker at runtime, but when processing the file we have to do it ourselves. Differential Revision: https://reviews.llvm.org/D55542 llvm-svn: 349120
This commit is contained in:
parent
6f0d069409
commit
aa9b3d7c8c
@ -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,
|
||||
|
BIN
test/tools/llvm-xray/X86/Inputs/elf64-pie.bin
Executable file
BIN
test/tools/llvm-xray/X86/Inputs/elf64-pie.bin
Executable file
Binary file not shown.
11
test/tools/llvm-xray/X86/extract-instrmap-pie.ll
Normal file
11
test/tools/llvm-xray/X86/extract-instrmap-pie.ll
Normal file
@ -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: ...
|
Loading…
Reference in New Issue
Block a user