vfs: check userland buffers before reading them.
[haiku.git] / src / kits / debugger / value / ValueWriter.cpp
blob0548c211f6b15ee573bb3986dd685768d1b2a87f
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 */
8 #include "ValueWriter.h"
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"
20 ValueWriter::ValueWriter(Architecture* architecture,
21 DebuggerInterface* interface, CpuState* cpuState, thread_id targetThread)
23 fArchitecture(architecture),
24 fDebuggerInterface(interface),
25 fCpuState(cpuState),
26 fTargetThread(targetThread)
28 fArchitecture->AcquireReference();
29 fDebuggerInterface->AcquireReference();
30 if (fCpuState != NULL)
31 fCpuState->AcquireReference();
35 ValueWriter::~ValueWriter()
37 fArchitecture->ReleaseReference();
38 fDebuggerInterface->ReleaseReference();
39 if (fCpuState != NULL)
40 fCpuState->ReleaseReference();
44 status_t
45 ValueWriter::WriteValue(ValueLocation* location, BVariant& value)
47 if (!location->IsWritable())
48 return B_BAD_VALUE;
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;
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;
71 uint8* targetData = (uint8*)value.Bytes() + byteOffset;
73 switch (piece.type) {
74 case VALUE_PIECE_LOCATION_MEMORY:
76 target_addr_t address = piece.address;
78 TRACE_LOCALS(" piece %" B_PRId32 ": memory address: %#"
79 B_PRIx64 ", bits: %" B_PRIu32 "\n", i, address,
80 bytesToWrite * 8);
82 ssize_t bytesWritten = fDebuggerInterface->WriteMemory(address,
83 targetData, bytesToWrite);
85 if (bytesWritten < 0)
86 return bytesWritten;
87 if ((uint32)bytesWritten != bytesToWrite)
88 return B_BAD_ADDRESS;
90 break;
92 case VALUE_PIECE_LOCATION_REGISTER:
94 TRACE_LOCALS(" piece %" B_PRId32 ": register: %" B_PRIu32
95 ", bits: %" B_PRIu64 "\n", i, piece.reg, piece.bitSize);
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;
118 if (!fCpuState->SetRegisterValue(target, pieceValue))
119 return B_NO_MEMORY;
121 cpuStateWriteNeeded = true;
122 break;
124 default:
125 return B_UNSUPPORTED;
128 byteOffset += bytesToWrite;
131 if (cpuStateWriteNeeded)
132 return fDebuggerInterface->SetCpuState(fTargetThread, fCpuState);
134 return B_OK;