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:
@@ -340,6 +340,7 @@ local sources =
|
||||
ValueNode.cpp
|
||||
ValueNodeContainer.cpp
|
||||
ValueNodeManager.cpp
|
||||
ValueWriter.cpp
|
||||
|
||||
# value/type_handlers
|
||||
BListTypeHandler.cpp
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user