4
4
* Copyright (C) 2022 Google LLC.
5
5
*/
6
6
#define pr_fmt (fmt ) "trace_fprobe: " fmt
7
+ #include <asm/ptrace.h>
7
8
8
9
#include <linux/fprobe.h>
9
10
#include <linux/module.h>
@@ -129,8 +130,8 @@ static bool trace_fprobe_is_registered(struct trace_fprobe *tf)
129
130
* from user space.
130
131
*/
131
132
static int
132
- process_fetch_insn (struct fetch_insn * code , void * rec , void * dest ,
133
- void * base )
133
+ process_fetch_insn (struct fetch_insn * code , void * rec , void * edata ,
134
+ void * dest , void * base )
134
135
{
135
136
struct pt_regs * regs = rec ;
136
137
unsigned long val ;
@@ -152,6 +153,9 @@ process_fetch_insn(struct fetch_insn *code, void *rec, void *dest,
152
153
case FETCH_OP_ARG :
153
154
val = regs_get_kernel_argument (regs , code -> param );
154
155
break ;
156
+ case FETCH_OP_EDATA :
157
+ val = * (unsigned long * )((unsigned long )edata + code -> offset );
158
+ break ;
155
159
#endif
156
160
case FETCH_NOP_SYMBOL : /* Ignore a place holder */
157
161
code ++ ;
@@ -184,7 +188,7 @@ __fentry_trace_func(struct trace_fprobe *tf, unsigned long entry_ip,
184
188
if (trace_trigger_soft_disabled (trace_file ))
185
189
return ;
186
190
187
- dsize = __get_data_size (& tf -> tp , regs );
191
+ dsize = __get_data_size (& tf -> tp , regs , NULL );
188
192
189
193
entry = trace_event_buffer_reserve (& fbuffer , trace_file ,
190
194
sizeof (* entry ) + tf -> tp .size + dsize );
@@ -194,7 +198,7 @@ __fentry_trace_func(struct trace_fprobe *tf, unsigned long entry_ip,
194
198
fbuffer .regs = regs ;
195
199
entry = fbuffer .entry = ring_buffer_event_data (fbuffer .event );
196
200
entry -> ip = entry_ip ;
197
- store_trace_args (& entry [1 ], & tf -> tp , regs , sizeof (* entry ), dsize );
201
+ store_trace_args (& entry [1 ], & tf -> tp , regs , NULL , sizeof (* entry ), dsize );
198
202
199
203
trace_event_buffer_commit (& fbuffer );
200
204
}
@@ -211,10 +215,23 @@ fentry_trace_func(struct trace_fprobe *tf, unsigned long entry_ip,
211
215
NOKPROBE_SYMBOL (fentry_trace_func );
212
216
213
217
/* function exit handler */
218
+ static int trace_fprobe_entry_handler (struct fprobe * fp , unsigned long entry_ip ,
219
+ unsigned long ret_ip , struct pt_regs * regs ,
220
+ void * entry_data )
221
+ {
222
+ struct trace_fprobe * tf = container_of (fp , struct trace_fprobe , fp );
223
+
224
+ if (tf -> tp .entry_arg )
225
+ store_trace_entry_data (entry_data , & tf -> tp , regs );
226
+
227
+ return 0 ;
228
+ }
229
+ NOKPROBE_SYMBOL (trace_fprobe_entry_handler )
230
+
214
231
static nokprobe_inline void
215
232
__fexit_trace_func (struct trace_fprobe * tf , unsigned long entry_ip ,
216
233
unsigned long ret_ip , struct pt_regs * regs ,
217
- struct trace_event_file * trace_file )
234
+ void * entry_data , struct trace_event_file * trace_file )
218
235
{
219
236
struct fexit_trace_entry_head * entry ;
220
237
struct trace_event_buffer fbuffer ;
@@ -227,7 +244,7 @@ __fexit_trace_func(struct trace_fprobe *tf, unsigned long entry_ip,
227
244
if (trace_trigger_soft_disabled (trace_file ))
228
245
return ;
229
246
230
- dsize = __get_data_size (& tf -> tp , regs );
247
+ dsize = __get_data_size (& tf -> tp , regs , entry_data );
231
248
232
249
entry = trace_event_buffer_reserve (& fbuffer , trace_file ,
233
250
sizeof (* entry ) + tf -> tp .size + dsize );
@@ -238,19 +255,19 @@ __fexit_trace_func(struct trace_fprobe *tf, unsigned long entry_ip,
238
255
entry = fbuffer .entry = ring_buffer_event_data (fbuffer .event );
239
256
entry -> func = entry_ip ;
240
257
entry -> ret_ip = ret_ip ;
241
- store_trace_args (& entry [1 ], & tf -> tp , regs , sizeof (* entry ), dsize );
258
+ store_trace_args (& entry [1 ], & tf -> tp , regs , entry_data , sizeof (* entry ), dsize );
242
259
243
260
trace_event_buffer_commit (& fbuffer );
244
261
}
245
262
246
263
static void
247
264
fexit_trace_func (struct trace_fprobe * tf , unsigned long entry_ip ,
248
- unsigned long ret_ip , struct pt_regs * regs )
265
+ unsigned long ret_ip , struct pt_regs * regs , void * entry_data )
249
266
{
250
267
struct event_file_link * link ;
251
268
252
269
trace_probe_for_each_link_rcu (link , & tf -> tp )
253
- __fexit_trace_func (tf , entry_ip , ret_ip , regs , link -> file );
270
+ __fexit_trace_func (tf , entry_ip , ret_ip , regs , entry_data , link -> file );
254
271
}
255
272
NOKPROBE_SYMBOL (fexit_trace_func );
256
273
@@ -269,7 +286,7 @@ static int fentry_perf_func(struct trace_fprobe *tf, unsigned long entry_ip,
269
286
if (hlist_empty (head ))
270
287
return 0 ;
271
288
272
- dsize = __get_data_size (& tf -> tp , regs );
289
+ dsize = __get_data_size (& tf -> tp , regs , NULL );
273
290
__size = sizeof (* entry ) + tf -> tp .size + dsize ;
274
291
size = ALIGN (__size + sizeof (u32 ), sizeof (u64 ));
275
292
size -= sizeof (u32 );
@@ -280,7 +297,7 @@ static int fentry_perf_func(struct trace_fprobe *tf, unsigned long entry_ip,
280
297
281
298
entry -> ip = entry_ip ;
282
299
memset (& entry [1 ], 0 , dsize );
283
- store_trace_args (& entry [1 ], & tf -> tp , regs , sizeof (* entry ), dsize );
300
+ store_trace_args (& entry [1 ], & tf -> tp , regs , NULL , sizeof (* entry ), dsize );
284
301
perf_trace_buf_submit (entry , size , rctx , call -> event .type , 1 , regs ,
285
302
head , NULL );
286
303
return 0 ;
@@ -289,7 +306,8 @@ NOKPROBE_SYMBOL(fentry_perf_func);
289
306
290
307
static void
291
308
fexit_perf_func (struct trace_fprobe * tf , unsigned long entry_ip ,
292
- unsigned long ret_ip , struct pt_regs * regs )
309
+ unsigned long ret_ip , struct pt_regs * regs ,
310
+ void * entry_data )
293
311
{
294
312
struct trace_event_call * call = trace_probe_event_call (& tf -> tp );
295
313
struct fexit_trace_entry_head * entry ;
@@ -301,7 +319,7 @@ fexit_perf_func(struct trace_fprobe *tf, unsigned long entry_ip,
301
319
if (hlist_empty (head ))
302
320
return ;
303
321
304
- dsize = __get_data_size (& tf -> tp , regs );
322
+ dsize = __get_data_size (& tf -> tp , regs , entry_data );
305
323
__size = sizeof (* entry ) + tf -> tp .size + dsize ;
306
324
size = ALIGN (__size + sizeof (u32 ), sizeof (u64 ));
307
325
size -= sizeof (u32 );
@@ -312,7 +330,7 @@ fexit_perf_func(struct trace_fprobe *tf, unsigned long entry_ip,
312
330
313
331
entry -> func = entry_ip ;
314
332
entry -> ret_ip = ret_ip ;
315
- store_trace_args (& entry [1 ], & tf -> tp , regs , sizeof (* entry ), dsize );
333
+ store_trace_args (& entry [1 ], & tf -> tp , regs , entry_data , sizeof (* entry ), dsize );
316
334
perf_trace_buf_submit (entry , size , rctx , call -> event .type , 1 , regs ,
317
335
head , NULL );
318
336
}
@@ -343,10 +361,10 @@ static void fexit_dispatcher(struct fprobe *fp, unsigned long entry_ip,
343
361
struct trace_fprobe * tf = container_of (fp , struct trace_fprobe , fp );
344
362
345
363
if (trace_probe_test_flag (& tf -> tp , TP_FLAG_TRACE ))
346
- fexit_trace_func (tf , entry_ip , ret_ip , regs );
364
+ fexit_trace_func (tf , entry_ip , ret_ip , regs , entry_data );
347
365
#ifdef CONFIG_PERF_EVENTS
348
366
if (trace_probe_test_flag (& tf -> tp , TP_FLAG_PROFILE ))
349
- fexit_perf_func (tf , entry_ip , ret_ip , regs );
367
+ fexit_perf_func (tf , entry_ip , ret_ip , regs , entry_data );
350
368
#endif
351
369
}
352
370
NOKPROBE_SYMBOL (fexit_dispatcher );
@@ -1109,6 +1127,11 @@ static int __trace_fprobe_create(int argc, const char *argv[])
1109
1127
goto error ; /* This can be -ENOMEM */
1110
1128
}
1111
1129
1130
+ if (is_return && tf -> tp .entry_arg ) {
1131
+ tf -> fp .entry_handler = trace_fprobe_entry_handler ;
1132
+ tf -> fp .entry_data_size = traceprobe_get_entry_data_size (& tf -> tp );
1133
+ }
1134
+
1112
1135
ret = traceprobe_set_print_fmt (& tf -> tp ,
1113
1136
is_return ? PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL );
1114
1137
if (ret < 0 )
0 commit comments