Exemplo n.º 1
0
static void gdb_read_command()
{
  u8 c;
  u8 chk_read, chk_calc;

  cmd_len = 0;
  memset(cmd_bfr, 0, sizeof cmd_bfr);

  c = gdb_read_byte();
  if (c == '+')
  {
    // ignore ack
    return;
  }
  else if (c == 0x03)
  {
    CPU::Break();
    gdb_signal(GDB_SIGTRAP);
    return;
  }
  else if (c != GDB_STUB_START)
  {
    DEBUG_LOG(GDB_STUB, "gdb: read invalid byte %02x", c);
    return;
  }

  while ((c = gdb_read_byte()) != GDB_STUB_END)
  {
    cmd_bfr[cmd_len++] = c;
    if (cmd_len == sizeof cmd_bfr)
    {
      ERROR_LOG(GDB_STUB, "gdb: cmd_bfr overflow");
      gdb_nak();
      return;
    }
  }

  chk_read = hex2char(gdb_read_byte()) << 4;
  chk_read |= hex2char(gdb_read_byte());

  chk_calc = gdb_calc_chksum();

  if (chk_calc != chk_read)
  {
    ERROR_LOG(GDB_STUB,
              "gdb: invalid checksum: calculated %02x and read %02x for $%s# (length: %d)",
              chk_calc, chk_read, cmd_bfr, cmd_len);
    cmd_len = 0;

    gdb_nak();
    return;
  }

  DEBUG_LOG(GDB_STUB, "gdb: read command %c with a length of %d: %s", cmd_bfr[0], cmd_len, cmd_bfr);
  gdb_ack();
}
Exemplo n.º 2
0
int gdb_trap(struct trap_state *ts)
{
	struct gdb_state r;
	int signo, orig_signo;
	oskit_u32_t pc;

	if (gdb_signal == 0)
		return -1;

	/* If a recovery address has been set,
	   use it and return immediately.  */
	if (gdb_trap_recover)
	{
		ts->pc = gdb_trap_recover;
		return 0;
	}
	pc = ts->pc;

	/* Convert the arm32 trap code into a generic signal number.  */
	/* XXX some of these are probably not really right.  */
	switch (ts->trapno)
	{
#define TRAP(trap, sig, adjust) case trap: signo = sig; pc += adjust; break
		TRAP(-1,		SIGINT,   0);
		TRAP(T_SWI,		SIGEMT,  -4);
		TRAP(T_PREFETCH_ABORT,	SIGSEGV, -4);
		TRAP(T_DATA_ABORT,	SIGSEGV, -8);
		TRAP(T_ADDREXC,		SIGSEGV, -4);
		TRAP(T_FIQ,		SIGTRAP, -4);
		TRAP(T_STACK_OVERFLOW,	SIGBUS,  -8);
	case T_UNDEF:
		/*
		 * Check for GDB breakpoint
		 */
		if (*((unsigned *) (ts->pc - 4)) == 0xe7ffdefe) {
			signo = SIGTRAP;
			pc -= 4;
		}
		else if (*((unsigned *) (ts->pc - 4)) == 0xe7ffdefd) {
			/* See gdb_set_bkpt() */
			signo = SIGTRAP;
		}
		else {
			signo = SIGILL;
			pc -= 4;
		}
		break;
	default:
		signo = SIGEMT;         /* "software generated"*/
#undef	TRAP
	}
	orig_signo = signo;

	/* Convert the trap state into GDB's format.  */
	memset((void *) &r, 0, sizeof(r));
	r.r0   = ts->r0;
	r.r1   = ts->r1;
	r.r2   = ts->r2;
	r.r3   = ts->r3;
	r.r4   = ts->r4;
	r.r5   = ts->r5;
	r.r6   = ts->r6;
	r.r7   = ts->r7;
	r.r8   = ts->r8;
	r.r9   = ts->r9;
	r.r10  = ts->r10;
	r.r11  = ts->r11;
	r.r12  = ts->r12;
	r.ps   = ts->spsr;
	r.pc   = pc;

	/*
	 * XXX Not bothering with user mode stuff
	 */
	r.sp   = ts->svc_sp;
	r.lr   = ts->svc_lr;

	/* Call the appropriate GDB stub to do its thing.  */
	gdb_signal(&signo, &r);

	/* Stuff GDB's modified state into our trap_state.  */
	ts->r0     = r.r0;
	ts->r1     = r.r1;
	ts->r2     = r.r2;
	ts->r3     = r.r3;
	ts->r4     = r.r4;
	ts->r5     = r.r5;
	ts->r6     = r.r6;
	ts->r7     = r.r7;
	ts->r8     = r.r8;
	ts->r9     = r.r9;
	ts->r10    = r.r10;
	ts->r11    = r.r11;
	ts->r12    = r.r12;
	ts->pc     = r.pc;
	ts->svc_lr = r.lr;

	/*
	 * XXX Not bothering with user mode stuff
	 */
	{
		/* XXX currently we don't know how to change the kernel esp.
		   We could do it by physically moving the trap frame.  */
		if (r.sp != (unsigned)ts->svc_sp)
			panic("gdb_trap: can't change stack pointer");
	}

	if (r.ps != ts->spsr)
		panic("gdb_trap: can't change PSR: 0x%x 0x%x", r.ps, ts->spsr);

	/* If GDB sent us back a signal number,
	   convert that back into a trap number.  */
	if (signo != 0)
	{
		/* If the signal number was unchanged from what we sent,
		   leave the trap number unchanged as well.  */
		if (signo == orig_signo)
			return -1;

		/* Otherwise, try to guess an appropriate trap number.
		   We can't do much, but try to get the common ones.
		   If we can't make a decent guess,
		   just leave the trap number unchanged.  */
		switch (signo)
		{
			case SIGTRAP:	ts->trapno = T_UNDEF; break;
			case SIGILL:	ts->trapno = T_UNDEF; break;
			case SIGSEGV:	ts->trapno = T_DATA_ABORT;
					break;
		}

		return -1;
	}

	/* GDB consumed the signal - just resume execution normally.  */
	return 0;
}
Exemplo n.º 3
0
int Interpreter::SingleStepInner()
{
	static UGeckoInstruction instCode;
	u32 function = HLE::GetFunctionIndex(PC);
	if (function != 0)
	{
		int type = HLE::GetFunctionTypeByIndex(function);
		if (type == HLE::HLE_HOOK_START || type == HLE::HLE_HOOK_REPLACE)
		{
			int flags = HLE::GetFunctionFlagsByIndex(function);
			if (HLE::IsEnabled(flags))
			{
				HLEFunction(function);
				if (type == HLE::HLE_HOOK_START)
				{
					// Run the original.
					function = 0;
				}
			}
			else
			{
				function = 0;
			}
		}
	}

	if (function == 0)
	{
		#ifdef USE_GDBSTUB
		if (gdb_active() && gdb_bp_x(PC))
		{
			Host_UpdateDisasmDialog();

			gdb_signal(SIGTRAP);
			gdb_handle_exception();
		}
		#endif

		NPC = PC + sizeof(UGeckoInstruction);
		instCode.hex = PowerPC::Read_Opcode(PC);

		// Uncomment to trace the interpreter
		//if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624)
		//	startTrace = 1;
		//else
		//	startTrace = 0;

		if (startTrace)
		{
			Trace(instCode);
		}

		if (instCode.hex != 0)
		{
			UReg_MSR& msr = (UReg_MSR&)MSR;
			if (msr.FP)  //If FPU is enabled, just execute
			{
				m_opTable[instCode.OPCD](instCode);
				if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
				{
					PowerPC::CheckExceptions();
					m_EndBlock = true;
				}
			}
			else
			{
				// check if we have to generate a FPU unavailable exception
				if (!PPCTables::UsesFPU(instCode))
				{
					m_opTable[instCode.OPCD](instCode);
					if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
					{
						PowerPC::CheckExceptions();
						m_EndBlock = true;
					}
				}
				else
				{
					PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
					PowerPC::CheckExceptions();
					m_EndBlock = true;
				}
			}
		}
		else
		{
			// Memory exception on instruction fetch
			PowerPC::CheckExceptions();
			m_EndBlock = true;
		}
	}
	last_pc = PC;
	PC = NPC;

	GekkoOPInfo *opinfo = GetOpInfo(instCode);
	return opinfo->numCycles;
}
Exemplo n.º 4
0
int main(int argc, char *argv[])
{
	u32 done;
	memset(&_ctx, 0x00, sizeof _ctx);
	ctx = &_ctx;
	parse_args(argc, argv);

#if 0
	u64 local_ptr;
	
	local_ptr = 0xdead0000dead0000ULL;
	
	ctx->reg[3][0] = (u32)(local_ptr >> 32);
	ctx->reg[3][1] = (u32)local_ptr;

	ctx->reg[4][0] = 0xdead0000;
	ctx->reg[4][1] = 0xdead0000;
#endif

	ctx->ls = (u8*)malloc(LS_SIZE);
	if (ctx->ls == NULL)
		fail("Unable to allocate local storage.");
	memset(ctx->ls, 0, LS_SIZE);

#if 0
	wbe64(ctx->ls + 0x3f000, 0x100000000ULL);
	wbe32(ctx->ls + 0x3f008, 0x10000);
	wbe32(ctx->ls + 0x3e000, 0xff);
#endif

	if (gdb_port < 0)
    {
		ctx->paused = 0;
	}
    else
    {
		gdb_init(gdb_port);
		ctx->paused = 1;
		gdb_signal(SIGABRT);
	}

	elf_load(elf_path);

    setup_context();

	done = 0;

	while(done == 0)
    {
		if (ctx->paused == 0 || ctx->paused == 2)
			done = emulate();

		// data watchpoints
		if (done == 2)
        {
			ctx->paused = 0;
			gdb_signal(SIGTRAP);
			done = 0;
		}
		
		if (done != 0)
        {
			printf("emulated() returned, sending SIGSEGV to gdb stub\n");
			ctx->paused = 1;
			done = gdb_signal(SIGSEGV);
		}

		if (done != 0)
        {
#ifdef STOP_DUMP_REGS
			dump_regs();
#endif
#ifdef STOP_DUMP_LS
			dump_ls();
#endif
		}

		//if (ctx->paused == 1)
			gdb_handle_events();
	}
	printf("emulate() returned. we're done!\n");
	dump_ls();
	free(ctx->ls);
	gdb_deinit();
	return 0;
}
Exemplo n.º 5
0
int Interpreter::SingleStepInner(void)
{
	static UGeckoInstruction instCode;
	u32 function = m_EndBlock ? HLE::GetFunctionIndex(PC) : 0; // Check for HLE functions after branches
	if (function != 0)
	{
		int type = HLE::GetFunctionTypeByIndex(function);
		if (type == HLE::HLE_HOOK_START || type == HLE::HLE_HOOK_REPLACE)
		{
			int flags = HLE::GetFunctionFlagsByIndex(function);
			if (HLE::IsEnabled(flags))
			{
				HLEFunction(function);
				if (type == HLE::HLE_HOOK_START)
				{
					// Run the original.
					function = 0;
				}
			}
			else
			{
				function = 0;
			}
		}
	}

	if (function == 0)
	{
		#ifdef USE_GDBSTUB
		if (gdb_active() && gdb_bp_x(PC)) {

			Host_UpdateDisasmDialog();

			gdb_signal(SIGTRAP);
			gdb_handle_exception();
		}
		#endif

		NPC = PC + sizeof(UGeckoInstruction);
		instCode.hex = Memory::Read_Opcode(PC);

		// Uncomment to trace the interpreter
		//if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624)
		//	startTrace = 1;
		//else
		//	startTrace = 0;

		if (startTrace)
		{
			Trace(instCode);
		}

		if (instCode.hex != 0)
		{
			UReg_MSR& msr = (UReg_MSR&)MSR;
			if (msr.FP)  //If FPU is enabled, just execute
			{
				m_opTable[instCode.OPCD](instCode);
				if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
				{
					PowerPC::CheckExceptions();
					m_EndBlock = true;
				}
			}
			else
			{
				// check if we have to generate a FPU unavailable exception
				if (!PPCTables::UsesFPU(instCode))
				{
					m_opTable[instCode.OPCD](instCode);
					if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
					{
						PowerPC::CheckExceptions();
						m_EndBlock = true;
					}
				}
				else
				{
					Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_FPU_UNAVAILABLE);
					PowerPC::CheckExceptions();
					m_EndBlock = true;
				}
			}
		}
		else
		{
			// Memory exception on instruction fetch
			PowerPC::CheckExceptions();
			m_EndBlock = true;
		}
	}
	last_pc = PC;
	PC = NPC;

#if defined(_DEBUG) || defined(DEBUGFAST)
	if (PowerPC::ppcState.gpr[1] == 0)
	{
		WARN_LOG(POWERPC, "%i Corrupt stack", PowerPC::ppcState.DebugCount);
	}
	PowerPC::ppcState.DebugCount++;
#endif
	patches();

	GekkoOPInfo *opinfo = GetOpInfo(instCode);
	return opinfo->numCyclesMinusOne + 1;
}
Exemplo n.º 6
0
int Interpreter::SingleStepInner()
{
  if (HandleFunctionHooking(PC))
  {
    UpdatePC();
    return PPCTables::GetOpInfo(m_prev_inst)->numCycles;
  }

#ifdef USE_GDBSTUB
  if (gdb_active() && gdb_bp_x(PC))
  {
    Host_UpdateDisasmDialog();

    gdb_signal(GDB_SIGTRAP);
    gdb_handle_exception();
  }
#endif

  NPC = PC + sizeof(UGeckoInstruction);
  m_prev_inst.hex = PowerPC::Read_Opcode(PC);

  // Uncomment to trace the interpreter
  // if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624)
  //	startTrace = 1;
  // else
  //	startTrace = 0;

  if (startTrace)
  {
    Trace(m_prev_inst);
  }

  if (m_prev_inst.hex != 0)
  {
    if (IsInvalidPairedSingleExecution(m_prev_inst))
    {
      GenerateProgramException();
      CheckExceptions();
    }
    else if (MSR.FP)
    {
      m_op_table[m_prev_inst.OPCD](m_prev_inst);
      if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
      {
        CheckExceptions();
      }
    }
    else
    {
      // check if we have to generate a FPU unavailable exception or a program exception.
      if (PPCTables::UsesFPU(m_prev_inst))
      {
        PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
        CheckExceptions();
      }
      else
      {
        m_op_table[m_prev_inst.OPCD](m_prev_inst);
        if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
        {
          CheckExceptions();
        }
      }
    }
  }
  else
  {
    // Memory exception on instruction fetch
    CheckExceptions();
  }

  UpdatePC();
  return PPCTables::GetOpInfo(m_prev_inst)->numCycles;
}
Exemplo n.º 7
0
int Interpreter::SingleStepInner()
{
  if (!HandleFunctionHooking(PC))
  {
#ifdef USE_GDBSTUB
    if (gdb_active() && gdb_bp_x(PC))
    {
      Host_UpdateDisasmDialog();

      gdb_signal(SIGTRAP);
      gdb_handle_exception();
    }
#endif

    NPC = PC + sizeof(UGeckoInstruction);
    m_prev_inst.hex = PowerPC::Read_Opcode(PC);

    // Uncomment to trace the interpreter
    // if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624)
    //	startTrace = 1;
    // else
    //	startTrace = 0;

    if (startTrace)
    {
      Trace(m_prev_inst);
    }

    if (m_prev_inst.hex != 0)
    {
      if (MSR.FP)  // If FPU is enabled, just execute
      {
        m_op_table[m_prev_inst.OPCD](m_prev_inst);
        if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
        {
          PowerPC::CheckExceptions();
          m_end_block = true;
        }
      }
      else
      {
        // check if we have to generate a FPU unavailable exception
        if (!PPCTables::UsesFPU(m_prev_inst))
        {
          m_op_table[m_prev_inst.OPCD](m_prev_inst);
          if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
          {
            PowerPC::CheckExceptions();
            m_end_block = true;
          }
        }
        else
        {
          PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
          PowerPC::CheckExceptions();
          m_end_block = true;
        }
      }
    }
    else
    {
      // Memory exception on instruction fetch
      PowerPC::CheckExceptions();
      m_end_block = true;
    }
  }
  last_pc = PC;
  PC = NPC;

  const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst);
  return opinfo->numCycles;
}