diff --git a/llvm/lib/XRay/InstrumentationMap.cpp b/llvm/lib/XRay/InstrumentationMap.cpp --- a/llvm/lib/XRay/InstrumentationMap.cpp +++ b/llvm/lib/XRay/InstrumentationMap.cpp @@ -61,9 +61,10 @@ 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( - "File format not supported (only does ELF and Mach-O little endian 64-bit).", + Twine("File format not supported. Supports: AArch64/ARM/ppc64le/x86-64."), std::make_error_code(std::errc::not_supported)); StringRef Contents = ""; @@ -123,12 +124,14 @@ // Copy the instrumentation map data into the Sleds data structure. auto C = Contents.bytes_begin(); - static constexpr size_t ELF64SledEntrySize = 32; - if ((C - Contents.bytes_end()) % ELF64SledEntrySize != 0) + bool Is32Bit = ObjFile.getBinary()->makeTriple().isArch32Bit(); + size_t ELFSledEntrySize = Is32Bit ? 16 : 32; + + if ((C - Contents.bytes_end()) % ELFSledEntrySize != 0) return make_error( 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) { @@ -143,17 +146,23 @@ 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(C), ELF64SledEntrySize), true, + StringRef(reinterpret_cast(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, diff --git a/llvm/test/tools/llvm-xray/ARM/extract-instrmap-arm.test b/llvm/test/tools/llvm-xray/ARM/extract-instrmap-arm.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-xray/ARM/extract-instrmap-arm.test @@ -0,0 +1,18 @@ +## This test makes sure we can extract the instrumentation map from an +## XRay-instrumented PIE file. + +RUN: yaml2obj %S/elf32-pic.yaml -o %t.so +RUN: llvm-xray extract %t.so -s > %t.test +RUN: llvm-xray extract %t.so -s --no-demangle >> %t.test +RUN: cat %t.test | FileCheck %s + +CHECK: --- +CHECK-NEXT: - { id: 1, address: 0x000000000000043C, function: 0x000000000000043C, kind: function-enter, always-instrument: true, function-name: 'bar()' } +CHECK-NEXT: - { id: 2, address: 0x000000000000045C, function: 0x000000000000045C, kind: function-enter, always-instrument: true, function-name: 'jar()' } +CHECK-NEXT: - { id: 3, address: 0x000000000000047C, function: 0x000000000000047C, kind: function-enter, always-instrument: true, function-name: 'foo()' } +CHECK: ... +CHECK: --- +CHECK-NEXT: - { id: 1, address: 0x000000000000043C, function: 0x000000000000043C, kind: function-enter, always-instrument: true, function-name: _Z3barv } +CHECK-NEXT: - { id: 2, address: 0x000000000000045C, function: 0x000000000000045C, kind: function-enter, always-instrument: true, function-name: _Z3jarv } +CHECK-NEXT: - { id: 3, address: 0x000000000000047C, function: 0x000000000000047C, kind: function-enter, always-instrument: true, function-name: _Z3foov } +CHECK: ... diff --git a/llvm/test/tools/llvm-xray/X86/bad-instrmap-sizes.txt b/llvm/test/tools/llvm-xray/X86/bad-instrmap-sizes.txt --- a/llvm/test/tools/llvm-xray/X86/bad-instrmap-sizes.txt +++ b/llvm/test/tools/llvm-xray/X86/bad-instrmap-sizes.txt @@ -1,3 +1,3 @@ ; RUN: not llvm-xray extract %S/Inputs/elf64-badentrysizes.bin 2>&1 | FileCheck %s ; CHECK: llvm-xray: Cannot extract instrumentation map from '{{.*}}elf64-badentrysizes.bin'. -; CHECK-NEXT: Instrumentation map entries not evenly divisible by size of an XRay sled entry in ELF64. +; CHECK-NEXT: Instrumentation map entries not evenly divisible by size of an XRay sled entry. diff --git a/llvm/test/tools/llvm-xray/X86/unsupported-elf32.txt b/llvm/test/tools/llvm-xray/X86/unsupported-elf32.txt --- a/llvm/test/tools/llvm-xray/X86/unsupported-elf32.txt +++ b/llvm/test/tools/llvm-xray/X86/unsupported-elf32.txt @@ -1,3 +1,3 @@ ; RUN: not llvm-xray extract %S/Inputs/elf32-noxray.bin 2>&1 | FileCheck %s ; CHECK: llvm-xray: Cannot extract instrumentation map from '{{.*}}elf32-noxray.bin'. -; CHECK-NEXT: File format not supported (only does ELF and Mach-O little endian 64-bit). +; CHECK-NEXT: File format not supported. Supports: AArch64/ARM/ppc64le/x86-64.