status_t DwarfType::ResolveLocation(DwarfTypeContext* typeContext, const LocationDescription* description, target_addr_t objectAddress, bool hasObjectAddress, ValueLocation& _location) { status_t error = typeContext->File()->ResolveLocation( typeContext->GetCompilationUnit(), typeContext->AddressSize(), typeContext->SubprogramEntry(), description, typeContext->TargetInterface(), typeContext->InstructionPointer(), objectAddress, hasObjectAddress, typeContext->FramePointer(), typeContext->RelocationDelta(), _location); if (error != B_OK) return error; // translate the DWARF register indices and the bit offset/size semantics const Register* registers = typeContext->GetArchitecture()->Registers(); bool bigEndian = typeContext->GetArchitecture()->IsBigEndian(); int32 count = _location.CountPieces(); for (int32 i = 0; i < count; i++) { ValuePieceLocation piece = _location.PieceAt(i); if (piece.type == VALUE_PIECE_LOCATION_REGISTER) { int32 reg = typeContext->FromDwarfRegisterMap()->MapRegisterIndex( piece.reg); if (reg >= 0) { piece.reg = reg; // The bit offset for registers is to the least // significant bit, while we want the offset to the most // significant bit. if (registers[reg].BitSize() > piece.bitSize) { piece.bitOffset = registers[reg].BitSize() - piece.bitSize - piece.bitOffset; } } else piece.SetToUnknown(); } else if (piece.type == VALUE_PIECE_LOCATION_MEMORY) { // Whether the bit offset is to the least or most significant bit // is target architecture and source language specific. // TODO: Check whether this is correct! // TODO: Source language! if (!bigEndian && piece.size * 8 > piece.bitSize) { piece.bitOffset = piece.size * 8 - piece.bitSize - piece.bitOffset; } } piece.Normalize(bigEndian); _location.SetPieceAt(i, piece); } // If we only have one piece and that doesn't have a size, try to retrieve // the size of the type. if (count == 1) { ValuePieceLocation piece = _location.PieceAt(0); if (piece.IsValid() && piece.size == 0 && piece.bitSize == 0) { piece.SetSize(ByteSize()); // TODO: Use bit size and bit offset, if specified! _location.SetPieceAt(0, piece); TRACE_LOCALS(" set single piece size to %" B_PRIu64 "\n", ByteSize()); } } return B_OK; }
bool ValueLocation::SetTo(const ValueLocation& other, uint64 bitOffset, uint64 bitSize) { Clear(); fBigEndian = other.fBigEndian; // compute the total bit size int32 count = other.CountPieces(); uint64 totalBitSize = 0; for (int32 i = 0; i < count; i++) { const ValuePieceLocation &piece = other.PieceAt(i); totalBitSize += piece.bitSize; } // adjust requested bit offset/size to something reasonable, if necessary if (bitOffset + bitSize > totalBitSize) { if (bitOffset >= totalBitSize) return true; bitSize = totalBitSize - bitOffset; } if (fBigEndian) { // Big endian: Skip the superfluous most significant bits, copy the // pieces we need (cutting the first and the last one as needed) and // ignore the remaining pieces. // skip pieces for the most significant bits we don't need anymore uint64 bitsToSkip = bitOffset; int32 i; ValuePieceLocation piece; for (i = 0; i < count; i++) { const ValuePieceLocation& tempPiece = other.PieceAt(i); if (tempPiece.bitSize > bitsToSkip) { if (!piece.Copy(tempPiece)) return false; break; } bitsToSkip -= tempPiece.bitSize; } // handle partial piece if (bitsToSkip > 0) { piece.bitOffset += bitsToSkip; piece.bitSize -= bitsToSkip; piece.Normalize(fBigEndian); } // handle remaining pieces while (bitSize > 0) { if (piece.bitSize > bitSize) { // the piece is bigger than the remaining size -- cut it piece.bitSize = bitSize; piece.Normalize(fBigEndian); bitSize = 0; } else bitSize -= piece.bitSize; if (!AddPiece(piece)) return false; if (++i >= count) break; if (!piece.Copy(other.PieceAt(i))) return false; } } else { // Little endian: Skip the superfluous least significant bits, copy the // pieces we need (cutting the first and the last one as needed) and // ignore the remaining pieces. // skip pieces for the least significant bits we don't need anymore uint64 bitsToSkip = totalBitSize - bitOffset - bitSize; int32 i; ValuePieceLocation piece; for (i = 0; i < count; i++) { const ValuePieceLocation& tempPiece = other.PieceAt(i); if (tempPiece.bitSize > bitsToSkip) { if (!piece.Copy(tempPiece)) return false; break; } bitsToSkip -= piece.bitSize; } // handle partial piece if (bitsToSkip > 0) { piece.bitSize -= bitsToSkip; piece.Normalize(fBigEndian); } // handle remaining pieces while (bitSize > 0) { if (piece.bitSize > bitSize) { // the piece is bigger than the remaining size -- cut it piece.bitOffset += piece.bitSize - bitSize; piece.bitSize = bitSize; piece.Normalize(fBigEndian); bitSize = 0; } else bitSize -= piece.bitSize; if (!AddPiece(piece)) return false; if (++i >= count) break; if (!piece.Copy(other.PieceAt(i))) return false; } } return true; }