#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #define error(msg) do { perror(msg); exit(1); } while(0) #define MAXN 128 // refer to https://lkml.kernel.org/netdev/D0757E13-27E8-4392-972A-399D6E132111@fb.com/t/ // // // static long perf_event_open(struct perf_event_attr *perf_event, pid_t pid, int cpu, int group_fd, unsigned long flags) { return syscall(__NR_perf_event_open, perf_event, pid, cpu, group_fd, flags); } static void *addr = NULL; static long long psize; map> res; static int alive=1; void int_exit(int s) { for (auto x: res) { auto y = x.second; void* addr = y.first; munmap(addr, (1+MAXN)*psize); close(x.first); } res.clear(); alive=0; exit(0); } char *func = NULL; using xtt = tuple; static map pids; int process_event(char *base, unsigned long long size, unsigned long long offset) { struct perf_event_header* p = NULL; int pid, i; unsigned long long abi, addr, arg1, arg2, arg3, arg4; offset%=size; // assuming the header would fit within size p = (struct perf_event_header*) (base+offset); offset+=sizeof(*p); if (offset>=size) offset-=size; if (p->type == PERF_RECORD_SAMPLE) { pid = *(int*)(base+offset); offset+=8; if (offset>=size) offset-=size; time_t ctime = time(NULL); if (pids.count(pid)==0 || ctime-get<0>(pids[pid]) > 1000) { char b[128]; char comm[128]; char host[128]; sprintf(b, "/proc/%d/comm", pid); FILE* fp; size_t i=0; fp = fopen(b, "r"); if (fp) { comm[0]=0; fgets(comm, sizeof(comm), fp); while(i=size) offset-=size; if (abi == PERF_SAMPLE_REGS_ABI_64) { addr = *(unsigned long long*)(base+offset); offset+=8; if (offset>=size) offset-=size; //rax arg3 = *(unsigned long long*)(base+offset); offset+=8; if (offset>=size) offset-=size; //rdx arg2 = *(unsigned long long*)(base+offset); offset+=8; if (offset>=size) offset-=size; //rsi arg1 = *(unsigned long long*)(base+offset); offset+=8; if (offset>=size) offset-=size; //rdi arg4 = *(unsigned long long*)(base+offset); offset+=8; if (offset>=size) offset-=size; //r10 printf("%s@%s[%d] %s(0x%llx,0x%llx,0x%llx,0x%llx)\n", get<1>(pids[pid]).c_str(), get<2>(pids[pid]).c_str(), pid, func, arg1, arg2, arg3, arg4); } } return p->size; } #define MAXCPU 1024 struct pollfd polls[MAXCPU]; int main(int argc, char *argv[]) { int i, k, type; // start perf event if (argc<2) { printf("Need kprobe function name, e.g. %s do_sys_open\n", argv[0]); return 1; } func = argv[1]; psize = sysconf(_SC_PAGE_SIZE); // getpagesize(); int cpu_num = sysconf(_SC_NPROCESSORS_ONLN); struct perf_event_attr attr; memset(&attr, 0, sizeof(attr)); // /sys/bus/event_source/devices/kprobe/type FILE *fp = fopen("/sys/bus/event_source/devices/kprobe/type", "r"); if (fp == NULL) { printf("fail to find type for kprobe\n"); return 1; } type = 0; fscanf(fp, "%d", &type); fclose(fp); if (type <= 0) { printf("unexpected type %d\n", type); return 1; } attr.type = type; attr.size = sizeof(attr); attr.config = 0; // (1<<0) for kreprobe attr.sample_period = 1; attr.wakeup_events = 1; attr.sample_type = PERF_SAMPLE_TID|PERF_SAMPLE_REGS_INTR; // ffffffff92ea9240 t bprm_execve attr.kprobe_func = (__u64)func; // "do_sys_open"; // "bprm_execve"; attr.probe_offset = 0; attr.sample_regs_intr = (1<0) { for (i=0; idata_head) continue; ioctl(fd, PERF_EVENT_IOC_PAUSE_OUTPUT, 1); head = mp->data_head-((mp->data_head-head)%mp->data_size); while(headdata_head) head+=process_event((char*)addr+mp->data_offset, mp->data_size, head); ioctl(fd, PERF_EVENT_IOC_PAUSE_OUTPUT, 0); res[fd].second = mp->data_head; } } int_exit(0); return 0; }