The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH 1/2] selftests/ftrace: Force C locale for readelf in uprobe test
@ 2026-08-06  8:31 Rui Qi
  2026-08-06  8:31 ` [PATCH 2/2] selftests/ftrace: Convert ELF entry point to file offset " Rui Qi
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Rui Qi @ 2026-08-06  8:31 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, Shuah Khan
  Cc: Heiko Carstens, linux-trace-kernel, linux-kselftest, linux-kernel,
	Rui Qi

The add_remove_uprobe test parses the entry point from readelf -h output
by looking for the English "Entry" field. readelf output is localized
via gettext, while the ftracetest runner does not force LC_ALL=C and the
top-level Makefile leaves LANG effective for child processes.

If readelf prints a translated field name, ENTRYPOINT becomes empty and
the uprobe_events write is rejected because the offset after PATH: is
missing.

Run readelf with LC_ALL=C so the parsed header field remains stable
across locales.

Signed-off-by: Rui Qi <qirui.001@bytedance.com>
---
 .../selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
index f2048c244526..f33a863be68b 100644
--- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
+++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
@@ -12,7 +12,7 @@ echo 0 > events/enable
 echo > dynamic_events
 
 REALBIN=`readlink -f /bin/sh`
-ENTRYPOINT=`readelf -h ${REALBIN} | grep Entry | sed -e 's/[^0]*//'`
+ENTRYPOINT=`LC_ALL=C readelf -h ${REALBIN} | grep Entry | sed -e 's/[^0]*//'`
 
 echo "p:myevent ${REALBIN}:${ENTRYPOINT}" >> uprobe_events
 
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/2] selftests/ftrace: Convert ELF entry point to file offset in uprobe test
  2026-08-06  8:31 [PATCH 1/2] selftests/ftrace: Force C locale for readelf in uprobe test Rui Qi
@ 2026-08-06  8:31 ` Rui Qi
  2026-08-07  1:47 ` [PATCH 1/2] selftests/ftrace: Force C locale for readelf " Masami Hiramatsu
  2026-08-07  8:15 ` [PATCH v2 0/2] selftests/ftrace: Fix add_remove_uprobe robustness Rui Qi
  2 siblings, 0 replies; 9+ messages in thread
From: Rui Qi @ 2026-08-06  8:31 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, Shuah Khan
  Cc: Heiko Carstens, linux-trace-kernel, linux-kselftest, linux-kernel,
	Rui Qi

The add_remove_uprobe test uses "readelf -h" to obtain the ELF entry
point (e_entry) and passes it directly as the offset to uprobe_events.
However, uprobe_events expects a file offset, not a virtual address.

For PIE binaries (ET_DYN), the virtual address happens to equal the file
offset because the first LOAD segment has p_vaddr == p_offset, so the
test works by coincidence. But for non-PIE executables (ET_EXEC),
e_entry is an absolute virtual address (e.g. 0x406ad0) that far exceeds
the file size (e.g. 0x7be60). When the probe is enabled, uprobe_register()
checks offset > i_size_read(inode) and rejects it with -EINVAL.

Fix this by converting the virtual address to a file offset using the
ELF program headers: scan readelf -lW output for the LOAD segment
containing the entry point, then compute file_offset = e_entry -
p_vaddr + p_offset. For PIE binaries the result is unchanged; for
non-PIE binaries the offset is correctly translated.

The conversion uses only POSIX shell primitives (printf, arithmetic
expansion) with no dependency on gawk or perl.

Fixes: dc4b165855f2 ("selftests/ftrace: Use readelf to find entry point in uprobe test")
Signed-off-by: Rui Qi <qirui.001@bytedance.com>
---
 .../test.d/dynevent/add_remove_uprobe.tc      | 27 +++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
index f33a863be68b..9207fd817aae 100644
--- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
+++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
@@ -12,9 +12,32 @@ echo 0 > events/enable
 echo > dynamic_events
 
 REALBIN=`readlink -f /bin/sh`
-ENTRYPOINT=`LC_ALL=C readelf -h ${REALBIN} | grep Entry | sed -e 's/[^0]*//'`
 
-echo "p:myevent ${REALBIN}:${ENTRYPOINT}" >> uprobe_events
+# Get the entry point virtual address from ELF header
+ENTRY=`LC_ALL=C readelf -hW ${REALBIN} | grep "Entry point" | awk '{print $NF}'`
+
+# Convert virtual address to file offset: find the LOAD segment containing
+# the entry point, then compute file_offset = e_entry - p_vaddr + p_offset.
+# For PIE binaries this is a no-op (vaddr == file offset), but for non-PIE
+# executables the virtual address is much larger than the file size and
+# must be converted, otherwise uprobe_register() rejects it with -EINVAL.
+ENTRY_DEC=$(printf '%d' "$ENTRY")
+OFFSET=$ENTRY
+while IFS= read -r line; do
+    set -- $line
+    [ "$1" = "LOAD" ] || continue
+    VA_DEC=$(printf '%d' "$3")
+    OFF_DEC=$(printf '%d' "$2")
+    FSZ_DEC=$(printf '%d' "$5")
+    if [ "$ENTRY_DEC" -ge "$VA_DEC" ] && [ "$ENTRY_DEC" -lt "$((VA_DEC + FSZ_DEC))" ]; then
+        OFFSET=$(printf '0x%x' "$((ENTRY_DEC - VA_DEC + OFF_DEC))")
+        break
+    fi
+done << EOF
+$(LC_ALL=C readelf -lW ${REALBIN} | grep LOAD)
+EOF
+
+echo "p:myevent ${REALBIN}:${OFFSET}" >> uprobe_events
 
 grep -q myevent uprobe_events
 test -d events/uprobes/myevent
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] selftests/ftrace: Force C locale for readelf in uprobe test
  2026-08-06  8:31 [PATCH 1/2] selftests/ftrace: Force C locale for readelf in uprobe test Rui Qi
  2026-08-06  8:31 ` [PATCH 2/2] selftests/ftrace: Convert ELF entry point to file offset " Rui Qi
@ 2026-08-07  1:47 ` Masami Hiramatsu
  2026-08-07  8:01   ` Rui Qi
  2026-08-07  8:15 ` [PATCH v2 0/2] selftests/ftrace: Fix add_remove_uprobe robustness Rui Qi
  2 siblings, 1 reply; 9+ messages in thread
From: Masami Hiramatsu @ 2026-08-07  1:47 UTC (permalink / raw)
  To: Rui Qi
  Cc: Steven Rostedt, Mathieu Desnoyers, Shuah Khan, Heiko Carstens,
	linux-trace-kernel, linux-kselftest, linux-kernel

On Thu,  6 Aug 2026 16:31:00 +0800
"Rui Qi" <qirui.001@bytedance.com> wrote:

> The add_remove_uprobe test parses the entry point from readelf -h output
> by looking for the English "Entry" field. readelf output is localized
> via gettext, while the ftracetest runner does not force LC_ALL=C and the
> top-level Makefile leaves LANG effective for child processes.

Hmm, to make it safer, I think we should force LC_ALL=C in the top level
of ftracetest, instead of setting it in each test case.

Thank you,

> 
> If readelf prints a translated field name, ENTRYPOINT becomes empty and
> the uprobe_events write is rejected because the offset after PATH: is
> missing.
> 
> Run readelf with LC_ALL=C so the parsed header field remains stable
> across locales.
> 
> Signed-off-by: Rui Qi <qirui.001@bytedance.com>
> ---
>  .../selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc       | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
> index f2048c244526..f33a863be68b 100644
> --- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
> +++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
> @@ -12,7 +12,7 @@ echo 0 > events/enable
>  echo > dynamic_events
>  
>  REALBIN=`readlink -f /bin/sh`
> -ENTRYPOINT=`readelf -h ${REALBIN} | grep Entry | sed -e 's/[^0]*//'`
> +ENTRYPOINT=`LC_ALL=C readelf -h ${REALBIN} | grep Entry | sed -e 's/[^0]*//'`
>  
>  echo "p:myevent ${REALBIN}:${ENTRYPOINT}" >> uprobe_events
>  
> -- 
> 2.20.1


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] selftests/ftrace: Force C locale for readelf in uprobe test
  2026-08-07  1:47 ` [PATCH 1/2] selftests/ftrace: Force C locale for readelf " Masami Hiramatsu
@ 2026-08-07  8:01   ` Rui Qi
  0 siblings, 0 replies; 9+ messages in thread
From: Rui Qi @ 2026-08-07  8:01 UTC (permalink / raw)
  To: Masami Hiramatsu (Google)
  Cc: Steven Rostedt, Mathieu Desnoyers, Shuah Khan, Heiko Carstens,
	linux-trace-kernel, linux-kselftest, linux-kernel

On 8/7/26 9:47 AM, Masami Hiramatsu (Google) wrote:
> On Thu,  6 Aug 2026 16:31:00 +0800
> "Rui Qi" <qirui.001@bytedance.com> wrote:
> 
>> The add_remove_uprobe test parses the entry point from readelf -h output
>> by looking for the English "Entry" field. readelf output is localized
>> via gettext, while the ftracetest runner does not force LC_ALL=C and the
>> top-level Makefile leaves LANG effective for child processes.
> 
> Hmm, to make it safer, I think we should force LC_ALL=C in the top level
> of ftracetest, instead of setting it in each test case.
> 
> Thank you,
> 

Thank you for the suggestion.

Agreed, setting LC_ALL=C in the ftracetest runner is better than fixing
this one readelf invocation. I will update ftracetest to export LC_ALL=C
so all test cases inherit the C locale, and send a v2.

Thanks,
Rui


>>
>> If readelf prints a translated field name, ENTRYPOINT becomes empty and
>> the uprobe_events write is rejected because the offset after PATH: is
>> missing.
>>
>> Run readelf with LC_ALL=C so the parsed header field remains stable
>> across locales.
>>
>> Signed-off-by: Rui Qi <qirui.001@bytedance.com>
>> ---
>>  .../selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc       | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
>> index f2048c244526..f33a863be68b 100644
>> --- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
>> +++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
>> @@ -12,7 +12,7 @@ echo 0 > events/enable
>>  echo > dynamic_events
>>  
>>  REALBIN=`readlink -f /bin/sh`
>> -ENTRYPOINT=`readelf -h ${REALBIN} | grep Entry | sed -e 's/[^0]*//'`
>> +ENTRYPOINT=`LC_ALL=C readelf -h ${REALBIN} | grep Entry | sed -e 's/[^0]*//'`
>>  
>>  echo "p:myevent ${REALBIN}:${ENTRYPOINT}" >> uprobe_events
>>  
>> -- 
>> 2.20.1
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 0/2] selftests/ftrace: Fix add_remove_uprobe robustness
  2026-08-06  8:31 [PATCH 1/2] selftests/ftrace: Force C locale for readelf in uprobe test Rui Qi
  2026-08-06  8:31 ` [PATCH 2/2] selftests/ftrace: Convert ELF entry point to file offset " Rui Qi
  2026-08-07  1:47 ` [PATCH 1/2] selftests/ftrace: Force C locale for readelf " Masami Hiramatsu
@ 2026-08-07  8:15 ` Rui Qi
  2026-08-07  8:15   ` [PATCH v2 1/2] selftests/ftrace: Force C locale in ftracetest Rui Qi
                     ` (2 more replies)
  2 siblings, 3 replies; 9+ messages in thread
From: Rui Qi @ 2026-08-07  8:15 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu
  Cc: Mathieu Desnoyers, Shuah Khan, Heiko Carstens, linux-kernel,
	linux-trace-kernel, linux-kselftest, Rui Qi

Hi,

This series fixes two ways add_remove_uprobe can construct an invalid
uprobe offset.

Patch 1 follows Masami's feedback on v1 and forces the C locale in the
top-level ftracetest runner, rather than setting LC_ALL=C around each
readelf invocation.

Patch 2 fixes the remaining offset issue. readelf reports the ELF entry
point as a virtual address, while uprobe_events expects a file offset.
Convert the entry point through the LOAD program headers so the test also
works for non-PIE executables.

Changes in v2:
- Move LC_ALL=C to the top-level ftracetest runner, as suggested by
  Masami.
- Keep the entry-point-to-file-offset conversion as the second patch and
  rely on the runner-provided locale for readelf output.

Testing:
- ./scripts/checkpatch.pl --strict -g HEAD~2..HEAD
- sh -n tools/testing/selftests/ftrace/ftracetest
- sh -n tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc

Rui Qi (2):
  selftests/ftrace: Force C locale in ftracetest
  selftests/ftrace: Convert ELF entry point to file offset in uprobe
    test

 tools/testing/selftests/ftrace/ftracetest     |  3 +++
 .../test.d/dynevent/add_remove_uprobe.tc      | 27 +++++++++++++++++--
 2 files changed, 28 insertions(+), 2 deletions(-)

-- 
2.20.1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/2] selftests/ftrace: Force C locale in ftracetest
  2026-08-07  8:15 ` [PATCH v2 0/2] selftests/ftrace: Fix add_remove_uprobe robustness Rui Qi
@ 2026-08-07  8:15   ` Rui Qi
  2026-08-07  8:15   ` [PATCH v2 2/2] selftests/ftrace: Convert ELF entry point to file offset in uprobe test Rui Qi
  2026-08-07 10:29   ` [PATCH v2 0/2] selftests/ftrace: Fix add_remove_uprobe robustness Masami Hiramatsu
  2 siblings, 0 replies; 9+ messages in thread
From: Rui Qi @ 2026-08-07  8:15 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu
  Cc: Mathieu Desnoyers, Shuah Khan, Heiko Carstens, linux-kernel,
	linux-trace-kernel, linux-kselftest, Rui Qi

Some ftracetest test cases parse command output by matching English
field names. Tools such as readelf may localize their output via
gettext, while ftracetest currently inherits the user locale from
the environment.

If a translated field name is printed, parsing can fail even though
the tested kernel behavior is unchanged. For example, add_remove_uprobe
can fail to find the ELF entry point and then write a uprobe event with
a missing offset.

Export LC_ALL=C in the top-level ftracetest runner so every test case
gets stable command output by default.

Signed-off-by: Rui Qi <qirui.001@bytedance.com>
---
 tools/testing/selftests/ftrace/ftracetest | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
index 8ad2c385407e..246d7e1d015c 100755
--- a/tools/testing/selftests/ftrace/ftracetest
+++ b/tools/testing/selftests/ftrace/ftracetest
@@ -7,6 +7,9 @@
 #  Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
 #
 
+# Keep command output parsing stable regardless of the user's locale.
+export LC_ALL=C
+
 usage() { # errno [message]
 [ ! -z "$2" ] && echo $2
 echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]"
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/2] selftests/ftrace: Convert ELF entry point to file offset in uprobe test
  2026-08-07  8:15 ` [PATCH v2 0/2] selftests/ftrace: Fix add_remove_uprobe robustness Rui Qi
  2026-08-07  8:15   ` [PATCH v2 1/2] selftests/ftrace: Force C locale in ftracetest Rui Qi
@ 2026-08-07  8:15   ` Rui Qi
  2026-08-07 10:30     ` Masami Hiramatsu
  2026-08-07 10:29   ` [PATCH v2 0/2] selftests/ftrace: Fix add_remove_uprobe robustness Masami Hiramatsu
  2 siblings, 1 reply; 9+ messages in thread
From: Rui Qi @ 2026-08-07  8:15 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu
  Cc: Mathieu Desnoyers, Shuah Khan, Heiko Carstens, linux-kernel,
	linux-trace-kernel, linux-kselftest, Rui Qi

The add_remove_uprobe test uses readelf -h to obtain the ELF entry
point (e_entry) and passes it directly as the offset to uprobe_events.
However, uprobe_events expects a file offset, not a virtual address.

For PIE binaries, the virtual address happens to equal the file offset
because the first LOAD segment has p_vaddr == p_offset, so the test
works by coincidence. But for non-PIE executables, e_entry is an
absolute virtual address that can far exceed the file size. When the
probe is enabled, uprobe_register() checks offset > i_size_read(inode)
and rejects it with -EINVAL.

Fix this by converting the virtual address to a file offset using the
ELF program headers: scan readelf -lW output for the LOAD segment
containing the entry point, then compute file_offset = e_entry -
p_vaddr + p_offset. For PIE binaries the result is unchanged; for
non-PIE binaries the offset is correctly translated.

The conversion uses only POSIX shell primitives, with no dependency on
gawk or perl.

Fixes: dc4b165855f2 ("selftests/ftrace: Use readelf to find entry point in uprobe test")
Signed-off-by: Rui Qi <qirui.001@bytedance.com>
---
 .../test.d/dynevent/add_remove_uprobe.tc      | 27 +++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
index f2048c244526..19430bd5864c 100644
--- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
+++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
@@ -12,9 +12,32 @@ echo 0 > events/enable
 echo > dynamic_events
 
 REALBIN=`readlink -f /bin/sh`
-ENTRYPOINT=`readelf -h ${REALBIN} | grep Entry | sed -e 's/[^0]*//'`
 
-echo "p:myevent ${REALBIN}:${ENTRYPOINT}" >> uprobe_events
+# Get the entry point virtual address from ELF header
+ENTRY=`readelf -hW ${REALBIN} | grep "Entry point" | awk '{print $NF}'`
+
+# Convert virtual address to file offset: find the LOAD segment containing
+# the entry point, then compute file_offset = e_entry - p_vaddr + p_offset.
+# For PIE binaries this is a no-op (vaddr == file offset), but for non-PIE
+# executables the virtual address is much larger than the file size and
+# must be converted, otherwise uprobe_register() rejects it with -EINVAL.
+ENTRY_DEC=$(printf '%d' "$ENTRY")
+OFFSET=$ENTRY
+while IFS= read -r line; do
+    set -- $line
+    [ "$1" = "LOAD" ] || continue
+    VA_DEC=$(printf '%d' "$3")
+    OFF_DEC=$(printf '%d' "$2")
+    FSZ_DEC=$(printf '%d' "$5")
+    if [ "$ENTRY_DEC" -ge "$VA_DEC" ] && [ "$ENTRY_DEC" -lt "$((VA_DEC + FSZ_DEC))" ]; then
+        OFFSET=$(printf '0x%x' "$((ENTRY_DEC - VA_DEC + OFF_DEC))")
+        break
+    fi
+done << EOF
+$(readelf -lW ${REALBIN} | grep LOAD)
+EOF
+
+echo "p:myevent ${REALBIN}:${OFFSET}" >> uprobe_events
 
 grep -q myevent uprobe_events
 test -d events/uprobes/myevent
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 0/2] selftests/ftrace: Fix add_remove_uprobe robustness
  2026-08-07  8:15 ` [PATCH v2 0/2] selftests/ftrace: Fix add_remove_uprobe robustness Rui Qi
  2026-08-07  8:15   ` [PATCH v2 1/2] selftests/ftrace: Force C locale in ftracetest Rui Qi
  2026-08-07  8:15   ` [PATCH v2 2/2] selftests/ftrace: Convert ELF entry point to file offset in uprobe test Rui Qi
@ 2026-08-07 10:29   ` Masami Hiramatsu
  2 siblings, 0 replies; 9+ messages in thread
From: Masami Hiramatsu @ 2026-08-07 10:29 UTC (permalink / raw)
  To: Rui Qi
  Cc: Steven Rostedt, Mathieu Desnoyers, Shuah Khan, Heiko Carstens,
	linux-kernel, linux-trace-kernel, linux-kselftest

On Fri,  7 Aug 2026 16:15:10 +0800
"Rui Qi" <qirui.001@bytedance.com> wrote:

> Hi,
> 
> This series fixes two ways add_remove_uprobe can construct an invalid
> uprobe offset.

Please send the series in the new thread (not reply) next time.
Instead, you can make a permalink to the previous discussion from your
mail's message-id and write it in the mail body so that we can follow
the discussion in the previous version.

e.g. 

 https://lore.kernel.org/all/20260806083101.2651025-1-qirui.001@bytedance.com/

You can get this using below script.
-----
#!/bin/sh
#
if [ -f "$1" ]; then
  MID=`grep -i ^"Message-Id:" $1 | cut -f2 -d: | tr -d ' <>'`
else
  MID=$1
fi

URL=`curl -Ls -o /dev/null -w %{url_effective} http://lkml.kernel.org/r/$MID`
echo ${URL%T/#u}
-----

Thank you,

> 
> Patch 1 follows Masami's feedback on v1 and forces the C locale in the
> top-level ftracetest runner, rather than setting LC_ALL=C around each
> readelf invocation.
> 
> Patch 2 fixes the remaining offset issue. readelf reports the ELF entry
> point as a virtual address, while uprobe_events expects a file offset.
> Convert the entry point through the LOAD program headers so the test also
> works for non-PIE executables.
> 
> Changes in v2:
> - Move LC_ALL=C to the top-level ftracetest runner, as suggested by
>   Masami.
> - Keep the entry-point-to-file-offset conversion as the second patch and
>   rely on the runner-provided locale for readelf output.
> 
> Testing:
> - ./scripts/checkpatch.pl --strict -g HEAD~2..HEAD
> - sh -n tools/testing/selftests/ftrace/ftracetest
> - sh -n tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
> 
> Rui Qi (2):
>   selftests/ftrace: Force C locale in ftracetest
>   selftests/ftrace: Convert ELF entry point to file offset in uprobe
>     test
> 
>  tools/testing/selftests/ftrace/ftracetest     |  3 +++
>  .../test.d/dynevent/add_remove_uprobe.tc      | 27 +++++++++++++++++--
>  2 files changed, 28 insertions(+), 2 deletions(-)
> 
> -- 
> 2.20.1
> 


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/2] selftests/ftrace: Convert ELF entry point to file offset in uprobe test
  2026-08-07  8:15   ` [PATCH v2 2/2] selftests/ftrace: Convert ELF entry point to file offset in uprobe test Rui Qi
@ 2026-08-07 10:30     ` Masami Hiramatsu
  0 siblings, 0 replies; 9+ messages in thread
From: Masami Hiramatsu @ 2026-08-07 10:30 UTC (permalink / raw)
  To: Rui Qi
  Cc: Steven Rostedt, Mathieu Desnoyers, Shuah Khan, Heiko Carstens,
	linux-kernel, linux-trace-kernel, linux-kselftest

On Fri,  7 Aug 2026 16:15:12 +0800
"Rui Qi" <qirui.001@bytedance.com> wrote:

> The add_remove_uprobe test uses readelf -h to obtain the ELF entry
> point (e_entry) and passes it directly as the offset to uprobe_events.
> However, uprobe_events expects a file offset, not a virtual address.
> 
> For PIE binaries, the virtual address happens to equal the file offset
> because the first LOAD segment has p_vaddr == p_offset, so the test
> works by coincidence. But for non-PIE executables, e_entry is an
> absolute virtual address that can far exceed the file size. When the
> probe is enabled, uprobe_register() checks offset > i_size_read(inode)
> and rejects it with -EINVAL.

Good catch!

> 
> Fix this by converting the virtual address to a file offset using the
> ELF program headers: scan readelf -lW output for the LOAD segment
> containing the entry point, then compute file_offset = e_entry -
> p_vaddr + p_offset. For PIE binaries the result is unchanged; for
> non-PIE binaries the offset is correctly translated.
> 
> The conversion uses only POSIX shell primitives, with no dependency on
> gawk or perl.
> 
> Fixes: dc4b165855f2 ("selftests/ftrace: Use readelf to find entry point in uprobe test")
> Signed-off-by: Rui Qi <qirui.001@bytedance.com>

OK, let me take it.

Thank you!

> ---
>  .../test.d/dynevent/add_remove_uprobe.tc      | 27 +++++++++++++++++--
>  1 file changed, 25 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
> index f2048c244526..19430bd5864c 100644
> --- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
> +++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_uprobe.tc
> @@ -12,9 +12,32 @@ echo 0 > events/enable
>  echo > dynamic_events
>  
>  REALBIN=`readlink -f /bin/sh`
> -ENTRYPOINT=`readelf -h ${REALBIN} | grep Entry | sed -e 's/[^0]*//'`
>  
> -echo "p:myevent ${REALBIN}:${ENTRYPOINT}" >> uprobe_events
> +# Get the entry point virtual address from ELF header
> +ENTRY=`readelf -hW ${REALBIN} | grep "Entry point" | awk '{print $NF}'`
> +
> +# Convert virtual address to file offset: find the LOAD segment containing
> +# the entry point, then compute file_offset = e_entry - p_vaddr + p_offset.
> +# For PIE binaries this is a no-op (vaddr == file offset), but for non-PIE
> +# executables the virtual address is much larger than the file size and
> +# must be converted, otherwise uprobe_register() rejects it with -EINVAL.
> +ENTRY_DEC=$(printf '%d' "$ENTRY")
> +OFFSET=$ENTRY
> +while IFS= read -r line; do
> +    set -- $line
> +    [ "$1" = "LOAD" ] || continue
> +    VA_DEC=$(printf '%d' "$3")
> +    OFF_DEC=$(printf '%d' "$2")
> +    FSZ_DEC=$(printf '%d' "$5")
> +    if [ "$ENTRY_DEC" -ge "$VA_DEC" ] && [ "$ENTRY_DEC" -lt "$((VA_DEC + FSZ_DEC))" ]; then
> +        OFFSET=$(printf '0x%x' "$((ENTRY_DEC - VA_DEC + OFF_DEC))")
> +        break
> +    fi
> +done << EOF
> +$(readelf -lW ${REALBIN} | grep LOAD)
> +EOF
> +
> +echo "p:myevent ${REALBIN}:${OFFSET}" >> uprobe_events
>  
>  grep -q myevent uprobe_events
>  test -d events/uprobes/myevent
> -- 
> 2.20.1


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-08-07 10:30 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-06  8:31 [PATCH 1/2] selftests/ftrace: Force C locale for readelf in uprobe test Rui Qi
2026-08-06  8:31 ` [PATCH 2/2] selftests/ftrace: Convert ELF entry point to file offset " Rui Qi
2026-08-07  1:47 ` [PATCH 1/2] selftests/ftrace: Force C locale for readelf " Masami Hiramatsu
2026-08-07  8:01   ` Rui Qi
2026-08-07  8:15 ` [PATCH v2 0/2] selftests/ftrace: Fix add_remove_uprobe robustness Rui Qi
2026-08-07  8:15   ` [PATCH v2 1/2] selftests/ftrace: Force C locale in ftracetest Rui Qi
2026-08-07  8:15   ` [PATCH v2 2/2] selftests/ftrace: Convert ELF entry point to file offset in uprobe test Rui Qi
2026-08-07 10:30     ` Masami Hiramatsu
2026-08-07 10:29   ` [PATCH v2 0/2] selftests/ftrace: Fix add_remove_uprobe robustness Masami Hiramatsu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox