bool CpuStateX8664::SetRegisterValue(const Register* reg, const BVariant& value) { int32 index = reg->Index(); if (index >= X86_64_XMM_REGISTER_END) return false; if (index < X86_64_INT_REGISTER_END) fIntRegisters[index] = value.ToUInt64(); else if (index >= X86_64_REGISTER_ST0 && index < X86_64_FP_REGISTER_END) fFloatRegisters[index - X86_64_REGISTER_ST0] = value.ToDouble(); else if (index >= X86_64_REGISTER_MM0 && index < X86_64_MMX_REGISTER_END) { if (value.Size() > sizeof(int64)) return false; memset(&fMMXRegisters[index - X86_64_REGISTER_MM0], 0, sizeof(x86_64_fp_register)); memcpy(fMMXRegisters[index - X86_64_REGISTER_MM0].value, value.ToPointer(), value.Size()); } else if (index >= X86_64_REGISTER_XMM0 && index < X86_64_XMM_REGISTER_END) { if (value.Size() > sizeof(x86_64_xmm_register)) return false; memset(&fXMMRegisters[index - X86_64_REGISTER_XMM0], 0, sizeof(x86_64_xmm_register)); memcpy(fXMMRegisters[index - X86_64_REGISTER_XMM0].value, value.ToPointer(), value.Size()); } else return false; fSetRegisters[index] = 1; return true; }
bool CpuStateX8664::SetRegisterValue(const Register* reg, const BVariant& value) { int32 index = reg->Index(); if (index >= X86_64_INT_REGISTER_END) return false; fIntRegisters[index] = value.ToUInt64(); fSetRegisters[index] = 1; return true; }
status_t DwarfImageDebugInfo::CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, bool getFullFrameInfo, ReturnValueInfoList* returnValueInfos, StackFrame*& _frame, CpuState*& _previousCpuState) { DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>( functionInstance->GetFunctionDebugInfo()); FunctionID* functionID = functionInstance->GetFunctionID(); BReference<FunctionID> functionIDReference; if (functionID != NULL) functionIDReference.SetTo(functionID, true); DIESubprogram* entry = function != NULL ? function->SubprogramEntry() : NULL; TRACE_CFI("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p, " "function: %s\n", entry, functionID->FunctionName().String()); int32 registerCount = fArchitecture->CountRegisters(); const Register* registers = fArchitecture->Registers(); // get the DWARF <-> architecture register maps RegisterMap* toDwarfMap; RegisterMap* fromDwarfMap; status_t error = fArchitecture->GetDwarfRegisterMaps(&toDwarfMap, &fromDwarfMap); if (error != B_OK) return error; BReference<RegisterMap> toDwarfMapReference(toDwarfMap, true); BReference<RegisterMap> fromDwarfMapReference(fromDwarfMap, true); // create a clean CPU state for the previous frame CpuState* previousCpuState; error = fArchitecture->CreateCpuState(previousCpuState); if (error != B_OK) return error; BReference<CpuState> previousCpuStateReference(previousCpuState, true); // create the target interfaces UnwindTargetInterface* inputInterface = new(std::nothrow) UnwindTargetInterface(registers, registerCount, fromDwarfMap, toDwarfMap, cpuState, fArchitecture, fDebuggerInterface); if (inputInterface == NULL) return B_NO_MEMORY; BReference<UnwindTargetInterface> inputInterfaceReference(inputInterface, true); UnwindTargetInterface* outputInterface = new(std::nothrow) UnwindTargetInterface(registers, registerCount, fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture, fDebuggerInterface); if (outputInterface == NULL) return B_NO_MEMORY; BReference<UnwindTargetInterface> outputInterfaceReference(outputInterface, true); // do the unwinding target_addr_t instructionPointer = cpuState->InstructionPointer() - fRelocationDelta; target_addr_t framePointer; CompilationUnit* unit = function != NULL ? function->GetCompilationUnit() : NULL; error = fFile->UnwindCallFrame(unit, fArchitecture->AddressSize(), entry, instructionPointer, inputInterface, outputInterface, framePointer); if (error != B_OK) { TRACE_CFI("Failed to unwind call frame: %s\n", strerror(error)); return B_UNSUPPORTED; } TRACE_CFI_ONLY( TRACE_CFI("unwound registers:\n"); for (int32 i = 0; i < registerCount; i++) { const Register* reg = registers + i; BVariant value; if (previousCpuState->GetRegisterValue(reg, value)) { TRACE_CFI(" %3s: %#" B_PRIx64 "\n", reg->Name(), value.ToUInt64()); } else TRACE_CFI(" %3s: undefined\n", reg->Name()); } )
void InspectorWindow::MessageReceived(BMessage* message) { switch (message->what) { case MSG_THREAD_STATE_CHANGED: { ::Thread* thread; if (message->FindPointer("thread", reinterpret_cast<void**>(&thread)) != B_OK) { break; } BReference< ::Thread> threadReference(thread, true); if (thread->State() == THREAD_STATE_STOPPED) { if (fCurrentBlock != NULL) { _SetCurrentBlock(NULL); _SetToAddress(fCurrentAddress); } } break; } case MSG_INSPECT_ADDRESS: { target_addr_t address = 0; if (message->FindUInt64("address", &address) != B_OK) { if (fAddressInput->TextView()->TextLength() == 0) break; fExpressionInfo->SetTo(fAddressInput->Text()); fListener->ExpressionEvaluationRequested(fLanguage, fExpressionInfo); } else _SetToAddress(address); break; } case MSG_EXPRESSION_EVALUATED: { BString errorMessage; BReference<ExpressionResult> reference; ExpressionResult* value = NULL; if (message->FindPointer("value", reinterpret_cast<void**>(&value)) == B_OK) { reference.SetTo(value, true); if (value->Kind() == EXPRESSION_RESULT_KIND_PRIMITIVE) { Value* primitive = value->PrimitiveValue(); BVariant variantValue; primitive->ToVariant(variantValue); if (variantValue.Type() == B_STRING_TYPE) { errorMessage.SetTo(variantValue.ToString()); } else { _SetToAddress(variantValue.ToUInt64()); break; } } } else { status_t result = message->FindInt32("result"); errorMessage.SetToFormat("Failed to evaluate expression: %s", strerror(result)); } BAlert* alert = new(std::nothrow) BAlert("Inspect Address", errorMessage.String(), "Close"); if (alert != NULL) alert->Go(); break; } case MSG_NAVIGATE_PREVIOUS_BLOCK: case MSG_NAVIGATE_NEXT_BLOCK: { if (fCurrentBlock != NULL) { target_addr_t address = fCurrentBlock->BaseAddress(); if (message->what == MSG_NAVIGATE_PREVIOUS_BLOCK) address -= fCurrentBlock->Size(); else address += fCurrentBlock->Size(); BMessage setMessage(MSG_INSPECT_ADDRESS); setMessage.AddUInt64("address", address); PostMessage(&setMessage); } break; } case MSG_MEMORY_BLOCK_RETRIEVED: { TeamMemoryBlock* block = NULL; status_t result; if (message->FindPointer("block", reinterpret_cast<void **>(&block)) != B_OK || message->FindInt32("result", &result) != B_OK) { break; } if (result == B_OK) { _SetCurrentBlock(block); fPreviousBlockButton->SetEnabled(true); fNextBlockButton->SetEnabled(true); } else { BString errorMessage; errorMessage.SetToFormat("Unable to read address 0x%" B_PRIx64 ": %s", block->BaseAddress(), strerror(result)); BAlert* alert = new(std::nothrow) BAlert("Inspect address", errorMessage.String(), "Close"); if (alert == NULL) break; alert->Go(NULL); block->ReleaseReference(); } break; } case MSG_EDIT_CURRENT_BLOCK: { _SetEditMode(true); break; } case MSG_MEMORY_DATA_CHANGED: { if (fCurrentBlock == NULL) break; target_addr_t address; if (message->FindUInt64("address", &address) == B_OK && address >= fCurrentBlock->BaseAddress() && address < fCurrentBlock->BaseAddress() + fCurrentBlock->Size()) { fCurrentBlock->Invalidate(); _SetEditMode(false); fListener->InspectRequested(address, this); } break; } case MSG_COMMIT_MODIFIED_BLOCK: { // TODO: this could conceivably be extended to detect the // individual modified regions and only write those back. // That would require potentially submitting multiple separate // write requests, and thus require tracking all the writes being // waited upon for completion. fListener->MemoryWriteRequested(fCurrentBlock->BaseAddress(), fMemoryView->GetEditedData(), fCurrentBlock->Size()); break; } case MSG_REVERT_MODIFIED_BLOCK: { _SetEditMode(false); break; } default: { BWindow::MessageReceived(message); break; } } }
status_t DwarfCompoundType::ResolveDataMemberLocation(DataMember* _member, const ValueLocation& parentLocation, ValueLocation*& _location) { DwarfDataMember* member = dynamic_cast<DwarfDataMember*>(_member); if (member == NULL) return B_BAD_VALUE; DwarfTypeContext* typeContext = TypeContext(); bool isBitField = true; DIEMember* memberEntry = member->Entry(); // TODO: handle DW_AT_data_bit_offset if (!memberEntry->ByteSize()->IsValid() && !memberEntry->BitOffset()->IsValid() && !memberEntry->BitSize()->IsValid()) { isBitField = false; } ValueLocation* location; status_t error = _ResolveDataMemberLocation(member->GetDwarfType(), member->Entry()->Location(), parentLocation, isBitField, location); if (error != B_OK) return error; // If the member isn't a bit field, we're done. if (!isBitField) { _location = location; return B_OK; } BReference<ValueLocation> locationReference(location); // get the byte size target_addr_t byteSize; if (memberEntry->ByteSize()->IsValid()) { BVariant value; error = typeContext->File()->EvaluateDynamicValue( typeContext->GetCompilationUnit(), typeContext->AddressSize(), typeContext->SubprogramEntry(), memberEntry->ByteSize(), typeContext->TargetInterface(), typeContext->InstructionPointer(), typeContext->FramePointer(), value); if (error != B_OK) return error; byteSize = value.ToUInt64(); } else byteSize = ByteSize(); // get the bit offset uint64 bitOffset = 0; if (memberEntry->BitOffset()->IsValid()) { BVariant value; error = typeContext->File()->EvaluateDynamicValue( typeContext->GetCompilationUnit(), typeContext->AddressSize(), typeContext->SubprogramEntry(), memberEntry->BitOffset(), typeContext->TargetInterface(), typeContext->InstructionPointer(), typeContext->FramePointer(), value); if (error != B_OK) return error; bitOffset = value.ToUInt64(); } // get the bit size uint64 bitSize = byteSize * 8; if (memberEntry->BitSize()->IsValid()) { BVariant value; error = typeContext->File()->EvaluateDynamicValue( typeContext->GetCompilationUnit(), typeContext->AddressSize(), typeContext->SubprogramEntry(), memberEntry->BitSize(), typeContext->TargetInterface(), typeContext->InstructionPointer(), typeContext->FramePointer(), value); if (error != B_OK) return error; bitSize = value.ToUInt64(); } TRACE_LOCALS("bit field: byte size: %" B_PRIu64 ", bit offset/size: %" B_PRIu64 "/%" B_PRIu64 "\n", byteSize, bitOffset, bitSize); if (bitOffset + bitSize > byteSize * 8) return B_BAD_VALUE; // create the bit field value location ValueLocation* bitFieldLocation = new(std::nothrow) ValueLocation; if (bitFieldLocation == NULL) return B_NO_MEMORY; BReference<ValueLocation> bitFieldLocationReference(bitFieldLocation, true); if (!bitFieldLocation->SetTo(*location, bitOffset, bitSize)) return B_NO_MEMORY; _location = bitFieldLocationReference.Detach(); return B_OK; }