⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trace-x86.c

📁 It s a Linux disassemble, can set break point, disassemble ELF file.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * libDebug * * Copyright (C) 2000 Patrick Alken * This library comes with absolutely NO WARRANTY * * Should you choose to use and/or modify this source code, please * do so under the terms of the GNU General Public License under which * this library is distributed. * * $Id: trace-x86.c,v 1.6 2004/10/09 17:34:15 pa33 Exp $ */#include <stdio.h>#include <stdlib.h>#include <assert.h>#include <sys/time.h>#include <sys/types.h>#include <sys/wait.h>#include <sys/ptrace.h>#include <signal.h>#include <unistd.h>#include <errno.h>#include <string.h>/* * Top-level includes */#include "args.h"#include "break.h"#include "libDebug.h"static int x86GetDebugProcessStatus(struct debugWorkspace *ws,                                    int ptfunc, int waitval,                                    int *data);static int x86DoSingleStep(struct debugWorkspace *ws, int *data);static int x86DoContinue(struct debugWorkspace *ws, int *data);/*x86execDebug()  Start execution of the debugged processInputs: ws - debug workspaceReturn: 2 if file is not executable        1 if successful        0 if notSide effects: DebugPid is assigned to the pid of the traced              process*/intx86execDebug(struct debugWorkspace *ws){  pid_t pid;  int waitval;  int err;  assert(ws->path != 0);  if (dbIsRedirect(ws))  {    if (pipe(ws->pipes) == (-1))      return (0);  }  pid = fork();  if (pid == (-1))  {    if (dbIsRedirect(ws))    {      close(ws->pipes[0]);      close(ws->pipes[1]);    }    return (0);  }  else if (pid == 0)  {    /*     * Child: allow parent to trace us     */    if (ptrace(PT_TRACE_ME, 0, 0, 0) != 0)      exit(0);    assert(ws->args && ws->args[0]);    if (dbIsRedirect(ws))    {      /*       * Redirect child's stdout and stderr to the parent's pipe       */      dup2(ws->pipes[1], 1);      dup2(ws->pipes[1], 2);      /*       * Redirect child's stdin to come from parent's pipe       */      /* dup2(ws->pipes[1], 0); */      /*       * Close file descriptors       */      close(ws->pipes[0]);      close(ws->pipes[1]);    }#if 0    if (ws->args)    {      printf("arg1 ==== %s\n", ws->args[1]);    }#endif    execv(ws->path, ws->args);    /*     * If we get here the execv() returned -1 and it is most likely     * an ENOEXEC - exiting now should alert the parent process that     * something went wrong     */    exit(0);  }  else  {    /*     * Parent process     */    ws->pid = pid;    /*     * wait for child to stop (execv)     */    wait(&waitval);    /*     * Set the instruction pointer to the program's entry point     */    err = 0;    ws->instructionPointer = x86getCurrentInstruction(ws, &err);    if (err)    {      /*       * The most likely cause of this is that the file is not       * executable       */      ws->pid = NOPID;      return (2);    }    dbSetRunning(ws);  }  return (1);} /* x86execDebug() *//*x86GetDebugProcessStatus()Inputs: ws      - debug workspace        ptfunc  - ptrace flag (PT_STEP or PT_CONTINUE)        waitval - value containing process status        data    - modified to contain data depending on process                  statusReturn: 0 if something goes wrong        1 if everything is successful        2 if program stops due to a signal (signal num goes in data)        3 if program encounters a breakpoint (brk pt num goes in data)        4 if program terminates normally (exit status goes in data)        5 if program writes to stdout or stderr and we are          redirecting output - the calling function can read the          output using GetDebugOutput()        6 (do not use)        7 if program terminates due to a signal (signal number goes in data)*/static intx86GetDebugProcessStatus(struct debugWorkspace *ws, int ptfunc,                         int waitval, int *data){  int sig;  if (WIFEXITED(waitval))  {    /*     * Process exited normally     */    endDebug(ws);    *data = WEXITSTATUS(waitval);    /*     * When a program exits, it sends two signals to the parent -     * one for the exit status and the other is a SIGCHLD, so     * make sure we catch the second.     */    wait(&waitval);    return (4);  }  else if (WIFSTOPPED(waitval))  {    sig = WSTOPSIG(waitval);    if (sig == SIGTRAP)    {      unsigned long addr;      struct Breakpoint *bptr;      /*       * InstructionPointer should be set appropriately by the       * calling function       */      addr = ws->instructionPointer;      if (ptfunc == PT_STEP)      {        /*         * A SIGTRAP is generated after every singlestep call         * so check before declaring it a user-defined breakpoint         */        if ((bptr = findBreakpoint(ws, addr)))        {          if (bptr->flags & BK_STEPOVER)            printf("HIT A STEP OVER BRKPT\n");          *data = bptr->number;          if (bptr->ignorecnt > 0)          {            /*             * Ignore this breakpoint for now and continue             * running the process             */            --bptr->ignorecnt;            return (1);          }          /*           * Check if breakpoint should be deleted           */          checkBreakpoint(ws, bptr);          dbSetHitBreakpoint(ws);          return (3);        }        /*         * If we get here, the SIGTRAP is the normal response         * after the cpu set the trap flag for singlestepping         */      } /* if (ptfunc == PT_STEP) */      else if (ptfunc == PT_CONTINUE)      {        /*         * We stopped exactly one byte after the breakpoint         * instruction - go back one         */        --addr;        bptr = findBreakpoint(ws, addr);        if (!bptr)        {          /*           * It appears to be a SIGTRAP which we did not set -           * this is rare, but possible.           */          *data = sig;          /*           * Do not pass this signal to the program on the next           * ptrace since it will cause the program to terminate           */          /*ws->lastSignal = sig;*/          return (2);        }        /*         * Set eip to the real address         */        x86setCurrentInstruction(ws, addr);        if (bptr->ignorecnt > 0)        {          /*           * Ignore this breakpoint for now and continue           * running the process           */          --bptr->ignorecnt;          return (1);        }        if (bptr->flags & BK_STEPOVER)          *data = 0;        else          *data = bptr->number;        /*         * Check to see if this breakpoint should be deleted         */        checkBreakpoint(ws, bptr);        dbSetHitBreakpoint(ws);        return (3);      } /* if (ptfunc == PT_CONTINUE) */    } /* if (sig == SIGTRAP) */    else    {      *data = sig;      /*       * If we received a SIGINT, do not pass it to the process the       * next time we continue ptracing, because it was probably       * caused by the user debugging the process       */      if (sig != SIGINT)        ws->lastSignal = sig;      return (2);    }  } /* else if (WIFSTOPPED(waitval)) */  else if (WIFSIGNALED(waitval))  {    /*     * Program terminated due to a signal     */    *data = WTERMSIG(waitval);    return (7);  }  /*   * Everything is normal   */  return (1);} /* x86GetDebugProcessStatus() *//*x86DoSingleStep()  Singlestep one instruction in the process being debuggedInputs: ws   - debug workspace        data - modified to contain info depending on the return               resultReturn: 0 if something goes wrong        1 if everything is successful        2 if program stops due to a signal (signal num goes in data)        3 if program encounters a breakpoint (brk pt num goes in data)        4 if program terminates normally (exit status goes in data)        5 if program writes to stdout or stderr and we are          redirecting output - the calling function can read the          output using GetDebugOutput()*/static intx86DoSingleStep(struct debugWorkspace *ws, int *data){  int waitval;  int err;  assert(ws->pid != NOPID);  if (ptrace(PT_STEP, ws->pid, CONTADDR, ws->lastSignal) != 0)    return (0); /* something went wrong */  /*   * Clear the last signal   */  ws->lastSignal = 0;  /*   * Wait for child to stop   */  wait(&waitval);  err = 0;  ws->instructionPointer = x86getCurrentInstruction(ws, &err);  return (x86GetDebugProcessStatus(ws, PT_STEP, waitval, data));} /* x86DoSingleStep() *//*x86DoContinue()  Continue the process being debuggedInputs: ws   - debug workspace        data - modified to contain info depending on the return               resultReturn: 0 if something goes wrong        1 if everything is successful        2 if program stops due to a signal (signal num goes in data)        3 if program encounters a breakpoint (brk pt num goes in data)        4 if program terminates normally (exit status goes in data)        5 if program writes to stdout or stderr and we are          redirecting output - the calling function can read the          output using GetDebugOutput()        6 (don't use)        7 if program terminates due to a signal (signal num goes in data)Special note about breakpoints:  If this function is invoked from x86SingleStepOver(), it ispossible that we will run into a temporary breakpoint markedwith BK_STEPOVER. Since this breakpoint was set by x86SingleStepOver()and not by the user, it does not have a legitimate breakpoint number,and so the special value of 0 will be placed into 'data' indicatingto x86SingleStepOver() that it's temporary breakpoint was reached.*/static intx86DoContinue(struct debugWorkspace *ws, int *data){  int waitval;  int ret;  int err;  pid_t wret;  assert(ws->pid != NOPID);  if (dbHitBreakpoint(ws))  {    dbClearHitBreakpoint(ws);    /*     * We just hit a breakpoint on the previous ptrace() call,     * and the user wants to continue from the break address.     * We will singlestep past the breakpoint address, then     * re-enable breakpoints and continue normally     */    ret = x86DoSingleStep(ws, data);    if (ret != 1)      return (ret); /* something stopped the process */  }  /*   * An infinite loop is needed to handle cases where breakpoints   * have an ignore count - we'll want to continue the process   * without notifying the user that the breakpoint was hit.   */  while (1)  {    /*     * Enable all breakpoints     */    enableBreakpoints(ws);    /*fprintf(stderr, "lastsig = %d\n", ws->lastSignal);*/    if (ptrace(PT_CONTINUE, ws->pid, CONTADDR, ws->lastSignal) != 0)      return (0); /* something went wrong */    /*     * Wait for child to stop     */    wret = wait(&waitval);    /*fprintf(stderr, "wret = %d\n", wret);*/    /*     * Disable all breakpoints     */    disableBreakpoints(ws);    /*     * Clear last signal     */    ws->lastSignal = 0;    err = 0;    ws->instructionPointer = x86getCurrentInstruction(ws, &err);    ret = x86GetDebugProcessStatus(ws, PT_CONTINUE, waitval, data);    if (ret != 1)    {      /*       * Something stopped the program (breakpoint, signal, exit, etc)       */      return (ret);    }    /*     * If we get here it we most likely hit a breakpoint which     * was ignored, so singlestep past the breakpoint instruction     * and continue tracing the process     */    ret = x86DoSingleStep(ws, data);    if (ret != 1)      return (ret); /* something stopped the process */  } /* while (1) */} /* x86DoContinue() *//*x86stepIntoDebug()  Single step our program, stepping into any subroutinesInputs: ws   - debug workspace        num  - number of instructions to step through        data - modified to contain info depending on the return               result, see belowReturn: 0 if unsuccessful        1 if successful        2 if program stops due to a signal        3 if breakpoint is encountered        4 if program terminatesSide effects: If the process stops due to a signal, data is              modified to contain the signal number.              If the process hits a breakpoint, the breakpoint              number is put into data              If the process terminates normally, data is modified              to contain the exit status.*/intx86stepIntoDebug(struct debugWorkspace *ws, int num, int *data){  int ii;  int ret;  assert(num > 0);  if (ws->pid == NOPID)  {    ret = x86execDebug(ws);    if (ret == 2)      return (6); /* not an executable file */    else if (ret == 0)      return (0); /* something went wrong */  }  dbSetRunning(ws);  for (ii = 0; ii < num; ++ii)  {    /*     * Perform single step     */    ret = x86DoSingleStep(ws, data);    if (ret != 1)    {      /*       * Something stopped the process (signal, breakpoint, exit, etc)       */      return (ret);    }  } /* for (ii = 0; ii < num; ++ii) */  /*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -