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