1 /* 2 * Copyright 2012-2015, Rene Gollent, rene@gollent.com 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "BListValueNode.h" 8 9 #include <new> 10 11 #include <AutoDeleter.h> 12 13 #include "AddressValueNode.h" 14 #include "Architecture.h" 15 #include "StringValue.h" 16 #include "TeamTypeInformation.h" 17 #include "Tracing.h" 18 #include "Type.h" 19 #include "TypeLookupConstraints.h" 20 #include "ValueLoader.h" 21 #include "ValueLocation.h" 22 #include "ValueNodeContainer.h" 23 24 25 // maximum number of array elements to show by default 26 static const int64 kMaxArrayElementCount = 20; 27 28 29 //#pragma mark - BListValueNode::BListElementNodeChild 30 31 32 class BListValueNode::BListElementNodeChild : public ValueNodeChild { 33 public: 34 BListElementNodeChild(BListValueNode* parent, 35 int64 elementIndex, Type* type); 36 virtual ~BListElementNodeChild(); 37 38 virtual const BString& Name() const { return fName; }; 39 virtual Type* GetType() const { return fType; }; 40 virtual ValueNode* Parent() const { return fParent; }; 41 42 virtual status_t ResolveLocation(ValueLoader* valueLoader, 43 ValueLocation*& _location); 44 45 private: 46 Type* fType; 47 BListValueNode* fParent; 48 int64 fElementIndex; 49 BString fName; 50 }; 51 52 53 BListValueNode::BListElementNodeChild::BListElementNodeChild( 54 BListValueNode* parent, int64 elementIndex, Type* type) 55 : 56 ValueNodeChild(), 57 fType(type), 58 fParent(parent), 59 fElementIndex(elementIndex), 60 fName() 61 { 62 fType->AcquireReference(); 63 fParent->AcquireReference(); 64 fName.SetToFormat("[%" B_PRId64 "]", fElementIndex); 65 } 66 67 68 BListValueNode::BListElementNodeChild::~BListElementNodeChild() 69 { 70 fType->ReleaseReference(); 71 fParent->ReleaseReference(); 72 } 73 74 75 status_t 76 BListValueNode::BListElementNodeChild::ResolveLocation( 77 ValueLoader* valueLoader, ValueLocation*& _location) 78 { 79 uint8 addressSize = valueLoader->GetArchitecture()->AddressSize(); 80 ValueLocation* location = new(std::nothrow) ValueLocation(); 81 if (location == NULL) 82 return B_NO_MEMORY; 83 84 85 uint64 listAddress = fParent->fDataLocation.ToUInt64(); 86 listAddress += fElementIndex * addressSize; 87 88 ValuePieceLocation piece; 89 piece.SetToMemory(listAddress); 90 piece.SetSize(addressSize); 91 location->AddPiece(piece); 92 93 _location = location; 94 return B_OK; 95 } 96 97 98 //#pragma mark - BListItemCountNodeChild 99 100 class BListValueNode::BListItemCountNodeChild : public ValueNodeChild { 101 public: 102 BListItemCountNodeChild(BVariant location, 103 BListValueNode* parent, Type* type); 104 virtual ~BListItemCountNodeChild(); 105 106 virtual const BString& Name() const { return fName; }; 107 virtual Type* GetType() const { return fType; }; 108 virtual ValueNode* Parent() const { return fParent; }; 109 110 virtual status_t ResolveLocation(ValueLoader* valueLoader, 111 ValueLocation*& _location); 112 113 private: 114 Type* fType; 115 BListValueNode* fParent; 116 BVariant fLocation; 117 BString fName; 118 }; 119 120 121 BListValueNode::BListItemCountNodeChild::BListItemCountNodeChild( 122 BVariant location, BListValueNode* parent, Type* type) 123 : 124 ValueNodeChild(), 125 fType(type), 126 fParent(parent), 127 fLocation(location), 128 fName("Capacity") 129 { 130 fType->AcquireReference(); 131 fParent->AcquireReference(); 132 } 133 134 135 BListValueNode::BListItemCountNodeChild::~BListItemCountNodeChild() 136 { 137 fType->ReleaseReference(); 138 fParent->ReleaseReference(); 139 } 140 141 142 status_t 143 BListValueNode::BListItemCountNodeChild::ResolveLocation( 144 ValueLoader* valueLoader, ValueLocation*& _location) 145 { 146 ValueLocation* location = new(std::nothrow) ValueLocation(); 147 if (location == NULL) 148 return B_NO_MEMORY; 149 150 ValuePieceLocation piece; 151 piece.SetToMemory(fLocation.ToUInt64()); 152 piece.SetSize(sizeof(int32)); 153 location->AddPiece(piece); 154 155 _location = location; 156 return B_OK; 157 } 158 159 160 //#pragma mark - BListValueNode 161 162 BListValueNode::BListValueNode(ValueNodeChild* nodeChild, 163 Type* type) 164 : 165 ValueNode(nodeChild), 166 fType(type), 167 fItemCountType(NULL), 168 fItemCount(0), 169 fCountChildCreated(false) 170 { 171 fType->AcquireReference(); 172 } 173 174 175 BListValueNode::~BListValueNode() 176 { 177 fType->ReleaseReference(); 178 for (int32 i = 0; i < fChildren.CountItems(); i++) 179 fChildren.ItemAt(i)->ReleaseReference(); 180 181 if (fItemCountType != NULL) 182 fItemCountType->ReleaseReference(); 183 } 184 185 186 Type* 187 BListValueNode::GetType() const 188 { 189 return fType; 190 } 191 192 193 status_t 194 BListValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader, 195 ValueLocation*& _location, Value*& _value) 196 { 197 // get the location 198 ValueLocation* location = NodeChild()->Location(); 199 if (location == NULL) 200 return B_BAD_VALUE; 201 202 203 // get the value type 204 type_code valueType; 205 if (valueLoader->GetArchitecture()->AddressSize() == 4) { 206 valueType = B_UINT32_TYPE; 207 TRACE_LOCALS(" -> 32 bit\n"); 208 } else { 209 valueType = B_UINT64_TYPE; 210 TRACE_LOCALS(" -> 64 bit\n"); 211 } 212 213 // load the value data 214 215 status_t error = B_OK; 216 217 ValueLocation* memberLocation = NULL; 218 CompoundType* baseType = dynamic_cast<CompoundType*>(fType); 219 220 if (baseType->CountTemplateParameters() != 0) { 221 // for BObjectList we need to walk up 222 // the hierarchy: BObjectList -> _PointerList_ -> BList 223 if (baseType->CountBaseTypes() == 0) 224 return B_BAD_DATA; 225 226 baseType = dynamic_cast<CompoundType*>(baseType->BaseTypeAt(0) 227 ->GetType()); 228 if (baseType == NULL || baseType->Name() != "_PointerList_") 229 return B_BAD_DATA; 230 231 if (baseType->CountBaseTypes() == 0) 232 return B_BAD_DATA; 233 234 baseType = dynamic_cast<CompoundType*>(baseType->BaseTypeAt(0) 235 ->GetType()); 236 if (baseType == NULL || baseType->Name() != "BList") 237 return B_BAD_DATA; 238 239 } 240 241 for (int32 i = 0; i < baseType->CountDataMembers(); i++) { 242 DataMember* member = baseType->DataMemberAt(i); 243 if (strcmp(member->Name(), "fObjectList") == 0) { 244 error = baseType->ResolveDataMemberLocation(member, 245 *location, memberLocation); 246 BReference<ValueLocation> locationRef(memberLocation, true); 247 if (error != B_OK) { 248 TRACE_LOCALS( 249 "BListValueNode::ResolvedLocationAndValue(): " 250 "failed to resolve location of header member: %s\n", 251 strerror(error)); 252 return error; 253 } 254 255 error = valueLoader->LoadValue(memberLocation, valueType, 256 false, fDataLocation); 257 if (error != B_OK) 258 return error; 259 } else if (strcmp(member->Name(), "fItemCount") == 0) { 260 error = baseType->ResolveDataMemberLocation(member, 261 *location, memberLocation); 262 BReference<ValueLocation> locationRef(memberLocation, true); 263 if (error != B_OK) { 264 TRACE_LOCALS( 265 "BListValueNode::ResolvedLocationAndValue(): " 266 "failed to resolve location of header member: %s\n", 267 strerror(error)); 268 return error; 269 } 270 271 fItemCountType = member->GetType(); 272 fItemCountType->AcquireReference(); 273 274 fItemCountLocation = memberLocation->PieceAt(0).address; 275 276 BVariant listSize; 277 error = valueLoader->LoadValue(memberLocation, B_INT32_TYPE, 278 false, listSize); 279 if (error != B_OK) 280 return error; 281 282 fItemCount = listSize.ToInt32(); 283 TRACE_LOCALS( 284 "BListValueNode::ResolvedLocationAndValue(): " 285 "detected list size %" B_PRId32 "\n", 286 fItemCount); 287 } 288 memberLocation = NULL; 289 } 290 291 location->AcquireReference(); 292 _location = location; 293 _value = NULL; 294 295 return B_OK; 296 } 297 298 299 status_t 300 BListValueNode::CreateChildren(TeamTypeInformation* info) 301 { 302 return CreateChildrenInRange(info, 0, kMaxArrayElementCount); 303 } 304 305 306 int32 307 BListValueNode::CountChildren() const 308 { 309 return fChildren.CountItems(); 310 } 311 312 313 ValueNodeChild* 314 BListValueNode::ChildAt(int32 index) const 315 { 316 return fChildren.ItemAt(index); 317 } 318 319 320 bool 321 BListValueNode::IsRangedContainer() const 322 { 323 return true; 324 } 325 326 327 bool 328 BListValueNode::IsContainerRangeFixed() const 329 { 330 return true; 331 } 332 333 334 void 335 BListValueNode::ClearChildren() 336 { 337 fChildren.MakeEmpty(); 338 fCountChildCreated = false; 339 if (fContainer != NULL) 340 fContainer->NotifyValueNodeChildrenDeleted(this); 341 } 342 343 344 status_t 345 BListValueNode::CreateChildrenInRange(TeamTypeInformation* info, 346 int32 lowIndex, int32 highIndex) 347 { 348 if (fLocationResolutionState != B_OK) 349 return fLocationResolutionState; 350 351 if (lowIndex < 0) 352 lowIndex = 0; 353 if (highIndex >= fItemCount) 354 highIndex = fItemCount - 1; 355 356 if (!fCountChildCreated && fItemCountType != NULL) { 357 BListItemCountNodeChild* countChild = new(std::nothrow) 358 BListItemCountNodeChild(fItemCountLocation, this, fItemCountType); 359 360 if (countChild == NULL) 361 return B_NO_MEMORY; 362 363 fCountChildCreated = true; 364 countChild->SetContainer(fContainer); 365 fChildren.AddItem(countChild); 366 } 367 368 BReference<Type> addressTypeRef; 369 Type* type = NULL; 370 CompoundType* objectType = dynamic_cast<CompoundType*>(fType); 371 if (objectType->CountTemplateParameters() != 0) { 372 AddressType* addressType = NULL; 373 status_t result = objectType->TemplateParameterAt(0)->GetType() 374 ->CreateDerivedAddressType(DERIVED_TYPE_POINTER, addressType); 375 if (result != B_OK) 376 return result; 377 378 type = addressType; 379 addressTypeRef.SetTo(type, true); 380 } else { 381 BString typeName; 382 TypeLookupConstraints constraints; 383 constraints.SetTypeKind(TYPE_ADDRESS); 384 constraints.SetBaseTypeName("void"); 385 status_t result = info->LookupTypeByName(typeName, constraints, 386 type); 387 if (result != B_OK) 388 return result; 389 } 390 391 for (int32 i = lowIndex; i <= highIndex; i++) 392 { 393 BListElementNodeChild* child = 394 new(std::nothrow) BListElementNodeChild(this, i, type); 395 if (child == NULL) 396 return B_NO_MEMORY; 397 child->SetContainer(fContainer); 398 fChildren.AddItem(child); 399 } 400 401 fChildrenCreated = true; 402 403 if (fContainer != NULL) 404 fContainer->NotifyValueNodeChildrenCreated(this); 405 406 return B_OK; 407 } 408 409 410 status_t 411 BListValueNode::SupportedChildRange(int32& lowIndex, int32& highIndex) const 412 { 413 lowIndex = 0; 414 highIndex = fItemCount - 1; 415 416 return B_OK; 417 } 418 419