summaryrefslogtreecommitdiff
path: root/llvm/lib/XRay/InstrumentationMap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/XRay/InstrumentationMap.cpp')
-rw-r--r--llvm/lib/XRay/InstrumentationMap.cpp76
1 files changed, 54 insertions, 22 deletions
diff --git a/llvm/lib/XRay/InstrumentationMap.cpp b/llvm/lib/XRay/InstrumentationMap.cpp
index 1e9b69a5f9dcc..de0a9e60a5111 100644
--- a/llvm/lib/XRay/InstrumentationMap.cpp
+++ b/llvm/lib/XRay/InstrumentationMap.cpp
@@ -52,26 +52,31 @@ using RelocMap = DenseMap<uint64_t, uint64_t>;
static Error
loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile,
- InstrumentationMap::SledContainer &Sleds,
- InstrumentationMap::FunctionAddressMap &FunctionAddresses,
- InstrumentationMap::FunctionAddressReverseMap &FunctionIds) {
+ InstrumentationMap::SledContainer &Sleds,
+ InstrumentationMap::FunctionAddressMap &FunctionAddresses,
+ InstrumentationMap::FunctionAddressReverseMap &FunctionIds) {
InstrumentationMap Map;
// Find the section named "xray_instr_map".
if ((!ObjFile.getBinary()->isELF() && !ObjFile.getBinary()->isMachO()) ||
!(ObjFile.getBinary()->getArch() == Triple::x86_64 ||
ObjFile.getBinary()->getArch() == Triple::ppc64le ||
+ ObjFile.getBinary()->getArch() == Triple::arm ||
ObjFile.getBinary()->getArch() == Triple::aarch64))
return make_error<StringError>(
- "File format not supported (only does ELF and Mach-O little endian 64-bit).",
+ "File format not supported (only does ELF and Mach-O little endian "
+ "64-bit).",
std::make_error_code(std::errc::not_supported));
StringRef Contents = "";
const auto &Sections = ObjFile.getBinary()->sections();
+ uint64_t Address = 0;
auto I = llvm::find_if(Sections, [&](object::SectionRef Section) {
Expected<StringRef> NameOrErr = Section.getName();
- if (NameOrErr)
+ if (NameOrErr) {
+ Address = Section.getAddress();
return *NameOrErr == "xray_instr_map";
+ }
consumeError(NameOrErr.takeError());
return false;
});
@@ -91,11 +96,14 @@ loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile,
uint32_t RelativeRelocation = [](object::ObjectFile *ObjFile) {
if (const auto *ELFObj = dyn_cast<object::ELF32LEObjectFile>(ObjFile))
return ELFObj->getELFFile()->getRelativeRelocationType();
- else if (const auto *ELFObj = dyn_cast<object::ELF32BEObjectFile>(ObjFile))
+ else if (const auto *ELFObj =
+ dyn_cast<object::ELF32BEObjectFile>(ObjFile))
return ELFObj->getELFFile()->getRelativeRelocationType();
- else if (const auto *ELFObj = dyn_cast<object::ELF64LEObjectFile>(ObjFile))
+ else if (const auto *ELFObj =
+ dyn_cast<object::ELF64LEObjectFile>(ObjFile))
return ELFObj->getELFFile()->getRelativeRelocationType();
- else if (const auto *ELFObj = dyn_cast<object::ELF64BEObjectFile>(ObjFile))
+ else if (const auto *ELFObj =
+ dyn_cast<object::ELF64BEObjectFile>(ObjFile))
return ELFObj->getELFFile()->getRelativeRelocationType();
else
return static_cast<uint32_t>(0);
@@ -108,11 +116,21 @@ loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile,
for (const object::SectionRef &Section : Sections) {
for (const object::RelocationRef &Reloc : Section.relocations()) {
- if (SupportsRelocation && SupportsRelocation(Reloc.getType())) {
+ if (ObjFile.getBinary()->getArch() == Triple::arm) {
+ if (SupportsRelocation && SupportsRelocation(Reloc.getType())) {
+ Expected<uint64_t> ValueOrErr = Reloc.getSymbol()->getValue();
+ if (!ValueOrErr)
+ return ValueOrErr.takeError();
+ Relocs.insert({Reloc.getOffset(), Resolver(Reloc, *ValueOrErr, 0)});
+ }
+ } else if (SupportsRelocation && SupportsRelocation(Reloc.getType())) {
auto AddendOrErr = object::ELFRelocationRef(Reloc).getAddend();
auto A = AddendOrErr ? *AddendOrErr : 0;
- uint64_t resolved = Resolver(Reloc, Reloc.getSymbol()->getValue(), A);
- Relocs.insert({Reloc.getOffset(), resolved});
+ Expected<uint64_t> ValueOrErr = Reloc.getSymbol()->getValue();
+ if (!ValueOrErr)
+ // TODO: Test this error.
+ return ValueOrErr.takeError();
+ Relocs.insert({Reloc.getOffset(), Resolver(Reloc, *ValueOrErr, A)});
} else if (Reloc.getType() == RelativeRelocation) {
if (auto AddendOrErr = object::ELFRelocationRef(Reloc).getAddend())
Relocs.insert({Reloc.getOffset(), *AddendOrErr});
@@ -123,12 +141,13 @@ loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile,
// Copy the instrumentation map data into the Sleds data structure.
auto C = Contents.bytes_begin();
- static constexpr size_t ELF64SledEntrySize = 32;
+ bool Is32Bit = ObjFile.getBinary()->makeTriple().isArch32Bit();
+ size_t ELFSledEntrySize = Is32Bit ? 16 : 32;
- if ((C - Contents.bytes_end()) % ELF64SledEntrySize != 0)
+ if ((C - Contents.bytes_end()) % ELFSledEntrySize != 0)
return make_error<StringError>(
Twine("Instrumentation map entries not evenly divisible by size of "
- "an XRay sled entry in ELF64."),
+ "an XRay sled entry."),
std::make_error_code(std::errc::executable_format_error));
auto RelocateOrElse = [&](uint64_t Offset, uint64_t Address) {
@@ -141,19 +160,26 @@ loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile,
return Address;
};
+ const int WordSize = Is32Bit ? 4 : 8;
int32_t FuncId = 1;
uint64_t CurFn = 0;
- for (; C != Contents.bytes_end(); C += ELF64SledEntrySize) {
+ for (; C != Contents.bytes_end(); C += ELFSledEntrySize) {
DataExtractor Extractor(
- StringRef(reinterpret_cast<const char *>(C), ELF64SledEntrySize), true,
+ StringRef(reinterpret_cast<const char *>(C), ELFSledEntrySize), true,
8);
Sleds.push_back({});
auto &Entry = Sleds.back();
uint64_t OffsetPtr = 0;
uint64_t AddrOff = OffsetPtr;
- Entry.Address = RelocateOrElse(AddrOff, Extractor.getU64(&OffsetPtr));
+ if (Is32Bit)
+ Entry.Address = RelocateOrElse(AddrOff, Extractor.getU32(&OffsetPtr));
+ else
+ Entry.Address = RelocateOrElse(AddrOff, Extractor.getU64(&OffsetPtr));
uint64_t FuncOff = OffsetPtr;
- Entry.Function = RelocateOrElse(FuncOff, Extractor.getU64(&OffsetPtr));
+ if (Is32Bit)
+ Entry.Function = RelocateOrElse(FuncOff, Extractor.getU32(&OffsetPtr));
+ else
+ Entry.Function = RelocateOrElse(FuncOff, Extractor.getU64(&OffsetPtr));
auto Kind = Extractor.getU8(&OffsetPtr);
static constexpr SledEntry::FunctionKinds Kinds[] = {
SledEntry::FunctionKinds::ENTRY, SledEntry::FunctionKinds::EXIT,
@@ -165,6 +191,11 @@ loadObj(StringRef Filename, object::OwningBinary<object::ObjectFile> &ObjFile,
std::make_error_code(std::errc::executable_format_error));
Entry.Kind = Kinds[Kind];
Entry.AlwaysInstrument = Extractor.getU8(&OffsetPtr) != 0;
+ Entry.Version = Extractor.getU8(&OffsetPtr);
+ if (Entry.Version >= 2) {
+ Entry.Address += C - Contents.bytes_begin() + Address;
+ Entry.Function += C - Contents.bytes_begin() + WordSize + Address;
+ }
// We do replicate the function id generation scheme implemented in the
// XRay runtime.
@@ -209,8 +240,8 @@ loadYAML(sys::fs::file_t Fd, size_t FileSize, StringRef Filename,
for (const auto &Y : YAMLSleds) {
FunctionAddresses[Y.FuncId] = Y.Function;
FunctionIds[Y.Function] = Y.FuncId;
- Sleds.push_back(
- SledEntry{Y.Address, Y.Function, Y.Kind, Y.AlwaysInstrument});
+ Sleds.push_back(SledEntry{Y.Address, Y.Function, Y.Kind, Y.AlwaysInstrument,
+ Y.Version});
}
return Error::success();
}
@@ -228,7 +259,8 @@ llvm::xray::loadInstrumentationMap(StringRef Filename) {
if (!ObjectFileOrError) {
auto E = ObjectFileOrError.takeError();
// We try to load it as YAML if the ELF load didn't work.
- Expected<sys::fs::file_t> FdOrErr = sys::fs::openNativeFileForRead(Filename);
+ Expected<sys::fs::file_t> FdOrErr =
+ sys::fs::openNativeFileForRead(Filename);
if (!FdOrErr) {
// Report the ELF load error if YAML failed.
consumeError(FdOrErr.takeError());
@@ -250,7 +282,7 @@ llvm::xray::loadInstrumentationMap(StringRef Filename) {
Map.FunctionAddresses, Map.FunctionIds))
return std::move(E);
} else if (auto E = loadObj(Filename, *ObjectFileOrError, Map.Sleds,
- Map.FunctionAddresses, Map.FunctionIds)) {
+ Map.FunctionAddresses, Map.FunctionIds)) {
return std::move(E);
}
return Map;