bool CpuStateX8664::SetRegisterValue(const Register* reg, const BVariant& value) { int32 index = reg->Index(); if (index >= X86_64_XMM_REGISTER_END) return false; if (index < X86_64_INT_REGISTER_END) fIntRegisters[index] = value.ToUInt64(); else if (index >= X86_64_REGISTER_ST0 && index < X86_64_FP_REGISTER_END) fFloatRegisters[index - X86_64_REGISTER_ST0] = value.ToDouble(); else if (index >= X86_64_REGISTER_MM0 && index < X86_64_MMX_REGISTER_END) { if (value.Size() > sizeof(int64)) return false; memset(&fMMXRegisters[index - X86_64_REGISTER_MM0], 0, sizeof(x86_64_fp_register)); memcpy(fMMXRegisters[index - X86_64_REGISTER_MM0].value, value.ToPointer(), value.Size()); } else if (index >= X86_64_REGISTER_XMM0 && index < X86_64_XMM_REGISTER_END) { if (value.Size() > sizeof(x86_64_xmm_register)) return false; memset(&fXMMRegisters[index - X86_64_REGISTER_XMM0], 0, sizeof(x86_64_xmm_register)); memcpy(fXMMRegisters[index - X86_64_REGISTER_XMM0].value, value.ToPointer(), value.Size()); } else return false; fSetRegisters[index] = 1; return true; }
status_t ValueLoader::LoadValue(ValueLocation* location, type_code valueType, bool shortValueIsFine, BVariant& _value) { static const size_t kMaxPieceSize = 16; uint64 totalBitSize = 0; int32 count = location->CountPieces(); for (int32 i = 0; i < count; i++) { ValuePieceLocation piece = location->PieceAt(i); switch (piece.type) { case VALUE_PIECE_LOCATION_INVALID: case VALUE_PIECE_LOCATION_UNKNOWN: return B_ENTRY_NOT_FOUND; case VALUE_PIECE_LOCATION_MEMORY: case VALUE_PIECE_LOCATION_REGISTER: break; } if (piece.size > kMaxPieceSize) { TRACE_LOCALS(" -> overly long piece size (%" B_PRIu64 " bytes)\n", piece.size); return B_UNSUPPORTED; } totalBitSize += piece.bitSize; } TRACE_LOCALS(" -> totalBitSize: %" B_PRIu64 "\n", totalBitSize); if (totalBitSize == 0) { TRACE_LOCALS(" -> no size\n"); return B_ENTRY_NOT_FOUND; } if (totalBitSize > 64) { TRACE_LOCALS(" -> longer than 64 bits: unsupported\n"); return B_UNSUPPORTED; } uint64 valueBitSize = BVariant::SizeOfType(valueType) * 8; if (!shortValueIsFine && totalBitSize < valueBitSize) { TRACE_LOCALS(" -> too short for value type (%" B_PRIu64 " vs. %" B_PRIu64 " bits)\n", totalBitSize, valueBitSize); return B_BAD_VALUE; } // Load the data. Since the BitBuffer class we're using only supports big // endian bit semantics, we convert all data to big endian before pushing // them to the buffer. For later conversion to BVariant we need to make sure // the final buffer has the size of the value type, so we pad the most // significant bits with zeros. BitBuffer valueBuffer; if (totalBitSize < valueBitSize) valueBuffer.AddZeroBits(valueBitSize - totalBitSize); 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 bytesToRead = piece.size; uint32 bitSize = piece.bitSize; uint8 bitOffset = piece.bitOffset; // TODO: the offset's ordinal position and direction aren't // specified by DWARF, and simply follow the target language. // To handle non C/C++ languages properly, the corresponding // SourceLanguage will need to be passed in and extended to // return the relevant information. switch (piece.type) { case VALUE_PIECE_LOCATION_INVALID: case VALUE_PIECE_LOCATION_UNKNOWN: return B_ENTRY_NOT_FOUND; 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, bitSize); uint8 pieceBuffer[kMaxPieceSize]; ssize_t bytesRead = fTeamMemory->ReadMemory(address, pieceBuffer, bytesToRead); if (bytesRead < 0) return bytesRead; if ((uint32)bytesRead != bytesToRead) return B_BAD_ADDRESS; TRACE_LOCALS_ONLY( TRACE_LOCALS(" -> read: "); for (ssize_t k = 0; k < bytesRead; k++) TRACE_LOCALS("%02x", pieceBuffer[k]); TRACE_LOCALS("\n"); ) // convert to big endian if (!bigEndian) { for (int32 k = bytesRead / 2 - 1; k >= 0; k--) { std::swap(pieceBuffer[k], pieceBuffer[bytesRead - k - 1]); } } valueBuffer.AddBits(pieceBuffer, bitSize, bitOffset); break; } case VALUE_PIECE_LOCATION_REGISTER: { TRACE_LOCALS(" piece %" B_PRId32 ": register: %" B_PRIu32 ", bits: %" B_PRIu32 "\n", i, piece.reg, bitSize); if (fCpuState == NULL) { WARNING("ValueLoader::LoadValue(): register piece, but no " "CpuState\n"); return B_UNSUPPORTED; } BVariant registerValue; if (!fCpuState->GetRegisterValue(registers + piece.reg, registerValue)) { return B_ENTRY_NOT_FOUND; } if (registerValue.Size() < bytesToRead) return B_ENTRY_NOT_FOUND; if (!bigEndian) { registerValue.SwapEndianess(); bitOffset = registerValue.Size() * 8 - bitOffset - bitSize; } valueBuffer.AddBits(registerValue.Bytes(), bitSize, bitOffset); break; } } }