Пример #1
0
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;
}
Пример #2
0
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;
        }
        }
    }