status_t ArchitectureX8664::ResolvePICFunctionAddress(target_addr_t instructionAddress, CpuState* state, target_addr_t& _targetAddress) { target_addr_t previousIP = state->InstructionPointer(); // if the function in question is position-independent, the call // will actually have taken us to its corresponding PLT slot. // in such a case, look at the disassembled jump to determine // where to find the actual function address. InstructionInfo info; if (GetInstructionInfo(instructionAddress, info, state) != B_OK) return B_BAD_VALUE; // x86-64 is likely to use a RIP-relative jump here // as such, set our instruction pointer to the address // after this instruction (where it would be during actual // execution), and recalculate the target address of the jump state->SetInstructionPointer(info.Address() + info.Size()); status_t result = GetInstructionInfo(info.Address(), info, state); state->SetInstructionPointer(previousIP); if (result != B_OK) return result; target_addr_t subroutineAddress; ssize_t bytesRead = fTeamMemory->ReadMemory(info.TargetAddress(), &subroutineAddress, fAddressSize); if (bytesRead != fAddressSize) return B_BAD_VALUE; _targetAddress = subroutineAddress; return B_OK; }
bool ThreadHandler::_DoStepOver(CpuState* cpuState) { TRACE_CONTROL("ThreadHandler::_DoStepOver()\n"); // The basic strategy is to single-step out of the statement like for // "step into", only we have to avoid stepping into subroutines. Hence we // check whether the current instruction is a subroutine call. If not, we // just single-step, otherwise we set a breakpoint after the instruction. InstructionInfo info; if (fDebuggerInterface->GetArchitecture()->GetInstructionInfo( cpuState->InstructionPointer(), info, cpuState) != B_OK) { TRACE_CONTROL(" failed to get instruction info\n"); return false; } if (info.Type() != INSTRUCTION_TYPE_SUBROUTINE_CALL) { _SingleStepThread(cpuState->InstructionPointer()); TRACE_CONTROL(" not a subroutine call\n"); return true; } TRACE_CONTROL(" subroutine call -- installing breakpoint at address " "%#" B_PRIx64 "\n", info.Address() + info.Size()); if (_InstallTemporaryBreakpoint(info.Address() + info.Size()) != B_OK) return false; fSteppedOverFunctionAddress = info.TargetAddress(); _RunThread(cpuState->InstructionPointer()); return true; }
status_t ArchitectureX8664::GetStatement(FunctionDebugInfo* function, target_addr_t address, Statement*& _statement) { // TODO: This is not architecture dependent anymore! // get the instruction info InstructionInfo info; status_t error = GetInstructionInfo(address, info, NULL); if (error != B_OK) return error; // create a statement ContiguousStatement* statement = new(std::nothrow) ContiguousStatement( SourceLocation(-1), TargetAddressRange(info.Address(), info.Size())); if (statement == NULL) return B_NO_MEMORY; _statement = statement; return B_OK; }