From 6dab839e1f20f9afe2fe812971081e654c71e2f9 Mon Sep 17 00:00:00 2001 From: not-matthias <26800596+not-matthias@users.noreply.github.com> Date: Tue, 21 Oct 2025 16:06:34 +0200 Subject: [PATCH 1/2] feat: add support for .plt.sec sections --- callgrind/fn.c | 2 +- coregrind/m_debuginfo/debuginfo.c | 17 ++++++++++++ coregrind/m_debuginfo/priv_storage.h | 4 +++ coregrind/m_debuginfo/readelf.c | 41 ++++++++++++++++++++++++++++ include/pub_tool_debuginfo.h | 5 +++- 5 files changed, 67 insertions(+), 2 deletions(-) diff --git a/callgrind/fn.c b/callgrind/fn.c index 855feda98..a291f012e 100644 --- a/callgrind/fn.c +++ b/callgrind/fn.c @@ -663,7 +663,7 @@ fn_node* CLG_(get_fn_node)(BB* bb) pure[1] = fn; fn->pure_cxt = CLG_(get_cxt)(pure+1); - if (bb->sect_kind == Vg_SectPLT) + if (bb->sect_kind == Vg_SectPLT || bb->sect_kind == Vg_SectPLTSEC) fn->skip = CLG_(clo).skip_plt; if (VG_(strncmp)(fn->name, "_dl_runtime_resolve", 19)==0) { diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c index 58d6d9825..fb3674565 100644 --- a/coregrind/m_debuginfo/debuginfo.c +++ b/coregrind/m_debuginfo/debuginfo.c @@ -4975,6 +4975,16 @@ SizeT VG_(DebugInfo_get_plt_size)(const DebugInfo* di) return di->plt_present ? di->plt_size : 0; } +Addr VG_(DebugInfo_get_pltsec_avma)(const DebugInfo* di) +{ + return di->pltsec_present ? di->pltsec_avma : 0; +} + +SizeT VG_(DebugInfo_get_pltsec_size)(const DebugInfo* di) +{ + return di->pltsec_present ? di->pltsec_size : 0; +} + Addr VG_(DebugInfo_get_gotplt_avma)(const DebugInfo* di) { return di->gotplt_present ? di->gotplt_avma : 0; @@ -5053,6 +5063,7 @@ const HChar* VG_(pp_SectKind)( VgSectKind kind ) case Vg_SectPLT: return "PLT"; case Vg_SectOPD: return "OPD"; case Vg_SectGOTPLT: return "GOTPLT"; + case Vg_SectPLTSEC: return "PLTSEC"; default: vg_assert(0); } } @@ -5115,6 +5126,12 @@ VgSectKind VG_(DebugInfo_sect_kind)( /*OUT*/const HChar** objname, Addr a) res = Vg_SectPLT; break; } + if (di->pltsec_present + && di->pltsec_size > 0 + && a >= di->pltsec_avma && a < di->pltsec_avma + di->pltsec_size) { + res = Vg_SectPLTSEC; + break; + } if (di->got_present && di->got_size > 0 && a >= di->got_avma && a < di->got_avma + di->got_size) { diff --git a/coregrind/m_debuginfo/priv_storage.h b/coregrind/m_debuginfo/priv_storage.h index d8cba81c4..055d75e6f 100644 --- a/coregrind/m_debuginfo/priv_storage.h +++ b/coregrind/m_debuginfo/priv_storage.h @@ -905,6 +905,10 @@ struct _DebugInfo { Bool plt_present; Addr plt_avma; SizeT plt_size; + /* .plt.sec */ + Bool pltsec_present; + Addr pltsec_avma; + SizeT pltsec_size; /* .got */ Bool got_present; Addr got_avma; diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c index 61a39af2a..72fccbab4 100644 --- a/coregrind/m_debuginfo/readelf.c +++ b/coregrind/m_debuginfo/readelf.c @@ -2734,6 +2734,17 @@ Bool ML_(read_elf_object) ( struct _DebugInfo* di ) BAD(".plt"); } } + /* Accept .plt.sec where mapped as rx (code) - hardened PLT section */ + if (0 == VG_(strcmp)(name, ".plt.sec")) { + if (inrx && !di->pltsec_present) { + di->pltsec_present = True; + di->pltsec_avma = svma + inrx->bias; + di->pltsec_size = size; + TRACE_SYMTAB("acquiring .plt.sec avma = %#lx\n", di->pltsec_avma); + } else { + BAD(".plt.sec"); + } + } # elif defined(VGP_ppc32_linux) /* Accept .plt where mapped as rw (data) */ if (0 == VG_(strcmp)(name, ".plt")) { @@ -2746,6 +2757,17 @@ Bool ML_(read_elf_object) ( struct _DebugInfo* di ) BAD(".plt"); } } + /* Accept .plt.sec where mapped as rw (data) - hardened PLT section */ + if (0 == VG_(strcmp)(name, ".plt.sec")) { + if (inrw1 && !di->pltsec_present) { + di->pltsec_present = True; + di->pltsec_avma = svma + inrw1->bias; + di->pltsec_size = size; + TRACE_SYMTAB("acquiring .plt.sec avma = %#lx\n", di->pltsec_avma); + } else { + BAD(".plt.sec"); + } + } # elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) /* Accept .plt where mapped as rw (data), or unmapped */ if (0 == VG_(strcmp)(name, ".plt")) { @@ -2766,6 +2788,25 @@ Bool ML_(read_elf_object) ( struct _DebugInfo* di ) BAD(".plt"); } } + /* Accept .plt.sec where mapped as rw (data), or unmapped - hardened PLT section */ + if (0 == VG_(strcmp)(name, ".plt.sec")) { + if (inrw1 && !di->pltsec_present) { + di->pltsec_present = True; + di->pltsec_avma = svma + inrw1->bias; + di->pltsec_size = size; + TRACE_SYMTAB("acquiring .plt.sec avma = %#lx\n", di->pltsec_avma); + } else + if ((!inrw1) && (!inrx) && size > 0 && !di->pltsec_present) { + /* File contains a .plt.sec, but it didn't get mapped. + Presumably it is not required on this platform. At + least don't reject the situation as invalid. */ + di->pltsec_present = True; + di->pltsec_avma = 0; + di->pltsec_size = 0; + } else { + BAD(".plt.sec"); + } + } # else # error "Unsupported platform" # endif diff --git a/include/pub_tool_debuginfo.h b/include/pub_tool_debuginfo.h index 7623c6663..f18f98fb3 100644 --- a/include/pub_tool_debuginfo.h +++ b/include/pub_tool_debuginfo.h @@ -282,6 +282,8 @@ Addr VG_(DebugInfo_get_bss_avma) ( const DebugInfo *di ); SizeT VG_(DebugInfo_get_bss_size) ( const DebugInfo *di ); Addr VG_(DebugInfo_get_plt_avma) ( const DebugInfo *di ); SizeT VG_(DebugInfo_get_plt_size) ( const DebugInfo *di ); +Addr VG_(DebugInfo_get_pltsec_avma) ( const DebugInfo *di ); +SizeT VG_(DebugInfo_get_pltsec_size) ( const DebugInfo *di ); Addr VG_(DebugInfo_get_gotplt_avma) ( const DebugInfo *di ); SizeT VG_(DebugInfo_get_gotplt_size) ( const DebugInfo *di ); Addr VG_(DebugInfo_get_got_avma) ( const DebugInfo *di ); @@ -310,7 +312,8 @@ typedef Vg_SectGOT, Vg_SectPLT, Vg_SectGOTPLT, - Vg_SectOPD + Vg_SectOPD, + Vg_SectPLTSEC } VgSectKind; From dd7e028b4da73ddc743b8f429422f146af28105b Mon Sep 17 00:00:00 2001 From: not-matthias <26800596+not-matthias@users.noreply.github.com> Date: Wed, 22 Oct 2025 11:35:41 +0200 Subject: [PATCH 2/2] docs: explain changes of --skip-plt --- CODSPEED-CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CODSPEED-CHANGELOG.md b/CODSPEED-CHANGELOG.md index 3b440563e..229119c0e 100644 --- a/CODSPEED-CHANGELOG.md +++ b/CODSPEED-CHANGELOG.md @@ -4,6 +4,17 @@ This file documents changes made to Valgrind for CodSpeed integration, beyond th ## Features +### Skip `.plt.sec` in `--skip-plt` + +**Feature**: Added support for skipping `.plt.sec` sections when using the `--skip-plt` option. + +**Motivation**: The `.plt.sec` section is a specialized variant of the Procedure Linkage Table (PLT) used in systems with Intel Control-flow Enforcement Technology (CET). When profiling applications using libraries compiled with it (e.g. libpython), symbols in `.plt.sec` were not skipped by the `--skip-plt` option, causing unresolved addresses to appear in profiling data (e.g., `_PySequence_Tuple` at 0x48ce4a0). Both `.plt` and `.plt.sec` sections contain only jumps to the actual function implementations, and do not have any symbols associated with those wrapper functions. + +**How it works**: +- Extends the existing PLT-skipping logic to also recognize and skip `.plt.sec` sections +- Whenever we see a function inside the `.plt.sec` section, skip it + +**Usage**: Enable `--skip-plt=yes` and both `.plt` and `.plt.sec` will be skipped. ### Callgrind: Inline Function Tracking