int main (int argc, char **argv) { // The debugger should be run as: // $ ./ssedb <file> // and this "if" checks this. if (argc<2) usage (); pid = fork (); // In the child if (0 == pid){ ptrace (PTRACE_TRACEME, 0, 0, 0); execve (argv[1], argv+1, 0); return; } // in the parent else{ // wait the child to stop. waitChild (); printf ("A minimal ptrace-based dubugger, copyright (C) 2012, by SSE of USTC.\n" "Now debugging: %s (pid: %d)\n", argv[1], pid); // now, the debugger is ready to read commands in // and handle them, repeatedly. loopCommand (); } return 0; }
int editconstraints(char *scriptfile) { int retvalue = 0; #if 0 char *editor, *defaulteditor; #define defaultXeditor "/usr/local/bin/nedit" #define defaultTeditor "/usr/bin/vi" if (scriptfile != NULL) { while (*scriptfile != 0 && isspace(*scriptfile)) scriptfile++; if (*scriptfile != 0 && prepScriptfile(scriptfile)) { pid_t child; defaulteditor = (getenv("DISPLAY") == NULL) ? defaultTeditor : defaultXeditor; editor = getenv("EDITOR"); if (editor == NULL) editor = defaulteditor; child = fork(); switch (child) { case 0: /* I am the child */ if ( launchEditor(editor, scriptfile) == -1 && editor != defaulteditor && launchEditor(defaulteditor, scriptfile) == -1 ) { printf("Failed to launch editor: %s: %s\n", editor, strerror(errno)); exit(errno); } break; /* gratuitous */ case -1: /* Failure */ printf("Cannot edit %s\n", scriptfile); break; default: /* Success. I am the parent */ retvalue = waitChild(child); } } else retvalue = 1; } else retvalue = 1; #endif return retvalue; }
int makeconstrain(char *scriptfile, char *objectfile) { int failure = 1; #if 0 pid_t child; if (scriptfile != NULL && objectfile != NULL) { while (*scriptfile != 0 && isspace(*scriptfile)) scriptfile++; while (*objectfile != 0 && isspace(*objectfile)) objectfile++; if (*scriptfile != 0 && *objectfile != 0) { sprintf(idparam, "0x%08lx", MAJOR | MINOR); if (makeBinary == NULL) makeBinary = getenv("MLAYER_CONSTRAINTS"); if (makeBinary == NULL) makeBinary = makeBinaryDefault; makeargv[0] = makeBinary; makeargv[1] = scriptfile; makeargv[2] = objectfile; makeargv[3] = idparam; makeargv[4] = prototype; child = fork(); switch (child) { case 0: /* I am the child */ if (execvp(makeBinary, makeargv) == -1) { printf("Cannot load strain compiler %s: %s\n", makeBinary, strerror(errno)); exit(errno); } break; /* gratuitous */ case -1: /* Failure */ printf("Cannot load strain compiler %s: %s\n", makeBinary, strerror(errno)); break; default: /* Success. I am the parent */ failure = waitChild(child); } } } #endif return failure; }
// Given a command and execute it. static void execCommand (Cmd_t c) { switch (c->kind){ case CMD_KIND_BREAK:{ int brk = 0x000000cc; int data; data = ptrace(PTRACE_PEEKDATA, pid, c->u.addr, 0); printf ("init data = %x\n", data); data = (data &0xffffff00) | brk; printf ("revised data = %x\n", data); ptrace(PTRACE_POKEDATA, pid, c->u.addr, data); ptrace(PTRACE_CONT, pid, 0, 0); waitChild (); return; } case CMD_KIND_CONT:{ ptrace(PTRACE_CONT, pid, 0, 0); waitChild (); return; } case CMD_KIND_FILE:{ kill (pid, SIGKILL); pid = fork (); if (0==pid){ ptrace (PTRACE_TRACEME, 0, 0, 0); execve (c->u.filename, &c->u.filename, 0); } else{ waitChild (); printf ("loading: %s (pid: %d)\n", c->u.filename, pid); return; } return; } case CMD_KIND_QUIT:{ int c; L: printf ("ssedb is quiting. Are you sure? (y|n) "); c = getchar (); if ('y'==c || 'Y'==c){ kill (pid, SIGKILL); exit (0); } else if ('n'==c || 'N'==c){ getchar (); return; } else { printf("\n"); goto L; } return; } case CMD_KIND_REGS:{ struct user_regs_struct regs; ptrace (PTRACE_GETREGS, pid, 0, ®s); printf ("eax = %ld\n" "ebx = %ld\n" "ecx = %ld\n" "edx = %ld\n" "esi = %ld\n" "edi = %ld\n" "esp = 0x%p\n" "ebp = 0x%p\n" "eip = 0x%p\n", regs.eax, regs.ebx, regs.ecx, regs.edx, regs.esi, regs.edi, (char *)regs.esp, (char *)regs.ebp, (char *)regs.eip); return; } case CMD_KIND_RUN:{ ptrace(PTRACE_DETACH, pid, 0, 0); waitChild (); return; } case CMD_KIND_SI:{ ptrace(PTRACE_SINGLESTEP, pid, 0, 0); return; } case CMD_KIND_XI:{ TODO; return; } case CMD_KIND_XX:{ // By default, we disassemble 40 bytes int i; int addr = c->u.addr; for (i=0; i<10; i++){ int data = ptrace(PTRACE_PEEKDATA, pid, addr, 0); printf ("%x: %x\n", addr, data); addr += 4; } return; } default: printf ("Unknown command: ssedb bug!\n"); return; } }
void run(int argc, char *argv[]) { int i, j; int array[16]; switch (testID) { case 0: if (processID == 0) { restart(); childWait(); for (i=0; i<1024; i++); ag2(-1,1); agDone(); } else { ag2(-1,2); parentSignal(); exit(0); } break; case 1: if (processID == 0) { for (i=0; i<16; i++) { array[i] = restart(); childWait(); } for (i=0; i<16; i++) for (j=0; j<16; j++) assert(i==j || array[i]!=array[j]); agDone(); } else { parentSignal(); exit(0); } break; case 2: if (processID == 0) { restart(); restart(); childWait(); exit(0); } else if (processID == 1) { parentSignal(); for (i=0; i<1024; i++); parentSignal(); exit(0); } else { childWait(); for (i=0; i<1024; i++); agDone(); } break; case 3: if (processID == 0) { i = restart(); assert(join(i, &j) == 1); assert(j == agLoad(valRandom)); agDone(); } else { exit(agLoad(valRandom)); } break; case 4: assert(exec("abcdefghijklmnopqrstuvwxyz", 0, null) == -1); agDone(); break; case 5: switch (processID) { case 0: restart(); childWait(); assert(join(agLoad(valChildProcessID), &j) == 1); assert(j == 0); agDone(); break; case 1: restart(); agStore(valChildProcessID, restart()); parentSignal(); break; case 2: exit(0); break; case 3: exit(agLoad(valRandom)); break; } break; case 6: if (processID == 0) { array[0] = (int) "this"; array[1] = (int) "is-dumb"; assert(exec(shellProgramName, 2, (char**) array) != -1); exit(0); } else { assert(argc == 2 && strcmp(argv[0], "this")==0 && strcmp(argv[1], "is-dumb")==0); agDone(); } break; case 7: for (i=0; i<8; i++) array[i] = (int) big; assert(exec(shellProgramName, 8, (char**) array) == -1); break; case 11: /* make lots of child processes */ if (processID == 0) { for (i=0; i<20; i++) { restart(); waitChild(); } agDone(); } else { signalParent(); exit(0); } break; } agFail(); }