diff --git a/llvm/test/tools/llvm-profgen/inline-cs-pseudoprobe.test b/llvm/test/tools/llvm-profgen/inline-cs-pseudoprobe.test --- a/llvm/test/tools/llvm-profgen/inline-cs-pseudoprobe.test +++ b/llvm/test/tools/llvm-profgen/inline-cs-pseudoprobe.test @@ -1,5 +1,9 @@ ; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-pseudoprobe.perfscript --binary=%S/Inputs/inline-cs-pseudoprobe.perfbin --output=%t --skip-symbolization --profile-summary-cold-count=0 --use-offset=0 ; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-UNWINDER +; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-pseudoprobe.perfscript --binary=%S/Inputs/inline-cs-pseudoprobe.perfbin --output=%t --skip-symbolization --profile-summary-cold-count=0 --use-offset=1 +; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-UNWINDER-OFFSET +; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-pseudoprobe.perfscript --binary=%S/Inputs/inline-cs-pseudoprobe.perfbin --output=%t --skip-symbolization --profile-summary-cold-count=0 --use-offset=1 --use-loadable-segment-as-base=1 +; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-UNWINDER-OFFSET2 ; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-pseudoprobe.perfscript --binary=%S/Inputs/inline-cs-pseudoprobe.perfbin --output=%t --profile-summary-cold-count=0 ; RUN: FileCheck %s --input-file %t @@ -27,6 +31,23 @@ ; CHECK-UNWINDER-NEXT: 20182b->201800:1 ; CHECK-UNWINDER-NEXT: 201858->20180e:15 + +; CHECK-UNWINDER-OFFSET: 3 +; CHECK-UNWINDER-OFFSET-NEXT: 800-858:1 +; CHECK-UNWINDER-OFFSET-NEXT: 80e-82b:1 +; CHECK-UNWINDER-OFFSET-NEXT: 80e-858:13 +; CHECK-UNWINDER-OFFSET-NEXT: 2 +; CHECK-UNWINDER-OFFSET-NEXT: 82b->800:1 +; CHECK-UNWINDER-OFFSET-NEXT: 858->80e:15 + +; CHECK-UNWINDER-OFFSET2: 3 +; CHECK-UNWINDER-OFFSET2-NEXT: 1800-1858:1 +; CHECK-UNWINDER-OFFSET2-NEXT: 180e-182b:1 +; CHECK-UNWINDER-OFFSET2-NEXT: 180e-1858:13 +; CHECK-UNWINDER-OFFSET2-NEXT: 2 +; CHECK-UNWINDER-OFFSET2-NEXT: 182b->1800:1 +; CHECK-UNWINDER-OFFSET2-NEXT: 1858->180e:15 + ; clang -O3 -fexperimental-new-pass-manager -fuse-ld=lld -fpseudo-probe-for-profiling ; -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -Xclang -mdisable-tail-calls ; -g test.c -o a.out diff --git a/llvm/tools/llvm-profgen/PerfReader.cpp b/llvm/tools/llvm-profgen/PerfReader.cpp --- a/llvm/tools/llvm-profgen/PerfReader.cpp +++ b/llvm/tools/llvm-profgen/PerfReader.cpp @@ -27,6 +27,14 @@ cl::desc("Work with `--skip-symbolization` or " "`--unsymbolized-profile` to write/read the " "offset instead of virtual address.")); + +static cl::opt + UseLoadableSegmentAsBase("use-loadable-segment-as-base", + cl::init(false), cl::ZeroOrMore, + cl::desc("Use first loadable segment address as base address " + "for offsets in unsymbolized profile. By default " + "first executable segment address is used")); + static cl::opt IgnoreStackSamples("ignore-stack-samples", cl::init(false), cl::ZeroOrMore, cl::desc("Ignore call stack samples for hybrid samples " @@ -699,10 +707,19 @@ OS.indent(Indent); OS << Counter.size() << "\n"; for (auto &I : Counter) { - uint64_t Start = UseOffset ? I.first.first - : Binary->offsetToVirtualAddr(I.first.first); - uint64_t End = UseOffset ? I.first.second - : Binary->offsetToVirtualAddr(I.first.second); + uint64_t Start = I.first.first; + uint64_t End = I.first.second; + + if (!UseOffset || (UseOffset && UseLoadableSegmentAsBase)) { + Start = Binary->offsetToVirtualAddr(Start); + End = Binary->offsetToVirtualAddr(End); + } + + if (UseOffset && UseLoadableSegmentAsBase) { + Start -= Binary->getFirstLoadableAddress(); + End -= Binary->getFirstLoadableAddress(); + } + OS.indent(Indent); OS << Twine::utohexstr(Start) << Separator << Twine::utohexstr(End) << ":" << I.second << "\n"; @@ -772,9 +789,13 @@ Range.second.getAsInteger(16, Target)) exitWithErrorForTraceLine(TraceIt); - if (!UseOffset) { - Source = Binary->virtualAddrToOffset(Source); - Target = Binary->virtualAddrToOffset(Target); + if (!UseOffset || (UseOffset&& UseLoadableSegmentAsBase)) { + uint64_t BaseAddr = 0; + if (UseOffset && UseLoadableSegmentAsBase) + BaseAddr = Binary->getFirstLoadableAddress(); + + Source = Binary->virtualAddrToOffset(Source + BaseAddr); + Target = Binary->virtualAddrToOffset(Target + BaseAddr); } Counter[{Source, Target}] += Count; diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.h b/llvm/tools/llvm-profgen/ProfiledBinary.h --- a/llvm/tools/llvm-profgen/ProfiledBinary.h +++ b/llvm/tools/llvm-profgen/ProfiledBinary.h @@ -172,6 +172,8 @@ Triple TheTriple; // The runtime base address that the first executable segment is loaded at. uint64_t BaseAddress = 0; + // The runtime base address that the first loadabe segment is loaded at. + uint64_t FirstLoadableAddress = 0; // The preferred load address of each executable segment. std::vector PreferredTextSegmentAddresses; // The file offset of each executable segment. @@ -301,6 +303,8 @@ // Return the preferred load address for the first executable segment. uint64_t getPreferredBaseAddress() const { return PreferredTextSegmentAddresses[0]; } + // Return the preferred load address for the first loadable segment. + uint64_t getFirstLoadableAddress() { return FirstLoadableAddress; } // Return the file offset for the first executable segment. uint64_t getTextSegmentOffset() const { return TextSegmentOffsets[0]; } const std::vector &getPreferredTextSegmentAddresses() const { diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/llvm/tools/llvm-profgen/ProfiledBinary.cpp --- a/llvm/tools/llvm-profgen/ProfiledBinary.cpp +++ b/llvm/tools/llvm-profgen/ProfiledBinary.cpp @@ -253,12 +253,16 @@ // because we may build the tools on non-linux. uint32_t PageSize = 0x1000; for (const typename ELFT::Phdr &Phdr : PhdrRange) { - if ((Phdr.p_type == ELF::PT_LOAD) && (Phdr.p_flags & ELF::PF_X)) { + if (Phdr.p_type == ELF::PT_LOAD) { + if (!FirstLoadableAddress) + FirstLoadableAddress = Phdr.p_vaddr & ~(PageSize - 1U); + if (Phdr.p_flags & ELF::PF_X) { // Segments will always be loaded at a page boundary. PreferredTextSegmentAddresses.push_back(Phdr.p_vaddr & ~(PageSize - 1U)); TextSegmentOffsets.push_back(Phdr.p_offset & ~(PageSize - 1U)); } + } } if (PreferredTextSegmentAddresses.empty())