Skip to content

Commit 2813b91

Browse files
olsajirianakryiko
authored andcommitted
selftests/bpf: Fix test_attach_probe for powerpc uprobes
When testing uprobes we the test gets GEP (Global Entry Point) address from kallsyms, but then the function is called locally so the uprobe is not triggered. Fixing this by adjusting the address to LEP (Local Entry Point) for powerpc arch plus instruction check stolen from ppc_function_entry function pointed out and explained by Michael and Naveen. Signed-off-by: Jiri Olsa <jolsa@kernel.org> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20210305134050.139840-1-jolsa@kernel.org
1 parent 256becd commit 2813b91

File tree

1 file changed

+44
-1
lines changed

1 file changed

+44
-1
lines changed

tools/testing/selftests/bpf/prog_tests/attach_probe.c

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,49 @@
22
#include <test_progs.h>
33
#include "test_attach_probe.skel.h"
44

5+
#if defined(__powerpc64__) && defined(_CALL_ELF) && _CALL_ELF == 2
6+
7+
#define OP_RT_RA_MASK 0xffff0000UL
8+
#define LIS_R2 0x3c400000UL
9+
#define ADDIS_R2_R12 0x3c4c0000UL
10+
#define ADDI_R2_R2 0x38420000UL
11+
12+
static ssize_t get_offset(ssize_t addr, ssize_t base)
13+
{
14+
u32 *insn = (u32 *) addr;
15+
16+
/*
17+
* A PPC64 ABIv2 function may have a local and a global entry
18+
* point. We need to use the local entry point when patching
19+
* functions, so identify and step over the global entry point
20+
* sequence.
21+
*
22+
* The global entry point sequence is always of the form:
23+
*
24+
* addis r2,r12,XXXX
25+
* addi r2,r2,XXXX
26+
*
27+
* A linker optimisation may convert the addis to lis:
28+
*
29+
* lis r2,XXXX
30+
* addi r2,r2,XXXX
31+
*/
32+
if ((((*insn & OP_RT_RA_MASK) == ADDIS_R2_R12) ||
33+
((*insn & OP_RT_RA_MASK) == LIS_R2)) &&
34+
((*(insn + 1) & OP_RT_RA_MASK) == ADDI_R2_R2))
35+
return (ssize_t)(insn + 2) - base;
36+
else
37+
return addr - base;
38+
}
39+
#else
40+
41+
static ssize_t get_offset(ssize_t addr, ssize_t base)
42+
{
43+
return addr - base;
44+
}
45+
46+
#endif
47+
548
ssize_t get_base_addr() {
649
size_t start, offset;
750
char buf[256];
@@ -36,7 +79,7 @@ void test_attach_probe(void)
3679
if (CHECK(base_addr < 0, "get_base_addr",
3780
"failed to find base addr: %zd", base_addr))
3881
return;
39-
uprobe_offset = (size_t)&get_base_addr - base_addr;
82+
uprobe_offset = get_offset((size_t)&get_base_addr, base_addr);
4083

4184
skel = test_attach_probe__open_and_load();
4285
if (CHECK(!skel, "skel_open", "failed to open skeleton\n"))

0 commit comments

Comments
 (0)