Exemplo n.º 1
0
/* Add a breakpoint without using a script command */
int		e2dbg_breakpoint_add(eresi_Addr addr)
{
  int		err;
  char		buf[BUFSIZ];
  char		*name;
  elfsh_SAddr	off;
  elfshobj_t	*file;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  /* Resolve source file */
  file = e2dbg_get_parent_object(addr);
  if (file == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
		      "Cannot resolve parent file for bp", -1);

  /* Resolve breakpoint address */
  name = revm_resolve(file, addr, &off);
  if (off)
    snprintf(buf, BUFSIZ, "<%s + " DFMT ">", name, off);
  else
    snprintf(buf, BUFSIZ, "<%s>", name);

  /* Really put the breakpoint */
  err = elfsh_bp_add(&e2dbgworld.bp, file, buf, addr);
  if (err < 0)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Cannot add breakpoint", -1);
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}
Exemplo n.º 2
0
/**
 * The Real routine that handles each thread-specific breakpoint state machine.
 * 
 * breakpoint case:
 * 
 * 0-1: restore old instr, enable step, set bp addr in ->past, reset pc to orig bp addr
 * 1-2: do nothing (just executed instr)
 * 2-3: reinstall, resetstep, thread_contall, curthread->was_step = 0, 
 *     stoppedthread->count = NONE; e2dbgworld.curbp = NULL; stoppedthread = RUNNING
 *
 * stepping case:
 * 
 * 0-1: print current instr; reinstall
 *      stoppedthread->state = BREAKING; thread_contall; 
 *      was_step = 0; count = NONE; curbp = NULL; stoppedthread->state = RUNNING
 */
void			e2dbg_breakpoint_process()
{
  char			buf[32];
  elfshbp_t		*bp;
  int			prot;
  char			*name;
  elfsh_SAddr		off;
  int			ret;
  asm_instr		ptr;
  char			*s;
  eresi_Addr		*pc; 
  eresi_Addr		savedpc;
  u_int			bpsz;
  elfshsect_t		*sect;
  elfshobj_t		*parent;
  elfsh_Sym		*sym;

#if __DEBUG_BP__
  fprintf(stderr, " [D] Entering breakpoint handler\n");
#endif

  /* Set all registers as variables and get PC */
  e2dbg_user_hooks_install();
  e2dbg_getregs(); 
  pc = e2dbg_getpc();

  parent = e2dbg_get_parent_object((eresi_Addr) *pc);
  bpsz = elfsh_get_breaksize(parent);

  /* Print variables and registers on breakpoints */
  //if (!world.state.revm_quiet)
  //cmd_vlist();

  /* Try to find the breakpoint at current instruction pointer */
#if __DEBUG_BP__
  fprintf(stderr, " [D] At PC = %08X : Trying to find breakpoint at addr %08X (bpsize = %u)\n", 
	  *pc, *pc - bpsz, bpsz);
#endif

  snprintf(buf, sizeof(buf), XFMT, *pc - bpsz);
  bp = hash_get(&e2dbgworld.bp, buf);

#if __DEBUG_BP__
  if (bp)
    fprintf(stderr, " [D] Saved instruction BYTE = %02X and PC-BPSZ BYTE = %02X \n",
	    bp->savedinstr[0], *((u_char *) *pc - bpsz));
  else
    fprintf(stderr, " [D] No BP found at %08X ! \n", *pc);
#endif

  /* Case of processing breakpoint, or if we are single-stepping */
  if (!bp || (bp->savedinstr[0] == *((u_char *) *pc - bpsz)))
    {

      /* We are single-stepping, display the instruction at $pc */
      if (e2dbgworld.stoppedthread->step)
	{

#if __DEBUG_BP__
	  fprintf(stderr, " [D] Single-stepping -IS- enabled \n");
#endif

	  ret = asm_read_instr(&ptr, (u_char *) *pc, 16, world.curjob->proc);
	  if (!ret)
	    ret++;
	  sect   = elfsh_get_parent_section(parent, (eresi_Addr) *pc, NULL);
	  name   = revm_resolve(parent, (eresi_Addr) *pc, &off);
	  off = 0;
	  sym    = elfsh_get_metasym_by_value(parent, (eresi_Addr) *pc, 
					      &off, ELFSH_LOWSYM);

#if __DEBUG_BP__
	  fprintf(stderr, 
		  " [D] Found parent = %08X (%s) in step (name = %s, parentsect = %s) off = %u\n", 
		  (eresi_Addr) parent, parent->name, name, sect->name, off);
#endif

	  revm_instr_display(-1, *pc, 0, 20, name, off, (char *) *pc);
	  e2dbg_display(e2dbgworld.displaycmd, e2dbgworld.displaynbr);
	  if (!e2dbgworld.stoppedthread->trace)
	    e2dbg_entry(NULL);
	  else
	    e2dbg_watch();

	  e2dbg_breakpoint_reinstall();
	  return;
	}

#if __DEBUG_BP__
      fprintf(stderr, " [D] Single-stepping is -NOT- enabled \n");
#endif

      /* Here starts the real stuff 
      **
      ** count == E2DBG_BREAK_EXEC     -> execute restored instruction
      ** count == E2DBG_BREAK_FINISHED -> restore breakpoint
      ** count >  E2DBG_BREAK_MAX      -> e2dbg is getting debugged by a third party debugger
      */
      e2dbgworld.stoppedthread->count++;	
      
#if __DEBUG_BP__
      fprintf(stderr, " [C] Count %u -> %u for thread ID %u \n", 
	     e2dbgworld.stoppedthread->count - 1, 
	     e2dbgworld.stoppedthread->count, 
	     ((unsigned int) e2dbgworld.stoppedthread->tid));
#endif
      
      /* execute the previously restored instruction */
      if (e2dbgworld.stoppedthread->count == E2DBG_BREAK_EXEC)
	{
#if __DEBUG_BP__
	  printf(" [D] At PC = 0x%X : Debuggee executed restored instruction \n", *pc);
#endif
	  return;
	}
      
      /* Suggested by andrewg, useful when debugging valgrind */
      if (e2dbgworld.stoppedthread->count > E2DBG_BREAK_MAX)
	{
	  printf(".::- E2DBG WARNING -::.\n"
		 "Breakpoint triggered at location " AFMT " which we don't know about.\n\n"
		 "This may be an anti-debug trick or the program may be inside another\n"
		 "debugger. Exiting (DEBUG: count = " UFMT ", step is off)\n\n",
		 *pc - bpsz, e2dbgworld.stoppedthread->count);
	  return;
	}

      e2dbg_breakpoint_reinstall();
      
      /* remove trace flag */	  
#if __DEBUG_BP__
      fprintf(stderr, " [D] At PC = " AFMT " Resetting STEP mode\n", *pc);
#endif
      e2dbg_resetstep();
      return;
    }

  /* Case of newly hit breakpoint */
  else
    {
      name = revm_resolve(parent, (eresi_Addr) *pc - bpsz, &off);
      s    = (e2dbg_is_watchpoint(bp) ? "Watch" : "Break");

#if __DEBUG_BP__
      fprintf(stderr, " [C] Count set to 1 (HIT) for thread ID %u \n", 
		(unsigned int) e2dbgworld.stoppedthread->tid);
#endif      
      
      if (off)
	printf(" [*] %spoint found at " XFMT " <%s + " DFMT "> in thread %u \n\n", 
	       s, *pc - bpsz, name, off, (unsigned int) e2dbgworld.stoppedthread->tid);
      else 
	printf(" [*] %spoint found at " XFMT " <%s> in thread %u \n\n",   
	       s, *pc - bpsz, name, (unsigned int) e2dbgworld.stoppedthread->tid);

      revm_doswitch(parent->id);
      mjr_set_current_context(&world.mjr_session, parent->name);
      
      *pc -= bpsz;
      prot = elfsh_munprotect(bp->obj, *pc,  bpsz);
      memcpy((u_char *) *pc, bp->savedinstr, bpsz);
      elfsh_mprotect(bp->obj, *pc, bpsz, prot);

      e2dbg_setstep();

#if __DEBUG_BP__
      fprintf(stderr, " [D] Setting Step mode \n");
#endif

      e2dbgworld.stoppedthread->past  = *pc;
      e2dbgworld.stoppedthread->count = E2DBG_BREAK_HIT;
      e2dbgworld.curbp                = bp;
      bp->tid                         = (uint32_t) e2dbgworld.stoppedthread->tid;

#if __DEBUG_BP__
      fprintf(stderr, " [D] Reset break \n");
#endif

      if (bp->cmdnbr)
	e2dbg_display(bp->cmd, bp->cmdnbr);
      else
	e2dbg_display(e2dbgworld.displaycmd, e2dbgworld.displaynbr);

#if __DEBUG_BP__
      fprintf(stderr, " [D] After BP display \n");
#endif

#if __DEBUG_BP__
      fprintf(stderr, " [D] PC before entry is addr 0x%X \n", *pc);
#endif
      
      savedpc = *pc;
      e2dbg_entry(NULL);
      *pc = savedpc;

#if __DEBUG_BP__
      fprintf(stderr, " [D] At PC = 0x%X : returned from BP handler with step enabled\n",
	      *pc);
#endif
    }
}