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.
This commit is contained in:
Rene Gollent
2015-07-17 22:03:24 -04:00
parent 5b026a2960
commit 568f200843
3 changed files with 181 additions and 0 deletions
+1
View File
@@ -340,6 +340,7 @@ local sources =
ValueNode.cpp
ValueNodeContainer.cpp
ValueNodeManager.cpp
ValueWriter.cpp
# value/type_handlers
BListTypeHandler.cpp
+135
View File
@@ -0,0 +1,135 @@
/*
* Copyright 2009-2012, Ingo Weinhold, [email protected].
* Copyright 2013-2015, Rene Gollent, [email protected].
* 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;
}
+45
View File
@@ -0,0 +1,45 @@
/*
* Copyright 2015, Rene Gollent, [email protected].
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef VALUE_WRITER_H
#define VALUE_WRITER_H
#include <OS.h>
#include <String.h>
#include <Variant.h>
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