1 /* SPDX-License-Identifier: GPL-2.0 */
3 * Traceprobe fetch helper inlines
6 static nokprobe_inline
void
7 fetch_store_raw(unsigned long val
, struct fetch_insn
*code
, void *buf
)
14 *(u16
*)buf
= (u16
)val
;
17 *(u32
*)buf
= (u32
)val
;
21 *(u64
*)buf
= (u64
)val
;
24 *(unsigned long *)buf
= val
;
28 static nokprobe_inline
void
29 fetch_apply_bitfield(struct fetch_insn
*code
, void *buf
)
31 switch (code
->basesize
) {
33 *(u8
*)buf
<<= code
->lshift
;
34 *(u8
*)buf
>>= code
->rshift
;
37 *(u16
*)buf
<<= code
->lshift
;
38 *(u16
*)buf
>>= code
->rshift
;
41 *(u32
*)buf
<<= code
->lshift
;
42 *(u32
*)buf
>>= code
->rshift
;
45 *(u64
*)buf
<<= code
->lshift
;
46 *(u64
*)buf
>>= code
->rshift
;
52 * These functions must be defined for each callsite.
53 * Return consumed dynamic data size (>= 0), or error (< 0).
54 * If dest is NULL, don't store result and return required dynamic data size.
57 process_fetch_insn(struct fetch_insn
*code
, struct pt_regs
*regs
,
58 void *dest
, void *base
);
59 static nokprobe_inline
int fetch_store_strlen(unsigned long addr
);
60 static nokprobe_inline
int
61 fetch_store_string(unsigned long addr
, void *dest
, void *base
);
62 static nokprobe_inline
int fetch_store_strlen_user(unsigned long addr
);
63 static nokprobe_inline
int
64 fetch_store_string_user(unsigned long addr
, void *dest
, void *base
);
65 static nokprobe_inline
int
66 probe_mem_read(void *dest
, void *src
, size_t size
);
67 static nokprobe_inline
int
68 probe_mem_read_user(void *dest
, void *src
, size_t size
);
70 /* From the 2nd stage, routine is same */
71 static nokprobe_inline
int
72 process_fetch_insn_bottom(struct fetch_insn
*code
, unsigned long val
,
73 void *dest
, void *base
)
75 struct fetch_insn
*s3
= NULL
;
76 int total
= 0, ret
= 0, i
= 0;
78 unsigned long lval
= val
;
81 /* 2nd stage: dereference memory if needed */
83 if (code
->op
== FETCH_OP_DEREF
) {
85 ret
= probe_mem_read(&val
, (void *)val
+ code
->offset
,
87 } else if (code
->op
== FETCH_OP_UDEREF
) {
89 ret
= probe_mem_read_user(&val
,
90 (void *)val
+ code
->offset
, sizeof(val
));
100 /* 3rd stage: store value to buffer */
101 if (unlikely(!dest
)) {
102 if (code
->op
== FETCH_OP_ST_STRING
) {
103 ret
= fetch_store_strlen(val
+ code
->offset
);
106 } else if (code
->op
== FETCH_OP_ST_USTRING
) {
107 ret
+= fetch_store_strlen_user(val
+ code
->offset
);
115 case FETCH_OP_ST_RAW
:
116 fetch_store_raw(val
, code
, dest
);
118 case FETCH_OP_ST_MEM
:
119 probe_mem_read(dest
, (void *)val
+ code
->offset
, code
->size
);
121 case FETCH_OP_ST_UMEM
:
122 probe_mem_read_user(dest
, (void *)val
+ code
->offset
, code
->size
);
124 case FETCH_OP_ST_STRING
:
126 ret
= fetch_store_string(val
+ code
->offset
, dest
, base
);
128 case FETCH_OP_ST_USTRING
:
130 ret
= fetch_store_string_user(val
+ code
->offset
, dest
, base
);
137 /* 4th stage: modify stored value if needed */
138 if (code
->op
== FETCH_OP_MOD_BF
) {
139 fetch_apply_bitfield(code
, dest
);
144 /* the last stage: Loop on array */
145 if (code
->op
== FETCH_OP_LP_ARRAY
) {
147 if (++i
< code
->param
) {
149 if (s3
->op
!= FETCH_OP_ST_STRING
&&
150 s3
->op
!= FETCH_OP_ST_USTRING
) {
156 val
= lval
+ sizeof(char *);
159 *(u32
*)dest
= update_data_loc(loc
, ret
);
167 return code
->op
== FETCH_OP_END
? ret
: -EILSEQ
;
170 /* Sum up total data length for dynamic arraies (strings) */
171 static nokprobe_inline
int
172 __get_data_size(struct trace_probe
*tp
, struct pt_regs
*regs
)
174 struct probe_arg
*arg
;
177 for (i
= 0; i
< tp
->nr_args
; i
++) {
179 if (unlikely(arg
->dynamic
)) {
180 len
= process_fetch_insn(arg
->code
, regs
, NULL
, NULL
);
189 /* Store the value of each argument */
190 static nokprobe_inline
void
191 store_trace_args(void *data
, struct trace_probe
*tp
, struct pt_regs
*regs
,
192 int header_size
, int maxlen
)
194 struct probe_arg
*arg
;
195 void *base
= data
- header_size
;
196 void *dyndata
= data
+ tp
->size
;
197 u32
*dl
; /* Data location */
200 for (i
= 0; i
< tp
->nr_args
; i
++) {
202 dl
= data
+ arg
->offset
;
203 /* Point the dynamic data area if needed */
204 if (unlikely(arg
->dynamic
))
205 *dl
= make_data_loc(maxlen
, dyndata
- base
);
206 ret
= process_fetch_insn(arg
->code
, regs
, dl
, base
);
207 if (unlikely(ret
< 0 && arg
->dynamic
)) {
208 *dl
= make_data_loc(0, dyndata
- base
);
217 print_probe_args(struct trace_seq
*s
, struct probe_arg
*args
, int nr_args
,
218 u8
*data
, void *field
)
223 for (i
= 0; i
< nr_args
; i
++) {
224 struct probe_arg
*a
= args
+ i
;
226 trace_seq_printf(s
, " %s=", a
->name
);
227 if (likely(!a
->count
)) {
228 if (!a
->type
->print(s
, data
+ a
->offset
, field
))
232 trace_seq_putc(s
, '{');
233 p
= data
+ a
->offset
;
234 for (j
= 0; j
< a
->count
; j
++) {
235 if (!a
->type
->print(s
, p
, field
))
237 trace_seq_putc(s
, j
== a
->count
- 1 ? '}' : ',');