xref: /haiku/src/kits/debugger/debug_info/DwarfTypeFactory.cpp (revision 151f01c21d79b2fc1be44dd22eab3a7270d60479)
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