Skip to content

Commit 6b9f772

Browse files
committed
tetragon: Use just single copy of read_reg/write_regs
We have read_reg/write_regs in uprobe_offload.h and generic_calls.h, add just one copy to regs.h. Signed-off-by: Jiri Olsa <[email protected]>
1 parent 1700421 commit 6b9f772

File tree

3 files changed

+145
-175
lines changed

3 files changed

+145
-175
lines changed

bpf/process/generic_calls.h

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "policy_stats.h"
1414
#include "generic_path.h"
1515
#include "bpf_ktime.h"
16+
#include "regs.h"
1617

1718
#define MAX_TOTAL 9000
1819

@@ -485,56 +486,7 @@ FUNC_INLINE long get_pt_regs_arg(struct pt_regs *ctx, struct event_config *confi
485486
if (config->syscall)
486487
return get_pt_regs_arg_syscall(ctx, reg->offset, shift);
487488

488-
#define READ_REG(reg) ({ \
489-
__u64 val; \
490-
asm volatile("%[val] = *(u64 *)(%[ctx] + %[off])\n" \
491-
: [ctx] "+r"(ctx), [val] "+r"(val) \
492-
: [off] "i"(offsetof(struct pt_regs, reg)) \
493-
:); \
494-
val <<= shift; \
495-
val >>= shift; \
496-
val; \
497-
})
498-
499-
switch (reg->offset) {
500-
case offsetof(struct pt_regs, r15):
501-
return READ_REG(r15);
502-
case offsetof(struct pt_regs, r14):
503-
return READ_REG(r14);
504-
case offsetof(struct pt_regs, r13):
505-
return READ_REG(r13);
506-
case offsetof(struct pt_regs, r12):
507-
return READ_REG(r12);
508-
case offsetof(struct pt_regs, bp):
509-
return READ_REG(bp);
510-
case offsetof(struct pt_regs, bx):
511-
return READ_REG(bx);
512-
case offsetof(struct pt_regs, r11):
513-
return READ_REG(r11);
514-
case offsetof(struct pt_regs, r10):
515-
return READ_REG(r10);
516-
case offsetof(struct pt_regs, r9):
517-
return READ_REG(r9);
518-
case offsetof(struct pt_regs, r8):
519-
return READ_REG(r8);
520-
case offsetof(struct pt_regs, ax):
521-
return READ_REG(ax);
522-
case offsetof(struct pt_regs, cx):
523-
return READ_REG(cx);
524-
case offsetof(struct pt_regs, dx):
525-
return READ_REG(dx);
526-
case offsetof(struct pt_regs, si):
527-
return READ_REG(si);
528-
case offsetof(struct pt_regs, di):
529-
return READ_REG(di);
530-
case offsetof(struct pt_regs, ip):
531-
return READ_REG(ip);
532-
case offsetof(struct pt_regs, sp):
533-
return READ_REG(sp);
534-
}
535-
536-
#undef READ_REG
537-
return 0;
489+
return read_reg(ctx, reg->offset, shift);
538490
}
539491
#else
540492
FUNC_INLINE long get_pt_regs_arg(struct pt_regs *ctx, struct event_config *config, int index)

bpf/process/regs.h

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+
/* Copyright Authors of Cilium */
3+
4+
#ifndef __REGS_H__
5+
#define __REGS_H__
6+
7+
#if defined(__TARGET_ARCH_x86)
8+
9+
FUNC_LOCAL __u64
10+
read_reg(struct pt_regs *ctx, __u32 src, __u8 shift)
11+
{
12+
/* Using inlined asm for same reason we use WRITE_REG above. */
13+
#define READ_REG(reg) ({ \
14+
__u64 val; \
15+
asm volatile("%[val] = *(u64 *)(%[ctx] + %[off])\n" \
16+
: [ctx] "+r"(ctx), [val] "+r"(val) \
17+
: [off] "i"(offsetof(struct pt_regs, reg)) \
18+
:); \
19+
val <<= shift; \
20+
val >>= shift; \
21+
val; \
22+
})
23+
24+
switch (src) {
25+
case offsetof(struct pt_regs, r15):
26+
return READ_REG(r15);
27+
case offsetof(struct pt_regs, r14):
28+
return READ_REG(r14);
29+
case offsetof(struct pt_regs, r13):
30+
return READ_REG(r13);
31+
case offsetof(struct pt_regs, r12):
32+
return READ_REG(r12);
33+
case offsetof(struct pt_regs, bp):
34+
return READ_REG(bp);
35+
case offsetof(struct pt_regs, bx):
36+
return READ_REG(bx);
37+
case offsetof(struct pt_regs, r11):
38+
return READ_REG(r11);
39+
case offsetof(struct pt_regs, r10):
40+
return READ_REG(r10);
41+
case offsetof(struct pt_regs, r9):
42+
return READ_REG(r9);
43+
case offsetof(struct pt_regs, r8):
44+
return READ_REG(r8);
45+
case offsetof(struct pt_regs, ax):
46+
return READ_REG(ax);
47+
case offsetof(struct pt_regs, cx):
48+
return READ_REG(cx);
49+
case offsetof(struct pt_regs, dx):
50+
return READ_REG(dx);
51+
case offsetof(struct pt_regs, si):
52+
return READ_REG(si);
53+
case offsetof(struct pt_regs, di):
54+
return READ_REG(di);
55+
case offsetof(struct pt_regs, ip):
56+
return READ_REG(ip);
57+
case offsetof(struct pt_regs, sp):
58+
return READ_REG(sp);
59+
}
60+
61+
#undef READ_REG
62+
return 0;
63+
}
64+
65+
FUNC_LOCAL int
66+
write_reg(struct pt_regs *ctx, __u32 dst, __u8 size, __u64 val)
67+
{
68+
/*
69+
* Using inlined asm to make sure we access context via 'ctx-reg + offset'.
70+
* When using switch on all registers offset values, clang-18 uses * modified
71+
* ctx-reg which fails verifier.
72+
*
73+
* Using clang-20 seems to work, but we need to upgrade first ;-)
74+
*/
75+
76+
#define WRITE_REG(reg) ({ \
77+
asm volatile("if %[size] != 8 goto +2\n" \
78+
"*(u64 *)(%[ctx] + %[off]) = %[val]\n" \
79+
"goto +8\n" \
80+
"if %[size] != 4 goto +2\n" \
81+
"*(u32 *)(%[ctx] + %[off]) = %[val]\n" \
82+
"goto +5\n" \
83+
"if %[size] != 2 goto +2\n" \
84+
"*(u16 *)(%[ctx] + %[off]) = %[val]\n" \
85+
"goto +2\n" \
86+
"if %[size] != 1 goto +1\n" \
87+
"*(u8 *)(%[ctx] + %[off]) = %[val]\n" \
88+
: [ctx] "+r"(ctx), [val] "+r"(val), [size] "+r"(size) \
89+
: [off] "i"(offsetof(struct pt_regs, reg)) \
90+
:); \
91+
0; \
92+
})
93+
94+
switch (dst) {
95+
case offsetof(struct pt_regs, r15):
96+
return WRITE_REG(r15);
97+
case offsetof(struct pt_regs, r14):
98+
return WRITE_REG(r14);
99+
case offsetof(struct pt_regs, r13):
100+
return WRITE_REG(r13);
101+
case offsetof(struct pt_regs, r12):
102+
return WRITE_REG(r12);
103+
case offsetof(struct pt_regs, bp):
104+
return WRITE_REG(bp);
105+
case offsetof(struct pt_regs, bx):
106+
return WRITE_REG(bx);
107+
case offsetof(struct pt_regs, r11):
108+
return WRITE_REG(r11);
109+
case offsetof(struct pt_regs, r10):
110+
return WRITE_REG(r10);
111+
case offsetof(struct pt_regs, r9):
112+
return WRITE_REG(r9);
113+
case offsetof(struct pt_regs, r8):
114+
return WRITE_REG(r8);
115+
case offsetof(struct pt_regs, ax):
116+
return WRITE_REG(ax);
117+
case offsetof(struct pt_regs, cx):
118+
return WRITE_REG(cx);
119+
case offsetof(struct pt_regs, dx):
120+
return WRITE_REG(dx);
121+
case offsetof(struct pt_regs, si):
122+
return WRITE_REG(si);
123+
case offsetof(struct pt_regs, di):
124+
return WRITE_REG(di);
125+
case offsetof(struct pt_regs, ip):
126+
return WRITE_REG(ip);
127+
case offsetof(struct pt_regs, sp):
128+
return WRITE_REG(sp);
129+
}
130+
131+
#undef WRITE_REG
132+
return 0;
133+
}
134+
135+
#endif /* __TARGET_ARCH_x86 */
136+
#endif /* __REGS_H__*/

bpf/process/uprobe_offload.h

Lines changed: 7 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#ifndef __UPROBE_OFFLOAD_H__
55
#define __UPROBE_OFFLOAD_H__
66

7+
#include "regs.h"
8+
79
struct reg_assignment {
810
__u8 type;
911
__u8 pad1;
@@ -60,133 +62,13 @@ FUNC_INLINE void do_uprobe_override(void *ctx, __u32 idx)
6062
map_update_elem(&sleepable_offload, &id, &idx, BPF_ANY);
6163
}
6264

63-
FUNC_LOCAL int
64-
write_reg(struct pt_regs *ctx, __u32 dst, __u8 size, __u64 val)
65-
{
66-
/*
67-
* Using inlined asm to make sure we access context via 'ctx-reg + offset'.
68-
* When using switch on all registers offset values, clang-18 uses * modified
69-
* ctx-reg which fails verifier.
70-
*
71-
* Using clang-20 seems to work, but we need to upgrade first ;-)
72-
*/
73-
74-
#define WRITE_REG(reg) ({ \
75-
asm volatile("if %[size] != 8 goto +2\n" \
76-
"*(u64 *)(%[ctx] + %[off]) = %[val]\n" \
77-
"goto +8\n" \
78-
"if %[size] != 4 goto +2\n" \
79-
"*(u32 *)(%[ctx] + %[off]) = %[val]\n" \
80-
"goto +5\n" \
81-
"if %[size] != 2 goto +2\n" \
82-
"*(u16 *)(%[ctx] + %[off]) = %[val]\n" \
83-
"goto +2\n" \
84-
"if %[size] != 1 goto +1\n" \
85-
"*(u8 *)(%[ctx] + %[off]) = %[val]\n" \
86-
: [ctx] "+r"(ctx), [val] "+r"(val), [size] "+r"(size) \
87-
: [off] "i"(offsetof(struct pt_regs, reg)) \
88-
:); \
89-
0; \
90-
})
91-
92-
switch (dst) {
93-
case offsetof(struct pt_regs, r15):
94-
return WRITE_REG(r15);
95-
case offsetof(struct pt_regs, r14):
96-
return WRITE_REG(r14);
97-
case offsetof(struct pt_regs, r13):
98-
return WRITE_REG(r13);
99-
case offsetof(struct pt_regs, r12):
100-
return WRITE_REG(r12);
101-
case offsetof(struct pt_regs, bp):
102-
return WRITE_REG(bp);
103-
case offsetof(struct pt_regs, bx):
104-
return WRITE_REG(bx);
105-
case offsetof(struct pt_regs, r11):
106-
return WRITE_REG(r11);
107-
case offsetof(struct pt_regs, r10):
108-
return WRITE_REG(r10);
109-
case offsetof(struct pt_regs, r9):
110-
return WRITE_REG(r9);
111-
case offsetof(struct pt_regs, r8):
112-
return WRITE_REG(r8);
113-
case offsetof(struct pt_regs, ax):
114-
return WRITE_REG(ax);
115-
case offsetof(struct pt_regs, cx):
116-
return WRITE_REG(cx);
117-
case offsetof(struct pt_regs, dx):
118-
return WRITE_REG(dx);
119-
case offsetof(struct pt_regs, si):
120-
return WRITE_REG(si);
121-
case offsetof(struct pt_regs, di):
122-
return WRITE_REG(di);
123-
case offsetof(struct pt_regs, ip):
124-
return WRITE_REG(ip);
125-
case offsetof(struct pt_regs, sp):
126-
return WRITE_REG(sp);
127-
}
128-
129-
#undef WRITE_REG
130-
return 0;
131-
}
132-
13365
FUNC_INLINE __u64
134-
read_reg(struct pt_regs *ctx, struct reg_assignment *ass)
66+
read_reg_ass(struct pt_regs *ctx, struct reg_assignment *ass)
13567
{
13668
__u32 src = ass->src;
13769
__u8 shift = 64 - ass->src_size * 8;
13870

139-
/* Using inlined asm for same reason we use WRITE_REG above. */
140-
#define READ_REG(reg) ({ \
141-
__u64 val; \
142-
asm volatile("%[val] = *(u64 *)(%[ctx] + %[off])\n" \
143-
: [ctx] "+r"(ctx), [val] "+r"(val) \
144-
: [off] "i"(offsetof(struct pt_regs, reg)) \
145-
:); \
146-
val <<= shift; \
147-
val >>= shift; \
148-
val; \
149-
})
150-
151-
switch (src) {
152-
case offsetof(struct pt_regs, r15):
153-
return READ_REG(r15);
154-
case offsetof(struct pt_regs, r14):
155-
return READ_REG(r14);
156-
case offsetof(struct pt_regs, r13):
157-
return READ_REG(r13);
158-
case offsetof(struct pt_regs, r12):
159-
return READ_REG(r12);
160-
case offsetof(struct pt_regs, bp):
161-
return READ_REG(bp);
162-
case offsetof(struct pt_regs, bx):
163-
return READ_REG(bx);
164-
case offsetof(struct pt_regs, r11):
165-
return READ_REG(r11);
166-
case offsetof(struct pt_regs, r10):
167-
return READ_REG(r10);
168-
case offsetof(struct pt_regs, r9):
169-
return READ_REG(r9);
170-
case offsetof(struct pt_regs, r8):
171-
return READ_REG(r8);
172-
case offsetof(struct pt_regs, ax):
173-
return READ_REG(ax);
174-
case offsetof(struct pt_regs, cx):
175-
return READ_REG(cx);
176-
case offsetof(struct pt_regs, dx):
177-
return READ_REG(dx);
178-
case offsetof(struct pt_regs, si):
179-
return READ_REG(si);
180-
case offsetof(struct pt_regs, di):
181-
return READ_REG(di);
182-
case offsetof(struct pt_regs, ip):
183-
return READ_REG(ip);
184-
case offsetof(struct pt_regs, sp):
185-
return READ_REG(sp);
186-
}
187-
188-
#undef READ_REG
189-
return 0;
71+
return read_reg(ctx, src, shift);
19072
}
19173

19274
FUNC_INLINE int
@@ -215,16 +97,16 @@ uprobe_offload_x86(struct pt_regs *ctx)
21597
write_reg(ctx, ass->dst, ass->dst_size, ass->off);
21698
break;
21799
case ASM_ASSIGNMENT_TYPE_REG:
218-
val = read_reg(ctx, ass);
100+
val = read_reg_ass(ctx, ass);
219101
write_reg(ctx, ass->dst, ass->dst_size, val);
220102
break;
221103
case ASM_ASSIGNMENT_TYPE_REG_OFF:
222-
val = read_reg(ctx, ass);
104+
val = read_reg_ass(ctx, ass);
223105
val += ass->off;
224106
write_reg(ctx, ass->dst, ass->dst_size, val);
225107
break;
226108
case ASM_ASSIGNMENT_TYPE_REG_DEREF:
227-
val = read_reg(ctx, ass);
109+
val = read_reg_ass(ctx, ass);
228110
err = probe_read_user(&val, sizeof(val), (void *)val + ass->off);
229111
if (!err)
230112
write_reg(ctx, ass->dst, ass->dst_size, val);

0 commit comments

Comments
 (0)