1 /*
2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2013-2015, Rene Gollent, rene@gollent.com.
4 * Distributed under the terms of the MIT License.
5 */
6
7
8 #include "ValueWriter.h"
9
10 #include "Architecture.h"
11 #include "BitBuffer.h"
12 #include "CpuState.h"
13 #include "DebuggerInterface.h"
14 #include "Register.h"
15 #include "TeamMemory.h"
16 #include "Tracing.h"
17 #include "ValueLocation.h"
18
19
ValueWriter(Architecture * architecture,DebuggerInterface * interface,CpuState * cpuState,thread_id targetThread)20 ValueWriter::ValueWriter(Architecture* architecture,
21 DebuggerInterface* interface, CpuState* cpuState, thread_id targetThread)
22 :
23 fArchitecture(architecture),
24 fDebuggerInterface(interface),
25 fCpuState(cpuState),
26 fTargetThread(targetThread)
27 {
28 fArchitecture->AcquireReference();
29 fDebuggerInterface->AcquireReference();
30 if (fCpuState != NULL)
31 fCpuState->AcquireReference();
32 }
33
34
~ValueWriter()35 ValueWriter::~ValueWriter()
36 {
37 fArchitecture->ReleaseReference();
38 fDebuggerInterface->ReleaseReference();
39 if (fCpuState != NULL)
40 fCpuState->ReleaseReference();
41 }
42
43
44 status_t
WriteValue(ValueLocation * location,BVariant & value)45 ValueWriter::WriteValue(ValueLocation* location, BVariant& value)
46 {
47 if (!location->IsWritable())
48 return B_BAD_VALUE;
49
50 int32 count = location->CountPieces();
51 if (fCpuState == NULL) {
52 for (int32 i = 0; i < count; i++) {
53 const ValuePieceLocation piece = location->PieceAt(i);
54 if (piece.type == VALUE_PIECE_LOCATION_REGISTER) {
55 TRACE_LOCALS(" -> asked to write value with register piece, "
56 "but no CPU state to write to.\n");
57 return B_UNSUPPORTED;
58 }
59 }
60 }
61
62 bool cpuStateWriteNeeded = false;
63 size_t byteOffset = 0;
64 bool bigEndian = fArchitecture->IsBigEndian();
65 const Register* registers = fArchitecture->Registers();
66 for (int32 i = 0; i < count; i++) {
67 ValuePieceLocation piece = location->PieceAt(
68 bigEndian ? i : count - i - 1);
69 uint32 bytesToWrite = piece.size;
70
71 uint8* targetData = (uint8*)value.Bytes() + byteOffset;
72
73 switch (piece.type) {
74 case VALUE_PIECE_LOCATION_MEMORY:
75 {
76 target_addr_t address = piece.address;
77
78 TRACE_LOCALS(" piece %" B_PRId32 ": memory address: %#"
79 B_PRIx64 ", bits: %" B_PRIu32 "\n", i, address,
80 bytesToWrite * 8);
81
82 ssize_t bytesWritten = fDebuggerInterface->WriteMemory(address,
83 targetData, bytesToWrite);
84
85 if (bytesWritten < 0)
86 return bytesWritten;
87 if ((uint32)bytesWritten != bytesToWrite)
88 return B_BAD_ADDRESS;
89
90 break;
91 }
92 case VALUE_PIECE_LOCATION_REGISTER:
93 {
94 TRACE_LOCALS(" piece %" B_PRId32 ": register: %" B_PRIu32
95 ", bits: %" B_PRIu64 "\n", i, piece.reg, piece.bitSize);
96
97 const Register* target = registers + piece.reg;
98 BVariant pieceValue;
99 switch (bytesToWrite) {
100 case 1:
101 pieceValue.SetTo(*(uint8*)targetData);
102 break;
103 case 2:
104 pieceValue.SetTo(*(uint16*)targetData);
105 break;
106 case 4:
107 pieceValue.SetTo(*(uint32*)targetData);
108 break;
109 case 8:
110 pieceValue.SetTo(*(uint64*)targetData);
111 break;
112 default:
113 TRACE_LOCALS("Asked to write unsupported piece size %"
114 B_PRId32 " to register\n", bytesToWrite);
115 return B_UNSUPPORTED;
116 }
117
118 if (!fCpuState->SetRegisterValue(target, pieceValue))
119 return B_NO_MEMORY;
120
121 cpuStateWriteNeeded = true;
122 break;
123 }
124 default:
125 return B_UNSUPPORTED;
126 }
127
128 byteOffset += bytesToWrite;
129 }
130
131 if (cpuStateWriteNeeded)
132 return fDebuggerInterface->SetCpuState(fTargetThread, fCpuState);
133
134 return B_OK;
135 }
136