Skip to content

Commit 680f925

Browse files
committed
Fix profiling after a binutils NOTE change
Resolves: rhbz#2322754 Ref: llvm/llvm-project#114605 Ref: llvm/llvm-project#114907
1 parent 5bc80c8 commit 680f925

File tree

2 files changed

+96
-1
lines changed

2 files changed

+96
-1
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
From ccc2b792e57d632bc887b226a4e7f0a8189eab8b Mon Sep 17 00:00:00 2001
2+
From: Josh Stone <[email protected]>
3+
Date: Mon, 4 Nov 2024 16:37:49 -0800
4+
Subject: [PATCH] [profile] Use base+vaddr for `__llvm_write_binary_ids` note
5+
pointers
6+
7+
This function is always examining its own ELF headers in memory, but it
8+
was trying to use conditions between examining files or memory, and it
9+
wasn't accounting for LOAD offsets at runtime. This is especially bad if
10+
a loaded segment has additional padding that's not in the file offsets.
11+
12+
Now we do a first scan of the program headers to figure out the runtime
13+
base address based on `PT_PHDR` and/or `PT_DYNAMIC` (else assume zero),
14+
similar to libc's `do_start`. Then each `PT_NOTE` pointer is simply the
15+
base plus the segments's `pt_vaddr`, which includes LOAD offsets.
16+
17+
Fixes #114605
18+
---
19+
.../lib/profile/InstrProfilingPlatformLinux.c | 40 ++++++++-----------
20+
1 file changed, 16 insertions(+), 24 deletions(-)
21+
22+
diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c
23+
index e2c06d51e0c6..c365129a0768 100644
24+
--- a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c
25+
+++ b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c
26+
@@ -194,41 +194,33 @@ static int WriteBinaryIds(ProfDataWriter *Writer, const ElfW(Nhdr) * Note,
27+
*/
28+
COMPILER_RT_VISIBILITY int __llvm_write_binary_ids(ProfDataWriter *Writer) {
29+
extern const ElfW(Ehdr) __ehdr_start __attribute__((visibility("hidden")));
30+
+ extern ElfW(Dyn) _DYNAMIC[] __attribute__((weak, visibility("hidden")));
31+
+
32+
const ElfW(Ehdr) *ElfHeader = &__ehdr_start;
33+
const ElfW(Phdr) *ProgramHeader =
34+
(const ElfW(Phdr) *)((uintptr_t)ElfHeader + ElfHeader->e_phoff);
35+
36+
+ /* Compute the added base address in case of position-independent code. */
37+
+ uintptr_t Base = 0;
38+
+ for (uint32_t I = 0; I < ElfHeader->e_phnum; I++) {
39+
+ if (ProgramHeader[I].p_type == PT_PHDR)
40+
+ Base = (uintptr_t)ProgramHeader - ProgramHeader[I].p_vaddr;
41+
+ if (ProgramHeader[I].p_type == PT_DYNAMIC && _DYNAMIC)
42+
+ Base = (uintptr_t)_DYNAMIC - ProgramHeader[I].p_vaddr;
43+
+ }
44+
+
45+
int TotalBinaryIdsSize = 0;
46+
- uint32_t I;
47+
/* Iterate through entries in the program header. */
48+
- for (I = 0; I < ElfHeader->e_phnum; I++) {
49+
+ for (uint32_t I = 0; I < ElfHeader->e_phnum; I++) {
50+
/* Look for the notes segment in program header entries. */
51+
if (ProgramHeader[I].p_type != PT_NOTE)
52+
continue;
53+
54+
/* There can be multiple notes segment, and examine each of them. */
55+
- const ElfW(Nhdr) * Note;
56+
- const ElfW(Nhdr) * NotesEnd;
57+
- /*
58+
- * When examining notes in file, use p_offset, which is the offset within
59+
- * the elf file, to find the start of notes.
60+
- */
61+
- if (ProgramHeader[I].p_memsz == 0 ||
62+
- ProgramHeader[I].p_memsz == ProgramHeader[I].p_filesz) {
63+
- Note = (const ElfW(Nhdr) *)((uintptr_t)ElfHeader +
64+
- ProgramHeader[I].p_offset);
65+
- NotesEnd = (const ElfW(Nhdr) *)((const char *)(Note) +
66+
- ProgramHeader[I].p_filesz);
67+
- } else {
68+
- /*
69+
- * When examining notes in memory, use p_vaddr, which is the address of
70+
- * section after loaded to memory, to find the start of notes.
71+
- */
72+
- Note =
73+
- (const ElfW(Nhdr) *)((uintptr_t)ElfHeader + ProgramHeader[I].p_vaddr);
74+
- NotesEnd =
75+
- (const ElfW(Nhdr) *)((const char *)(Note) + ProgramHeader[I].p_memsz);
76+
- }
77+
+ const ElfW(Nhdr) *Note =
78+
+ (const ElfW(Nhdr) *)(Base + ProgramHeader[I].p_vaddr);
79+
+ const ElfW(Nhdr) *NotesEnd =
80+
+ (const ElfW(Nhdr) *)((const char *)(Note) + ProgramHeader[I].p_memsz);
81+
82+
int BinaryIdsSize = WriteBinaryIds(Writer, Note, NotesEnd);
83+
if (TotalBinaryIdsSize == -1)
84+
--
85+
2.47.0
86+

llvm.spec

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@
182182
#region main package
183183
Name: %{pkg_name_llvm}
184184
Version: %{maj_ver}.%{min_ver}.%{patch_ver}%{?rc_ver:~rc%{rc_ver}}%{?llvm_snapshot_version_suffix:~%{llvm_snapshot_version_suffix}}
185-
Release: 2%{?dist}
185+
Release: 3%{?dist}
186186
Summary: The Low Level Virtual Machine
187187

188188
License: Apache-2.0 WITH LLVM-exception OR NCSA
@@ -277,6 +277,12 @@ Patch501: 0001-Fix-page-size-constant-on-aarch64-and-ppc64le.patch
277277
# Fixes RHEL-49517.
278278
Patch1801: 18-99273.patch
279279

280+
# Fix profiling after a binutils NOTE change.
281+
# https://github.com/llvm/llvm-project/pull/114907
282+
Patch1802: 0001-profile-Use-base-vaddr-for-__llvm_write_binary_ids-n.patch
283+
Patch1903: 0001-profile-Use-base-vaddr-for-__llvm_write_binary_ids-n.patch
284+
Patch2001: 0001-profile-Use-base-vaddr-for-__llvm_write_binary_ids-n.patch
285+
280286
%if 0%{?rhel} == 8
281287
%global python3_pkgversion 3.12
282288
%global __python3 /usr/bin/python3.12
@@ -2472,6 +2478,9 @@ fi
24722478

24732479
#region changelog
24742480
%changelog
2481+
* Mon Nov 18 2024 Josh Stone <[email protected]> - 19.1.3-3
2482+
- Fix profiling after a binutils NOTE change (rhbz#2322754)
2483+
24752484
* Mon Nov 18 2024 Timm Bäder <[email protected]> - 19.1.3-2
24762485
- Install i386 config files on x86_64
24772486

0 commit comments

Comments
 (0)