void syslogd_print (int priority, char const * format, ...) { extern char const * host_name; extern char const * program_name; char buffer [TEXTLINE_MAX] = "no error message"; size_t length = 0; #if SYSLOGD_TRACE trace_enter ("syslogd_error"); #endif if (program_name != (char const *) (0)) { length += snprintf (buffer + length, sizeof (buffer) - length, "%s: ", program_name); } if ((format != (char const *) (0)) && (* format != (char) (0))) { va_list arglist; va_start (arglist, format); length += vsnprintf (buffer + length, sizeof (buffer) - length, format, arglist); va_end (arglist); } syslogd_queue (priority, host_name, buffer); #if SYSLOGD_TRACE trace_leave ("syslogd_error"); #endif return; }
VOID fn_ret(CONTEXT *ctxt, UINT32 fid) { trace_enter(); counter += 1; if (!call_stack.is_top_forgotten()) { while (is_jump_stack.top()) { FID fid = call_stack.top(); if (is_instrumented[fid]) { param_t *new_ret = (param_t *) malloc(sizeof(param_t)); new_ret->fid = fid; new_ret->counter = counter; new_ret->val = val_from_reg(ctxt, 0); new_ret->is_addr = param_addr[fid][0]; param_out->push_front(new_ret); } call_stack.pop(); is_jump_stack.pop(); } FID fid = call_stack.top(); if (is_instrumented[fid]) { param_t *new_ret = (param_t *) malloc(sizeof(param_t)); new_ret->fid = fid; new_ret->counter = counter; new_ret->val = val_from_reg(ctxt, 0); new_ret->is_addr = param_addr[fid][0]; param_out->push_front(new_ret); } call_stack.pop(); is_jump_stack.pop(); } trace_leave(); return; }
VOID check_parameter_out(ADDRINT addr) { trace_enter(); if (call_stack.is_top_forgotten()) { trace_leave(); return; } FID fid = call_stack.top(); UINT64 sp = sp_stack.top(); if (sp + 1000 <= addr && addr < sp) { trace_leave(); return; } unsigned int param_val_size = 1 + nb_param_int[fid] + nb_param_int_stack[fid]; for (unsigned int pid = 1; pid < param_val_size; pid++) { if (param_val[fid][pid]->back() == addr) { nb_out[fid][pid]++; trace_leave(); return; } } trace_leave(); }
void fn_registered( FID fid, unsigned int nb_param, vector<bool> type_param ) { trace_enter(); /* Set the number of parameters */ nb_p[fid] = nb_param; /* Set the array of booleans indicating which parameter is an ADDR */ param_addr[fid] = (bool *) calloc(nb_p[fid], sizeof(bool)); /* Is this function instrumented?*/ is_instrumented[fid] = false; /* Iteration on parameters */ for (unsigned int i = 0; i <= nb_p[fid]; i++) { if (type_param[i]) { param_addr[fid][i] = true; is_instrumented[fid] = true; } else param_addr[fid][i] = false; } trace_leave(); return; }
void syslogd_open_sockets (struct socket *sockets) { struct socket *socket = sockets; #if SYSLOGD_TRACE trace_enter ("syslogd_open_sockets"); #endif do { socket = socket->next; if (socket->desc != -1) { continue; } if (socket->sockaddr == (struct sockaddr *)(0)) { syslogd_error (EINVAL, "Missing socket address"); continue; } #ifdef SYSLOGD_UNIXAF if (socket->sockaddr->sa_family == AF_UNIX) { struct sockaddr_un * sockaddr_un = (struct sockaddr_un *)(socket->sockaddr); syslogd_print (SYSLOG_SYSLOG | SYSLOG_NOTICE, "Opening host connection on %s", sockaddr_un->sun_path); socket->desc = syslogd_unix_socket (sockaddr_un); continue; } #endif #ifdef SYSLOGD_INETAF if (socket->sockaddr->sa_family == AF_INET) { char buffer [HOSTADDR_MAX]; struct sockaddr_in * sockaddr_in = (struct sockaddr_in *)(socket->sockaddr); getsocketname (buffer, sizeof (buffer), sockaddr_in); syslogd_print (SYSLOG_SYSLOG | SYSLOG_NOTICE, "Opening inet connection on %s", buffer); socket->desc = syslogd_inet_socket (sockaddr_in); continue; } #endif } while (socket != sockets); #if SYSLOGD_TRACE trace_leave ("syslogd_open_sockets"); #endif return; }
/* Instrumentation of each instruction * that uses a memory operand */ VOID Instruction(INS ins, VOID *v) { trace_enter(); if (!INS_IsStackRead(ins)) { for (UINT32 memopIdx = 0; memopIdx < INS_MemoryOperandCount(ins); memopIdx++) { if (INS_MemoryOperandIsWritten(ins, memopIdx)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) update_stack_heap_region, IARG_CONST_CONTEXT, IARG_MEMORYOP_EA, memopIdx, IARG_END); UINT32 opIdx = INS_MemoryOperandIndexToOperandIndex(ins, memopIdx); REG base_reg = INS_OperandMemoryBaseReg(ins, opIdx); if (base_reg != REG_INVALID()) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) check_parameter_out, IARG_REG_VALUE, base_reg, IARG_END); } } } } if (INS_IsCall(ins)) { if (INS_IsDirectCall(ins)) { ADDRINT addr = INS_DirectBranchOrCallTargetAddress(ins); FID fid = fn_lookup_by_address(addr); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) fn_call, IARG_CONST_CONTEXT, IARG_UINT32, fid, IARG_END); } else { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) fn_indirect_call, IARG_CONST_CONTEXT, IARG_BRANCH_TARGET_ADDR, IARG_END); } } if (INS_IsRet(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) fn_ret, IARG_CONST_CONTEXT, IARG_END); } trace_leave(); }
VOID update_stack_heap_region(CONTEXT* ctxt, ADDRINT addr) { trace_enter(); if (!is_addr(addr)) { stack_heap_region.extend(addr); } trace_leave(); }
VOID Commence() { trace_enter(); /* Init instruction counter */ counter = 0; init = true; string _addr, _name; if (ifile.is_open()) { while (ifile) { char m; unsigned int nb_param = 0; vector<bool> type_param; string img_name = read_part(&m); if (img_name.empty()) { continue; } ADDRINT img_addr = atol(read_part(&m).c_str()); string name = read_part(&m); /* Read parameters */ while (ifile && m != '\n') { string part = read_part(&m); switch (part[0]) { case 'A': type_param.push_back(true); break; case 'I': case 'V': type_param.push_back(false); break; case 'F': type_param.push_back(false); break; default: type_param.push_back(false); } nb_param += 1; } FID fid = fn_register(img_name, img_addr, name); if (fid != FID_UNKNOWN) { fn_registered(fid, nb_param - 1, type_param); } } } gettimeofday(&start, NULL); trace_leave(); return; }
VOID Fini(INT32 code, VOID *v) { trace_enter(); list<param_t *>::reverse_iterator it_in, it_out; it_in = param_in->rbegin(); it_out = param_out->rbegin(); int depth = 0; UINT64 last_date = -1; bool is_in = false; gettimeofday(&stop, NULL); ofile << "Elapsed time ] Commence ; Fini [ : " << (stop.tv_usec / 1000.0 + 1000 * stop.tv_sec - start.tv_sec * 1000 - start.tv_usec / 1000.0) / 1000.0 << "s" << endl; while (it_in != param_in->rend() || it_out != param_out->rend()) { // for (int i = 0; i < depth; i++) // ofile << " "; param_t *p; if (it_in == param_in->rend()) { p = *it_out; it_out++; is_in = false; ofile << "out:"; } else if (it_out == param_out->rend() || (*it_out)->counter >= (*it_in)->counter) { p = *it_in; it_in++; is_in = true; ofile << "in:"; } else { p = *it_out; it_out++; is_in = false; ofile << "out:"; } if (p->is_addr) ofile << "addr:"; else ofile << "int:"; if (last_date != p->counter) { if (is_in) depth++; else depth--; } last_date = p->counter; ofile << p->val << ":" << fn_img(p->fid) << ":" << fn_imgaddr(p->fid) << ":" << fn_name(p->fid) << ":" << p->pos << ":" << p->counter << endl; } ofile.close(); trace_leave(); return; }
VOID image_loaded(IMG img, void* data) { trace_enter(); for (int i = 0; i < IMG_NumRegions(img); i++) { Region* region = data_regions + data_regions_size; data_regions_size++; region->low = IMG_RegionLowAddress(img, i); region->high = IMG_RegionHighAddress(img, i); } trace_leave(); }
void syslogd_stop (struct syslogd * syslogs, flag_t flags) { extern char const * program_name; struct syslogd * syslog; #if SYSLOGD_TRACE trace_enter ("syslogd_stop"); #endif syslogd_print (SYSLOG_SYSLOG | SYSLOG_NOTICE, "%s %s.%s stopped", program_name, VERSION, RELEASE); while (syslogs->next != syslogs) { syslog = syslogs->next; syslog->next->prev = syslogs; syslogs->next = syslog->next; if (syslog->f_repeat > 0) { syslogd_write (syslog, flags); } if (syslog->f_sockaddr_in != (struct sockaddr_in *) (0)) { free (syslog->f_sockaddr_in); syslog->f_sockaddr_in = (struct sockaddr_in *) (0); } switch (syslog->f_type) { case SYSLOGD_TYPE_HOST: case SYSLOGD_TYPE_FILE: case SYSLOGD_TYPE_PIPE: case SYSLOGD_TYPE_TERM: case SYSLOGD_TYPE_CONSOLE: close (syslog->f_desc); break; } syslog->prev = (struct syslogd *) (0); syslog->next = (struct syslogd *) (0); free (syslog->f_name); free (syslog); } #if SYSLOGD_TRACE trace_leave ("syslogd_stop"); #endif return; }
VOID fn_indirect_call(CONTEXT* ctxt, ADDRINT target) { trace_enter(); // Indirect call, we have to look up the function each time // The functions `fn_lookup` & `fn_register` needs PIN's Lock. // Locking is not implicit in inserted call, as opposed // to callback added with *_AddInstrumentFunction(). PIN_LockClient(); FID fid = fn_lookup_by_address(target); PIN_UnlockClient(); fn_call(ctxt, fid); trace_leave(); }
VOID fn_ret(CONTEXT *ctxt) { trace_enter(); if (!call_stack.is_top_forgotten()) { FID fid = call_stack.top(); if (has_return[fid] == 1) { add_val(fid, ctxt, 0, 0); } } call_stack.pop(); sp_stack.pop(); trace_leave(); }
void syslogd_configure (struct syslogd * syslogs, flag_t flags, char const * filename) { file_t fd; char string [TEXTLINE_MAX]; size_t lineno = 0; #if SYSLOGD_TRACE trace_enter ("syslogd_configure"); #endif if ((fd = open (filename, O_RDONLY)) == - 1) { syslogd_error (errno, "cant open %s", filename); return; } while (statement (fd, string, sizeof (string), & lineno)) { if (* string != (char) (0)) { struct syslogd * syslog = NEW (struct syslogd); syslogd_parse (syslog, flags, string); if (syslog->f_type == SYSLOGD_TYPE_NONE) { free (syslog->f_name); free (syslog); continue; } syslog->prev = syslogs->prev; syslogs->prev->next = syslog; syslogs->prev = syslog; syslog->next = syslogs; } } close (fd); #if SYSLOGD_TRACE trace_leave ("syslogd_configure"); #endif return; }
VOID fn_call(CONTEXT *ctxt, FID fid) { trace_enter(); call_stack.push(fid); UINT64 sp; PIN_GetContextRegval(ctxt, REG_RSP, (UINT8*) &sp); sp_stack.push(sp); nb_call[fid]++; unsigned int param_val_size = 1 + nb_param_int[fid] + nb_param_int_stack[fid]; for (unsigned int pid = 1; pid < param_val_size; pid++) { if (!param_is_not_addr[fid][pid]) add_val(fid, ctxt, pid, sp); } trace_leave(); }
VOID fn_call(CONTEXT *ctxt, FID fid, bool is_jump) { trace_enter(); call_stack.push(fid); is_jump_stack.push(is_jump); counter += 1; bool param_pushed = false; if (!is_instrumented[fid]) { trace_leave(); return; } for (unsigned int i = 1; i <= nb_p[fid]; i++) { if (!param_addr[fid][i]) continue; param_t *new_param = (param_t *) malloc(sizeof(param_t)); new_param->fid = fid; new_param->counter = counter; new_param->val = val_from_reg(ctxt, i); new_param->is_addr = param_addr[fid][i]; new_param->pos = i; param_in->push_front(new_param); param_pushed = true; } /* If the function is instrumented (ie for instance has an ADDR as a return value) AND was not logged yet, create a special entry to log the date of call */ if (!param_pushed) { param_t *new_addr = (param_t *) malloc(sizeof(param_t)); new_addr->fid = fid; new_addr->counter = counter; new_addr->val = 0; // val_from_reg(ctxt, i); new_addr->pos = 0; new_addr->is_addr = false; // true; param_in->push_front(new_addr); } trace_leave(); return; }
void netbsd32_syscall(struct trapframe *frame) { char *params; const struct sysent *callp; struct proc *p; struct lwp *l; int error; int i; register32_t code, args[2 + SYS_MAXSYSARGS]; register_t rval[2]; register_t args64[SYS_MAXSYSARGS]; l = curlwp; p = l->l_proc; code = frame->tf_rax & (SYS_NSYSENT - 1); callp = p->p_emul->e_sysent + code; LWP_CACHE_CREDS(l, p); SYSCALL_COUNT(syscall_counts, code); SYSCALL_TIME_SYS_ENTRY(l, syscall_times, code); params = (char *)frame->tf_rsp + sizeof(int); if (callp->sy_argsize) { error = copyin(params, args, callp->sy_argsize); if (__predict_false(error != 0)) goto bad; /* Recover 'code' - not in a register */ code = frame->tf_rax & (SYS_NSYSENT - 1); } if (__predict_false(p->p_trace_enabled) && !__predict_false(callp->sy_flags & SYCALL_INDIRECT)) { int narg = callp->sy_argsize >> 2; for (i = 0; i < narg; i++) args64[i] = args[i]; error = trace_enter(code, args64, narg); if (__predict_false(error != 0)) goto out; }
ADDRINT val_from_reg(CONTEXT *ctxt, unsigned int pid) { trace_enter(); REG reg; switch (pid) { case 0: reg = REG_RAX; break; case 1: reg = REG_RDI; break; case 2: reg = REG_RSI; break; case 3: reg = REG_RDX; break; case 4: reg = REG_RCX; break; case 5: reg = REG_R8; break; case 6: reg = REG_R9; break; default: trace_leave(); return 0; } trace_leave(); return PIN_GetContextReg(ctxt, reg); }
VOID add_val(unsigned int fid, CONTEXT *ctxt, unsigned int pid, UINT64 sp) { trace_enter(); if (param_val[fid][pid]->size() >= MAX_VALS_TO_COLLECT) { trace_leave(); return; } UINT64 val; if (pid < 1 + nb_param_int[fid]) { PIN_GetContextRegval(ctxt, param_reg(pid), (UINT8*) &val); } else { unsigned int sp_offset = pid - (1 + nb_param_int[fid]); UINT64* addr = (UINT64*) (sp + sp_offset * 8); val = *addr; } if (val != 0) param_val[fid][pid]->push_front(val); trace_leave(); }
void syslogd_admin (struct syslogd * syslogs, flag_t flags, char const * filename) { FILE * fp; struct syslogd * syslog; #if SYSLOGD_TRACE trace_enter ("syslogd_admin"); #endif if ((filename == (char *) (0)) || (* filename == (char) (0))) { return; } if ((fp = fopen (filename, "w")) == (FILE *) (0)) { syslogd_error (errno, "can't open %s", filename); return; } syslogd_enumerate (syslogs, flags, fp); for (syslog = syslogs->next; syslog != syslogs; syslog = syslog->next) { syslogd_state (syslog, flags, fp); } syslogd_state (syslog, flags, fp); fclose (fp); #if SYSLOGD_TRACE trace_leave ("syslogd_admin"); #endif return; }
/* * syscall(frame): * System call request from POSIX system call gate interface to kernel. * Like trap(), argument is call by reference. */ void linux_syscall(struct trapframe *frame) { register const struct sysent *callp; struct lwp *l; int error; register_t code, args[6], rval[2]; l = curlwp; LWP_CACHE_CREDS(l, l->l_proc); code = frame->tf_eax & (LINUX_SYS_NSYSENT - 1); callp = linux_sysent; callp += code; /* * Linux passes the args in ebx, ecx, edx, esi, edi, ebp, in * increasing order. */ args[0] = frame->tf_ebx; args[1] = frame->tf_ecx; args[2] = frame->tf_edx; args[3] = frame->tf_esi; args[4] = frame->tf_edi; args[5] = frame->tf_ebp; rval[0] = 0; rval[1] = 0; if (__predict_false(l->l_proc->p_trace_enabled)) { error = trace_enter(code, args, callp->sy_narg); if (__predict_true(error == 0)) { error = sy_call(callp, l, args, rval); code = frame->tf_eax & (LINUX_SYS_NSYSENT - 1); trace_exit(code, rval, error); } } else error = sy_call(callp, l, args, rval); if (__predict_true(error == 0)) { frame->tf_eax = rval[0]; /* * XXX The linux libc code I (dsl) looked at doesn't use the * carry bit. * Values above 0xfffff000 are assumed to be errno values and * not result codes! */ frame->tf_eflags &= ~PSL_C; /* carry bit */ } else { switch (error) { case ERESTART: /* * The offset to adjust the PC by depends on whether * we entered the kernel through the trap or call gate. * We save the instruction size in tf_err on entry. */ frame->tf_eip -= frame->tf_err; break; case EJUSTRETURN: /* nothing to do */ break; default: error = native_to_linux_errno[error]; frame->tf_eax = error; frame->tf_eflags |= PSL_C; /* carry bit */ break; } } userret(l); }
/* * syscall(frame): * System call request from POSIX system call gate interface to kernel. * Like trap(), argument is call by reference. */ static void linux_syscall(struct trapframe *frame) { const struct sysent *callp; struct proc *p; struct lwp *l; int error; register_t code, rval[2]; #define args (&frame->tf_rdi) l = curlwp; p = l->l_proc; code = frame->tf_rax; LWP_CACHE_CREDS(l, p); callp = p->p_emul->e_sysent; code &= (LINUX_SYS_NSYSENT - 1); callp += code; /* * Linux system calls have a maximum of 6 arguments, they are * already adjacent in the syscall trapframe. */ if (__predict_false(p->p_trace_enabled) && (error = trace_enter(code, args, callp->sy_narg)) != 0) goto out; rval[0] = 0; rval[1] = 0; error = sy_call(callp, l, args, rval); out: switch (error) { case 0: frame->tf_rax = rval[0]; break; case ERESTART: /* * The offset to adjust the PC by depends on whether we entered * the kernel through the trap or call gate. We pushed the * size of the instruction into tf_err on entry. */ frame->tf_rip -= frame->tf_err; break; case EJUSTRETURN: /* nothing to do */ break; default: error = native_to_linux_errno[error]; frame->tf_rax = error; break; } if (__predict_false(p->p_trace_enabled)) trace_exit(code, rval, error); userret(l); }
static void syscall_fancy(register_t code, struct lwp *l, struct frame *frame) { char *params; const struct sysent *callp; int error, nsys; size_t argsize; register_t args[16], rval[2]; struct proc *p = l->l_proc; nsys = p->p_emul->e_nsysent; callp = p->p_emul->e_sysent; params = (char *)frame->f_regs[SP] + sizeof(int); switch (code) { case SYS_syscall: /* * Code is first argument, followed by actual args. */ code = fuword(params); params += sizeof(int); #if defined(COMPAT_13) || defined(COMPAT_16) /* * XXX sigreturn requires special stack manipulation * that is only done if entered via the sigreturn * trap. Cannot allow it here so make sure we fail. */ switch (code) { #ifdef COMPAT_13 case SYS_compat_13_sigreturn13: #endif #ifdef COMPAT_16 case SYS_compat_16___sigreturn14: #endif code = nsys; break; } #endif break; case SYS___syscall: /* * Like syscall, but code is a quad, so as to maintain * quad alignment for the rest of the arguments. */ code = fuword(params + _QUAD_LOWWORD * sizeof(int)); params += sizeof(quad_t); break; default: break; } if (code < 0 || code >= nsys) callp += p->p_emul->e_nosys; /* illegal */ else callp += code; argsize = callp->sy_argsize; if (argsize) { error = copyin(params, (void *)args, argsize); if (error) goto bad; } if ((error = trace_enter(code, args, callp->sy_narg)) != 0) goto out; rval[0] = 0; rval[1] = frame->f_regs[D1]; error = sy_call(callp, l, args, rval); out: switch (error) { case 0: /* * Reinitialize lwp/proc pointers as they may be different * if this is a child returning from fork syscall. */ l = curlwp; p = l->l_proc; frame->f_regs[D0] = rval[0]; frame->f_regs[D1] = rval[1]; frame->f_sr &= ~PSL_C; /* carry bit */ #ifdef COMPAT_50 /* see syscall_plain for a comment explaining this */ /* * Some pre-m68k ELF libc assembler stubs assume * %a0 is preserved across system calls... */ if (p->p_emul == &emul_netbsd) frame->f_regs[A0] = rval[0]; #endif break; case ERESTART: /* * We always enter through a `trap' instruction, which is 2 * bytes, so adjust the pc by that amount. */ frame->f_pc = frame->f_pc - 2; break; case EJUSTRETURN: /* nothing to do */ break; default: bad: /* * XXX: SVR4 uses this code-path, so we may have * to translate errno. */ if (p->p_emul->e_errno) error = p->p_emul->e_errno[error]; frame->f_regs[D0] = error; frame->f_sr |= PSL_C; /* carry bit */ break; } trace_exit(code, rval, error); }
void syscall(struct trapframe *frame, lwp_t *l, uint32_t insn) { struct proc * const p = l->l_proc; const struct sysent *callp; int error; u_int nargs; register_t *args; register_t copyargs[2+SYS_MAXSYSARGS]; register_t rval[2]; ksiginfo_t ksi; const uint32_t os_mask = insn & SWI_OS_MASK; uint32_t code = insn & 0x000fffff; /* test new official and old unofficial NetBSD ranges */ if (__predict_false(os_mask != SWI_OS_NETBSD) && __predict_false(os_mask != 0)) { if (os_mask == SWI_OS_ARM && (code == SWI_IMB || code == SWI_IMBrange)) { userret(l); return; } /* Undefined so illegal instruction */ KSI_INIT_TRAP(&ksi); ksi.ksi_signo = SIGILL; ksi.ksi_code = 0; /* XXX get an ILL_ILLSYSCALL assigned */ #ifdef THUMB_CODE if (frame->tf_spsr & PSR_T_bit) ksi.ksi_addr = (void *)(frame->tf_pc - THUMB_INSN_SIZE); else #endif ksi.ksi_addr = (void *)(frame->tf_pc - INSN_SIZE); ksi.ksi_trap = insn; trapsignal(l, &ksi); userret(l); return; } code &= (SYS_NSYSENT - 1); callp = p->p_emul->e_sysent + code; nargs = callp->sy_narg; if (nargs > 4) { args = copyargs; memcpy(args, &frame->tf_r0, 4 * sizeof(register_t)); error = copyin((void *)frame->tf_usr_sp, args + 4, (nargs - 4) * sizeof(register_t)); if (error) goto bad; } else { args = &frame->tf_r0; } if (!__predict_false(p->p_trace_enabled) || __predict_false(callp->sy_flags & SYCALL_INDIRECT) || (error = trace_enter(code, args, nargs)) == 0) { rval[0] = 0; rval[1] = 0; KASSERT(l->l_holdcnt == 0); error = (*callp->sy_call)(l, args, rval); } if (__predict_false(p->p_trace_enabled) || !__predict_false(callp->sy_flags & SYCALL_INDIRECT)) trace_exit(code, rval, error); switch (error) { case 0: frame->tf_r0 = rval[0]; frame->tf_r1 = rval[1]; #ifdef __PROG32 frame->tf_spsr &= ~PSR_C_bit; /* carry bit */ #else frame->tf_r15 &= ~R15_FLAG_C; /* carry bit */ #endif break; case ERESTART: /* * Reconstruct the pc to point at the swi. */ #ifdef THUMB_CODE if (frame->tf_spsr & PSR_T_bit) frame->tf_pc -= THUMB_INSN_SIZE; else #endif frame->tf_pc -= INSN_SIZE; break; case EJUSTRETURN: /* nothing to do */ break; default: bad: frame->tf_r0 = error; #ifdef __PROG32 frame->tf_spsr |= PSR_C_bit; /* carry bit */ #else frame->tf_r15 |= R15_FLAG_C; /* carry bit */ #endif break; } userret(l); }
int trace_read (const char *filename) { FILE *trace = fopen(filename, "r"); assert_inner(trace, "fopen"); void *trace_buf = NULL; unsigned long trace_bufsize = 0; size_t n = fread(&trace_bufsize, sizeof(unsigned long), 1, trace); assert_set_errno(ENOTSUP, n == 1, "fread"); trace_buf = malloc(trace_bufsize); assert_inner(trace_buf, "malloc"); n = fread(trace_buf, 1, trace_bufsize, trace); assert_set_errno(ENOTSUP, n == trace_bufsize, "fread"); assert_set_errno(ENOTSUP, feof(trace), "feof"); unsigned int trace_ended = 0; unsigned long trace_index = 0; while (trace_index < trace_bufsize) { char sign = *((char*)(trace_buf + trace_index)); trace_index += sizeof(char); switch (sign) { case 'e': trace_enter(trace_buf + trace_index); trace_index += 2 * sizeof(uintptr_t) + sizeof(unsigned long long); break; case 'x': trace_exit(trace_buf + trace_index); trace_index += sizeof(unsigned long long); break; case '+': trace_malloc(trace_buf + trace_index); trace_index += sizeof(size_t) + 2 * sizeof(uintptr_t) + sizeof(unsigned long long); break; case '*': trace_realloc(trace_buf + trace_index); trace_index += sizeof(size_t) + 3 * sizeof(uintptr_t) + sizeof(unsigned long long); break; case '-': trace_free(trace_buf + trace_index); trace_index += 2 * sizeof(uintptr_t) + sizeof(unsigned long long); break; case 'E': trace_end(trace_buf + trace_index); trace_index += sizeof(unsigned long long); trace_ended = 1; assert_set_errno(ENOTSUP, trace_bufsize == trace_index, "END not at end"); break; default: assert_set_errno(ENOTSUP, 0, "sign switch"); break; } } if (!trace_ended) assert_set_errno(ENOTSUP, 0, "no END at end"); free(trace_buf); fclose(trace); return 0; }
void syslogd_start (struct syslogd * syslogs, flag_t flags, char const * filename) { extern char const * program_name; char buffer [TEXTLINE_MAX]; size_t lineno = 0; file_t fd; #if SYSLOGD_TRACE trace_enter ("syslogd_start"); #endif if ((fd = open (filename, O_RDONLY)) == - 1) { syslogd_error (errno, "Can't open %s", filename); return; } while (statement (fd, buffer, sizeof (buffer), & lineno)) { struct syslogd * syslog = NEW (struct syslogd); memset (syslog, 0, sizeof (struct syslogd)); syslog->f_type = SYSLOGD_TYPE_NONE; syslog->f_name = ""; syslog->f_line = lineno; syslog->f_desc = - 1; syslog->f_time = time ((time_t *) (0)); syslogd_parse (syslog, flags, buffer); syslogd_ready (syslog, flags); if (syslog->f_type == SYSLOGD_TYPE_NONE) { free (syslog->f_name); free (syslog); continue; } syslog->prev = syslogs->prev; syslogs->prev->next = syslog; syslogs->prev = syslog; syslog->next = syslogs; for (syslog = syslogs->next; syslog != syslogs->prev; syslog = syslog->next) { if (!strcmp (syslog->f_name, syslogs->prev->f_name)) { syslogd_print (SYSLOG_SYSLOG | SYSLOG_WARNING, "New %s selections on line %d replace old ones on line %d", syslogs->prev->f_name, syslogs->prev->f_line, syslog->f_line); syslog->next->prev = syslog->prev; syslog->prev->next = syslog->next; syslog->prev = (struct syslogd *) (0); syslog->next = (struct syslogd *) (0); free (syslog->f_name); free (syslog); break; } } } close (fd); syslogd_print (SYSLOG_SYSLOG | SYSLOG_NOTICE, "%s %s.%s started", program_name, VERSION, RELEASE); syslogd_print (SYSLOG_SYSLOG | SYSLOG_INFO, "Configured with %s", filename); #if SYSLOGD_TRACE trace_leave ("syslogd_start"); #endif return; }
static void sunos_syscall_fancy(register_t code, struct lwp *l, struct frame *frame) { struct proc *p = l->l_proc; char *params; const struct sysent *callp; int error, nsys; size_t argsize; register_t args[16], rval[2]; nsys = p->p_emul->e_nsysent; callp = p->p_emul->e_sysent; /* * SunOS passes the syscall-number on the stack, whereas * BSD passes it in D0. So, we have to get the real "code" * from the stack, and clean up the stack, as SunOS glue * code assumes the kernel pops the syscall argument the * glue pushed on the stack. Sigh... */ code = fuword((void *)frame->f_regs[SP]); /* * XXX * Don't do this for sunos_sigreturn, as there's no stored pc * on the stack to skip, the argument follows the syscall * number without a gap. */ if (code != SUNOS_SYS_sigreturn) { frame->f_regs[SP] += sizeof (int); /* * remember that we adjusted the SP, * might have to undo this if the system call * returns ERESTART. */ l->l_md.md_flags |= MDL_STACKADJ; } else l->l_md.md_flags &= ~MDL_STACKADJ; params = (char *)frame->f_regs[SP] + sizeof(int); switch (code) { case SUNOS_SYS_syscall: /* * Code is first argument, followed by actual args. */ code = fuword(params); params += sizeof(int); break; default: break; } if (code < 0 || code >= nsys) callp += p->p_emul->e_nosys; /* illegal */ else callp += code; argsize = callp->sy_argsize; if (argsize) { error = copyin(params, (void *)args, argsize); if (error) goto bad; } if ((error = trace_enter(code, args, callp->sy_narg)) != 0) goto out; rval[0] = 0; rval[1] = frame->f_regs[D1]; error = sy_call(callp, l, args, rval); out: switch (error) { case 0: /* * Reinitialize proc pointer `p' as it may be different * if this is a child returning from fork syscall. */ p = curproc; frame->f_regs[D0] = rval[0]; frame->f_regs[D1] = rval[1]; frame->f_sr &= ~PSL_C; /* carry bit */ break; case ERESTART: /* * We always enter through a `trap' instruction, which is 2 * bytes, so adjust the pc by that amount. */ frame->f_pc = frame->f_pc - 2; break; case EJUSTRETURN: /* nothing to do */ break; default: bad: frame->f_regs[D0] = error; frame->f_sr |= PSL_C; /* carry bit */ break; } /* need new p-value for this */ if (l->l_md.md_flags & MDL_STACKADJ) { l->l_md.md_flags &= ~MDL_STACKADJ; if (error == ERESTART) frame->f_regs[SP] -= sizeof (int); } trace_exit(code, rval, error); }
void linux32_syscall(struct trapframe *frame) { const struct sysent *callp; struct proc *p; struct lwp *l; int error; size_t narg; register32_t code, args[6]; register_t rval[2]; int i; register_t args64[6]; l = curlwp; p = l->l_proc; code = frame->tf_rax; LWP_CACHE_CREDS(l, p); callp = p->p_emul->e_sysent; code &= (LINUX32_SYS_NSYSENT - 1); callp += code; /* * Linux passes the args in ebx, ecx, edx, esi, edi, ebp, in * increasing order. */ args[0] = frame->tf_rbx & 0xffffffff; args[1] = frame->tf_rcx & 0xffffffff; args[2] = frame->tf_rdx & 0xffffffff; args[3] = frame->tf_rsi & 0xffffffff; args[4] = frame->tf_rdi & 0xffffffff; args[5] = frame->tf_rbp & 0xffffffff; if (__predict_false(p->p_trace_enabled)) { narg = callp->sy_narg; if (__predict_false(narg > __arraycount(args))) panic("impossible syscall narg, code %d, narg %zd", code, narg); for (i = 0; i < narg; i++) args64[i] = args[i] & 0xffffffff; if ((error = trace_enter(code, args64, narg)) != 0) goto out; } rval[0] = 0; rval[1] = 0; error = sy_call(callp, l, args, rval); out: switch (error) { case 0: frame->tf_rax = rval[0]; frame->tf_rflags &= ~PSL_C; /* carry bit */ break; case ERESTART: /* * The offset to adjust the PC by depends on whether we entered * the kernel through the trap or call gate. We pushed the * size of the instruction into tf_err on entry. */ frame->tf_rip -= frame->tf_err; break; case EJUSTRETURN: /* nothing to do */ break; default: error = native_to_linux32_errno[error]; frame->tf_rax = error; frame->tf_rflags |= PSL_C; /* carry bit */ break; } if (__predict_false(p->p_trace_enabled)) trace_exit(code, rval, error); userret(l); }
VOID Fini(INT32 code, VOID *v) { trace_enter(); list<param_t *>::reverse_iterator it_in, it_out; it_in = param_in->rbegin(); it_out = param_out->rbegin(); int depth = 0; UINT64 last_date = -1; bool is_in = false; gettimeofday(&stop, NULL); ofile << "Elapsed time ] Commence ; Fini [ : " << (stop.tv_usec / 1000.0 + 1000 * stop.tv_sec - start.tv_sec * 1000 - start.tv_usec / 1000.0) / 1000.0 << "s" << endl; while (it_in != param_in->rend() || it_out != param_out->rend()) { param_t *p; if (it_in == param_in->rend()) { p = *it_out; it_out++; is_in = false; } else if (it_out == param_out->rend() || (*it_out)->counter >= (*it_in)->counter) { p = *it_in; it_in++; is_in = true; } else { p = *it_out; it_out++; is_in = false; } #if 0 if (p->is_addr) ofile << "a:"; else ofile << "n:"; #endif if (last_date != p->counter) { if (is_in) depth++; else depth--; } last_date = p->counter; char head = 0x00; /* Construct the first byte */ /* First two bits are for i/o and addr/not addr */ head |= 0x80 & ((is_in?1:0) << 7); head |= 0x40 & ((p->is_addr?1:0) << 6); /* Then we encode the position of the parameter */ head |= 0x3F & p->pos; if (!pushed_in_log[p->fid]) { ofile << '\xff' << p->fid << ":" << fn_img(p->fid) << ":" << fn_imgaddr(p->fid) << ":" << fn_name(p->fid) << endl; pushed_in_log[p->fid] = true; } ofile << head; ofile << p->fid << ":" << p->counter << ":" << p->val << endl; #if 0 ofile << p->val << ":" << fn_img(p->fid) << ":" << fn_imgaddr(p->fid) << ":" << fn_name(p->fid) << ":" << p->pos << ":" << p->counter << endl; #endif } ofile.close(); trace_leave(); return; }
VOID Fini(INT32 code, VOID *v) { trace_enter(); #define append_type(type) \ if (need_comma) \ ofile << "," ; \ ofile << (type); \ need_comma = true for(unsigned int fid = 1; fid <= fn_nb(); fid++) { if (nb_call[fid] < NB_CALLS_TO_CONCLUDE) continue; ofile << fn_img(fid) << ":" << fn_imgaddr(fid) << ":" << fn_name(fid) << ":"; bool need_comma = false; unsigned int param_val_size = 1 + nb_param_int[fid] + nb_param_int_stack[fid]; for (unsigned int pid = 0; pid < param_val_size; pid++) { if (((float) nb_out[fid][pid]) > 0.75 * ((float) nb_call[fid])) { debug("Found 'out parameter' candidate : [%s@%lX] %s %u (%u <=> %u)\n", fn_img(fid).c_str(), fn_imgaddr(fid), fn_name(fid).c_str(), pid, nb_out[fid][pid], nb_call[fid]); } if (pid == 0 && has_return[fid] == 0) { append_type("VOID"); } else if (pid == 0 && has_return[fid] == 2) { append_type("FLOAT"); } else if (pid < 1 + nb_param_int[fid] && param_is_not_addr[fid][pid]) { append_type("INT"); } else if (param_val[fid][pid]->size() == 0) { append_type("UNDEF"); } else { int param_addr = 0; for (list<UINT64>::iterator it = param_val[fid][pid]->begin(); it != param_val[fid][pid]->end(); it++) { if (is_addr(*it)) { param_addr++; } } float coef = ((float) param_addr) / ((float) param_val[fid][pid]->size()); append_type(coef > THRESHOLD ? "ADDR" : "INT"); ofile << "(" << coef << ")"; } } for (unsigned int pid = 0; pid < nb_param_float[fid] + nb_param_float_stack[fid]; pid++) { append_type("FLOAT"); } ofile << endl; } ofile.close(); trace_leave(); }