12
12
// ===----------------------------------------------------------------------===//
13
13
14
14
#include " llvm/XRay/InstrumentationMap.h"
15
+ #include " llvm/ADT/DenseMap.h"
15
16
#include " llvm/ADT/None.h"
16
17
#include " llvm/ADT/STLExtras.h"
17
18
#include " llvm/ADT/StringRef.h"
18
19
#include " llvm/ADT/Triple.h"
19
20
#include " llvm/ADT/Twine.h"
20
21
#include " llvm/Object/Binary.h"
22
+ #include " llvm/Object/ELFObjectFile.h"
21
23
#include " llvm/Object/ObjectFile.h"
22
24
#include " llvm/Support/DataExtractor.h"
23
25
#include " llvm/Support/Error.h"
@@ -46,6 +48,8 @@ Optional<uint64_t> InstrumentationMap::getFunctionAddr(int32_t FuncId) const {
46
48
return None;
47
49
}
48
50
51
+ using RelocMap = DenseMap<uint64_t , uint64_t >;
52
+
49
53
static Error
50
54
loadObj (StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile,
51
55
InstrumentationMap::SledContainer &Sleds,
@@ -79,6 +83,31 @@ loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile,
79
83
return errorCodeToError (
80
84
std::make_error_code (std::errc::executable_format_error));
81
85
86
+ RelocMap Relocs;
87
+ if (ObjFile.getBinary ()->isELF ()) {
88
+ uint32_t RelrRelocationType = [](object::ObjectFile *ObjFile) {
89
+ if (const auto *ELFObj = dyn_cast<object::ELF32LEObjectFile>(ObjFile))
90
+ return ELFObj->getELFFile ()->getRelrRelocationType ();
91
+ else if (const auto *ELFObj = dyn_cast<object::ELF32BEObjectFile>(ObjFile))
92
+ return ELFObj->getELFFile ()->getRelrRelocationType ();
93
+ else if (const auto *ELFObj = dyn_cast<object::ELF64LEObjectFile>(ObjFile))
94
+ return ELFObj->getELFFile ()->getRelrRelocationType ();
95
+ else if (const auto *ELFObj = dyn_cast<object::ELF64BEObjectFile>(ObjFile))
96
+ return ELFObj->getELFFile ()->getRelrRelocationType ();
97
+ else
98
+ return static_cast <uint32_t >(0 );
99
+ }(ObjFile.getBinary ());
100
+
101
+ for (const object::SectionRef &Section : Sections) {
102
+ for (const object::RelocationRef &Reloc : Section.relocations ()) {
103
+ if (Reloc.getType () != RelrRelocationType)
104
+ continue ;
105
+ if (auto AddendOrErr = object::ELFRelocationRef (Reloc).getAddend ())
106
+ Relocs.insert ({Reloc.getOffset (), *AddendOrErr});
107
+ }
108
+ }
109
+ }
110
+
82
111
// Copy the instrumentation map data into the Sleds data structure.
83
112
auto C = Contents.bytes_begin ();
84
113
static constexpr size_t ELF64SledEntrySize = 32 ;
@@ -89,6 +118,16 @@ loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile,
89
118
" an XRay sled entry in ELF64." ),
90
119
std::make_error_code (std::errc::executable_format_error));
91
120
121
+ auto RelocateOrElse = [&](uint32_t Offset, uint64_t Address) {
122
+ if (!Address) {
123
+ uint64_t A = I->getAddress () + C - Contents.bytes_begin () + Offset;
124
+ RelocMap::const_iterator R = Relocs.find (A);
125
+ if (R != Relocs.end ())
126
+ return R->second ;
127
+ }
128
+ return Address;
129
+ };
130
+
92
131
int32_t FuncId = 1 ;
93
132
uint64_t CurFn = 0 ;
94
133
for (; C != Contents.bytes_end (); C += ELF64SledEntrySize) {
@@ -98,8 +137,8 @@ loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile,
98
137
Sleds.push_back ({});
99
138
auto &Entry = Sleds.back ();
100
139
uint32_t OffsetPtr = 0 ;
101
- Entry.Address = Extractor.getU64 (&OffsetPtr);
102
- Entry.Function = Extractor.getU64 (&OffsetPtr);
140
+ Entry.Address = RelocateOrElse (OffsetPtr, Extractor.getU64 (&OffsetPtr) );
141
+ Entry.Function = RelocateOrElse (OffsetPtr, Extractor.getU64 (&OffsetPtr) );
103
142
auto Kind = Extractor.getU8 (&OffsetPtr);
104
143
static constexpr SledEntry::FunctionKinds Kinds[] = {
105
144
SledEntry::FunctionKinds::ENTRY, SledEntry::FunctionKinds::EXIT,
0 commit comments