1 /*
2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2013, Rene Gollent, rene@gollent.com.
4 * Distributed under the terms of the MIT License.
5 */
6
7
8 #include "DwarfTypeFactory.h"
9
10 #include <algorithm>
11 #include <new>
12
13 #include <AutoLocker.h>
14 #include <Variant.h>
15
16 #include "ArrayIndexPath.h"
17 #include "Architecture.h"
18 #include "CompilationUnit.h"
19 #include "DebugInfoEntries.h"
20 #include "Dwarf.h"
21 #include "DwarfFile.h"
22 #include "DwarfTargetInterface.h"
23 #include "DwarfUtils.h"
24 #include "DwarfTypes.h"
25 #include "GlobalTypeLookup.h"
26 #include "Register.h"
27 #include "RegisterMap.h"
28 #include "SourceLanguageInfo.h"
29 #include "Tracing.h"
30 #include "TypeLookupConstraints.h"
31 #include "ValueLocation.h"
32
33
34 namespace {
35
36
37 // #pragma mark - HasTypePredicate
38
39
40 template<typename EntryType>
41 struct HasTypePredicate {
operator ()__anon79d13b350111::HasTypePredicate42 inline bool operator()(EntryType* entry) const
43 {
44 return entry->GetType() != NULL;
45 }
46 };
47
48
49 // #pragma mark - HasReturnTypePredicate
50
51
52 template<typename EntryType>
53 struct HasReturnTypePredicate {
operator ()__anon79d13b350111::HasReturnTypePredicate54 inline bool operator()(EntryType* entry) const
55 {
56 return entry->ReturnType() != NULL;
57 }
58 };
59
60
61 // #pragma mark - HasEnumeratorsPredicate
62
63
64 struct HasEnumeratorsPredicate {
operator ()__anon79d13b350111::HasEnumeratorsPredicate65 inline bool operator()(DIEEnumerationType* entry) const
66 {
67 return !entry->Enumerators().IsEmpty();
68 }
69 };
70
71
72 // #pragma mark - HasDimensionsPredicate
73
74
75 struct HasDimensionsPredicate {
operator ()__anon79d13b350111::HasDimensionsPredicate76 inline bool operator()(DIEArrayType* entry) const
77 {
78 return !entry->Dimensions().IsEmpty();
79 }
80 };
81
82
83 // #pragma mark - HasMembersPredicate
84
85
86 struct HasMembersPredicate {
operator ()__anon79d13b350111::HasMembersPredicate87 inline bool operator()(DIECompoundType* entry) const
88 {
89 return !entry->DataMembers().IsEmpty();
90 }
91 };
92
93
94 // #pragma mark - HasBaseTypesPredicate
95
96
97 struct HasBaseTypesPredicate {
operator ()__anon79d13b350111::HasBaseTypesPredicate98 inline bool operator()(DIEClassBaseType* entry) const
99 {
100 return !entry->BaseTypes().IsEmpty();
101 }
102 };
103
104
105 // #pragma mark - HasTemplateParametersPredicate
106
107
108 struct HasTemplateParametersPredicate {
operator ()__anon79d13b350111::HasTemplateParametersPredicate109 inline bool operator()(DIEClassBaseType* entry) const
110 {
111 return !entry->TemplateParameters().IsEmpty();
112 }
113 };
114
115
116 // #pragma mark - HasParametersPredicate
117
118
119 template<typename EntryType>
120 struct HasParametersPredicate {
operator ()__anon79d13b350111::HasParametersPredicate121 inline bool operator()(EntryType* entry) const
122 {
123 return !entry->Parameters().IsEmpty();
124 }
125 };
126
127
128 // #pragma mark - HasLowerBoundPredicate
129
130
131 struct HasLowerBoundPredicate {
operator ()__anon79d13b350111::HasLowerBoundPredicate132 inline bool operator()(DIESubrangeType* entry) const
133 {
134 return entry->LowerBound()->IsValid();
135 }
136 };
137
138
139 // #pragma mark - HasUpperBoundPredicate
140
141
142 struct HasUpperBoundPredicate {
operator ()__anon79d13b350111::HasUpperBoundPredicate143 inline bool operator()(DIESubrangeType* entry) const
144 {
145 return entry->UpperBound()->IsValid();
146 }
147 };
148
149
150 // #pragma mark - HasCountPredicate
151
152
153 struct HasCountPredicate {
operator ()__anon79d13b350111::HasCountPredicate154 inline bool operator()(DIESubrangeType* entry) const
155 {
156 return entry->Count()->IsValid();
157 }
158 };
159
160
161 // #pragma mark - HasContainingTypePredicate
162
163
164 struct HasContainingTypePredicate {
operator ()__anon79d13b350111::HasContainingTypePredicate165 inline bool operator()(DIEPointerToMemberType* entry) const
166 {
167 return entry->ContainingType() != NULL;
168 }
169 };
170
171
172 } // unnamed namespace
173
174
175 // #pragma mark - ArtificialIntegerType
176
177
178 class DwarfTypeFactory::ArtificialIntegerType : public PrimitiveType {
179 public:
ArtificialIntegerType(const BString & id,const BString & name,target_size_t byteSize,uint32 typeConstant)180 ArtificialIntegerType(const BString& id, const BString& name,
181 target_size_t byteSize, uint32 typeConstant)
182 :
183 fID(id),
184 fName(name),
185 fByteSize(byteSize),
186 fTypeConstant(typeConstant)
187 {
188 }
189
Create(target_size_t byteSize,bool isSigned,Type * & _type)190 static status_t Create(target_size_t byteSize, bool isSigned, Type*& _type)
191 {
192 // get the matching type constant
193 uint32 typeConstant;
194 switch (byteSize) {
195 case 1:
196 typeConstant = isSigned ? B_INT8_TYPE : B_UINT8_TYPE;
197 break;
198 case 2:
199 typeConstant = isSigned ? B_INT16_TYPE : B_UINT16_TYPE;
200 break;
201 case 4:
202 typeConstant = isSigned ? B_INT32_TYPE : B_UINT32_TYPE;
203 break;
204 case 8:
205 typeConstant = isSigned ? B_INT64_TYPE : B_UINT64_TYPE;
206 break;
207 default:
208 return B_BAD_VALUE;
209 }
210
211 // name and ID
212 char buffer[16];
213 snprintf(buffer, sizeof(buffer), isSigned ? "int%d" : "uint%d",
214 (int)byteSize * 8);
215 BString id(buffer);
216 if (id.Length() == 0)
217 return B_NO_MEMORY;
218
219 // create the type
220 ArtificialIntegerType* type = new(std::nothrow) ArtificialIntegerType(
221 id, id, byteSize, typeConstant);
222 if (type == NULL)
223 return B_NO_MEMORY;
224
225 _type = type;
226 return B_OK;
227 }
228
ImageID() const229 virtual image_id ImageID() const
230 {
231 return -1;
232 }
233
ID() const234 virtual const BString& ID() const
235 {
236 return fID;
237 }
238
Name() const239 virtual const BString& Name() const
240 {
241 return fName;
242 }
243
ByteSize() const244 virtual target_size_t ByteSize() const
245 {
246 return fByteSize;
247 }
248
ResolveObjectDataLocation(const ValueLocation & objectLocation,ValueLocation * & _location)249 virtual status_t ResolveObjectDataLocation(
250 const ValueLocation& objectLocation, ValueLocation*& _location)
251 {
252 // TODO: Implement!
253 return B_UNSUPPORTED;
254 }
255
ResolveObjectDataLocation(target_addr_t objectAddress,ValueLocation * & _location)256 virtual status_t ResolveObjectDataLocation(target_addr_t objectAddress,
257 ValueLocation*& _location)
258 {
259 // TODO: Implement!
260 return B_UNSUPPORTED;
261 }
262
TypeConstant() const263 virtual uint32 TypeConstant() const
264 {
265 return fTypeConstant;
266 }
267
268 private:
269 BString fID;
270 BString fName;
271 uint32 fByteSize;
272 uint32 fTypeConstant;
273 };
274
275
276 // #pragma mark - DwarfTypeFactory
277
278
DwarfTypeFactory(DwarfTypeContext * typeContext,GlobalTypeLookup * typeLookup,GlobalTypeCache * typeCache)279 DwarfTypeFactory::DwarfTypeFactory(DwarfTypeContext* typeContext,
280 GlobalTypeLookup* typeLookup, GlobalTypeCache* typeCache)
281 :
282 fTypeContext(typeContext),
283 fTypeLookup(typeLookup),
284 fTypeCache(typeCache)
285 {
286 fTypeContext->AcquireReference();
287 fTypeCache->AcquireReference();
288 }
289
290
~DwarfTypeFactory()291 DwarfTypeFactory::~DwarfTypeFactory()
292 {
293 fTypeContext->ReleaseReference();
294 fTypeCache->ReleaseReference();
295 }
296
297
298 status_t
CreateType(DIEType * typeEntry,DwarfType * & _type)299 DwarfTypeFactory::CreateType(DIEType* typeEntry, DwarfType*& _type)
300 {
301 // try the type cache first
302 BString name;
303 DwarfUtils::GetFullyQualifiedDIEName(typeEntry, name);
304
305 TypeLookupConstraints constraints(
306 dwarf_tag_to_type_kind(typeEntry->Tag()));
307 int32 subtypeKind = dwarf_tag_to_subtype_kind(typeEntry->Tag());
308 if (subtypeKind >= 0)
309 constraints.SetSubtypeKind(subtypeKind);
310
311 AutoLocker<GlobalTypeCache> cacheLocker(fTypeCache);
312 Type* globalType = name.Length() > 0
313 ? fTypeCache->GetType(name, constraints) : NULL;
314 if (globalType == NULL) {
315 // lookup by name failed -- try lookup by ID
316 BString id;
317 if (DwarfType::GetTypeID(typeEntry, id))
318 globalType = fTypeCache->GetTypeByID(id);
319 }
320
321 if (globalType != NULL) {
322 DwarfType* globalDwarfType = dynamic_cast<DwarfType*>(globalType);
323 if (globalDwarfType != NULL) {
324 globalDwarfType->AcquireReference();
325 _type = globalDwarfType;
326 return B_OK;
327 }
328 }
329
330 cacheLocker.Unlock();
331
332 // If the type entry indicates a declaration only, we try to look the
333 // type up globally first.
334 if (typeEntry->IsDeclaration() && name.Length() > 0
335 && fTypeLookup->GetType(fTypeCache, name,
336 constraints, globalType)
337 == B_OK) {
338 DwarfType* globalDwarfType
339 = dynamic_cast<DwarfType*>(globalType);
340 if (globalDwarfType != NULL) {
341 _type = globalDwarfType;
342 return B_OK;
343 }
344
345 globalType->ReleaseReference();
346 }
347
348 // No luck yet -- create the type.
349 DwarfType* type;
350 status_t error = _CreateTypeInternal(name, typeEntry, type);
351 if (error != B_OK)
352 return error;
353 BReference<DwarfType> typeReference(type, true);
354
355 // Insert the type into the cache. Re-check, as the type may already
356 // have been inserted (e.g. in the compound type case).
357 cacheLocker.Lock();
358 if (name.Length() > 0
359 ? fTypeCache->GetType(name, constraints) == NULL
360 : fTypeCache->GetTypeByID(type->ID()) == NULL) {
361 error = fTypeCache->AddType(type);
362 if (error != B_OK)
363 return error;
364 }
365 cacheLocker.Unlock();
366
367 // try to get the type's size
368 uint64 size;
369 if (_ResolveTypeByteSize(typeEntry, size) == B_OK)
370 type->SetByteSize(size);
371
372 _type = typeReference.Detach();
373 return B_OK;
374 }
375
376
377 status_t
_CreateTypeInternal(const BString & name,DIEType * typeEntry,DwarfType * & _type)378 DwarfTypeFactory::_CreateTypeInternal(const BString& name,
379 DIEType* typeEntry, DwarfType*& _type)
380 {
381 switch (typeEntry->Tag()) {
382 case DW_TAG_class_type:
383 case DW_TAG_structure_type:
384 case DW_TAG_union_type:
385 case DW_TAG_interface_type:
386 return _CreateCompoundType(name,
387 dynamic_cast<DIECompoundType*>(typeEntry),
388 (compound_type_kind)dwarf_tag_to_subtype_kind(
389 typeEntry->Tag()), _type);
390
391 case DW_TAG_base_type:
392 return _CreatePrimitiveType(name,
393 dynamic_cast<DIEBaseType*>(typeEntry), _type);
394
395 case DW_TAG_pointer_type:
396 return _CreateAddressType(name,
397 dynamic_cast<DIEAddressingType*>(typeEntry),
398 DERIVED_TYPE_POINTER, _type);
399 case DW_TAG_reference_type:
400 return _CreateAddressType(name,
401 dynamic_cast<DIEAddressingType*>(typeEntry),
402 DERIVED_TYPE_REFERENCE, _type);
403
404 case DW_TAG_const_type:
405 return _CreateModifiedType(name,
406 dynamic_cast<DIEModifiedType*>(typeEntry),
407 TYPE_MODIFIER_CONST, _type);
408 case DW_TAG_packed_type:
409 return _CreateModifiedType(name,
410 dynamic_cast<DIEModifiedType*>(typeEntry),
411 TYPE_MODIFIER_PACKED, _type);
412 case DW_TAG_volatile_type:
413 return _CreateModifiedType(name,
414 dynamic_cast<DIEModifiedType*>(typeEntry),
415 TYPE_MODIFIER_VOLATILE, _type);
416 case DW_TAG_restrict_type:
417 return _CreateModifiedType(name,
418 dynamic_cast<DIEModifiedType*>(typeEntry),
419 TYPE_MODIFIER_RESTRICT, _type);
420 case DW_TAG_shared_type:
421 return _CreateModifiedType(name,
422 dynamic_cast<DIEModifiedType*>(typeEntry),
423 TYPE_MODIFIER_SHARED, _type);
424
425 case DW_TAG_typedef:
426 return _CreateTypedefType(name,
427 dynamic_cast<DIETypedef*>(typeEntry), _type);
428
429 case DW_TAG_array_type:
430 return _CreateArrayType(name,
431 dynamic_cast<DIEArrayType*>(typeEntry), _type);
432
433 case DW_TAG_enumeration_type:
434 return _CreateEnumerationType(name,
435 dynamic_cast<DIEEnumerationType*>(typeEntry), _type);
436
437 case DW_TAG_subrange_type:
438 return _CreateSubrangeType(name,
439 dynamic_cast<DIESubrangeType*>(typeEntry), _type);
440
441 case DW_TAG_unspecified_type:
442 return _CreateUnspecifiedType(name,
443 dynamic_cast<DIEUnspecifiedType*>(typeEntry), _type);
444
445 case DW_TAG_subroutine_type:
446 return _CreateFunctionType(name,
447 dynamic_cast<DIESubroutineType*>(typeEntry), _type);
448
449 case DW_TAG_ptr_to_member_type:
450 return _CreatePointerToMemberType(name,
451 dynamic_cast<DIEPointerToMemberType*>(typeEntry), _type);
452
453 case DW_TAG_string_type:
454 case DW_TAG_file_type:
455 case DW_TAG_set_type:
456 // TODO: Implement (not relevant for C++)!
457 return B_UNSUPPORTED;
458 }
459
460 return B_UNSUPPORTED;
461 }
462
463
464 status_t
_CreateCompoundType(const BString & name,DIECompoundType * typeEntry,compound_type_kind compoundKind,DwarfType * & _type)465 DwarfTypeFactory::_CreateCompoundType(const BString& name,
466 DIECompoundType* typeEntry, compound_type_kind compoundKind, DwarfType*& _type)
467 {
468 TRACE_LOCALS("DwarfTypeFactory::_CreateCompoundType(\"%s\", %p, %d)\n",
469 name.String(), typeEntry, compoundKind);
470
471 // create the type
472 DwarfCompoundType* type = new(std::nothrow) DwarfCompoundType(fTypeContext,
473 name, typeEntry, compoundKind);
474 if (type == NULL)
475 return B_NO_MEMORY;
476 BReference<DwarfCompoundType> typeReference(type, true);
477
478 // Already add the type at this pointer to the cache, since otherwise
479 // we could run into an infinite recursion when trying to create the types
480 // for the data members.
481 // TODO: Since access to the type lookup context is multi-threaded, the
482 // incomplete type could become visible to other threads. Hence we keep the
483 // context locked, but that essentially kills multi-threading for this context.
484 AutoLocker<GlobalTypeCache> cacheLocker(fTypeCache);
485 status_t error = fTypeCache->AddType(type);
486 if (error != B_OK)
487 {
488 printf(" -> failed to add type to cache\n");
489 return error;
490 }
491 // cacheLocker.Unlock();
492
493 // find the abstract origin or specification that defines the data members
494 DIECompoundType* memberOwnerEntry = DwarfUtils::GetDIEByPredicate(typeEntry,
495 HasMembersPredicate());
496
497 // create the data member objects
498 if (memberOwnerEntry != NULL) {
499 for (DebugInfoEntryList::ConstIterator it
500 = memberOwnerEntry->DataMembers().GetIterator();
501 DebugInfoEntry* _memberEntry = it.Next();) {
502 DIEMember* memberEntry = dynamic_cast<DIEMember*>(_memberEntry);
503
504 TRACE_LOCALS(" member %p\n", memberEntry);
505
506 // get the type
507 DwarfType* memberType;
508 if (CreateType(memberEntry->GetType(), memberType) != B_OK)
509 continue;
510 BReference<DwarfType> memberTypeReference(memberType, true);
511
512 // get the name
513 BString memberName;
514 DwarfUtils::GetDIEName(memberEntry, memberName);
515
516 // create and add the member object
517 DwarfDataMember* member = new(std::nothrow) DwarfDataMember(
518 memberEntry, memberName, memberType);
519 BReference<DwarfDataMember> memberReference(member, true);
520 if (member == NULL || !type->AddDataMember(member)) {
521 cacheLocker.Lock();
522 fTypeCache->RemoveType(type);
523 return B_NO_MEMORY;
524 }
525 }
526 }
527
528 // If the type is a class/struct/interface type, we also need to add its
529 // base types, and possibly template parameters.
530 if (DIEClassBaseType* classTypeEntry
531 = dynamic_cast<DIEClassBaseType*>(typeEntry)) {
532 // find the abstract origin or specification that defines the base types
533 classTypeEntry = DwarfUtils::GetDIEByPredicate(classTypeEntry,
534 HasBaseTypesPredicate());
535
536 // create the inheritance objects for the base types
537 if (classTypeEntry != NULL) {
538 for (DebugInfoEntryList::ConstIterator it
539 = classTypeEntry->BaseTypes().GetIterator();
540 DebugInfoEntry* _inheritanceEntry = it.Next();) {
541 DIEInheritance* inheritanceEntry
542 = dynamic_cast<DIEInheritance*>(_inheritanceEntry);
543
544 // get the type
545 DwarfType* baseType;
546 if (CreateType(inheritanceEntry->GetType(), baseType) != B_OK)
547 continue;
548 BReference<DwarfType> baseTypeReference(baseType, true);
549
550 // create and add the inheritance object
551 DwarfInheritance* inheritance = new(std::nothrow)
552 DwarfInheritance(inheritanceEntry, baseType);
553 BReference<DwarfInheritance> inheritanceReference(inheritance,
554 true);
555 if (inheritance == NULL || !type->AddInheritance(inheritance)) {
556 cacheLocker.Lock();
557 fTypeCache->RemoveType(type);
558 return B_NO_MEMORY;
559 }
560 }
561 }
562
563 // find the abstract origin or specification that defines the template
564 // parameters
565 classTypeEntry = DwarfUtils::GetDIEByPredicate(
566 dynamic_cast<DIEClassBaseType*>(typeEntry),
567 HasTemplateParametersPredicate());
568
569 if (classTypeEntry != NULL) {
570 for (DebugInfoEntryList::ConstIterator it
571 = classTypeEntry->TemplateParameters()
572 .GetIterator();
573 DebugInfoEntry* _typeEntry = it.Next();) {
574 DIETemplateTypeParameter* templateTypeEntry
575 = dynamic_cast<DIETemplateTypeParameter*>(_typeEntry);
576 DwarfType* templateType;
577 if (templateTypeEntry != NULL) {
578 if (templateTypeEntry->GetType() == NULL
579 || CreateType(templateTypeEntry->GetType(),
580 templateType) != B_OK) {
581 continue;
582 }
583 } else {
584 DIETemplateValueParameter* templateValueEntry
585 = dynamic_cast<DIETemplateValueParameter*>(_typeEntry);
586 if (CreateType(templateValueEntry->GetType(), templateType)
587 != B_OK) {
588 continue;
589 }
590 }
591 BReference<DwarfType> templateTypeReference(templateType,
592 true);
593 DwarfTemplateParameter* parameter
594 = new(std::nothrow) DwarfTemplateParameter(_typeEntry,
595 templateType);
596 if (parameter == NULL) {
597 cacheLocker.Lock();
598 fTypeCache->RemoveType(type);
599 return B_NO_MEMORY;
600 }
601
602 if (!type->AddTemplateParameter(parameter)) {
603 cacheLocker.Lock();
604 fTypeCache->RemoveType(type);
605 return B_NO_MEMORY;
606 }
607 }
608 }
609 }
610
611 _type = typeReference.Detach();
612 return B_OK;;
613 }
614
615
616 status_t
_CreatePrimitiveType(const BString & name,DIEBaseType * typeEntry,DwarfType * & _type)617 DwarfTypeFactory::_CreatePrimitiveType(const BString& name,
618 DIEBaseType* typeEntry, DwarfType*& _type)
619 {
620 const DynamicAttributeValue* byteSizeValue = typeEntry->ByteSize();
621 // const DynamicAttributeValue* bitOffsetValue = typeEntry->BitOffset();
622 const DynamicAttributeValue* bitSizeValue = typeEntry->BitSize();
623
624 uint32 bitSize = 0;
625 if (byteSizeValue->IsValid()) {
626 BVariant value;
627 status_t error = fTypeContext->File()->EvaluateDynamicValue(
628 fTypeContext->GetCompilationUnit(),
629 fTypeContext->AddressSize(), fTypeContext->IsBigEndian(),
630 fTypeContext->SubprogramEntry(), byteSizeValue,
631 fTypeContext->TargetInterface(),
632 fTypeContext->InstructionPointer(), fTypeContext->FramePointer(),
633 value);
634 if (error == B_OK && value.IsInteger())
635 bitSize = value.ToUInt32() * 8;
636 } else if (bitSizeValue->IsValid()) {
637 BVariant value;
638 status_t error = fTypeContext->File()->EvaluateDynamicValue(
639 fTypeContext->GetCompilationUnit(),
640 fTypeContext->AddressSize(), fTypeContext->IsBigEndian(),
641 fTypeContext->SubprogramEntry(), bitSizeValue,
642 fTypeContext->TargetInterface(),
643 fTypeContext->InstructionPointer(), fTypeContext->FramePointer(),
644 value);
645 if (error == B_OK && value.IsInteger())
646 bitSize = value.ToUInt32();
647 }
648
649 // determine type constant
650 uint32 typeConstant = 0;
651 switch (typeEntry->Encoding()) {
652 case DW_ATE_boolean:
653 typeConstant = B_BOOL_TYPE;
654 break;
655
656 case DW_ATE_float:
657 switch (bitSize) {
658 case 32:
659 typeConstant = B_FLOAT_TYPE;
660 break;
661 case 64:
662 typeConstant = B_DOUBLE_TYPE;
663 break;
664 }
665 break;
666
667 case DW_ATE_signed:
668 case DW_ATE_signed_char:
669 switch (bitSize) {
670 case 8:
671 typeConstant = B_INT8_TYPE;
672 break;
673 case 16:
674 typeConstant = B_INT16_TYPE;
675 break;
676 case 32:
677 typeConstant = B_INT32_TYPE;
678 break;
679 case 64:
680 typeConstant = B_INT64_TYPE;
681 break;
682 }
683 break;
684
685 case DW_ATE_address:
686 case DW_ATE_unsigned:
687 case DW_ATE_unsigned_char:
688 switch (bitSize) {
689 case 8:
690 typeConstant = B_UINT8_TYPE;
691 break;
692 case 16:
693 typeConstant = B_UINT16_TYPE;
694 break;
695 case 32:
696 typeConstant = B_UINT32_TYPE;
697 break;
698 case 64:
699 typeConstant = B_UINT64_TYPE;
700 break;
701 }
702 break;
703
704 case DW_ATE_complex_float:
705 case DW_ATE_imaginary_float:
706 case DW_ATE_packed_decimal:
707 case DW_ATE_numeric_string:
708 case DW_ATE_edited:
709 case DW_ATE_signed_fixed:
710 case DW_ATE_unsigned_fixed:
711 case DW_ATE_decimal_float:
712 default:
713 break;
714 }
715
716 // create the type
717 DwarfPrimitiveType* type = new(std::nothrow) DwarfPrimitiveType(
718 fTypeContext, name, typeEntry, typeConstant);
719 if (type == NULL)
720 return B_NO_MEMORY;
721
722 _type = type;
723 return B_OK;
724 }
725
726
727 status_t
_CreateAddressType(const BString & name,DIEAddressingType * typeEntry,address_type_kind addressKind,DwarfType * & _type)728 DwarfTypeFactory::_CreateAddressType(const BString& name,
729 DIEAddressingType* typeEntry, address_type_kind addressKind,
730 DwarfType*& _type)
731 {
732 // get the base type entry
733 DIEAddressingType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate(
734 typeEntry, HasTypePredicate<DIEAddressingType>());
735
736 // create the base type
737 DwarfType* baseType;
738 if (baseTypeOwnerEntry != NULL) {
739 status_t error = CreateType(baseTypeOwnerEntry->GetType(), baseType);
740 if (error != B_OK)
741 return error;
742 } else {
743 // According to the DWARF 3 specs a modified type *has* a base type.
744 // GCC 4 doesn't (always?) bother to add one for "void".
745 // TODO: We should probably search for a respective type by name. ATM
746 // we just create a DwarfUnspecifiedType without DIE.
747 TRACE_LOCALS("no base type for address type entry -- creating "
748 "unspecified type\n");
749 baseType = new(std::nothrow) DwarfUnspecifiedType(fTypeContext, "void",
750 NULL);
751 if (baseType == NULL)
752 return B_NO_MEMORY;
753 }
754 BReference<Type> baseTypeReference(baseType, true);
755
756 DwarfAddressType* type = new(std::nothrow) DwarfAddressType(fTypeContext,
757 name, typeEntry, addressKind, baseType);
758 if (type == NULL)
759 return B_NO_MEMORY;
760
761 _type = type;
762 return B_OK;
763 }
764
765
766 status_t
_CreateModifiedType(const BString & name,DIEModifiedType * typeEntry,uint32 modifiers,DwarfType * & _type)767 DwarfTypeFactory::_CreateModifiedType(const BString& name,
768 DIEModifiedType* typeEntry, uint32 modifiers, DwarfType*& _type)
769 {
770 // Get the base type entry. If it is a modified type too or a typedef,
771 // collect all modifiers and iterate until hitting an actual base type.
772 DIEType* baseTypeEntry = NULL;
773 DwarfType* baseType = NULL;
774 while (true) {
775 DIEModifiedType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate(
776 typeEntry, HasTypePredicate<DIEModifiedType>());
777 if (baseTypeOwnerEntry == NULL) {
778 if (typeEntry->GetType() == NULL) {
779 // in the case of a modified type that points to an
780 // unspecified type (i.e. const void* in C/C++),
781 // gcc appears to omit the base type attribute entirely.
782 status_t result = _CreateUnspecifiedType(name,
783 NULL, baseType);
784 if (result != B_OK)
785 return result;
786 break;
787 } else
788 return B_BAD_VALUE;
789 } else
790 baseTypeEntry = baseTypeOwnerEntry->GetType();
791
792 // resolve a typedef
793 if (baseTypeEntry->Tag() == DW_TAG_typedef) {
794 status_t error = _ResolveTypedef(
795 dynamic_cast<DIETypedef*>(baseTypeEntry), baseTypeEntry);
796 if (error != B_OK)
797 return error;
798 }
799
800 if (baseTypeEntry == NULL)
801 return B_BAD_VALUE;
802
803 // If the base type is a modified type, too, resolve it.
804 switch (baseTypeEntry->Tag()) {
805 case DW_TAG_const_type:
806 modifiers |= TYPE_MODIFIER_CONST;
807 baseTypeOwnerEntry
808 = dynamic_cast<DIEModifiedType*>(baseTypeEntry);
809 continue;
810 case DW_TAG_packed_type:
811 modifiers |= TYPE_MODIFIER_PACKED;
812 baseTypeOwnerEntry
813 = dynamic_cast<DIEModifiedType*>(baseTypeEntry);
814 continue;
815 case DW_TAG_volatile_type:
816 modifiers |= TYPE_MODIFIER_VOLATILE;
817 baseTypeOwnerEntry
818 = dynamic_cast<DIEModifiedType*>(baseTypeEntry);
819 continue;
820 case DW_TAG_restrict_type:
821 modifiers |= TYPE_MODIFIER_RESTRICT;
822 baseTypeOwnerEntry
823 = dynamic_cast<DIEModifiedType*>(baseTypeEntry);
824 continue;
825 case DW_TAG_shared_type:
826 modifiers |= TYPE_MODIFIER_SHARED;
827 baseTypeOwnerEntry
828 = dynamic_cast<DIEModifiedType*>(baseTypeEntry);
829 continue;
830
831 default:
832 break;
833 }
834
835 // If we get here, we've found an actual base type.
836 break;
837 }
838
839 if (baseType == NULL) {
840 // create the base type
841 status_t error = CreateType(baseTypeEntry, baseType);
842 if (error != B_OK)
843 return error;
844 }
845
846 BReference<Type> baseTypeReference(baseType, true);
847
848 DwarfModifiedType* type = new(std::nothrow) DwarfModifiedType(fTypeContext,
849 name, typeEntry, modifiers, baseType);
850 if (type == NULL)
851 return B_NO_MEMORY;
852
853 _type = type;
854 return B_OK;
855 }
856
857
858 status_t
_CreateTypedefType(const BString & name,DIETypedef * typeEntry,DwarfType * & _type)859 DwarfTypeFactory::_CreateTypedefType(const BString& name,
860 DIETypedef* typeEntry, DwarfType*& _type)
861 {
862 // resolve the base type
863 DIEType* baseTypeEntry;
864 status_t error = _ResolveTypedef(typeEntry, baseTypeEntry);
865 if (error != B_OK)
866 return error;
867
868 // create the base type
869 DwarfType* baseType;
870 error = CreateType(baseTypeEntry, baseType);
871 if (error != B_OK)
872 return error;
873 BReference<Type> baseTypeReference(baseType, true);
874
875 DwarfTypedefType* type = new(std::nothrow) DwarfTypedefType(fTypeContext,
876 name, typeEntry, baseType);
877 if (type == NULL)
878 return B_NO_MEMORY;
879
880 _type = type;
881 return B_OK;
882 }
883
884
885 status_t
_CreateArrayType(const BString & name,DIEArrayType * typeEntry,DwarfType * & _type)886 DwarfTypeFactory::_CreateArrayType(const BString& name,
887 DIEArrayType* typeEntry, DwarfType*& _type)
888 {
889 TRACE_LOCALS("DwarfTypeFactory::_CreateArrayType(\"%s\", %p)\n",
890 name.String(), typeEntry);
891
892 // create the base type
893 DIEArrayType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate(
894 typeEntry, HasTypePredicate<DIEArrayType>());
895 if (baseTypeOwnerEntry == NULL) {
896 WARNING("Failed to get base type for array type \"%s\"\n",
897 name.String());
898 return B_BAD_VALUE;
899 }
900
901 DwarfType* baseType = NULL;
902 status_t error = CreateType(baseTypeOwnerEntry->GetType(), baseType);
903 if (error != B_OK) {
904 WARNING("Failed to create base type for array type \"%s\": %s\n",
905 name.String(), strerror(error));
906 return error;
907 }
908 BReference<Type> baseTypeReference(baseType, true);
909
910 // create the array type
911 DwarfArrayType* type = new(std::nothrow) DwarfArrayType(fTypeContext, name,
912 typeEntry, baseType);
913 if (type == NULL)
914 return B_NO_MEMORY;
915 BReference<DwarfType> typeReference(type, true);
916
917 // add the array dimensions
918 DIEArrayType* dimensionOwnerEntry = DwarfUtils::GetDIEByPredicate(
919 typeEntry, HasDimensionsPredicate());
920
921 if (dimensionOwnerEntry == NULL) {
922 WARNING("Failed to get dimensions for array type \"%s\"\n",
923 name.String());
924 return B_BAD_VALUE;
925 }
926
927 for (DebugInfoEntryList::ConstIterator it
928 = dimensionOwnerEntry->Dimensions().GetIterator();
929 DebugInfoEntry* _dimensionEntry = it.Next();) {
930 DIEType* dimensionEntry = dynamic_cast<DIEType*>(_dimensionEntry);
931
932 // get/create the dimension type
933 DwarfType* dimensionType = NULL;
934 status_t error = CreateType(dimensionEntry, dimensionType);
935 if (error != B_OK) {
936 WARNING("Failed to create type for array dimension: %s\n",
937 strerror(error));
938 return error;
939 }
940 BReference<Type> dimensionTypeReference(dimensionType, true);
941
942 // create and add the array dimension object
943 DwarfArrayDimension* dimension
944 = new(std::nothrow) DwarfArrayDimension(dimensionType);
945 BReference<DwarfArrayDimension> dimensionReference(dimension, true);
946 if (dimension == NULL || !type->AddDimension(dimension))
947 return B_NO_MEMORY;
948 }
949
950 _type = typeReference.Detach();
951 return B_OK;
952 }
953
954
955 status_t
_CreateEnumerationType(const BString & name,DIEEnumerationType * typeEntry,DwarfType * & _type)956 DwarfTypeFactory::_CreateEnumerationType(const BString& name,
957 DIEEnumerationType* typeEntry, DwarfType*& _type)
958 {
959 // create the base type (it's optional)
960 DIEEnumerationType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate(
961 typeEntry, HasTypePredicate<DIEEnumerationType>());
962
963 DwarfType* baseType = NULL;
964 if (baseTypeOwnerEntry != NULL) {
965 status_t error = CreateType(baseTypeOwnerEntry->GetType(), baseType);
966 if (error != B_OK)
967 return error;
968 }
969 BReference<Type> baseTypeReference(baseType, true);
970
971 // create the enumeration type
972 DwarfEnumerationType* type = new(std::nothrow) DwarfEnumerationType(
973 fTypeContext, name, typeEntry, baseType);
974 if (type == NULL)
975 return B_NO_MEMORY;
976 BReference<DwarfEnumerationType> typeReference(type, true);
977
978 // get the enumeration values
979 DIEEnumerationType* enumeratorOwnerEntry = DwarfUtils::GetDIEByPredicate(
980 typeEntry, HasEnumeratorsPredicate());
981
982 if (enumeratorOwnerEntry != NULL) {
983 for (DebugInfoEntryList::ConstIterator it
984 = enumeratorOwnerEntry->Enumerators().GetIterator();
985 DebugInfoEntry* _enumeratorEntry = it.Next();) {
986 DIEEnumerator* enumeratorEntry = dynamic_cast<DIEEnumerator*>(
987 _enumeratorEntry);
988
989 // evaluate the value
990 BVariant value;
991 status_t error = fTypeContext->File()->EvaluateConstantValue(
992 fTypeContext->GetCompilationUnit(),
993 fTypeContext->AddressSize(), fTypeContext->IsBigEndian(),
994 fTypeContext->SubprogramEntry(), enumeratorEntry->ConstValue(),
995 fTypeContext->TargetInterface(),
996 fTypeContext->InstructionPointer(),
997 fTypeContext->FramePointer(), value);
998 if (error != B_OK) {
999 // The value is probably not stored -- just ignore the
1000 // enumerator.
1001 TRACE_LOCALS("Failed to get value for enum type value %s::%s\n",
1002 name.String(), enumeratorEntry->Name());
1003 continue;
1004 }
1005
1006 // create and add the enumeration value object
1007 DwarfEnumeratorValue* enumValue
1008 = new(std::nothrow) DwarfEnumeratorValue(enumeratorEntry,
1009 enumeratorEntry->Name(), value);
1010 BReference<DwarfEnumeratorValue> enumValueReference(enumValue,
1011 true);
1012 if (enumValue == NULL || !type->AddValue(enumValue))
1013 return B_NO_MEMORY;
1014 }
1015 }
1016
1017 _type = typeReference.Detach();
1018 return B_OK;
1019 }
1020
1021
1022 status_t
_CreateSubrangeType(const BString & name,DIESubrangeType * typeEntry,DwarfType * & _type)1023 DwarfTypeFactory::_CreateSubrangeType(const BString& name,
1024 DIESubrangeType* typeEntry, DwarfType*& _type)
1025 {
1026 // get the base type
1027 DIESubrangeType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate(
1028 typeEntry, HasTypePredicate<DIESubrangeType>());
1029 DIEType* baseTypeEntry = baseTypeOwnerEntry != NULL
1030 ? baseTypeOwnerEntry->GetType() : NULL;
1031
1032 // get the lower bound
1033 BVariant lowerBound;
1034 DIESubrangeType* lowerBoundOwnerEntry = DwarfUtils::GetDIEByPredicate(
1035 typeEntry, HasLowerBoundPredicate());
1036 if (lowerBoundOwnerEntry != NULL) {
1037 // evaluate it
1038 DIEType* valueType;
1039 status_t error = fTypeContext->File()->EvaluateDynamicValue(
1040 fTypeContext->GetCompilationUnit(),
1041 fTypeContext->AddressSize(), fTypeContext->IsBigEndian(),
1042 fTypeContext->SubprogramEntry(),
1043 lowerBoundOwnerEntry->LowerBound(),
1044 fTypeContext->TargetInterface(),
1045 fTypeContext->InstructionPointer(),
1046 fTypeContext->FramePointer(), lowerBound, &valueType);
1047 if (error != B_OK) {
1048 WARNING(" failed to evaluate lower bound: %s\n", strerror(error));
1049 return error;
1050 }
1051
1052 // If we don't have a base type yet, and the lower bound attribute
1053 // refers to an object, the type of that object is our base type.
1054 if (baseTypeEntry == NULL)
1055 baseTypeEntry = valueType;
1056 } else {
1057 // that's ok -- use the language default
1058 lowerBound.SetTo(fTypeContext->GetCompilationUnit()->SourceLanguage()
1059 ->subrangeLowerBound);
1060 }
1061
1062 // get the upper bound
1063 BVariant upperBound;
1064 DIESubrangeType* upperBoundOwnerEntry = DwarfUtils::GetDIEByPredicate(
1065 typeEntry, HasUpperBoundPredicate());
1066 if (upperBoundOwnerEntry != NULL) {
1067 // evaluate it
1068 DIEType* valueType;
1069 status_t error = fTypeContext->File()->EvaluateDynamicValue(
1070 fTypeContext->GetCompilationUnit(),
1071 fTypeContext->AddressSize(), fTypeContext->IsBigEndian(),
1072 fTypeContext->SubprogramEntry(),
1073 upperBoundOwnerEntry->UpperBound(),
1074 fTypeContext->TargetInterface(),
1075 fTypeContext->InstructionPointer(), fTypeContext->FramePointer(),
1076 upperBound, &valueType);
1077 if (error != B_OK) {
1078 WARNING(" failed to evaluate upper bound: %s\n", strerror(error));
1079 return error;
1080 }
1081
1082 // If we don't have a base type yet, and the upper bound attribute
1083 // refers to an object, the type of that object is our base type.
1084 if (baseTypeEntry == NULL)
1085 baseTypeEntry = valueType;
1086 } else {
1087 // get the count instead
1088 DIESubrangeType* countOwnerEntry = DwarfUtils::GetDIEByPredicate(
1089 typeEntry, HasCountPredicate());
1090 if (countOwnerEntry != NULL) {
1091 // evaluate it
1092 BVariant count;
1093 DIEType* valueType;
1094 status_t error = fTypeContext->File()->EvaluateDynamicValue(
1095 fTypeContext->GetCompilationUnit(),
1096 fTypeContext->AddressSize(), fTypeContext->IsBigEndian(),
1097 fTypeContext->SubprogramEntry(),
1098 countOwnerEntry->Count(), fTypeContext->TargetInterface(),
1099 fTypeContext->InstructionPointer(),
1100 fTypeContext->FramePointer(), count, &valueType);
1101 if (error != B_OK) {
1102 WARNING(" failed to evaluate count: %s\n", strerror(error));
1103 return error;
1104 }
1105
1106 // If we don't have a base type yet, and the count attribute refers
1107 // to an object, the type of that object is our base type.
1108 if (baseTypeEntry == NULL)
1109 baseTypeEntry = valueType;
1110
1111 // we only support integers
1112 bool isSigned;
1113 if (!lowerBound.IsInteger(&isSigned) || !count.IsInteger()) {
1114 WARNING(" count given for subrange type, but lower bound or "
1115 "count is not integer\n");
1116 return B_BAD_VALUE;
1117 }
1118
1119 if (isSigned)
1120 upperBound.SetTo(lowerBound.ToInt64() + count.ToInt64() - 1);
1121 else
1122 upperBound.SetTo(lowerBound.ToUInt64() + count.ToUInt64() - 1);
1123 }
1124 }
1125
1126 // create the base type
1127 Type* baseType = NULL;
1128 status_t error;
1129 if (baseTypeEntry != NULL) {
1130 DwarfType* dwarfBaseType;
1131 error = CreateType(baseTypeEntry, dwarfBaseType);
1132 baseType = dwarfBaseType;
1133 } else {
1134 // We still don't have a base type yet. In this case the base type is
1135 // supposed to be a signed integer type with the same size as an address
1136 // for that compilation unit.
1137 error = ArtificialIntegerType::Create(
1138 fTypeContext->GetCompilationUnit()->AddressSize(), true, baseType);
1139 }
1140 if (error != B_OK)
1141 return error;
1142 BReference<Type> baseTypeReference(baseType, true);
1143
1144 // TODO: Support the thread scaling attribute!
1145
1146 // create the type
1147 DwarfSubrangeType* type = new(std::nothrow) DwarfSubrangeType(fTypeContext,
1148 name, typeEntry, baseType, lowerBound, upperBound);
1149 if (type == NULL)
1150 return B_NO_MEMORY;
1151
1152 _type = type;
1153 return B_OK;
1154 }
1155
1156
1157 status_t
_CreateUnspecifiedType(const BString & name,DIEUnspecifiedType * typeEntry,DwarfType * & _type)1158 DwarfTypeFactory::_CreateUnspecifiedType(const BString& name,
1159 DIEUnspecifiedType* typeEntry, DwarfType*& _type)
1160 {
1161 DwarfUnspecifiedType* type = new(std::nothrow) DwarfUnspecifiedType(
1162 fTypeContext, name, typeEntry);
1163 if (type == NULL)
1164 return B_NO_MEMORY;
1165
1166 _type = type;
1167 return B_OK;
1168 }
1169
1170 status_t
_CreateFunctionType(const BString & name,DIESubroutineType * typeEntry,DwarfType * & _type)1171 DwarfTypeFactory::_CreateFunctionType(const BString& name,
1172 DIESubroutineType* typeEntry, DwarfType*& _type)
1173 {
1174 // get the return type
1175 DIESubroutineType* returnTypeOwnerEntry = DwarfUtils::GetDIEByPredicate(
1176 typeEntry, HasReturnTypePredicate<DIESubroutineType>());
1177
1178 // create the base type
1179 DwarfType* returnType = NULL;
1180 if (returnTypeOwnerEntry != NULL) {
1181 status_t error = CreateType(returnTypeOwnerEntry->ReturnType(),
1182 returnType);
1183 if (error != B_OK)
1184 return error;
1185 }
1186 BReference<Type> returnTypeReference(returnType, true);
1187
1188 DwarfFunctionType* type = new(std::nothrow) DwarfFunctionType(fTypeContext,
1189 name, typeEntry, returnType);
1190 if (type == NULL)
1191 return B_NO_MEMORY;
1192 BReference<DwarfType> typeReference(type, true);
1193
1194 // get the parameters
1195 DIESubroutineType* parameterOwnerEntry = DwarfUtils::GetDIEByPredicate(
1196 typeEntry, HasParametersPredicate<DIESubroutineType>());
1197
1198 if (parameterOwnerEntry != NULL) {
1199 for (DebugInfoEntryList::ConstIterator it
1200 = parameterOwnerEntry->Parameters().GetIterator();
1201 DebugInfoEntry* _parameterEntry = it.Next();) {
1202 if (_parameterEntry->Tag() == DW_TAG_unspecified_parameters) {
1203 type->SetHasVariableArguments(true);
1204 continue;
1205 }
1206
1207 DIEFormalParameter* parameterEntry
1208 = dynamic_cast<DIEFormalParameter*>(_parameterEntry);
1209
1210 // get the type
1211 DIEFormalParameter* typeOwnerEntry = DwarfUtils::GetDIEByPredicate(
1212 parameterEntry, HasTypePredicate<DIEFormalParameter>());
1213 if (typeOwnerEntry == NULL)
1214 return B_BAD_VALUE;
1215
1216 DwarfType* parameterType;
1217 status_t error = CreateType(typeOwnerEntry->GetType(),
1218 parameterType);
1219 if (error != B_OK)
1220 return error;
1221 BReference<DwarfType> parameterTypeReference(parameterType, true);
1222
1223 // get the name
1224 BString parameterName;
1225 DwarfUtils::GetDIEName(parameterEntry, parameterName);
1226
1227 // create and add the parameter object
1228 DwarfFunctionParameter* parameter
1229 = new(std::nothrow) DwarfFunctionParameter(parameterEntry,
1230 parameterName, parameterType);
1231 BReference<DwarfFunctionParameter> parameterReference(parameter,
1232 true);
1233 if (parameter == NULL || !type->AddParameter(parameter))
1234 return B_NO_MEMORY;
1235 }
1236 }
1237
1238
1239 _type = typeReference.Detach();
1240 return B_OK;
1241 }
1242
1243
1244 status_t
_CreatePointerToMemberType(const BString & name,DIEPointerToMemberType * typeEntry,DwarfType * & _type)1245 DwarfTypeFactory::_CreatePointerToMemberType(const BString& name,
1246 DIEPointerToMemberType* typeEntry, DwarfType*& _type)
1247 {
1248 // get the containing and base type entries
1249 DIEPointerToMemberType* containingTypeOwnerEntry
1250 = DwarfUtils::GetDIEByPredicate(typeEntry,
1251 HasContainingTypePredicate());
1252 DIEPointerToMemberType* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate(
1253 typeEntry, HasTypePredicate<DIEPointerToMemberType>());
1254
1255 if (containingTypeOwnerEntry == NULL || baseTypeOwnerEntry == NULL) {
1256 WARNING("Failed to get containing or base type for pointer to member "
1257 "type \"%s\"\n", name.String());
1258 return B_BAD_VALUE;
1259 }
1260
1261 // create the containing type
1262 DwarfType* containingType;
1263 status_t error = CreateType(containingTypeOwnerEntry->ContainingType(),
1264 containingType);
1265 if (error != B_OK)
1266 return error;
1267 BReference<Type> containingTypeReference(containingType, true);
1268
1269 DwarfCompoundType* compoundContainingType
1270 = dynamic_cast<DwarfCompoundType*>(containingType);
1271 if (compoundContainingType == NULL) {
1272 WARNING("Containing type for pointer to member type \"%s\" is not a "
1273 "compound type.\n", name.String());
1274 return B_BAD_VALUE;
1275 }
1276
1277 // create the base type
1278 DwarfType* baseType;
1279 error = CreateType(baseTypeOwnerEntry->GetType(), baseType);
1280 if (error != B_OK)
1281 return error;
1282 BReference<Type> baseTypeReference(baseType, true);
1283
1284 // create the type object
1285 DwarfPointerToMemberType* type = new(std::nothrow) DwarfPointerToMemberType(
1286 fTypeContext, name, typeEntry, compoundContainingType, baseType);
1287 if (type == NULL)
1288 return B_NO_MEMORY;
1289
1290 _type = type;
1291 return B_OK;
1292 }
1293
1294
1295 status_t
_ResolveTypedef(DIETypedef * entry,DIEType * & _baseTypeEntry)1296 DwarfTypeFactory::_ResolveTypedef(DIETypedef* entry,
1297 DIEType*& _baseTypeEntry)
1298 {
1299 while (true) {
1300 // resolve the base type, possibly following abstract origin or
1301 // specification
1302 DIETypedef* baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate(
1303 entry, HasTypePredicate<DIETypedef>());
1304 if (baseTypeOwnerEntry == NULL)
1305 return B_BAD_VALUE;
1306
1307 DIEType* baseTypeEntry = baseTypeOwnerEntry->GetType();
1308 if (baseTypeEntry->Tag() != DW_TAG_typedef) {
1309 _baseTypeEntry = baseTypeEntry;
1310 return B_OK;
1311 }
1312
1313 entry = dynamic_cast<DIETypedef*>(baseTypeEntry);
1314 }
1315 }
1316
1317
1318 status_t
_ResolveTypeByteSize(DIEType * typeEntry,uint64 & _size)1319 DwarfTypeFactory::_ResolveTypeByteSize(DIEType* typeEntry,
1320 uint64& _size)
1321 {
1322 TRACE_LOCALS("DwarfTypeFactory::_ResolveTypeByteSize(%p)\n",
1323 typeEntry);
1324
1325 // get the size attribute
1326 const DynamicAttributeValue* sizeValue;
1327
1328 while (true) {
1329 // resolve a typedef
1330 if (typeEntry->Tag() == DW_TAG_typedef) {
1331 TRACE_LOCALS(" resolving typedef...\n");
1332
1333 status_t error = _ResolveTypedef(
1334 dynamic_cast<DIETypedef*>(typeEntry), typeEntry);
1335 if (error != B_OK)
1336 return error;
1337 }
1338
1339 sizeValue = typeEntry->ByteSize();
1340 if (sizeValue != NULL && sizeValue->IsValid())
1341 break;
1342
1343 // resolve abstract origin
1344 if (DIEType* abstractOrigin = dynamic_cast<DIEType*>(
1345 typeEntry->AbstractOrigin())) {
1346 TRACE_LOCALS(" resolving abstract origin (%p)...\n",
1347 abstractOrigin);
1348
1349 typeEntry = abstractOrigin;
1350 sizeValue = typeEntry->ByteSize();
1351 if (sizeValue != NULL && sizeValue->IsValid())
1352 break;
1353 }
1354
1355 // resolve specification
1356 if (DIEType* specification = dynamic_cast<DIEType*>(
1357 typeEntry->Specification())) {
1358 TRACE_LOCALS(" resolving specification (%p)...\n", specification);
1359
1360 typeEntry = specification;
1361 sizeValue = typeEntry->ByteSize();
1362 if (sizeValue != NULL && sizeValue->IsValid())
1363 break;
1364 }
1365
1366 // For some types we have a special handling. For modified types we
1367 // follow the base type, for address types we know the size anyway.
1368 TRACE_LOCALS(" nothing yet, special type handling\n");
1369
1370 switch (typeEntry->Tag()) {
1371 case DW_TAG_const_type:
1372 case DW_TAG_packed_type:
1373 case DW_TAG_volatile_type:
1374 case DW_TAG_restrict_type:
1375 case DW_TAG_shared_type:
1376 typeEntry = dynamic_cast<DIEModifiedType*>(typeEntry)
1377 ->GetType();
1378
1379 TRACE_LOCALS(" following modified type -> %p\n", typeEntry);
1380
1381 if (typeEntry == NULL)
1382 return B_ENTRY_NOT_FOUND;
1383 break;
1384 case DW_TAG_pointer_type:
1385 case DW_TAG_reference_type:
1386 case DW_TAG_ptr_to_member_type:
1387 _size = fTypeContext->GetCompilationUnit()->AddressSize();
1388
1389 TRACE_LOCALS(" pointer/reference type: size: %" B_PRIu64 "\n",
1390 _size);
1391
1392 return B_OK;
1393 default:
1394 return B_ENTRY_NOT_FOUND;
1395 }
1396 }
1397
1398 TRACE_LOCALS(" found attribute\n");
1399
1400 // get the actual value
1401 BVariant size;
1402 status_t error = fTypeContext->File()->EvaluateDynamicValue(
1403 fTypeContext->GetCompilationUnit(),
1404 fTypeContext->AddressSize(), fTypeContext->IsBigEndian(),
1405 fTypeContext->SubprogramEntry(), sizeValue,
1406 fTypeContext->TargetInterface(), fTypeContext->InstructionPointer(),
1407 fTypeContext->FramePointer(), size);
1408 if (error != B_OK) {
1409 TRACE_LOCALS(" failed to resolve attribute: %s\n", strerror(error));
1410 return error;
1411 }
1412
1413 _size = size.ToUInt64();
1414
1415 TRACE_LOCALS(" -> size: %" B_PRIu64 "\n", _size);
1416
1417 return B_OK;
1418 }
1419