https://github.com/JohnLee1243 updated https://github.com/llvm/llvm-project/pull/65494
>From 8d0b2089e00d3cae74f4ba30a0e8c5464678ead0 Mon Sep 17 00:00:00 2001 From: JohnLee1243 <lizhuohang...@126.com> Date: Wed, 6 Sep 2023 23:27:18 +0800 Subject: [PATCH] [Bolt] Solving pie support issue Offering: BiSheng Now PIE is default supported. It cause parsing error when using perf2bolt. The reason is the base address can not get correctly. Fix the method of geting base address. If SegInfo.Alignment is not equal to pagesize, alignDown(SegInfo.FileOffset, SegInfo.Alignment) can not equal to FileOffset. So the SegInfo.FileOffset and FileOffset should be aligned by SegInfo.Alignment first and then judge whether they are equal. The .text segment's offset from base address in VAS is aligned by pagesize. So MMapAddress's offset from base address is alignDown(SegInfo.Address, pagesize) instead of alignDown(SegInfo.Address, SegInfo.Alignment). So the base address calculate way should be changed. --- bolt/lib/Core/BinaryContext.cpp | 25 +++++++++++++++++++++---- bolt/test/Inputs/perf_test.c | 26 ++++++++++++++++++++++++++ bolt/test/Inputs/perf_test.lds | 13 +++++++++++++ bolt/test/lit.cfg.py | 4 ++++ bolt/test/perf_test.test | 17 +++++++++++++++++ 5 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 bolt/test/Inputs/perf_test.c create mode 100644 bolt/test/Inputs/perf_test.lds create mode 100644 bolt/test/perf_test.test diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index ffecc5209804351a..ed36dbced99beaa0 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -1888,10 +1888,27 @@ BinaryContext::getBaseAddressForMapping(uint64_t MMapAddress, // Find a segment with a matching file offset. for (auto &KV : SegmentMapInfo) { const SegmentInfo &SegInfo = KV.second; - if (alignDown(SegInfo.FileOffset, SegInfo.Alignment) == FileOffset) { - // Use segment's aligned memory offset to calculate the base address. - const uint64_t MemOffset = alignDown(SegInfo.Address, SegInfo.Alignment); - return MMapAddress - MemOffset; + // FileOffset is got from perf event, + // and it is equal to alignDown(SegInfo.FileOffset, pagesize). + // If the pagesize is not equal to SegInfo.Alignment. + // FileOffset and SegInfo.FileOffset should be aligned first, + // and then judge whether they are equal. + if (alignDown(SegInfo.FileOffset, SegInfo.Alignment) == + alignDown(FileOffset, SegInfo.Alignment)) { + // The function's offset from base address in VAS is aligned by pagesize + // instead of SegInfo.Alignment. Pagesize can't be got from perf events. + // However, The ELF document says that SegInfo.FileOffset should equal + // to SegInfo.Address, modulo the pagesize. + // Reference: https://refspecs.linuxfoundation.org/elf/elf.pdf + + // So alignDown(SegInfo.Address, pagesize) can be calculated by: + // alignDown(SegInfo.Address, pagesize) + // = SegInfo.Address - (SegInfo.Address % pagesize) + // = SegInfo.Address - (SegInfo.FileOffset % pagesize) + // = SegInfo.Address - SegInfo.FileOffset + + // alignDown(SegInfo.FileOffset, pagesize) + // = SegInfo.Address - SegInfo.FileOffset + FileOffset + return MMapAddress - (SegInfo.Address - SegInfo.FileOffset + FileOffset); } } diff --git a/bolt/test/Inputs/perf_test.c b/bolt/test/Inputs/perf_test.c new file mode 100644 index 0000000000000000..456f9567c5551de2 --- /dev/null +++ b/bolt/test/Inputs/perf_test.c @@ -0,0 +1,26 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +int add(int a, int b) { return a + b; } +int minus(int a, int b) { return a - b; } +int multiple(int a, int b) { return a * b; } +int divide(int a, int b) { + if (b == 0) + return 0; + return a / b; +} + +int main() { + int a = 16; + int b = 8; + + for (int i = 1; i < 10000000; i++) { + add(a, b); + minus(a, b); + multiple(a, b); + divide(a, b); + } + + return 0; +} \ No newline at end of file diff --git a/bolt/test/Inputs/perf_test.lds b/bolt/test/Inputs/perf_test.lds new file mode 100644 index 0000000000000000..9cb4ebbf1e9f83bc --- /dev/null +++ b/bolt/test/Inputs/perf_test.lds @@ -0,0 +1,13 @@ +SECTIONS { + . = SIZEOF_HEADERS; + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + . = 0x212e8; + .dynsym : { *(.dynsym) } + . = 0x31860; + .text : { *(.text*) } + . = 0x41c20; + .fini_array : { *(.fini_array) } + . = 0x54e18; + .data : { *(.data) } +} diff --git a/bolt/test/lit.cfg.py b/bolt/test/lit.cfg.py index 3a6da210e01f080e..427e13b7e561d91a 100644 --- a/bolt/test/lit.cfg.py +++ b/bolt/test/lit.cfg.py @@ -3,6 +3,7 @@ import os import platform import re +import shutil import subprocess import tempfile @@ -75,6 +76,9 @@ if lit.util.which("fuser"): config.available_features.add("fuser") +if shutil.which('perf') != None: + config.available_features.add('perf') + llvm_config.use_default_substitutions() llvm_config.config.environment["CLANG"] = config.bolt_clang diff --git a/bolt/test/perf_test.test b/bolt/test/perf_test.test new file mode 100644 index 0000000000000000..44db899ab30de564 --- /dev/null +++ b/bolt/test/perf_test.test @@ -0,0 +1,17 @@ +# Check perf2bolt binary function which was compiled with pie + +REQUIRES: system-linux, perf + +RUN: %clang %S/Inputs/perf_test.c -fuse-ld=lld -Wl,--script=%S/Inputs/perf_test.lds -o %t +RUN: perf record -e cycles:u -o %t2 -- %t +RUN: perf2bolt %t -p=%t2 -o %t3 -nl -ignore-build-id 2>&1 | FileCheck %s + +CHECK-NOT: PERF2BOLT-ERROR +CHECK-NOT: !! WARNING !! This high mismatch ratio indicates the input binary is probably not the same binary used during profiling collection. + +RUN: %clang %S/Inputs/perf_test.c -no-pie -fuse-ld=lld -o %t4 +RUN: perf record -e cycles:u -o %t5 -- %t4 +RUN: perf2bolt %t4 -p=%t5 -o %t6 -nl -ignore-build-id 2>&1 | FileCheck %s --check-prefix=CHECK-NO-PIE + +CHECK-NO-PIE-NOT: PERF2BOLT-ERROR +CHECK-NO-PIE-NOT: !! WARNING !! This high mismatch ratio indicates the input binary is probably not the same binary used during profiling collection. \ No newline at end of file _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits