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 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 35 ValueWriter::~ValueWriter() 36 { 37 fArchitecture->ReleaseReference(); 38 fDebuggerInterface->ReleaseReference(); 39 if (fCpuState != NULL) 40 fCpuState->ReleaseReference(); 41 } 42 43 44 status_t 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