From 568f200843b1a3261696d01ba1db8a15e50ef86b Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Wed, 24 Jun 2015 17:51:42 -0400 Subject: [PATCH] Debugger: Add ValueWriter support class. - Given a value + corresponding location description, this handles ensuring that the data ends up in the appropriate locations in the target team. --- src/apps/debugger/Jamfile | 1 + src/apps/debugger/value/ValueWriter.cpp | 135 ++++++++++++++++++++++++ src/apps/debugger/value/ValueWriter.h | 45 ++++++++ 3 files changed, 181 insertions(+) create mode 100644 src/apps/debugger/value/ValueWriter.cpp create mode 100644 src/apps/debugger/value/ValueWriter.h diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 6e71466246..648b3cf693 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -340,6 +340,7 @@ local sources = ValueNode.cpp ValueNodeContainer.cpp ValueNodeManager.cpp + ValueWriter.cpp # value/type_handlers BListTypeHandler.cpp diff --git a/src/apps/debugger/value/ValueWriter.cpp b/src/apps/debugger/value/ValueWriter.cpp new file mode 100644 index 0000000000..705e694727 --- /dev/null +++ b/src/apps/debugger/value/ValueWriter.cpp @@ -0,0 +1,135 @@ +/* + * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2013-2015, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ + + +#include "ValueWriter.h" + +#include "Architecture.h" +#include "BitBuffer.h" +#include "CpuState.h" +#include "DebuggerInterface.h" +#include "Register.h" +#include "TeamMemory.h" +#include "Tracing.h" +#include "ValueLocation.h" + + +ValueWriter::ValueWriter(Architecture* architecture, + DebuggerInterface* interface, CpuState* cpuState, thread_id targetThread) + : + fArchitecture(architecture), + fDebuggerInterface(interface), + fCpuState(cpuState), + fTargetThread(targetThread) +{ + fArchitecture->AcquireReference(); + fDebuggerInterface->AcquireReference(); + if (fCpuState != NULL) + fCpuState->AcquireReference(); +} + + +ValueWriter::~ValueWriter() +{ + fArchitecture->ReleaseReference(); + fDebuggerInterface->ReleaseReference(); + if (fCpuState != NULL) + fCpuState->ReleaseReference(); +} + + +status_t +ValueWriter::WriteValue(ValueLocation* location, BVariant& value) +{ + if (!location->IsWritable()) + return B_BAD_VALUE; + + int32 count = location->CountPieces(); + if (fCpuState == NULL) { + for (int32 i = 0; i < count; i++) { + const ValuePieceLocation piece = location->PieceAt(i); + if (piece.type == VALUE_PIECE_LOCATION_REGISTER) { + TRACE_LOCALS(" -> asked to write value with register piece, " + "but no CPU state to write to.\n"); + return B_UNSUPPORTED; + } + } + } + + bool cpuStateWriteNeeded = false; + size_t byteOffset = 0; + bool bigEndian = fArchitecture->IsBigEndian(); + const Register* registers = fArchitecture->Registers(); + for (int32 i = 0; i < count; i++) { + ValuePieceLocation piece = location->PieceAt( + bigEndian ? i : count - i - 1); + uint32 bytesToWrite = piece.size; + + uint8* targetData = (uint8*)value.Bytes() + byteOffset; + + switch (piece.type) { + case VALUE_PIECE_LOCATION_MEMORY: + { + target_addr_t address = piece.address; + + TRACE_LOCALS(" piece %" B_PRId32 ": memory address: %#" + B_PRIx64 ", bits: %" B_PRIu32 "\n", i, address, + bytesToWrite * 8); + + ssize_t bytesWritten = fDebuggerInterface->WriteMemory(address, + targetData, bytesToWrite); + + if (bytesWritten < 0) + return bytesWritten; + if ((uint32)bytesWritten != bytesToWrite) + return B_BAD_ADDRESS; + + break; + } + case VALUE_PIECE_LOCATION_REGISTER: + { + TRACE_LOCALS(" piece %" B_PRId32 ": register: %" B_PRIu32 + ", bits: %" B_PRIu32 "\n", i, piece.reg, bitSize); + + const Register* target = registers + piece.reg; + BVariant pieceValue; + switch (bytesToWrite) { + case 1: + pieceValue.SetTo(*(uint8*)targetData); + break; + case 2: + pieceValue.SetTo(*(uint16*)targetData); + break; + case 4: + pieceValue.SetTo(*(uint32*)targetData); + break; + case 8: + pieceValue.SetTo(*(uint64*)targetData); + break; + default: + TRACE_LOCALS("Asked to write unsupported piece size %" + B_PRId32 " to register\n", bytesToWrite); + return B_UNSUPPORTED; + } + + if (!fCpuState->SetRegisterValue(target, pieceValue)) + return B_NO_MEMORY; + + cpuStateWriteNeeded = true; + break; + } + default: + return B_UNSUPPORTED; + } + + byteOffset += bytesToWrite; + } + + if (cpuStateWriteNeeded) + return fDebuggerInterface->SetCpuState(fTargetThread, fCpuState); + + return B_OK; +} diff --git a/src/apps/debugger/value/ValueWriter.h b/src/apps/debugger/value/ValueWriter.h new file mode 100644 index 0000000000..8a5ed07547 --- /dev/null +++ b/src/apps/debugger/value/ValueWriter.h @@ -0,0 +1,45 @@ +/* + * Copyright 2015, Rene Gollent, rene@gollent.com. + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef VALUE_WRITER_H +#define VALUE_WRITER_H + + +#include +#include + +#include + + +class Architecture; +class CpuState; +class DebuggerInterface; +class ValueLocation; + + +class ValueWriter { +public: + ValueWriter(Architecture* architecture, + DebuggerInterface* interface, + CpuState* cpuState, + thread_id targetThread); + // cpuState can be NULL + ~ValueWriter(); + + Architecture* GetArchitecture() const + { return fArchitecture; } + + status_t WriteValue(ValueLocation* location, + BVariant& value); + +private: + Architecture* fArchitecture; + DebuggerInterface* fDebuggerInterface; + CpuState* fCpuState; + thread_id fTargetThread; +}; + + +#endif // VALUE_WRITER_H