/** * Executes a single instruction. * * @param tid The thread ID of the thread that executes the instruction. * @param address The address of the instruction pointer after the single step. * * @return A NaviError code that describes whether the operation was successful or not. */ NaviError LinuxSystem::doSingleStep(unsigned int& pid, CPUADDRESS& address) { msglog->log(LOG_VERBOSE, "Trying to do single step"); STOP_PROCESS_IF_NECESSARY if (ptrace(PTRACE_SINGLESTEP, getPID(), 0, 0)) { RESUME_PROCESS_IF_NECESSARY msglog->log(LOG_ALWAYS, "Error: Couldn't perform single step"); return NaviErrors::COULDNT_SINGLE_STEP; } wait(0); RESUME_PROCESS_IF_NECESSARY NaviError eipResult = getInstructionPointer(getPID(), address); if (eipResult) { return NaviErrors::COULDNT_READ_REGISTERS; } return NaviErrors::SUCCESS; }
/** * Processes a stop-reply message. * * @param msg The message to process. * * @return A NaviError code that describes whether the operation was successful * or not. */ NaviError GdbSystem::processMessage(const std::string& msg) { if (cpu->isBreakpointMessage(msg)) { bool isRegular = cpu->hasRegularBreakpointMessage(); unsigned int signal = isRegular ? zylib::zycon::parseHexString<unsigned int>(msg.substr(2, 2)) : 0; msglog->log(LOG_VERBOSE, "Received stop message %s", msg.c_str()); if (!isRegular || signal == 5) { return processBreakpointMessage(msg); } else if (signal == SIGSEGV) { // SEGFAULT msglog->log(LOG_ALWAYS, "Target process segfaulted"); cpu->sendAck(); CPUADDRESS address = 0; NaviError eipResult = getInstructionPointer( threadFromBreakpointMessage(msg), address); if (eipResult) { msglog->log(LOG_VERBOSE, "Error: Couldn't read the value of the " "instruction pointer (Code %d)", eipResult); return eipResult; } exceptionRaised(threadFromBreakpointMessage(msg), address, signal); return NaviErrors::SUCCESS; } else { msglog->log(LOG_ALWAYS, "Received unknown stop message %s", msg.c_str()); cpu->sendAck(); resume(threadFromBreakpointMessage(msg)); return NaviErrors::SUCCESS; } } else if (cpu->isProcessExitMessage(msg) || cpu->isProcessTerminateMessage(msg)) { cpu->sendAck(); // Tell the base system that the process exited processExit(); } else { msglog->log(LOG_ALWAYS, "Error: Received unknown message %s", msg.c_str()); } return NaviErrors::SUCCESS; }
void BinaryDebugger::runToBreakpoint() { if (breakpoints_.isEmpty()) { sendCommand(PTRACE_CONT, child_, 0, (void*)sendSignal_); waitForChild(); } else { while (1) { singleStep(); if (isTerminated()) break; user_regs_struct regs; sendCommand(PTRACE_GETREGS, child_, 0, ®s); if (breakpoints_.exists(getInstructionPointer(regs))) break; } } }
NaviError GdbSystem::processBreakpointMessage(const std::string& msg) { // If the received message is a breakpoint message, it // is necessary to find out where the breakpoint exception // occurred. // TODO: Not all require this cpu->sendAck(); CPUADDRESS address = 0; NaviError getProgramCounterError = getInstructionPointerFromStopMessage( msg, cpu->getInstructionPointerIndex(), address); if (getProgramCounterError) { msglog->log( LOG_VERBOSE, "Error: Couldn't read the value of the instruction pointer (Code %d)", getProgramCounterError); return getProgramCounterError; } synchronizeThreadState(); unsigned int threadId = threadFromBreakpointMessage(msg); NaviError eipResult = getInstructionPointer(threadId, address); address = cpu->correctBreakpointAddress(address); if (hasBreakpoint(address, BPX_simple) || hasBreakpoint(address, BPX_echo) || hasBreakpoint(address, BPX_stepping)) { handleBreakpointHit(address); } else if (cpu->getDebuggerOptions().canHalt) { // Some other reason caused the process to stop // If the target CPU can halt arbitrarily, let's hope // that the halt was caused by the user. } else { // None of our breakpoints and the target CPU can not // halt arbitrarily => Handle the issue farther up in the chain. handleBreakpointHit(address); } return NaviErrors::SUCCESS; }
rose_addr_t BinaryDebugger::executionAddress() { user_regs_struct regs; sendCommand(PTRACE_GETREGS, child_, 0, ®s); return getInstructionPointer(regs); }