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

Reply via email to