static void handle_arch_sysret(Event *event) { debug(DEBUG_FUNCTION, "handle_arch_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); if (event->proc->state != STATE_IGNORED) { if (opt_T || options.summary) { calc_time_spent(event->proc); } if (options.syscalls) { output_right(LT_TOF_SYSCALLR, event->proc, arch_sysname(event->proc, event->e_un.sysnum)); } callstack_pop(event->proc); } continue_process(event->proc->pid); }
static void handle_sysret(Event *event) { debug(DEBUG_FUNCTION, "handle_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum); if (event->proc->state != STATE_IGNORED) { if (opt_T || options.summary) { calc_time_spent(event->proc); } if (options.syscalls) { output_right(LT_TOF_SYSCALLR, event->proc, sysname(event->proc, event->e_un.sysnum)); } assert(event->proc->callstack_depth > 0); unsigned d = event->proc->callstack_depth - 1; assert(event->proc->callstack[d].is_syscall); callstack_pop(event->proc); } continue_after_syscall(event->proc, event->e_un.sysnum, 1); }
static void handle_breakpoint(Event *event) { int i, j; Breakpoint *sbp; Process *leader = event->proc->leader; /* The leader has terminated. */ if (leader == NULL) { continue_process(event->proc->pid); return; } debug(DEBUG_FUNCTION, "handle_breakpoint(pid=%d, addr=%p)", event->proc->pid, event->e_un.brk_addr); debug(2, "event: breakpoint (%p)", event->e_un.brk_addr); #ifdef __powerpc__ /* Need to skip following NOP's to prevent a fake function from being stacked. */ long stub_addr = (long) get_count_register(event->proc); Breakpoint *stub_bp = NULL; char nop_instruction[] = PPC_NOP; stub_bp = address2bpstruct(leader, event->e_un.brk_addr); if (stub_bp) { unsigned char *bp_instruction = stub_bp->orig_value; if (memcmp(bp_instruction, nop_instruction, PPC_NOP_LENGTH) == 0) { if (stub_addr != (long) event->e_un.brk_addr) { set_instruction_pointer (event->proc, event->e_un.brk_addr + 4); continue_process(event->proc->pid); return; } } } #endif for (i = event->proc->callstack_depth - 1; i >= 0; i--) { if (event->e_un.brk_addr == event->proc->callstack[i].return_addr) { #ifdef __powerpc__ /* * PPC HACK! (XXX FIXME TODO) * The PLT gets modified during the first call, * so be sure to re-enable the breakpoint. */ unsigned long a; struct library_symbol *libsym = event->proc->callstack[i].c_un.libfunc; void *addr = sym2addr(event->proc, libsym); if (libsym->plt_type != LS_TOPLT_POINT) { unsigned char break_insn[] = BREAKPOINT_VALUE; sbp = address2bpstruct(leader, addr); assert(sbp); a = ptrace(PTRACE_PEEKTEXT, event->proc->pid, addr); if (memcmp(&a, break_insn, BREAKPOINT_LENGTH)) { sbp->enabled--; insert_breakpoint(event->proc, addr, libsym, 1); } } else { sbp = dict_find_entry(leader->breakpoints, addr); /* On powerpc, the breakpoint address may end up being actual entry point of the library symbol, not the PLT address we computed. In that case, sbp is NULL. */ if (sbp == NULL || addr != sbp->addr) { insert_breakpoint(event->proc, addr, libsym, 1); } } #elif defined(__mips__) void *addr = NULL; struct library_symbol *sym= event->proc->callstack[i].c_un.libfunc; struct library_symbol *new_sym; assert(sym); addr = sym2addr(event->proc, sym); sbp = dict_find_entry(leader->breakpoints, addr); if (sbp) { if (addr != sbp->addr) { insert_breakpoint(event->proc, addr, sym, 1); } } else { new_sym=malloc(sizeof(*new_sym) + strlen(sym->name) + 1); memcpy(new_sym,sym,sizeof(*new_sym) + strlen(sym->name) + 1); new_sym->next = leader->list_of_symbols; leader->list_of_symbols = new_sym; insert_breakpoint(event->proc, addr, new_sym, 1); } #endif for (j = event->proc->callstack_depth - 1; j > i; j--) { callstack_pop(event->proc); } if (event->proc->state != STATE_IGNORED) { if (opt_T || options.summary) { calc_time_spent(event->proc); } } event->proc->return_addr = event->e_un.brk_addr; if (event->proc->state != STATE_IGNORED) { mock_return(LT_TOF_FUNCTIONR, event->proc, event->proc->callstack[i].c_un.libfunc->name); output_right(LT_TOF_FUNCTIONR, event->proc, event->proc->callstack[i].c_un.libfunc->name); } callstack_pop(event->proc); sbp = address2bpstruct(leader, event->e_un.brk_addr); continue_after_breakpoint(event->proc, sbp); return; } } if ((sbp = address2bpstruct(leader, event->e_un.brk_addr))) { if (sbp->libsym == NULL) { continue_after_breakpoint(event->proc, sbp); return; } if (strcmp(sbp->libsym->name, "") == 0) { debug(DEBUG_PROCESS, "Hit _dl_debug_state breakpoint!\n"); arch_check_dbg(leader); } if (event->proc->state != STATE_IGNORED) { event->proc->stack_pointer = get_stack_pointer(event->proc); event->proc->return_addr = get_return_addr(event->proc, event->proc->stack_pointer); callstack_push_symfunc(event->proc, sbp->libsym); output_left(LT_TOF_FUNCTION, event->proc, sbp->libsym->name); } #ifdef PLT_REINITALISATION_BP if (event->proc->need_to_reinitialize_breakpoints && (strcmp(sbp->libsym->name, PLTs_initialized_by_here) == 0)) reinitialize_breakpoints(leader); #endif continue_after_breakpoint(event->proc, sbp); return; } if (event->proc->state != STATE_IGNORED && !options.no_plt) { output_line(event->proc, "unexpected breakpoint at %p", (void *)event->e_un.brk_addr); } continue_process(event->proc->pid); }
/* CALL FUNCTION HOOK */ static void callhook(lua_State *L, lua_Function func, char *file, int line) { check_start(L); Meta **array = get_metadata_array(L); if (!array) return; // check if exists (call profile_stop ?) if (STACK_INDEX > MEM_BLOCKSIZE - 1) { // Reached memory limit, relocated to double. int blocksize = MEM_BLOCKSIZE * 2; array = realloc(array, blocksize * sizeof(Meta **)); if (array) { lua_unref(L, META_REF); // Remove the old reference (new block of memory). lua_pushuserdata(L, array); // Saves the new reference. META_REF = lua_ref(L, 1); MEM_BLOCKSIZE = blocksize; // Updates the size of the memory block. } else { lua_error(L, "profiler: out of memory!"); return; // suppress inspect } } char *func_name; char *func_scope; if (lua_isfunction(L, func)) { func_scope = lua_getobjname(L, func, &func_name); Meta *meta = (Meta *) malloc(sizeof(Meta)); meta->fun_name = func_name ? func_name : "unnamed"; if (func_scope && strlen(func_scope) > 0) { meta->fun_scope = func_scope; } else { meta->fun_scope = "unknown"; } meta->func_file = file ? file : "unnamed"; meta->stack_level = STACK_SIZE; meta->line = line; Children *children = (Children *) malloc(sizeof(Children)); meta->children = children; children->index = 0; children->list = NULL; children->size = 20; Measure *measure = (Measure *) malloc(sizeof(Measure)); measure->begin = clock(); meta->measure = measure; stack_record.meta = meta; push(&stack, stack_record); if (STACK_SIZE == 0) { array[STACK_INDEX] = meta; STACK_INDEX++; } STACK_SIZE++; } else if (STACK_SIZE > 0) { STACK_RECORD top_record = pop(&stack); STACK_RECORD *new_record = next(&stack); Meta *meta = top_record.meta; meta->measure->end = clock(); meta->measure->time_spent = calc_time_spent(meta->measure); if (new_record != NULL && meta->measure->time_spent >= PROFILE_RECORD_TIME) { Meta *_meta = new_record->meta; if (!_meta->children->list) { // already allocated ? _meta->children->list = (Meta **) malloc(_meta->children->size * sizeof(Meta **)); if (!_meta->children->list) lua_error(L, "out of memory"); } if (_meta->children->index > _meta->children->size - 1) { _meta->children->size *= 2; // more _meta->children->list = (Meta **) realloc(_meta->children->list, _meta->children->size * sizeof(Meta **)); if (!_meta->children->list) lua_error(L, "out of memory"); } _meta->children->list[_meta->children->index] = meta; _meta->children->index++; } STACK_SIZE--; } }