1*287e80b3SSadaf Ebrahimilibtracefs(3) 2*287e80b3SSadaf Ebrahimi============= 3*287e80b3SSadaf Ebrahimi 4*287e80b3SSadaf EbrahimiNAME 5*287e80b3SSadaf Ebrahimi---- 6*287e80b3SSadaf Ebrahimitracefs_kprobe_alloc, tracefs_kretprobe_alloc, tracefs_kprobe_raw, tracefs_kretprobe_raw - 7*287e80b3SSadaf EbrahimiAllocate, get, and create kprobes 8*287e80b3SSadaf Ebrahimi 9*287e80b3SSadaf EbrahimiSYNOPSIS 10*287e80b3SSadaf Ebrahimi-------- 11*287e80b3SSadaf Ebrahimi[verse] 12*287e80b3SSadaf Ebrahimi-- 13*287e80b3SSadaf Ebrahimi*#include <tracefs.h>* 14*287e80b3SSadaf Ebrahimi 15*287e80b3SSadaf Ebrahimistruct tracefs_dynevent pass:[*] 16*287e80b3SSadaf Ebrahimi*tracefs_kprobe_alloc*(const char pass:[*]_system_, const char pass:[*]_event_, 17*287e80b3SSadaf Ebrahimi const char pass:[*]_addr_, const char pass:[*]_format_); 18*287e80b3SSadaf Ebrahimistruct tracefs_dynevent pass:[*] 19*287e80b3SSadaf Ebrahimi*tracefs_kretprobe_alloc*(const char pass:[*]_system_, const char pass:[*]_event_, 20*287e80b3SSadaf Ebrahimi const char pass:[*]_addr_, const char pass:[*]_format_, unsigned int _max_); 21*287e80b3SSadaf Ebrahimiint *tracefs_kprobe_raw*(const char pass:[*]_system_, const char pass:[*]_event_, 22*287e80b3SSadaf Ebrahimi const char pass:[*]_addr_, const char pass:[*]_format_); 23*287e80b3SSadaf Ebrahimiint *tracefs_kretprobe_raw*(const char pass:[*]_system_, const char pass:[*]_event_, 24*287e80b3SSadaf Ebrahimi const char pass:[*]_addr_, const char pass:[*]_format_); 25*287e80b3SSadaf Ebrahimi-- 26*287e80b3SSadaf Ebrahimi 27*287e80b3SSadaf EbrahimiDESCRIPTION 28*287e80b3SSadaf Ebrahimi----------- 29*287e80b3SSadaf Ebrahimi*tracefs_kprobe_alloc*() allocates a new kprobe context. The kbrobe is not configured in the system. 30*287e80b3SSadaf EbrahimiThe new kprobe will be in the _system_ group (or kprobes if _system_ is NULL) and have the name of 31*287e80b3SSadaf Ebrahimi_event_ (or _addr_ if _event_ is NULL). The kprobe will be inserted to _addr_ (function name, with 32*287e80b3SSadaf Ebrahimior without offset, or a address), and the _format_ will define the format of the kprobe. See the 33*287e80b3SSadaf EbrahimiLinux documentation file under: Documentation/trace/kprobetrace.rst 34*287e80b3SSadaf Ebrahimi 35*287e80b3SSadaf Ebrahimi*tracefs_kretprobe_alloc*() is the same as *tracefs_kprobe_alloc*, but allocates context for 36*287e80b3SSadaf Ebrahimikretprobe. It has one additional parameter, which is optional, _max_ - maxactive count. 37*287e80b3SSadaf EbrahimiSee description of kretprobes in the Documentation/trace/kprobetrace.rst file. 38*287e80b3SSadaf Ebrahimi 39*287e80b3SSadaf Ebrahimi*tracefs_kprobe_raw*() will create a kprobe event. If _system_ is NULL, then 40*287e80b3SSadaf Ebrahimithe default "kprobes" is used for the group (event system). Otherwise if _system_ 41*287e80b3SSadaf Ebrahimiis specified then the kprobe will be created under the group by that name. The 42*287e80b3SSadaf Ebrahimi_event_ is the name of the kprobe event to create. The _addr_ can be a function, 43*287e80b3SSadaf Ebrahimia function and offset, or a kernel address. This is where the location of the 44*287e80b3SSadaf Ebrahimikprobe will be inserted in the kernel. The _format_ is the kprobe format as 45*287e80b3SSadaf Ebrahimispecified as FETCHARGS in the Linux kernel source in the Documentation/trace/kprobetrace.rst 46*287e80b3SSadaf Ebrahimidocument. 47*287e80b3SSadaf Ebrahimi 48*287e80b3SSadaf Ebrahimi*tracefs_kretprobe_raw*() is the same as *tracefs_kprobe_raw()*, except that it 49*287e80b3SSadaf Ebrahimicreates a kretprobe instead of a kprobe. The difference is also described 50*287e80b3SSadaf Ebrahimiin the Linux kernel source in the Documentation/trace/kprobetrace.rst file. 51*287e80b3SSadaf Ebrahimi 52*287e80b3SSadaf EbrahimiRETURN VALUE 53*287e80b3SSadaf Ebrahimi------------ 54*287e80b3SSadaf Ebrahimi 55*287e80b3SSadaf Ebrahimi*tracefs_kprobe_raw*() and *tracefs_kretprobe_raw*() return 0 on success, or -1 on error. 56*287e80b3SSadaf EbrahimiIf a parsing error occurs on *tracefs_kprobe_raw*() or *tracefs_kretprobe_raw*() then 57*287e80b3SSadaf Ebrahimi*tracefs_error_last*(3) may be used to retrieve the error message explaining the parsing issue. 58*287e80b3SSadaf Ebrahimi 59*287e80b3SSadaf EbrahimiThe *tracefs_kprobe_alloc*() and *tracefs_kretprobe_alloc*() APIs return a pointer to an allocated 60*287e80b3SSadaf Ebrahimitracefs_dynevent structure, describing the probe. This pointer must be freed by 61*287e80b3SSadaf Ebrahimi*tracefs_dynevent_free*(3). Note, this only allocates a descriptor representing the kprobe. It does 62*287e80b3SSadaf Ebrahiminot modify the running system. 63*287e80b3SSadaf Ebrahimi 64*287e80b3SSadaf EbrahimiERRORS 65*287e80b3SSadaf Ebrahimi------ 66*287e80b3SSadaf EbrahimiThe following errors are for all the above calls: 67*287e80b3SSadaf Ebrahimi 68*287e80b3SSadaf Ebrahimi*EPERM* Not run as root user 69*287e80b3SSadaf Ebrahimi 70*287e80b3SSadaf Ebrahimi*ENODEV* Kprobe events are not configured for the running kernel. 71*287e80b3SSadaf Ebrahimi 72*287e80b3SSadaf Ebrahimi*ENOMEM* Memory allocation error. 73*287e80b3SSadaf Ebrahimi 74*287e80b3SSadaf Ebrahimi*tracefs_kprobe_raw*(), *tracefs_kretprobe_raw*(), *tracefs_kprobe_alloc*(), 75*287e80b3SSadaf Ebrahimiand *tracefs_kretprobe_alloc*() can fail with the following errors: 76*287e80b3SSadaf Ebrahimi 77*287e80b3SSadaf Ebrahimi*EBADMSG* if _addr_ is NULL. 78*287e80b3SSadaf Ebrahimi 79*287e80b3SSadaf Ebrahimi*EINVAL* Most likely a parsing error occurred (use *tracefs_error_last*(3) to possibly 80*287e80b3SSadaf Ebrahimi see what that error was). 81*287e80b3SSadaf Ebrahimi 82*287e80b3SSadaf EbrahimiOther errors may also happen caused by internal system calls. 83*287e80b3SSadaf Ebrahimi 84*287e80b3SSadaf EbrahimiEXAMPLE 85*287e80b3SSadaf Ebrahimi------- 86*287e80b3SSadaf Ebrahimi[source,c] 87*287e80b3SSadaf Ebrahimi-- 88*287e80b3SSadaf Ebrahimi#include <stdlib.h> 89*287e80b3SSadaf Ebrahimi#include <unistd.h> 90*287e80b3SSadaf Ebrahimi#include <sys/wait.h> 91*287e80b3SSadaf Ebrahimi 92*287e80b3SSadaf Ebrahimi#include <tracefs.h> 93*287e80b3SSadaf Ebrahimi 94*287e80b3SSadaf Ebrahimistatic struct tep_event *open_event; 95*287e80b3SSadaf Ebrahimistatic struct tep_format_field *file_field; 96*287e80b3SSadaf Ebrahimi 97*287e80b3SSadaf Ebrahimistatic struct tep_event *openret_event; 98*287e80b3SSadaf Ebrahimistatic struct tep_format_field *ret_field; 99*287e80b3SSadaf Ebrahimi 100*287e80b3SSadaf Ebrahimistatic int callback(struct tep_event *event, struct tep_record *record, 101*287e80b3SSadaf Ebrahimi int cpu, void *data) 102*287e80b3SSadaf Ebrahimi{ 103*287e80b3SSadaf Ebrahimi struct trace_seq seq; 104*287e80b3SSadaf Ebrahimi 105*287e80b3SSadaf Ebrahimi trace_seq_init(&seq); 106*287e80b3SSadaf Ebrahimi tep_print_event(event->tep, &seq, record, "%d-%s: ", TEP_PRINT_PID, TEP_PRINT_COMM); 107*287e80b3SSadaf Ebrahimi 108*287e80b3SSadaf Ebrahimi if (event->id == open_event->id) { 109*287e80b3SSadaf Ebrahimi trace_seq_puts(&seq, "open file='"); 110*287e80b3SSadaf Ebrahimi tep_print_field(&seq, record->data, file_field); 111*287e80b3SSadaf Ebrahimi trace_seq_puts(&seq, "'\n"); 112*287e80b3SSadaf Ebrahimi } else if (event->id == openret_event->id) { 113*287e80b3SSadaf Ebrahimi unsigned long long ret; 114*287e80b3SSadaf Ebrahimi tep_read_number_field(ret_field, record->data, &ret); 115*287e80b3SSadaf Ebrahimi trace_seq_printf(&seq, "open ret=%lld\n", ret); 116*287e80b3SSadaf Ebrahimi } else { 117*287e80b3SSadaf Ebrahimi goto out; 118*287e80b3SSadaf Ebrahimi } 119*287e80b3SSadaf Ebrahimi 120*287e80b3SSadaf Ebrahimi trace_seq_terminate(&seq); 121*287e80b3SSadaf Ebrahimi trace_seq_do_printf(&seq); 122*287e80b3SSadaf Ebrahimiout: 123*287e80b3SSadaf Ebrahimi trace_seq_destroy(&seq); 124*287e80b3SSadaf Ebrahimi 125*287e80b3SSadaf Ebrahimi return 0; 126*287e80b3SSadaf Ebrahimi} 127*287e80b3SSadaf Ebrahimi 128*287e80b3SSadaf Ebrahimistatic pid_t run_exec(char **argv, char **env) 129*287e80b3SSadaf Ebrahimi{ 130*287e80b3SSadaf Ebrahimi pid_t pid; 131*287e80b3SSadaf Ebrahimi 132*287e80b3SSadaf Ebrahimi pid = fork(); 133*287e80b3SSadaf Ebrahimi if (pid) 134*287e80b3SSadaf Ebrahimi return pid; 135*287e80b3SSadaf Ebrahimi 136*287e80b3SSadaf Ebrahimi execve(argv[0], argv, env); 137*287e80b3SSadaf Ebrahimi perror("exec"); 138*287e80b3SSadaf Ebrahimi exit(-1); 139*287e80b3SSadaf Ebrahimi} 140*287e80b3SSadaf Ebrahimi 141*287e80b3SSadaf Ebrahimiconst char *mykprobe = "my_kprobes"; 142*287e80b3SSadaf Ebrahimi 143*287e80b3SSadaf Ebrahimienum kprobe_type { 144*287e80b3SSadaf Ebrahimi KPROBE, 145*287e80b3SSadaf Ebrahimi KRETPROBE, 146*287e80b3SSadaf Ebrahimi}; 147*287e80b3SSadaf Ebrahimi 148*287e80b3SSadaf Ebrahimistatic void __kprobe_create(enum kprobe_type type, const char *event, 149*287e80b3SSadaf Ebrahimi const char *addr, const char *fmt) 150*287e80b3SSadaf Ebrahimi{ 151*287e80b3SSadaf Ebrahimi char *err; 152*287e80b3SSadaf Ebrahimi int r; 153*287e80b3SSadaf Ebrahimi 154*287e80b3SSadaf Ebrahimi if (type == KPROBE) 155*287e80b3SSadaf Ebrahimi r = tracefs_kprobe_raw(mykprobe, event, addr, fmt); 156*287e80b3SSadaf Ebrahimi else 157*287e80b3SSadaf Ebrahimi r = tracefs_kretprobe_raw(mykprobe, event, addr, fmt); 158*287e80b3SSadaf Ebrahimi if (r < 0) { 159*287e80b3SSadaf Ebrahimi err = tracefs_error_last(NULL); 160*287e80b3SSadaf Ebrahimi perror("Failed to create kprobe:"); 161*287e80b3SSadaf Ebrahimi if (err && strlen(err)) 162*287e80b3SSadaf Ebrahimi fprintf(stderr, "%s\n", err); 163*287e80b3SSadaf Ebrahimi } 164*287e80b3SSadaf Ebrahimi} 165*287e80b3SSadaf Ebrahimi 166*287e80b3SSadaf Ebrahimistatic void kprobe_create(const char *event, const char *addr, 167*287e80b3SSadaf Ebrahimi const char *fmt) 168*287e80b3SSadaf Ebrahimi{ 169*287e80b3SSadaf Ebrahimi __kprobe_create(KPROBE, event, addr, fmt); 170*287e80b3SSadaf Ebrahimi} 171*287e80b3SSadaf Ebrahimi 172*287e80b3SSadaf Ebrahimistatic void kretprobe_create(const char *event, const char *addr, 173*287e80b3SSadaf Ebrahimi const char *fmt) 174*287e80b3SSadaf Ebrahimi{ 175*287e80b3SSadaf Ebrahimi __kprobe_create(KRETPROBE, event, addr, fmt); 176*287e80b3SSadaf Ebrahimi} 177*287e80b3SSadaf Ebrahimi 178*287e80b3SSadaf Ebrahimiint main (int argc, char **argv, char **env) 179*287e80b3SSadaf Ebrahimi{ 180*287e80b3SSadaf Ebrahimi struct tracefs_instance *instance; 181*287e80b3SSadaf Ebrahimi struct tep_handle *tep; 182*287e80b3SSadaf Ebrahimi const char *sysnames[] = { mykprobe, NULL }; 183*287e80b3SSadaf Ebrahimi pid_t pid; 184*287e80b3SSadaf Ebrahimi 185*287e80b3SSadaf Ebrahimi if (argc < 2) { 186*287e80b3SSadaf Ebrahimi printf("usage: %s command\n", argv[0]); 187*287e80b3SSadaf Ebrahimi exit(-1); 188*287e80b3SSadaf Ebrahimi } 189*287e80b3SSadaf Ebrahimi 190*287e80b3SSadaf Ebrahimi instance = tracefs_instance_create("exec_open"); 191*287e80b3SSadaf Ebrahimi if (!instance) { 192*287e80b3SSadaf Ebrahimi perror("creating instance"); 193*287e80b3SSadaf Ebrahimi exit(-1); 194*287e80b3SSadaf Ebrahimi } 195*287e80b3SSadaf Ebrahimi 196*287e80b3SSadaf Ebrahimi tracefs_dynevent_destroy_all(TRACEFS_DYNEVENT_KPROBE | TRACEFS_DYNEVENT_KRETPROBE, true); 197*287e80b3SSadaf Ebrahimi 198*287e80b3SSadaf Ebrahimi kprobe_create("open", "do_sys_openat2", 199*287e80b3SSadaf Ebrahimi "file=+0($arg2):ustring flags=+0($arg3):x64 mode=+8($arg3):x64\n"); 200*287e80b3SSadaf Ebrahimi 201*287e80b3SSadaf Ebrahimi kretprobe_create("openret", "do_sys_openat2", "ret=%ax"); 202*287e80b3SSadaf Ebrahimi 203*287e80b3SSadaf Ebrahimi tep = tracefs_local_events_system(NULL, sysnames); 204*287e80b3SSadaf Ebrahimi if (!tep) { 205*287e80b3SSadaf Ebrahimi perror("reading events"); 206*287e80b3SSadaf Ebrahimi exit(-1); 207*287e80b3SSadaf Ebrahimi } 208*287e80b3SSadaf Ebrahimi open_event = tep_find_event_by_name(tep, mykprobe, "open"); 209*287e80b3SSadaf Ebrahimi file_field = tep_find_field(open_event, "file"); 210*287e80b3SSadaf Ebrahimi 211*287e80b3SSadaf Ebrahimi openret_event = tep_find_event_by_name(tep, mykprobe, "openret"); 212*287e80b3SSadaf Ebrahimi ret_field = tep_find_field(openret_event, "ret"); 213*287e80b3SSadaf Ebrahimi 214*287e80b3SSadaf Ebrahimi tracefs_event_enable(instance, mykprobe, NULL); 215*287e80b3SSadaf Ebrahimi pid = run_exec(&argv[1], env); 216*287e80b3SSadaf Ebrahimi 217*287e80b3SSadaf Ebrahimi /* Let the child start to run */ 218*287e80b3SSadaf Ebrahimi sched_yield(); 219*287e80b3SSadaf Ebrahimi 220*287e80b3SSadaf Ebrahimi do { 221*287e80b3SSadaf Ebrahimi tracefs_load_cmdlines(NULL, tep); 222*287e80b3SSadaf Ebrahimi tracefs_iterate_raw_events(tep, instance, NULL, 0, callback, NULL); 223*287e80b3SSadaf Ebrahimi } while (waitpid(pid, NULL, WNOHANG) != pid); 224*287e80b3SSadaf Ebrahimi 225*287e80b3SSadaf Ebrahimi /* Will disable the events */ 226*287e80b3SSadaf Ebrahimi tracefs_dynevent_destroy_all(TRACEFS_DYNEVENT_KPROBE | TRACEFS_DYNEVENT_KRETPROBE, true); 227*287e80b3SSadaf Ebrahimi tracefs_instance_destroy(instance); 228*287e80b3SSadaf Ebrahimi tep_free(tep); 229*287e80b3SSadaf Ebrahimi 230*287e80b3SSadaf Ebrahimi return 0; 231*287e80b3SSadaf Ebrahimi} 232*287e80b3SSadaf Ebrahimi-- 233*287e80b3SSadaf Ebrahimi 234*287e80b3SSadaf EbrahimiFILES 235*287e80b3SSadaf Ebrahimi----- 236*287e80b3SSadaf Ebrahimi[verse] 237*287e80b3SSadaf Ebrahimi-- 238*287e80b3SSadaf Ebrahimi*tracefs.h* 239*287e80b3SSadaf Ebrahimi Header file to include in order to have access to the library APIs. 240*287e80b3SSadaf Ebrahimi*-ltracefs* 241*287e80b3SSadaf Ebrahimi Linker switch to add when building a program that uses the library. 242*287e80b3SSadaf Ebrahimi-- 243*287e80b3SSadaf Ebrahimi 244*287e80b3SSadaf EbrahimiSEE ALSO 245*287e80b3SSadaf Ebrahimi-------- 246*287e80b3SSadaf Ebrahimi*libtracefs*(3), 247*287e80b3SSadaf Ebrahimi*libtraceevent*(3), 248*287e80b3SSadaf Ebrahimi*trace-cmd*(1) 249*287e80b3SSadaf Ebrahimi 250*287e80b3SSadaf EbrahimiAUTHOR 251*287e80b3SSadaf Ebrahimi------ 252*287e80b3SSadaf Ebrahimi[verse] 253*287e80b3SSadaf Ebrahimi-- 254*287e80b3SSadaf Ebrahimi*Steven Rostedt* <[email protected]> 255*287e80b3SSadaf Ebrahimi*Tzvetomir Stoyanov* <[email protected]> 256*287e80b3SSadaf Ebrahimi*sameeruddin shaik* <[email protected]> 257*287e80b3SSadaf Ebrahimi-- 258*287e80b3SSadaf EbrahimiREPORTING BUGS 259*287e80b3SSadaf Ebrahimi-------------- 260*287e80b3SSadaf EbrahimiReport bugs to <[email protected]> 261*287e80b3SSadaf Ebrahimi 262*287e80b3SSadaf EbrahimiLICENSE 263*287e80b3SSadaf Ebrahimi------- 264*287e80b3SSadaf Ebrahimilibtracefs is Free Software licensed under the GNU LGPL 2.1 265*287e80b3SSadaf Ebrahimi 266*287e80b3SSadaf EbrahimiRESOURCES 267*287e80b3SSadaf Ebrahimi--------- 268*287e80b3SSadaf Ebrahimihttps://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/ 269*287e80b3SSadaf Ebrahimi 270*287e80b3SSadaf EbrahimiCOPYING 271*287e80b3SSadaf Ebrahimi------- 272*287e80b3SSadaf EbrahimiCopyright \(C) 2021 VMware, Inc. Free use of this software is granted under 273*287e80b3SSadaf Ebrahimithe terms of the GNU Public License (GPL). 274