📄 util.c
字号:
#ifndef USE_PROCFSintsetbpt(tcp)struct tcb *tcp;{#ifdef LINUX#ifdef SPARC /* We simply use the SunOS breakpoint code. */ struct regs regs;#define LOOPA 0x30800000 /* ba,a 0 */ if (tcp->flags & TCB_BPTSET) { fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid); return -1; } if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) { perror("setbpt: ptrace(PTRACE_GETREGS, ...)"); return -1; } tcp->baddr = regs.r_o7 + 8; errno = 0; tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0); if(errno) { perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)"); return -1; } /* * XXX - BRUTAL MODE ON * We cannot set a real BPT in the child, since it will not be * traced at the moment it will reach the trap and would probably * die with a core dump. * Thus, we are force our way in by taking out two instructions * and insert an eternal loop instead, in expectance of the SIGSTOP * generated by out PTRACE_ATTACH. * Of cause, if we evaporate ourselves in the middle of all this... */ errno = 0; ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA); if(errno) { perror("setbpt: ptrace(PTRACE_POKETEXT, ...)"); return -1; } tcp->flags |= TCB_BPTSET;#else /* !SPARC */#ifdef IA64 /* * Our strategy here is to replace the bundle that contained * the clone() syscall with a bundle of the form: * * { 1: br 1b; br 1b; br 1b } * * This ensures that the newly forked child will loop * endlessly until we've got a chance to attach to it. */ {# define LOOP0 0x0000100000000017# define LOOP1 0x4000000000200000 unsigned long addr, ipsr; pid_t pid; pid = tcp->pid; if (upeek(pid, PT_CR_IPSR, &ipsr) < 0) return -1; if (upeek(pid, PT_CR_IIP, &addr) < 0) return -1; tcp->baddr = addr | ((ipsr >> 41) & 0x3); /* store "ri" in low two bits */ errno = 0; tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0, 0); tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8, 0); if (errno) { perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)"); return -1; } errno = 0; ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0); ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1); if (errno) { perror("setbpt: ptrace(PTRACE_POKETEXT, ...)"); return -1; } tcp->flags |= TCB_BPTSET; }#else /* !IA64 */#if defined (I386)#define LOOP 0x0000feeb#elif defined (M68K)#define LOOP 0x60fe0000#elif defined (ALPHA)#define LOOP 0xc3ffffff#elif defined (POWERPC)#define LOOP 0x0000feeb#elif defined(ARM)#define LOOP 0xEAFFFFFE#elif defined(MIPS)#define LOOP 0x1000ffff#elif defined(S390)#define LOOP 0xa7f40000 /* BRC 15,0 */#elif defined(HPPA)#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */#else#error unknown architecture#endif if (tcp->flags & TCB_BPTSET) { fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid); return -1; }#if defined (I386) if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0) return -1;#elif defined (M68K) if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0) return -1;#elif defined (ALPHA) return -1;#elif defined (ARM) return -1;#elif defined (MIPS) return -1; /* FIXME: I do not know what i do - Flo */#elif defined (POWERPC) if (upeek(tcp->pid, 4*PT_NIP, &tcp->baddr) < 0) return -1;#elif defined(S390) if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0) return -1;#elif defined(HPPA) if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0) return -1; tcp->baddr &= ~0x03;#else#error unknown architecture#endif if (debug) fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr); tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0); if (errno) { perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)"); return -1; } ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP); if (errno) { perror("setbpt: ptrace(PTRACE_POKETEXT, ...)"); return -1; } tcp->flags |= TCB_BPTSET;#endif /* !IA64 */#endif /* SPARC */#endif /* LINUX */#ifdef SUNOS4#ifdef SPARC /* This code is slightly sparc specific */ struct regs regs;#define BPT 0x91d02001 /* ta 1 */#define LOOP 0x10800000 /* ba 0 */#define LOOPA 0x30800000 /* ba,a 0 */#define NOP 0x01000000#if LOOPA static int loopdeloop[1] = {LOOPA};#else static int loopdeloop[2] = {LOOP, NOP};#endif if (tcp->flags & TCB_BPTSET) { fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid); return -1; } if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) { perror("setbpt: ptrace(PTRACE_GETREGS, ...)"); return -1; } tcp->baddr = regs.r_o7 + 8; if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr, sizeof tcp->inst, (char *)tcp->inst) < 0) { perror("setbpt: ptrace(PTRACE_READTEXT, ...)"); return -1; } /* * XXX - BRUTAL MODE ON * We cannot set a real BPT in the child, since it will not be * traced at the moment it will reach the trap and would probably * die with a core dump. * Thus, we are force our way in by taking out two instructions * and insert an eternal loop in stead, in expectance of the SIGSTOP * generated by out PTRACE_ATTACH. * Of cause, if we evaporate ourselves in the middle of all this... */ if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr, sizeof loopdeloop, (char *) loopdeloop) < 0) { perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)"); return -1; } tcp->flags |= TCB_BPTSET;#endif /* SPARC */#endif /* SUNOS4 */ return 0;}intclearbpt(tcp)struct tcb *tcp;{#ifdef LINUX#if defined(I386) long eip;#elif defined(POWERPC) long pc;#elif defined(M68K) long pc;#elif defined(ALPHA) long pc;#elif defined(HPPA) long iaoq;#endif /* architecture */#ifdef SPARC /* Again, we borrow the SunOS breakpoint code. */ if (!(tcp->flags & TCB_BPTSET)) { fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid); return -1; } errno = 0; ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]); if(errno) { perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)"); return -1; } tcp->flags &= ~TCB_BPTSET;#elif defined(IA64) { unsigned long addr, ipsr; pid_t pid; pid = tcp->pid; if (upeek(pid, PT_CR_IPSR, &ipsr) < 0) return -1; if (upeek(pid, PT_CR_IIP, &addr) < 0) return -1; /* restore original bundle: */ errno = 0; ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]); ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]); if (errno) { perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)"); return -1; } /* restore original "ri" in ipsr: */ ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41); errno = 0; ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr); if (errno) { perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)"); return -1; } tcp->flags &= ~TCB_BPTSET; if (addr != (tcp->baddr & ~0x3)) { /* the breakpoint has not been reached yet. */ if (debug) fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n", addr, tcp->baddr); return 0; } }#else /* !IA64 && ! SPARC */ if (debug) fprintf(stderr, "[%d] clearing bpt\n", tcp->pid); if (!(tcp->flags & TCB_BPTSET)) { fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid); return -1; } errno = 0; ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]); if (errno) { perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)"); return -1; } tcp->flags &= ~TCB_BPTSET;#ifdef I386 if (upeek(tcp->pid, 4*EIP, &eip) < 0) return -1; if (eip != tcp->baddr) { /* The breakpoint has not been reached yet. */ if (debug) fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n", eip, tcp->baddr); return 0; }#elif defined(POWERPC) if (upeek(tcp->pid, 4*PT_NIP, &pc) < 0) return -1; if (pc != tcp->baddr) { /* The breakpoint has not been reached yet. */ if (debug) fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n", pc, tcp->baddr); return 0; }#elif defined(M68K) if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) return -1; if (pc != tcp->baddr) { /* The breakpoint has not been reached yet. */ if (debug) fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n", pc, tcp->baddr); return 0; }#elif defined(ALPHA) if (upeek(tcp->pid, REG_PC, &pc) < 0) return -1; if (pc != tcp->baddr) { /* The breakpoint has not been reached yet. */ if (debug) fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n", pc, tcp->baddr); return 0; }#elif defined(HPPA) if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0) return -1; iaoq &= ~0x03; if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) { /* The breakpoint has not been reached yet. */ if (debug) fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n", iaoq, tcp->baddr); return 0; } iaoq = tcp->baddr | 3; /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit * has no significant effect. */ ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq); ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);#endif /* arch */#endif /* !SPARC && !IA64 */#endif /* LINUX */#ifdef SUNOS4#ifdef SPARC#if !LOOPA struct regs regs;#endif if (!(tcp->flags & TCB_BPTSET)) { fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid); return -1; } if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr, sizeof tcp->inst, (char *) tcp->inst) < 0) { perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)"); return -1; } tcp->flags &= ~TCB_BPTSET;#if !LOOPA /* * Since we don't have a single instruction breakpoint, we may have * to adjust the program counter after removing the our `breakpoint'. */ if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) { perror("clearbpt: ptrace(PTRACE_GETREGS, ...)"); return -1; } if ((regs.r_pc < tcp->baddr) || (regs.r_pc > tcp->baddr + 4)) { /* The breakpoint has not been reached yet */ if (debug) fprintf(stderr, "NOTE: PC not at bpt (pc %#x baddr %#x)\n", regs.r_pc, tcp->parent->baddr); return 0; } if (regs.r_pc != tcp->baddr) if (debug) fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n", regs.r_pc, tcp->baddr); regs.r_pc = tcp->baddr; if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) { perror("clearbpt: ptrace(PTRACE_SETREGS, ...)"); return -1; }#endif /* LOOPA */#endif /* SPARC */#endif /* SUNOS4 */ return 0;}#endif /* !USE_PROCFS */#ifdef SUNOS4static intgetex(pid, hdr)int pid;struct exec *hdr;{ int n; for (n = 0; n < sizeof *hdr; n += 4) { long res; if (upeek(pid, uoff(u_exdata) + n, &res) < 0) return -1; memcpy(((char *) hdr) + n, &res, 4); } if (debug) { fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n", hdr->a_magic, hdr->a_toolversion, hdr->a_machtype); fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n", hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry); } return 0;}intfixvfork(tcp)struct tcb *tcp;{ int pid = tcp->pid; /* * Change `vfork' in a freshly exec'ed dynamically linked * executable's (internal) symbol table to plain old `fork' */ struct exec hdr; struct link_dynamic dyn; struct link_dynamic_2 ld; char *strtab, *cp; if (getex(pid, &hdr) < 0) return -1; if (!hdr.a_dynamic) return -1; if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) { fprintf(stderr, "Cannot read DYNAMIC\n"); return -1; } if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) { fprintf(stderr, "Cannot read link_dynamic_2\n"); return -1; } if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) { fprintf(stderr, "fixvfork: out of memory\n"); return -1; } if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr), (int)ld.ld_symb_size, strtab) < 0) goto err;#if 0 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) { fprintf(stderr, "[symbol: %s]\n", cp); cp += strlen(cp)+1; } return 0;#endif for (cp = strtab; cp < strtab + ld.ld_symb_size; ) { if (strcmp(cp, "_vfork") == 0) { if (debug) fprintf(stderr, "fixvfork: FOUND _vfork\n"); strcpy(cp, "_fork"); break; } cp += strlen(cp)+1; } if (cp < strtab + ld.ld_symb_size) /* * Write entire symbol table back to avoid * memory alignment bugs in ptrace */ if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr), (int)ld.ld_symb_size, strtab) < 0) goto err; free(strtab); return 0;err: free(strtab); return -1;}#endif /* SUNOS4 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -