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
63 probe_mem_read(void *dest
, void *src
, size_t size
);
65 /* From the 2nd stage, routine is same */
66 static nokprobe_inline
int
67 process_fetch_insn_bottom(struct fetch_insn
*code
, unsigned long val
,
68 void *dest
, void *base
)
70 struct fetch_insn
*s3
= NULL
;
71 int total
= 0, ret
= 0, i
= 0;
73 unsigned long lval
= val
;
76 /* 2nd stage: dereference memory if needed */
77 while (code
->op
== FETCH_OP_DEREF
) {
79 ret
= probe_mem_read(&val
, (void *)val
+ code
->offset
,
88 /* 3rd stage: store value to buffer */
89 if (unlikely(!dest
)) {
90 if (code
->op
== FETCH_OP_ST_STRING
) {
91 ret
= fetch_store_strlen(val
+ code
->offset
);
100 fetch_store_raw(val
, code
, dest
);
102 case FETCH_OP_ST_MEM
:
103 probe_mem_read(dest
, (void *)val
+ code
->offset
, code
->size
);
105 case FETCH_OP_ST_STRING
:
107 ret
= fetch_store_string(val
+ code
->offset
, dest
, base
);
114 /* 4th stage: modify stored value if needed */
115 if (code
->op
== FETCH_OP_MOD_BF
) {
116 fetch_apply_bitfield(code
, dest
);
121 /* the last stage: Loop on array */
122 if (code
->op
== FETCH_OP_LP_ARRAY
) {
124 if (++i
< code
->param
) {
126 if (s3
->op
!= FETCH_OP_ST_STRING
) {
132 val
= lval
+ sizeof(char *);
135 *(u32
*)dest
= update_data_loc(loc
, ret
);
143 return code
->op
== FETCH_OP_END
? ret
: -EILSEQ
;
146 /* Sum up total data length for dynamic arraies (strings) */
147 static nokprobe_inline
int
148 __get_data_size(struct trace_probe
*tp
, struct pt_regs
*regs
)
150 struct probe_arg
*arg
;
153 for (i
= 0; i
< tp
->nr_args
; i
++) {
155 if (unlikely(arg
->dynamic
)) {
156 len
= process_fetch_insn(arg
->code
, regs
, NULL
, NULL
);
165 /* Store the value of each argument */
166 static nokprobe_inline
void
167 store_trace_args(void *data
, struct trace_probe
*tp
, struct pt_regs
*regs
,
168 int header_size
, int maxlen
)
170 struct probe_arg
*arg
;
171 void *base
= data
- header_size
;
172 void *dyndata
= data
+ tp
->size
;
173 u32
*dl
; /* Data location */
176 for (i
= 0; i
< tp
->nr_args
; i
++) {
178 dl
= data
+ arg
->offset
;
179 /* Point the dynamic data area if needed */
180 if (unlikely(arg
->dynamic
))
181 *dl
= make_data_loc(maxlen
, dyndata
- base
);
182 ret
= process_fetch_insn(arg
->code
, regs
, dl
, base
);
183 if (unlikely(ret
< 0 && arg
->dynamic
)) {
184 *dl
= make_data_loc(0, dyndata
- base
);
193 print_probe_args(struct trace_seq
*s
, struct probe_arg
*args
, int nr_args
,
194 u8
*data
, void *field
)
199 for (i
= 0; i
< nr_args
; i
++) {
200 struct probe_arg
*a
= args
+ i
;
202 trace_seq_printf(s
, " %s=", a
->name
);
203 if (likely(!a
->count
)) {
204 if (!a
->type
->print(s
, data
+ a
->offset
, field
))
208 trace_seq_putc(s
, '{');
209 p
= data
+ a
->offset
;
210 for (j
= 0; j
< a
->count
; j
++) {
211 if (!a
->type
->print(s
, p
, field
))
213 trace_seq_putc(s
, j
== a
->count
- 1 ? '}' : ',');