status_t AbstractArrayValueNode::CreateChildrenInRange(int32 lowIndex, int32 highIndex) { // TODO: ensure that we don't already have children in the specified // index range. These need to be skipped if so. TRACE_LOCALS("TYPE_ARRAY\n"); int32 dimensionCount = fType->CountDimensions(); bool isFinalDimension = fDimension + 1 == dimensionCount; status_t error = B_OK; if (!fBoundsInitialized) { int32 lowerBound, upperBound; error = SupportedChildRange(lowerBound, upperBound); if (error != B_OK) return error; fLowerBound = lowerBound; fUpperBound = upperBound; fBoundsInitialized = true; } if (lowIndex < fLowerBound) lowIndex = fLowerBound; if (highIndex > fUpperBound) highIndex = fUpperBound; // create children for the array elements for (int32 i = lowIndex; i <= highIndex; i++) { BString name(Name()); name << '[' << i << ']'; if (name.Length() <= Name().Length()) return B_NO_MEMORY; AbstractArrayValueNodeChild* child; if (isFinalDimension) { child = new(std::nothrow) ArrayValueNodeChild(this, name, i, fType->BaseType()); } else { child = new(std::nothrow) InternalArrayValueNodeChild(this, name, i, fType); } if (child == NULL || !fChildren.AddItem(child)) { delete child; return B_NO_MEMORY; } child->SetContainer(fContainer); } if (fContainer != NULL) fContainer->NotifyValueNodeChildrenCreated(this); return B_OK; }
status_t AbstractArrayValueNode::CreateChildren() { if (!fChildren.IsEmpty()) return B_OK; TRACE_LOCALS("TYPE_ARRAY\n"); int32 dimensionCount = fType->CountDimensions(); bool isFinalDimension = fDimension + 1 == dimensionCount; ArrayDimension* dimension = fType->DimensionAt(fDimension); uint64 elementCount = dimension->CountElements(); if (elementCount == 0 || elementCount > kMaxArrayElementCount) elementCount = kMaxArrayElementCount; // create children for the array elements for (int32 i = 0; i < (int32)elementCount; i++) { BString name(Name()); name << '[' << i << ']'; if (name.Length() <= Name().Length()) return B_NO_MEMORY; AbstractArrayValueNodeChild* child; if (isFinalDimension) { child = new(std::nothrow) ArrayValueNodeChild(this, name, i, fType->BaseType()); } else { child = new(std::nothrow) InternalArrayValueNodeChild(this, name, i, fType); } if (child == NULL || !fChildren.AddItem(child)) { delete child; return B_NO_MEMORY; } child->SetContainer(fContainer); } if (fContainer != NULL) fContainer->NotifyValueNodeChildrenCreated(this); return B_OK; }
status_t ArrayValueNodeChild::ResolveLocation(ValueLoader* valueLoader, ValueLocation*& _location) { // get the parent (== array) location ValueLocation* parentLocation = fParent->Location(); if (parentLocation == NULL) return B_BAD_VALUE; // create an array index path ArrayType* arrayType = fParent->GetArrayType(); int32 dimensionCount = arrayType->CountDimensions(); // add dummy indices first -- we'll replace them on our way back through // our ancestors ArrayIndexPath indexPath; for (int32 i = 0; i < dimensionCount; i++) { if (!indexPath.AddIndex(0)) return B_NO_MEMORY; } AbstractArrayValueNodeChild* child = this; for (int32 i = dimensionCount - 1; i >= 0; i--) { indexPath.SetIndexAt(i, child->ElementIndex()); child = dynamic_cast<AbstractArrayValueNodeChild*>( child->ArrayParent()->NodeChild()); } // resolve the element location ValueLocation* location; status_t error = arrayType->ResolveElementLocation(indexPath, *parentLocation, location); if (error != B_OK) { TRACE_LOCALS("ArrayValueNodeChild::ResolveLocation(): " "ResolveElementLocation() failed: %s\n", strerror(error)); return error; } _location = location; return B_OK; }
status_t DwarfCompoundType::ResolveDataMemberLocation(DataMember* _member, const ValueLocation& parentLocation, ValueLocation*& _location) { DwarfDataMember* member = dynamic_cast<DwarfDataMember*>(_member); if (member == NULL) return B_BAD_VALUE; DwarfTypeContext* typeContext = TypeContext(); bool isBitField = true; DIEMember* memberEntry = member->Entry(); // TODO: handle DW_AT_data_bit_offset if (!memberEntry->ByteSize()->IsValid() && !memberEntry->BitOffset()->IsValid() && !memberEntry->BitSize()->IsValid()) { isBitField = false; } ValueLocation* location; status_t error = _ResolveDataMemberLocation(member->GetDwarfType(), member->Entry()->Location(), parentLocation, isBitField, location); if (error != B_OK) return error; // If the member isn't a bit field, we're done. if (!isBitField) { _location = location; return B_OK; } BReference<ValueLocation> locationReference(location); // get the byte size target_addr_t byteSize; if (memberEntry->ByteSize()->IsValid()) { BVariant value; error = typeContext->File()->EvaluateDynamicValue( typeContext->GetCompilationUnit(), typeContext->AddressSize(), typeContext->SubprogramEntry(), memberEntry->ByteSize(), typeContext->TargetInterface(), typeContext->InstructionPointer(), typeContext->FramePointer(), value); if (error != B_OK) return error; byteSize = value.ToUInt64(); } else byteSize = ByteSize(); // get the bit offset uint64 bitOffset = 0; if (memberEntry->BitOffset()->IsValid()) { BVariant value; error = typeContext->File()->EvaluateDynamicValue( typeContext->GetCompilationUnit(), typeContext->AddressSize(), typeContext->SubprogramEntry(), memberEntry->BitOffset(), typeContext->TargetInterface(), typeContext->InstructionPointer(), typeContext->FramePointer(), value); if (error != B_OK) return error; bitOffset = value.ToUInt64(); } // get the bit size uint64 bitSize = byteSize * 8; if (memberEntry->BitSize()->IsValid()) { BVariant value; error = typeContext->File()->EvaluateDynamicValue( typeContext->GetCompilationUnit(), typeContext->AddressSize(), typeContext->SubprogramEntry(), memberEntry->BitSize(), typeContext->TargetInterface(), typeContext->InstructionPointer(), typeContext->FramePointer(), value); if (error != B_OK) return error; bitSize = value.ToUInt64(); } TRACE_LOCALS("bit field: byte size: %" B_PRIu64 ", bit offset/size: %" B_PRIu64 "/%" B_PRIu64 "\n", byteSize, bitOffset, bitSize); if (bitOffset + bitSize > byteSize * 8) return B_BAD_VALUE; // create the bit field value location ValueLocation* bitFieldLocation = new(std::nothrow) ValueLocation; if (bitFieldLocation == NULL) return B_NO_MEMORY; BReference<ValueLocation> bitFieldLocationReference(bitFieldLocation, true); if (!bitFieldLocation->SetTo(*location, bitOffset, bitSize)) return B_NO_MEMORY; _location = bitFieldLocationReference.Detach(); return B_OK; }
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; }
status_t DwarfArrayType::ResolveElementLocation(const ArrayIndexPath& indexPath, const ValueLocation& parentLocation, ValueLocation*& _location) { if (indexPath.CountIndices() != CountDimensions()) return B_BAD_VALUE; DwarfTypeContext* typeContext = TypeContext(); // If the array entry has a bit stride, get it. Otherwise fall back to the // element type size. int64 bitStride; DIEArrayType* bitStrideOwnerEntry = NULL; if (fEntry != NULL && (bitStrideOwnerEntry = DwarfUtils::GetDIEByPredicate( fEntry, HasBitStridePredicate<DIEArrayType>()))) { BVariant value; status_t error = typeContext->File()->EvaluateDynamicValue( typeContext->GetCompilationUnit(), typeContext->AddressSize(), typeContext->SubprogramEntry(), bitStrideOwnerEntry->BitStride(), typeContext->TargetInterface(), typeContext->InstructionPointer(), typeContext->FramePointer(), value); if (error != B_OK) return error; if (!value.IsInteger()) return B_BAD_VALUE; bitStride = value.ToInt64(); } else bitStride = BaseType()->ByteSize() * 8; // Iterate backward through the dimensions and compute the total offset of // the element. int64 elementOffset = 0; DwarfArrayDimension* previousDimension = NULL; int64 previousDimensionStride = 0; for (int32 dimensionIndex = CountDimensions() - 1; dimensionIndex >= 0; dimensionIndex--) { DwarfArrayDimension* dimension = DwarfDimensionAt(dimensionIndex); int64 index = indexPath.IndexAt(dimensionIndex); // If the dimension has a special bit/byte stride, get it. int64 dimensionStride = 0; DwarfType* dimensionType = dimension->GetDwarfType(); DIEArrayIndexType* dimensionTypeEntry = dimensionType != NULL ? dynamic_cast<DIEArrayIndexType*>(dimensionType->GetDIEType()) : NULL; if (dimensionTypeEntry != NULL) { DIEArrayIndexType* bitStrideOwnerEntry = DwarfUtils::GetDIEByPredicate(dimensionTypeEntry, HasBitStridePredicate<DIEArrayIndexType>()); if (bitStrideOwnerEntry != NULL) { BVariant value; status_t error = typeContext->File()->EvaluateDynamicValue( typeContext->GetCompilationUnit(), typeContext->AddressSize(), typeContext->SubprogramEntry(), bitStrideOwnerEntry->BitStride(), typeContext->TargetInterface(), typeContext->InstructionPointer(), typeContext->FramePointer(), value); if (error != B_OK) return error; if (!value.IsInteger()) return B_BAD_VALUE; dimensionStride = value.ToInt64(); } else { DIEArrayIndexType* byteStrideOwnerEntry = DwarfUtils::GetDIEByPredicate(dimensionTypeEntry, HasByteStridePredicate<DIEArrayIndexType>()); if (byteStrideOwnerEntry != NULL) { BVariant value; status_t error = typeContext->File()->EvaluateDynamicValue( typeContext->GetCompilationUnit(), typeContext->AddressSize(), typeContext->SubprogramEntry(), byteStrideOwnerEntry->ByteStride(), typeContext->TargetInterface(), typeContext->InstructionPointer(), typeContext->FramePointer(), value); if (error != B_OK) return error; if (!value.IsInteger()) return B_BAD_VALUE; dimensionStride = value.ToInt64() * 8; } } } // If we don't have a stride for the dimension yet, use the stride of // the previous dimension multiplied by the size of the dimension. if (dimensionStride == 0) { if (previousDimension != NULL) { dimensionStride = previousDimensionStride * previousDimension->CountElements(); } else { // the last dimension -- use the element bit stride dimensionStride = bitStride; } } // If the dimension stride is still 0 (that can happen, if the dimension // doesn't have a stride and the previous dimension's element count is // not known), we can only resolve the first element. if (dimensionStride == 0 && index != 0) { WARNING("No dimension bit stride for dimension %" B_PRId32 " and " "element index is not 0.\n", dimensionIndex); return B_BAD_VALUE; } elementOffset += dimensionStride * index; previousDimension = dimension; previousDimensionStride = dimensionStride; } TRACE_LOCALS("total element bit offset: %" B_PRId64 "\n", elementOffset); // create the value location object for the element ValueLocation* location = new(std::nothrow) ValueLocation( parentLocation.IsBigEndian()); if (location == NULL) return B_NO_MEMORY; BReference<ValueLocation> locationReference(location, true); // If we have a single memory piece location for the array, we compute the // element's location by hand -- not uncommonly the array size isn't known. if (parentLocation.CountPieces() == 1) { ValuePieceLocation piece = parentLocation.PieceAt(0); if (piece.type == VALUE_PIECE_LOCATION_MEMORY) { int64 byteOffset = elementOffset >= 0 ? elementOffset / 8 : (elementOffset - 7) / 8; piece.SetToMemory(piece.address + byteOffset); piece.SetSize(BaseType()->ByteSize()); // TODO: Support bit offsets correctly! // TODO: Support bit fields (primitive types) correctly! if (!location->AddPiece(piece)) return B_NO_MEMORY; _location = locationReference.Detach(); return B_OK; } } // We can't deal with negative element offsets at this point. It doesn't // make a lot of sense anyway, if the array location consists of multiple // pieces or lives in a register. if (elementOffset < 0) { WARNING("Negative element offset unsupported for multiple location " "pieces or register pieces.\n"); return B_UNSUPPORTED; } if (!location->SetTo(parentLocation, elementOffset, BaseType()->ByteSize() * 8)) { return B_NO_MEMORY; } _location = locationReference.Detach(); return B_OK; }
status_t ResolveValueNodeValueJob::_ResolveNodeValue() { // get the node child and parent node AutoLocker<ValueNodeContainer> containerLocker(fContainer); ValueNodeChild* nodeChild = fValueNode->NodeChild(); BReference<ValueNodeChild> nodeChildReference(nodeChild); ValueNode* parentNode = nodeChild->Parent(); BReference<ValueNode> parentNodeReference(parentNode); // Check whether the node child location has been resolved already // (successfully). status_t nodeChildResolutionState = nodeChild->LocationResolutionState(); bool nodeChildDone = nodeChildResolutionState != VALUE_NODE_UNRESOLVED; if (nodeChildDone && nodeChildResolutionState != B_OK) return nodeChildResolutionState; // If the child node location has not been resolved yet, check whether the // parent node location and value have been resolved already (successfully). bool parentDone = true; if (!nodeChildDone && parentNode != NULL) { status_t parentResolutionState = parentNode->LocationAndValueResolutionState(); parentDone = parentResolutionState != VALUE_NODE_UNRESOLVED; if (parentDone && parentResolutionState != B_OK) return parentResolutionState; } containerLocker.Unlock(); // resolve the parent node location and value, if necessary if (!parentDone) { status_t error = _ResolveParentNodeValue(parentNode); if (error != B_OK) { TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value " "node: %p (\"%s\"): _ResolveParentNodeValue(%p) failed\n", fValueNode, fValueNode->Name().String(), parentNode); return error; } } // resolve the node child location, if necessary if (!nodeChildDone) { status_t error = _ResolveNodeChildLocation(nodeChild); if (error != B_OK) { TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value " "node: %p (\"%s\"): _ResolveNodeChildLocation(%p) failed\n", fValueNode, fValueNode->Name().String(), nodeChild); return error; } } // resolve the node location and value ValueLoader valueLoader(fArchitecture, fDebuggerInterface, fTypeInformation, fCpuState); ValueLocation* location; Value* value; status_t error = fValueNode->ResolvedLocationAndValue(&valueLoader, location, value); if (error != B_OK) { TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value " "node: %p (\"%s\"): fValueNode->ResolvedLocationAndValue() " "failed\n", fValueNode, fValueNode->Name().String()); return error; } BReference<ValueLocation> locationReference(location, true); BReference<Value> valueReference(value, true); // set location and value on the node containerLocker.Lock(); status_t nodeResolutionState = fValueNode->LocationAndValueResolutionState(); if (nodeResolutionState != VALUE_NODE_UNRESOLVED) return nodeResolutionState; fValueNode->SetLocationAndValue(location, value, B_OK); containerLocker.Unlock(); return B_OK; }
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; } } }
status_t BListValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader, ValueLocation*& _location, Value*& _value) { // get the location ValueLocation* location = NodeChild()->Location(); if (location == NULL) return B_BAD_VALUE; // get the value type type_code valueType; if (valueLoader->GetArchitecture()->AddressSize() == 4) { valueType = B_UINT32_TYPE; TRACE_LOCALS(" -> 32 bit\n"); } else { valueType = B_UINT64_TYPE; TRACE_LOCALS(" -> 64 bit\n"); } // load the value data status_t error = B_OK; _location = location; _value = NULL; ValueLocation* memberLocation = NULL; CompoundType* baseType = dynamic_cast<CompoundType*>(fType); if (baseType->CountTemplateParameters() != 0) { // for BObjectList we need to walk up // the hierarchy: BObjectList -> _PointerList_ -> BList if (baseType->CountBaseTypes() == 0) return B_BAD_DATA; baseType = dynamic_cast<CompoundType*>(baseType->BaseTypeAt(0) ->GetType()); if (baseType == NULL || baseType->Name() != "_PointerList_") return B_BAD_DATA; if (baseType->CountBaseTypes() == 0) return B_BAD_DATA; baseType = dynamic_cast<CompoundType*>(baseType->BaseTypeAt(0) ->GetType()); if (baseType == NULL || baseType->Name() != "BList") return B_BAD_DATA; } for (int32 i = 0; i < baseType->CountDataMembers(); i++) { DataMember* member = baseType->DataMemberAt(i); if (strcmp(member->Name(), "fObjectList") == 0) { error = baseType->ResolveDataMemberLocation(member, *location, memberLocation); BReference<ValueLocation> locationRef(memberLocation, true); if (error != B_OK) { TRACE_LOCALS( "BListValueNode::ResolvedLocationAndValue(): " "failed to resolve location of header member: %s\n", strerror(error)); return error; } error = valueLoader->LoadValue(memberLocation, valueType, false, fDataLocation); if (error != B_OK) return error; } else if (strcmp(member->Name(), "fItemCount") == 0) { error = baseType->ResolveDataMemberLocation(member, *location, memberLocation); BReference<ValueLocation> locationRef(memberLocation, true); if (error != B_OK) { TRACE_LOCALS( "BListValueNode::ResolvedLocationAndValue(): " "failed to resolve location of header member: %s\n", strerror(error)); return error; } fItemCountType = member->GetType(); fItemCountType->AcquireReference(); fItemCountLocation = memberLocation->PieceAt(0).address; BVariant listSize; error = valueLoader->LoadValue(memberLocation, valueType, false, listSize); if (error != B_OK) return error; fItemCount = listSize.ToInt32(); TRACE_LOCALS( "BListValueNode::ResolvedLocationAndValue(): " "detected list size %" B_PRId32 "\n", fItemCount); } memberLocation = NULL; } return B_OK; }