xref: /haiku/src/kits/debugger/debug_info/DwarfTypes.cpp (revision 3c16ba4e780846dc1973050c97b54d39c2eb854f)
1 /*
2  * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copryight 2012-2014, Rene Gollent, rene@gollent.com.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include "DwarfTypes.h"
9 
10 #include <new>
11 
12 #include "Architecture.h"
13 #include "ArrayIndexPath.h"
14 #include "CompilationUnit.h"
15 #include "Dwarf.h"
16 #include "DwarfFile.h"
17 #include "DwarfTargetInterface.h"
18 #include "DwarfUtils.h"
19 #include "Register.h"
20 #include "RegisterMap.h"
21 #include "Tracing.h"
22 #include "ValueLocation.h"
23 
24 
25 namespace {
26 
27 
28 // #pragma mark - HasBitStridePredicate
29 
30 
31 template<typename EntryType>
32 struct HasBitStridePredicate {
operator ()__anon2fd659300111::HasBitStridePredicate33 	inline bool operator()(EntryType* entry) const
34 	{
35 		return entry->BitStride()->IsValid();
36 	}
37 };
38 
39 
40 // #pragma mark - HasByteStridePredicate
41 
42 
43 template<typename EntryType>
44 struct HasByteStridePredicate {
operator ()__anon2fd659300111::HasByteStridePredicate45 	inline bool operator()(EntryType* entry) const
46 	{
47 		return entry->ByteStride()->IsValid();
48 	}
49 };
50 
51 
52 }	// unnamed namespace
53 
54 
55 type_kind
dwarf_tag_to_type_kind(int32 tag)56 dwarf_tag_to_type_kind(int32 tag)
57 {
58 	switch (tag) {
59 		case DW_TAG_class_type:
60 		case DW_TAG_structure_type:
61 		case DW_TAG_union_type:
62 		case DW_TAG_interface_type:
63 			return TYPE_COMPOUND;
64 
65 		case DW_TAG_base_type:
66 			return TYPE_PRIMITIVE;
67 
68 		case DW_TAG_pointer_type:
69 		case DW_TAG_reference_type:
70 			return TYPE_ADDRESS;
71 
72 		case DW_TAG_const_type:
73 		case DW_TAG_packed_type:
74 		case DW_TAG_volatile_type:
75 		case DW_TAG_restrict_type:
76 		case DW_TAG_shared_type:
77 			return TYPE_MODIFIED;
78 
79 		case DW_TAG_typedef:
80 			return TYPE_TYPEDEF;
81 
82 		case DW_TAG_array_type:
83 			return TYPE_ARRAY;
84 
85 		case DW_TAG_enumeration_type:
86 			return TYPE_ENUMERATION;
87 
88 		case DW_TAG_subrange_type:
89 			return TYPE_SUBRANGE;
90 
91 		case DW_TAG_unspecified_type:
92 			return TYPE_UNSPECIFIED;
93 
94 		case DW_TAG_subroutine_type:
95 			return TYPE_FUNCTION;
96 
97 		case DW_TAG_ptr_to_member_type:
98 			return TYPE_POINTER_TO_MEMBER;
99 
100 	}
101 
102 	return TYPE_UNSPECIFIED;
103 }
104 
105 
106 int32
dwarf_tag_to_subtype_kind(int32 tag)107 dwarf_tag_to_subtype_kind(int32 tag)
108 {
109 	switch (tag) {
110 		case DW_TAG_class_type:
111 			return COMPOUND_TYPE_CLASS;
112 
113 		case DW_TAG_structure_type:
114 			return COMPOUND_TYPE_STRUCT;
115 
116 		case DW_TAG_union_type:
117 			return COMPOUND_TYPE_UNION;
118 
119 		case DW_TAG_interface_type:
120 			return COMPOUND_TYPE_INTERFACE;
121 
122 		case DW_TAG_pointer_type:
123 			return DERIVED_TYPE_POINTER;
124 
125 		case DW_TAG_reference_type:
126 			return DERIVED_TYPE_REFERENCE;
127 	}
128 
129 	return -1;
130 }
131 
132 
133 // #pragma mark - DwarfTypeContext
134 
135 
DwarfTypeContext(Architecture * architecture,image_id imageID,DwarfFile * file,CompilationUnit * compilationUnit,DIESubprogram * subprogramEntry,target_addr_t instructionPointer,target_addr_t framePointer,target_addr_t relocationDelta,DwarfTargetInterface * targetInterface,RegisterMap * fromDwarfRegisterMap)136 DwarfTypeContext::DwarfTypeContext(Architecture* architecture, image_id imageID,
137 	DwarfFile* file, CompilationUnit* compilationUnit,
138 	DIESubprogram* subprogramEntry, target_addr_t instructionPointer,
139 	target_addr_t framePointer, target_addr_t relocationDelta,
140 	DwarfTargetInterface* targetInterface, RegisterMap* fromDwarfRegisterMap)
141 	:
142 	fArchitecture(architecture),
143 	fImageID(imageID),
144 	fFile(file),
145 	fCompilationUnit(compilationUnit),
146 	fSubprogramEntry(subprogramEntry),
147 	fInstructionPointer(instructionPointer),
148 	fFramePointer(framePointer),
149 	fRelocationDelta(relocationDelta),
150 	fTargetInterface(targetInterface),
151 	fFromDwarfRegisterMap(fromDwarfRegisterMap)
152 {
153 	fArchitecture->AcquireReference();
154 	fFile->AcquireReference();
155 	if (fTargetInterface != NULL)
156 		fTargetInterface->AcquireReference();
157 }
158 
159 
~DwarfTypeContext()160 DwarfTypeContext::~DwarfTypeContext()
161 {
162 	fArchitecture->ReleaseReference();
163 	fFile->ReleaseReference();
164 	if (fTargetInterface != NULL)
165 		fTargetInterface->ReleaseReference();
166 }
167 
168 
169 uint8
AddressSize() const170 DwarfTypeContext::AddressSize() const
171 {
172 	return fCompilationUnit != NULL ? fCompilationUnit->AddressSize()
173 		: fArchitecture->AddressSize();
174 }
175 
176 
177 bool
IsBigEndian() const178 DwarfTypeContext::IsBigEndian() const
179 {
180 	return fCompilationUnit != NULL ? fCompilationUnit->IsBigEndian()
181 		: fArchitecture->IsBigEndian();
182 }
183 
184 
185 // #pragma mark - DwarfType
186 
187 
DwarfType(DwarfTypeContext * typeContext,const BString & name,const DIEType * entry)188 DwarfType::DwarfType(DwarfTypeContext* typeContext, const BString& name,
189 	const DIEType* entry)
190 	:
191 	fTypeContext(typeContext),
192 	fName(name),
193 	fByteSize(0)
194 {
195 	fTypeContext->AcquireReference();
196 
197 	GetTypeID(entry, fID);
198 }
199 
200 
~DwarfType()201 DwarfType::~DwarfType()
202 {
203 	fTypeContext->ReleaseReference();
204 }
205 
206 
207 /*static*/ bool
GetTypeID(const DIEType * entry,BString & _id)208 DwarfType::GetTypeID(const DIEType* entry, BString& _id)
209 {
210 	char buffer[32];
211 	snprintf(buffer, sizeof(buffer), "dwarf:%p", entry);
212 	BString id = buffer;
213 	if (id.Length() == 0)
214 		return false;
215 
216 	_id = id;
217 	return true;
218 }
219 
220 
221 image_id
ImageID() const222 DwarfType::ImageID() const
223 {
224 	return fTypeContext->ImageID();
225 }
226 
227 
228 const BString&
ID() const229 DwarfType::ID() const
230 {
231 	return fID;
232 }
233 
234 
235 const BString&
Name() const236 DwarfType::Name() const
237 {
238 	return fName;
239 }
240 
241 
242 target_size_t
ByteSize() const243 DwarfType::ByteSize() const
244 {
245 	return fByteSize;
246 }
247 
248 
249 status_t
CreateDerivedAddressType(address_type_kind addressType,AddressType * & _resultType)250 DwarfType::CreateDerivedAddressType(address_type_kind addressType,
251 	AddressType*& _resultType)
252 {
253 	BString derivedName;
254 	derivedName.SetToFormat("%s%c", fName.String(),
255 		addressType == DERIVED_TYPE_POINTER ? '*' : '&');
256 	DwarfAddressType* resultType = new(std::nothrow)
257 		DwarfAddressType(fTypeContext, derivedName, NULL, addressType, this);
258 
259 	if (resultType == NULL)
260 		return B_NO_MEMORY;
261 
262 	resultType->SetByteSize(fTypeContext->GetArchitecture()->AddressSize());
263 
264 	_resultType = resultType;
265 	return B_OK;
266 }
267 
268 
269 status_t
CreateDerivedArrayType(int64 lowerBound,int64 elementCount,bool extendExisting,ArrayType * & _resultType)270 DwarfType::CreateDerivedArrayType(int64 lowerBound, int64 elementCount,
271 	bool extendExisting, ArrayType*& _resultType)
272 {
273 	DwarfArrayType* resultType = NULL;
274 	BReference<DwarfType> baseTypeReference;
275 	if (extendExisting)
276 		resultType = dynamic_cast<DwarfArrayType*>(this);
277 
278 	if (resultType == NULL) {
279 		BString derivedName;
280 		derivedName.SetToFormat("%s[]", fName.String());
281 		resultType = new(std::nothrow)
282 			DwarfArrayType(fTypeContext, derivedName, NULL, this);
283 		baseTypeReference.SetTo(resultType, true);
284 	}
285 
286 	if (resultType == NULL)
287 		return B_NO_MEMORY;
288 
289 	DwarfSubrangeType* subrangeType = new(std::nothrow) DwarfSubrangeType(
290 		fTypeContext, fName, NULL, resultType, BVariant(lowerBound),
291 		BVariant(lowerBound + elementCount - 1));
292 	if (subrangeType == NULL)
293 		return B_NO_MEMORY;
294 
295 	BReference<DwarfSubrangeType> subrangeReference(subrangeType, true);
296 
297 	DwarfArrayDimension* dimension = new(std::nothrow) DwarfArrayDimension(
298 		subrangeType);
299 	if (dimension == NULL)
300 		return B_NO_MEMORY;
301 	BReference<DwarfArrayDimension> dimensionReference(dimension, true);
302 
303 	if (!resultType->AddDimension(dimension))
304 		return B_NO_MEMORY;
305 
306 	baseTypeReference.Detach();
307 
308 	_resultType = resultType;
309 	return B_OK;
310 }
311 
312 
313 status_t
ResolveObjectDataLocation(const ValueLocation & objectLocation,ValueLocation * & _location)314 DwarfType::ResolveObjectDataLocation(const ValueLocation& objectLocation,
315 	ValueLocation*& _location)
316 {
317 	// TODO: In some source languages the object address might be a pointer
318 	// to a descriptor, not the actual object data.
319 
320 	// If the given location looks good already, just clone it.
321 	int32 count = objectLocation.CountPieces();
322 	if (count == 0)
323 		return B_BAD_VALUE;
324 
325 	ValuePieceLocation piece;
326 	if (!piece.Copy(objectLocation.PieceAt(0)))
327 		return B_NO_MEMORY;
328 
329 	if (count > 1 || piece.type != VALUE_PIECE_LOCATION_MEMORY
330 		|| piece.size != 0 || piece.bitSize != 0) {
331 		ValueLocation* location
332 			= new(std::nothrow) ValueLocation(objectLocation);
333 		if (location == NULL || location->CountPieces() != count) {
334 			delete location;
335 			return B_NO_MEMORY;
336 		}
337 
338 		_location = location;
339 		return B_OK;
340 	}
341 
342 	// The location contains just a single address piece with a zero size
343 	// -- set the type's size.
344 	piece.SetSize(ByteSize());
345 		// TODO: Use bit size and bit offset, if specified!
346 
347 	ValueLocation* location = new(std::nothrow) ValueLocation(
348 		objectLocation.IsBigEndian());
349 	if (location == NULL || !location->AddPiece(piece)) {
350 		delete location;
351 		return B_NO_MEMORY;
352 	}
353 
354 	_location = location;
355 	return B_OK;
356 }
357 
358 
359 status_t
ResolveObjectDataLocation(target_addr_t objectAddress,ValueLocation * & _location)360 DwarfType::ResolveObjectDataLocation(target_addr_t objectAddress,
361 	ValueLocation*& _location)
362 {
363 	ValuePieceLocation piece;
364 	piece.SetToMemory(objectAddress);
365 	piece.SetSize(0);
366 		// We set the piece size to 0 as an indicator that the size has to be
367 		// set.
368 		// TODO: We could set the byte size from type, but that may not be
369 		// accurate. We may want to add bit offset and size to Type.
370 
371 	ValueLocation location(fTypeContext->GetArchitecture()->IsBigEndian());
372 	if (!location.AddPiece(piece))
373 		return B_NO_MEMORY;
374 
375 	return ResolveObjectDataLocation(location, _location);
376 }
377 
378 
379 status_t
ResolveLocation(DwarfTypeContext * typeContext,const LocationDescription * description,target_addr_t objectAddress,bool hasObjectAddress,ValueLocation & _location)380 DwarfType::ResolveLocation(DwarfTypeContext* typeContext,
381 	const LocationDescription* description, target_addr_t objectAddress,
382 	bool hasObjectAddress, ValueLocation& _location)
383 {
384 	status_t error = typeContext->File()->ResolveLocation(
385 		typeContext->GetCompilationUnit(),
386 		typeContext->AddressSize(), typeContext->IsBigEndian(),
387 		typeContext->SubprogramEntry(), description,
388 		typeContext->TargetInterface(), typeContext->InstructionPointer(),
389 		objectAddress, hasObjectAddress, typeContext->FramePointer(),
390 		typeContext->RelocationDelta(), _location);
391 	if (error != B_OK)
392 		return error;
393 
394 	// translate the DWARF register indices and the bit offset/size semantics
395 	const Register* registers = typeContext->GetArchitecture()->Registers();
396 	bool bigEndian = typeContext->GetArchitecture()->IsBigEndian();
397 	int32 count = _location.CountPieces();
398 	for (int32 i = 0; i < count; i++) {
399 		ValuePieceLocation piece;
400 		if (!piece.Copy(_location.PieceAt(i)))
401 			return B_NO_MEMORY;
402 
403 		if (piece.type == VALUE_PIECE_LOCATION_REGISTER) {
404 			int32 reg = typeContext->FromDwarfRegisterMap()->MapRegisterIndex(
405 				piece.reg);
406 			if (reg >= 0) {
407 				piece.reg = reg;
408 				// The bit offset for registers is to the least
409 				// significant bit, while we want the offset to the most
410 				// significant bit.
411 				if (registers[reg].BitSize() > piece.bitSize) {
412 					piece.bitOffset = registers[reg].BitSize() - piece.bitSize
413 						- piece.bitOffset;
414 				}
415 			} else
416 				piece.SetToUnknown();
417 		} else if (piece.type == VALUE_PIECE_LOCATION_MEMORY) {
418 			// Whether the bit offset is to the least or most significant bit
419 			// is target architecture and source language specific.
420 			// TODO: Check whether this is correct!
421 			// TODO: Source language!
422 			if (!bigEndian && piece.size * 8 > piece.bitSize) {
423 				piece.bitOffset = piece.size * 8 - piece.bitSize
424 					- piece.bitOffset;
425 			}
426 		}
427 
428 		piece.Normalize(bigEndian);
429 		if (!_location.SetPieceAt(i, piece))
430 			return B_NO_MEMORY;
431 	}
432 
433 	// If we only have one piece and that doesn't have a size, try to retrieve
434 	// the size of the type.
435 	if (count == 1) {
436 		ValuePieceLocation piece;
437 		if (!piece.Copy(_location.PieceAt(0)))
438 			return B_NO_MEMORY;
439 
440 		if (piece.IsValid() && piece.size == 0 && piece.bitSize == 0) {
441 			piece.SetSize(ByteSize());
442 				// TODO: Use bit size and bit offset, if specified!
443 			if (!_location.SetPieceAt(0, piece))
444 				return B_NO_MEMORY;
445 
446 			TRACE_LOCALS("  set single piece size to %" B_PRIu64 "\n",
447 				ByteSize());
448 		}
449 	}
450 
451 	return B_OK;
452 }
453 
454 
455 // #pragma mark - DwarfInheritance
456 
457 
DwarfInheritance(DIEInheritance * entry,DwarfType * type)458 DwarfInheritance::DwarfInheritance(DIEInheritance* entry, DwarfType* type)
459 	:
460 	fEntry(entry),
461 	fType(type)
462 {
463 	fType->AcquireReference();
464 }
465 
466 
~DwarfInheritance()467 DwarfInheritance::~DwarfInheritance()
468 {
469 	fType->ReleaseReference();
470 }
471 
472 
473 Type*
GetType() const474 DwarfInheritance::GetType() const
475 {
476 	return fType;
477 }
478 
479 
480 // #pragma mark - DwarfDataMember
481 
482 
DwarfDataMember(DIEMember * entry,const BString & name,DwarfType * type)483 DwarfDataMember::DwarfDataMember(DIEMember* entry, const BString& name,
484 	DwarfType* type)
485 	:
486 	fEntry(entry),
487 	fName(name),
488 	fType(type)
489 {
490 	fType->AcquireReference();
491 }
492 
493 
~DwarfDataMember()494 DwarfDataMember::~DwarfDataMember()
495 {
496 	fType->ReleaseReference();
497 }
498 
499 const char*
Name() const500 DwarfDataMember::Name() const
501 {
502 	return fName.Length() > 0 ? fName.String() : NULL;
503 }
504 
505 
506 Type*
GetType() const507 DwarfDataMember::GetType() const
508 {
509 	return fType;
510 }
511 
512 
513 // #pragma mark - DwarfEnumeratorValue
514 
515 
DwarfEnumeratorValue(DIEEnumerator * entry,const BString & name,const BVariant & value)516 DwarfEnumeratorValue::DwarfEnumeratorValue(DIEEnumerator* entry,
517 	const BString& name, const BVariant& value)
518 	:
519 	fEntry(entry),
520 	fName(name),
521 	fValue(value)
522 {
523 }
524 
525 
~DwarfEnumeratorValue()526 DwarfEnumeratorValue::~DwarfEnumeratorValue()
527 {
528 }
529 
530 const char*
Name() const531 DwarfEnumeratorValue::Name() const
532 {
533 	return fName.Length() > 0 ? fName.String() : NULL;
534 }
535 
536 
537 BVariant
Value() const538 DwarfEnumeratorValue::Value() const
539 {
540 	return fValue;
541 }
542 
543 
544 // #pragma mark - DwarfArrayDimension
545 
546 
DwarfArrayDimension(DwarfType * type)547 DwarfArrayDimension::DwarfArrayDimension(DwarfType* type)
548 	:
549 	fType(type)
550 {
551 	fType->AcquireReference();
552 }
553 
554 
~DwarfArrayDimension()555 DwarfArrayDimension::~DwarfArrayDimension()
556 {
557 	fType->ReleaseReference();
558 }
559 
560 
561 Type*
GetType() const562 DwarfArrayDimension::GetType() const
563 {
564 	return fType;
565 }
566 
567 
568 // #pragma mark - DwarfFunctionParameter
569 
570 
DwarfFunctionParameter(DIEFormalParameter * entry,const BString & name,DwarfType * type)571 DwarfFunctionParameter::DwarfFunctionParameter(DIEFormalParameter* entry,
572 	const BString& name, DwarfType* type)
573 	:
574 	fEntry(entry),
575 	fName(name),
576 	fType(type)
577 {
578 	fType->AcquireReference();
579 }
580 
581 
~DwarfFunctionParameter()582 DwarfFunctionParameter::~DwarfFunctionParameter()
583 {
584 	fType->ReleaseReference();
585 }
586 
587 
588 const char*
Name() const589 DwarfFunctionParameter::Name() const
590 {
591 	return fName.Length() > 0 ? fName.String() : NULL;
592 }
593 
594 
595 Type*
GetType() const596 DwarfFunctionParameter::GetType() const
597 {
598 	return fType;
599 }
600 
601 
602 // #pragma mark - DwarfTemplateParameter
603 
604 
DwarfTemplateParameter(DebugInfoEntry * entry,DwarfType * type)605 DwarfTemplateParameter::DwarfTemplateParameter(DebugInfoEntry* entry,
606 	DwarfType* type)
607 	:
608 	fEntry(entry),
609 	fType(type)
610 {
611 	fType->AcquireReference();
612 	DIETemplateTypeParameter* typeParameter
613 		= dynamic_cast<DIETemplateTypeParameter *>(entry);
614 	if (typeParameter != NULL)
615 		fTemplateKind = TEMPLATE_TYPE_TYPE;
616 	else {
617 		DIETemplateValueParameter* valueParameter
618 			= dynamic_cast<DIETemplateValueParameter *>(entry);
619 		fTemplateKind = TEMPLATE_TYPE_VALUE;
620 		const ConstantAttributeValue* constValue = valueParameter
621 			->ConstValue();
622 		switch (constValue->attributeClass) {
623 			case ATTRIBUTE_CLASS_CONSTANT:
624 				fValue.SetTo(constValue->constant);
625 				break;
626 			case ATTRIBUTE_CLASS_STRING:
627 				fValue.SetTo(constValue->string);
628 				break;
629 			// TODO: ATTRIBUTE_CLASS_BLOCK_DATA
630 		}
631 	}
632 }
633 
634 
~DwarfTemplateParameter()635 DwarfTemplateParameter::~DwarfTemplateParameter()
636 {
637 	fType->ReleaseReference();
638 }
639 
640 
641 // #pragma mark - DwarfPrimitiveType
642 
643 
DwarfPrimitiveType(DwarfTypeContext * typeContext,const BString & name,DIEBaseType * entry,uint32 typeConstant)644 DwarfPrimitiveType::DwarfPrimitiveType(DwarfTypeContext* typeContext,
645 	const BString& name, DIEBaseType* entry, uint32 typeConstant)
646 	:
647 	DwarfType(typeContext, name, entry),
648 	fEntry(entry),
649 	fTypeConstant(typeConstant)
650 {
651 }
652 
653 
654 DIEType*
GetDIEType() const655 DwarfPrimitiveType::GetDIEType() const
656 {
657 	return fEntry;
658 }
659 
660 
661 uint32
TypeConstant() const662 DwarfPrimitiveType::TypeConstant() const
663 {
664 	return fTypeConstant;
665 }
666 
667 
668 // #pragma mark - DwarfCompoundType
669 
670 
DwarfCompoundType(DwarfTypeContext * typeContext,const BString & name,DIECompoundType * entry,compound_type_kind compoundKind)671 DwarfCompoundType::DwarfCompoundType(DwarfTypeContext* typeContext,
672 	const BString& name, DIECompoundType* entry,
673 	compound_type_kind compoundKind)
674 	:
675 	DwarfType(typeContext, name, entry),
676 	fCompoundKind(compoundKind),
677 	fEntry(entry)
678 {
679 }
680 
681 
~DwarfCompoundType()682 DwarfCompoundType::~DwarfCompoundType()
683 {
684 	for (int32 i = 0;
685 			DwarfInheritance* inheritance = fInheritances.ItemAt(i); i++) {
686 		inheritance->ReleaseReference();
687 	}
688 	for (int32 i = 0; DwarfDataMember* member = fDataMembers.ItemAt(i); i++)
689 		member->ReleaseReference();
690 
691 	for (int32 i = 0; DwarfTemplateParameter* parameter
692 		= fTemplateParameters.ItemAt(i); i++) {
693 		parameter->ReleaseReference();
694 	}
695 }
696 
697 
698 compound_type_kind
CompoundKind() const699 DwarfCompoundType::CompoundKind() const
700 {
701 	return fCompoundKind;
702 }
703 
704 
705 int32
CountBaseTypes() const706 DwarfCompoundType::CountBaseTypes() const
707 {
708 	return fInheritances.CountItems();
709 }
710 
711 
712 BaseType*
BaseTypeAt(int32 index) const713 DwarfCompoundType::BaseTypeAt(int32 index) const
714 {
715 	return fInheritances.ItemAt(index);
716 }
717 
718 
719 int32
CountDataMembers() const720 DwarfCompoundType::CountDataMembers() const
721 {
722 	return fDataMembers.CountItems();
723 }
724 
725 
726 DataMember*
DataMemberAt(int32 index) const727 DwarfCompoundType::DataMemberAt(int32 index) const
728 {
729 	return fDataMembers.ItemAt(index);
730 }
731 
732 
733 int32
CountTemplateParameters() const734 DwarfCompoundType::CountTemplateParameters() const
735 {
736 	return fTemplateParameters.CountItems();
737 }
738 
739 
740 TemplateParameter*
TemplateParameterAt(int32 index) const741 DwarfCompoundType::TemplateParameterAt(int32 index) const
742 {
743 	return fTemplateParameters.ItemAt(index);
744 }
745 
746 
747 status_t
ResolveBaseTypeLocation(BaseType * _baseType,const ValueLocation & parentLocation,ValueLocation * & _location)748 DwarfCompoundType::ResolveBaseTypeLocation(BaseType* _baseType,
749 	const ValueLocation& parentLocation, ValueLocation*& _location)
750 {
751 	DwarfInheritance* baseType = dynamic_cast<DwarfInheritance*>(_baseType);
752 	if (baseType == NULL)
753 		return B_BAD_VALUE;
754 
755 	return _ResolveDataMemberLocation(baseType->GetDwarfType(),
756 		baseType->Entry()->Location(), parentLocation, false, _location);
757 }
758 
759 
760 status_t
ResolveDataMemberLocation(DataMember * _member,const ValueLocation & parentLocation,ValueLocation * & _location)761 DwarfCompoundType::ResolveDataMemberLocation(DataMember* _member,
762 	const ValueLocation& parentLocation, ValueLocation*& _location)
763 {
764 	DwarfDataMember* member = dynamic_cast<DwarfDataMember*>(_member);
765 	if (member == NULL)
766 		return B_BAD_VALUE;
767 	DwarfTypeContext* typeContext = TypeContext();
768 
769 	bool isBitField = true;
770 	DIEMember* memberEntry = member->Entry();
771 	// TODO: handle DW_AT_data_bit_offset
772 	if (!memberEntry->ByteSize()->IsValid()
773 		&& !memberEntry->BitOffset()->IsValid()
774 		&& !memberEntry->BitSize()->IsValid()) {
775 		isBitField = false;
776 	}
777 
778 	ValueLocation* location;
779 	status_t error = _ResolveDataMemberLocation(member->GetDwarfType(),
780 		member->Entry()->Location(), parentLocation, isBitField, location);
781 	if (error != B_OK)
782 		return error;
783 
784 	// If the member isn't a bit field, we're done.
785 	if (!isBitField) {
786 		_location = location;
787 		return B_OK;
788 	}
789 
790 	BReference<ValueLocation> locationReference(location);
791 
792 	// get the byte size
793 	target_addr_t byteSize;
794 	if (memberEntry->ByteSize()->IsValid()) {
795 		BVariant value;
796 		error = typeContext->File()->EvaluateDynamicValue(
797 			typeContext->GetCompilationUnit(),
798 			typeContext->AddressSize(), typeContext->IsBigEndian(),
799 			typeContext->SubprogramEntry(), memberEntry->ByteSize(),
800 			typeContext->TargetInterface(), typeContext->InstructionPointer(),
801 			typeContext->FramePointer(), value);
802 		if (error != B_OK)
803 			return error;
804 		byteSize = value.ToUInt64();
805 	} else
806 		byteSize = ByteSize();
807 
808 	// get the bit offset
809 	uint64 bitOffset = 0;
810 	if (memberEntry->BitOffset()->IsValid()) {
811 		BVariant value;
812 		error = typeContext->File()->EvaluateDynamicValue(
813 			typeContext->GetCompilationUnit(),
814 			typeContext->AddressSize(), typeContext->IsBigEndian(),
815 			typeContext->SubprogramEntry(), memberEntry->BitOffset(),
816 			typeContext->TargetInterface(), typeContext->InstructionPointer(),
817 			typeContext->FramePointer(), value);
818 		if (error != B_OK)
819 			return error;
820 		bitOffset = value.ToUInt64();
821 	}
822 
823 	// get the bit size
824 	uint64 bitSize = byteSize * 8;
825 	if (memberEntry->BitSize()->IsValid()) {
826 		BVariant value;
827 		error = typeContext->File()->EvaluateDynamicValue(
828 			typeContext->GetCompilationUnit(),
829 			typeContext->AddressSize(), typeContext->IsBigEndian(),
830 			typeContext->SubprogramEntry(), memberEntry->BitSize(),
831 			typeContext->TargetInterface(), typeContext->InstructionPointer(),
832 			typeContext->FramePointer(), value);
833 		if (error != B_OK)
834 			return error;
835 		bitSize = value.ToUInt64();
836 	}
837 
838 	TRACE_LOCALS("bit field: byte size: %" B_PRIu64 ", bit offset/size: %"
839 		B_PRIu64 "/%" B_PRIu64 "\n", byteSize, bitOffset, bitSize);
840 
841 	if (bitOffset + bitSize > byteSize * 8)
842 		return B_BAD_VALUE;
843 
844 	// create the bit field value location
845 	ValueLocation* bitFieldLocation = new(std::nothrow) ValueLocation;
846 	if (bitFieldLocation == NULL)
847 		return B_NO_MEMORY;
848 	BReference<ValueLocation> bitFieldLocationReference(bitFieldLocation, true);
849 
850 	if (!bitFieldLocation->SetTo(*location, bitOffset, bitSize))
851 		return B_NO_MEMORY;
852 
853 	_location = bitFieldLocationReference.Detach();
854 	return B_OK;
855 }
856 
857 
858 DIEType*
GetDIEType() const859 DwarfCompoundType::GetDIEType() const
860 {
861 	return fEntry;
862 }
863 
864 
865 bool
AddInheritance(DwarfInheritance * inheritance)866 DwarfCompoundType::AddInheritance(DwarfInheritance* inheritance)
867 {
868 	if (!fInheritances.AddItem(inheritance))
869 		return false;
870 
871 	inheritance->AcquireReference();
872 	return true;
873 }
874 
875 
876 bool
AddDataMember(DwarfDataMember * member)877 DwarfCompoundType::AddDataMember(DwarfDataMember* member)
878 {
879 	if (!fDataMembers.AddItem(member))
880 		return false;
881 
882 	member->AcquireReference();
883 	return true;
884 }
885 
886 
887 bool
AddTemplateParameter(DwarfTemplateParameter * parameter)888 DwarfCompoundType::AddTemplateParameter(DwarfTemplateParameter* parameter)
889 {
890 	if (!fTemplateParameters.AddItem(parameter))
891 		return false;
892 
893 	parameter->AcquireReference();
894 	return true;
895 }
896 
897 
898 status_t
_ResolveDataMemberLocation(DwarfType * memberType,const MemberLocation * memberLocation,const ValueLocation & parentLocation,bool isBitField,ValueLocation * & _location)899 DwarfCompoundType::_ResolveDataMemberLocation(DwarfType* memberType,
900 	const MemberLocation* memberLocation,
901 	const ValueLocation& parentLocation, bool isBitField,
902 	ValueLocation*& _location)
903 {
904 	// create the value location object for the member
905 	ValueLocation* location = new(std::nothrow) ValueLocation(
906 		parentLocation.IsBigEndian());
907 	if (location == NULL)
908 		return B_NO_MEMORY;
909 	BReference<ValueLocation> locationReference(location, true);
910 
911 	switch (memberLocation->attributeClass) {
912 		case ATTRIBUTE_CLASS_CONSTANT:
913 		{
914 			if (isBitField) {
915 				if (!location->SetTo(parentLocation,
916 					memberLocation->constant * 8,
917 					memberType->ByteSize() * 8)) {
918 					return B_NO_MEMORY;
919 				}
920 			} else {
921 				if (!location->SetToByteOffset(parentLocation,
922 					memberLocation->constant,
923 					memberType->ByteSize())) {
924 					return B_NO_MEMORY;
925 				}
926 			}
927 
928 			break;
929 		}
930 		case ATTRIBUTE_CLASS_BLOCK:
931 		case ATTRIBUTE_CLASS_LOCLISTPTR:
932 		{
933 			// The attribute is a location description. Since we need to push
934 			// the parent object value onto the stack, we require the parent
935 			// location to be a memory location.
936 			if (parentLocation.CountPieces() != 1)
937 				return B_BAD_VALUE;
938 			const ValuePieceLocation& piece = parentLocation.PieceAt(0);
939 
940 			if (piece.type != VALUE_PIECE_LOCATION_MEMORY)
941 				return B_BAD_VALUE;
942 
943 			// convert member location to location description
944 			LocationDescription locationDescription;
945 			if (memberLocation->attributeClass == ATTRIBUTE_CLASS_BLOCK) {
946 				locationDescription.SetToExpression(
947 					memberLocation->expression.data,
948 					memberLocation->expression.length);
949 			} else {
950 				locationDescription.SetToLocationList(
951 					memberLocation->listOffset);
952 			}
953 
954 			// evaluate the location description
955 			status_t error = memberType->ResolveLocation(TypeContext(),
956 				&locationDescription, piece.address, true, *location);
957 			if (error != B_OK)
958 				return error;
959 
960 			break;
961 		}
962 		default:
963 		{
964 			// for unions the member location can be omitted -- all members
965 			// start at the beginning of the parent object
966 			if (fEntry->Tag() != DW_TAG_union_type)
967 				return B_BAD_VALUE;
968 
969 			// since all members start at the same location, set up
970 			// the location by hand since we don't want the size difference
971 			// between the overall union and the member being
972 			// factored into the assigned address.
973 			ValuePieceLocation piece;
974 			if (!piece.Copy(parentLocation.PieceAt(0)))
975 				return B_NO_MEMORY;
976 
977 			piece.SetSize(memberType->ByteSize());
978 			if (!location->AddPiece(piece))
979 				return B_NO_MEMORY;
980 
981 			break;
982 		}
983 	}
984 
985 	_location = locationReference.Detach();
986 	return B_OK;
987 }
988 
989 
990 // #pragma mark - DwarfArrayType
991 
992 
DwarfArrayType(DwarfTypeContext * typeContext,const BString & name,DIEArrayType * entry,DwarfType * baseType)993 DwarfArrayType::DwarfArrayType(DwarfTypeContext* typeContext,
994 	const BString& name, DIEArrayType* entry, DwarfType* baseType)
995 	:
996 	DwarfType(typeContext, name, entry),
997 	fEntry(entry),
998 	fBaseType(baseType)
999 {
1000 	fBaseType->AcquireReference();
1001 }
1002 
1003 
~DwarfArrayType()1004 DwarfArrayType::~DwarfArrayType()
1005 {
1006 	for (int32 i = 0;
1007 		DwarfArrayDimension* dimension = fDimensions.ItemAt(i); i++) {
1008 		dimension->ReleaseReference();
1009 	}
1010 
1011 	fBaseType->ReleaseReference();
1012 }
1013 
1014 
1015 Type*
BaseType() const1016 DwarfArrayType::BaseType() const
1017 {
1018 	return fBaseType;
1019 }
1020 
1021 
1022 int32
CountDimensions() const1023 DwarfArrayType::CountDimensions() const
1024 {
1025 	return fDimensions.CountItems();
1026 }
1027 
1028 
1029 ArrayDimension*
DimensionAt(int32 index) const1030 DwarfArrayType::DimensionAt(int32 index) const
1031 {
1032 	return fDimensions.ItemAt(index);
1033 }
1034 
1035 
1036 status_t
ResolveElementLocation(const ArrayIndexPath & indexPath,const ValueLocation & parentLocation,ValueLocation * & _location)1037 DwarfArrayType::ResolveElementLocation(const ArrayIndexPath& indexPath,
1038 	const ValueLocation& parentLocation, ValueLocation*& _location)
1039 {
1040 	if (indexPath.CountIndices() != CountDimensions())
1041 		return B_BAD_VALUE;
1042 	DwarfTypeContext* typeContext = TypeContext();
1043 
1044 	// If the array entry has a bit stride, get it. Otherwise fall back to the
1045 	// element type size.
1046 	int64 bitStride;
1047 	DIEArrayType* bitStrideOwnerEntry = NULL;
1048 	if (fEntry != NULL && (bitStrideOwnerEntry = DwarfUtils::GetDIEByPredicate(
1049 			fEntry, HasBitStridePredicate<DIEArrayType>()))) {
1050 		BVariant value;
1051 		status_t error = typeContext->File()->EvaluateDynamicValue(
1052 			typeContext->GetCompilationUnit(),
1053 			typeContext->AddressSize(), typeContext->IsBigEndian(),
1054 			typeContext->SubprogramEntry(), bitStrideOwnerEntry->BitStride(),
1055 			typeContext->TargetInterface(), typeContext->InstructionPointer(),
1056 			typeContext->FramePointer(), value);
1057 		if (error != B_OK)
1058 			return error;
1059 		if (!value.IsInteger())
1060 			return B_BAD_VALUE;
1061 		bitStride = value.ToInt64();
1062 	} else
1063 		bitStride = BaseType()->ByteSize() * 8;
1064 
1065 	// Iterate backward through the dimensions and compute the total offset of
1066 	// the element.
1067 	int64 elementOffset = 0;
1068 	DwarfArrayDimension* previousDimension = NULL;
1069 	int64 previousDimensionStride = 0;
1070 	for (int32 dimensionIndex = CountDimensions() - 1;
1071 			dimensionIndex >= 0; dimensionIndex--) {
1072 		DwarfArrayDimension* dimension = DwarfDimensionAt(dimensionIndex);
1073 		int64 index = indexPath.IndexAt(dimensionIndex);
1074 
1075 		// If the dimension has a special bit/byte stride, get it.
1076 		int64 dimensionStride = 0;
1077 		DwarfType* dimensionType = dimension->GetDwarfType();
1078 		DIEArrayIndexType* dimensionTypeEntry = dimensionType != NULL
1079 			? dynamic_cast<DIEArrayIndexType*>(dimensionType->GetDIEType())
1080 			: NULL;
1081 		if (dimensionTypeEntry != NULL) {
1082 			DIEArrayIndexType* bitStrideOwnerEntry
1083 				= DwarfUtils::GetDIEByPredicate(dimensionTypeEntry,
1084 					HasBitStridePredicate<DIEArrayIndexType>());
1085 			if (bitStrideOwnerEntry != NULL) {
1086 				BVariant value;
1087 				status_t error = typeContext->File()->EvaluateDynamicValue(
1088 					typeContext->GetCompilationUnit(),
1089 					typeContext->AddressSize(), typeContext->IsBigEndian(),
1090 					typeContext->SubprogramEntry(),
1091 					bitStrideOwnerEntry->BitStride(),
1092 					typeContext->TargetInterface(),
1093 					typeContext->InstructionPointer(),
1094 					typeContext->FramePointer(), value);
1095 				if (error != B_OK)
1096 					return error;
1097 				if (!value.IsInteger())
1098 					return B_BAD_VALUE;
1099 				dimensionStride = value.ToInt64();
1100 			} else {
1101 				DIEArrayIndexType* byteStrideOwnerEntry
1102 					= DwarfUtils::GetDIEByPredicate(dimensionTypeEntry,
1103 						HasByteStridePredicate<DIEArrayIndexType>());
1104 				if (byteStrideOwnerEntry != NULL) {
1105 					BVariant value;
1106 					status_t error = typeContext->File()->EvaluateDynamicValue(
1107 						typeContext->GetCompilationUnit(),
1108 						typeContext->AddressSize(), typeContext->IsBigEndian(),
1109 						typeContext->SubprogramEntry(),
1110 						byteStrideOwnerEntry->ByteStride(),
1111 						typeContext->TargetInterface(),
1112 						typeContext->InstructionPointer(),
1113 						typeContext->FramePointer(), value);
1114 					if (error != B_OK)
1115 						return error;
1116 					if (!value.IsInteger())
1117 						return B_BAD_VALUE;
1118 					dimensionStride = value.ToInt64() * 8;
1119 				}
1120 			}
1121 		}
1122 
1123 		// If we don't have a stride for the dimension yet, use the stride of
1124 		// the previous dimension multiplied by the size of the dimension.
1125 		if (dimensionStride == 0) {
1126 			if (previousDimension != NULL) {
1127 				dimensionStride = previousDimensionStride
1128 					* previousDimension->CountElements();
1129 			} else {
1130 				// the last dimension -- use the element bit stride
1131 				dimensionStride = bitStride;
1132 			}
1133 		}
1134 
1135 		// If the dimension stride is still 0 (that can happen, if the dimension
1136 		// doesn't have a stride and the previous dimension's element count is
1137 		// not known), we can only resolve the first element.
1138 		if (dimensionStride == 0 && index != 0) {
1139 			WARNING("No dimension bit stride for dimension %" B_PRId32 " and "
1140 				"element index is not 0.\n", dimensionIndex);
1141 			return B_BAD_VALUE;
1142 		}
1143 
1144 		elementOffset += dimensionStride * index;
1145 
1146 		previousDimension = dimension;
1147 		previousDimensionStride = dimensionStride;
1148 	}
1149 
1150 	TRACE_LOCALS("total element bit offset: %" B_PRId64 "\n", elementOffset);
1151 
1152 	// create the value location object for the element
1153 	ValueLocation* location = new(std::nothrow) ValueLocation(
1154 		parentLocation.IsBigEndian());
1155 	if (location == NULL)
1156 		return B_NO_MEMORY;
1157 	BReference<ValueLocation> locationReference(location, true);
1158 
1159 	// If we have a single memory piece location for the array, we compute the
1160 	// element's location by hand -- not uncommonly the array size isn't known.
1161 	if (parentLocation.CountPieces() == 1) {
1162 		ValuePieceLocation piece;
1163 		if (!piece.Copy(parentLocation.PieceAt(0)))
1164 			return B_NO_MEMORY;
1165 
1166 		if (piece.type == VALUE_PIECE_LOCATION_MEMORY) {
1167 			int64 byteOffset = elementOffset >= 0
1168 				? elementOffset / 8 : (elementOffset - 7) / 8;
1169 			piece.SetToMemory(piece.address + byteOffset);
1170 			piece.SetSize(BaseType()->ByteSize());
1171 			// TODO: Support bit offsets correctly!
1172 			// TODO: Support bit fields (primitive types) correctly!
1173 
1174 			if (!location->AddPiece(piece))
1175 				return B_NO_MEMORY;
1176 
1177 			_location = locationReference.Detach();
1178 			return B_OK;
1179 		}
1180 	}
1181 
1182 	// We can't deal with negative element offsets at this point. It doesn't
1183 	// make a lot of sense anyway, if the array location consists of multiple
1184 	// pieces or lives in a register.
1185 	if (elementOffset < 0) {
1186 		WARNING("Negative element offset unsupported for multiple location "
1187 			"pieces or register pieces.\n");
1188 		return B_UNSUPPORTED;
1189 	}
1190 
1191 	if (!location->SetTo(parentLocation, elementOffset,
1192 			BaseType()->ByteSize() * 8)) {
1193 		return B_NO_MEMORY;
1194 	}
1195 
1196 	_location = locationReference.Detach();
1197 	return B_OK;
1198 }
1199 
1200 
1201 
1202 DIEType*
GetDIEType() const1203 DwarfArrayType::GetDIEType() const
1204 {
1205 	return fEntry;
1206 }
1207 
1208 
1209 bool
AddDimension(DwarfArrayDimension * dimension)1210 DwarfArrayType::AddDimension(DwarfArrayDimension* dimension)
1211 {
1212 	if (!fDimensions.AddItem(dimension))
1213 		return false;
1214 
1215 	dimension->AcquireReference();
1216 	return true;
1217 }
1218 
1219 
1220 // #pragma mark - DwarfModifiedType
1221 
1222 
DwarfModifiedType(DwarfTypeContext * typeContext,const BString & name,DIEModifiedType * entry,uint32 modifiers,DwarfType * baseType)1223 DwarfModifiedType::DwarfModifiedType(DwarfTypeContext* typeContext,
1224 	const BString& name, DIEModifiedType* entry, uint32 modifiers,
1225 	DwarfType* baseType)
1226 	:
1227 	DwarfType(typeContext, name, entry),
1228 	fEntry(entry),
1229 	fModifiers(modifiers),
1230 	fBaseType(baseType)
1231 {
1232 	fBaseType->AcquireReference();
1233 }
1234 
1235 
~DwarfModifiedType()1236 DwarfModifiedType::~DwarfModifiedType()
1237 {
1238 	fBaseType->ReleaseReference();
1239 }
1240 
1241 
1242 uint32
Modifiers() const1243 DwarfModifiedType::Modifiers() const
1244 {
1245 	return fModifiers;
1246 }
1247 
1248 
1249 Type*
BaseType() const1250 DwarfModifiedType::BaseType() const
1251 {
1252 	return fBaseType;
1253 }
1254 
1255 
1256 DIEType*
GetDIEType() const1257 DwarfModifiedType::GetDIEType() const
1258 {
1259 	return fEntry;
1260 }
1261 
1262 
1263 // #pragma mark - DwarfTypedefType
1264 
1265 
DwarfTypedefType(DwarfTypeContext * typeContext,const BString & name,DIETypedef * entry,DwarfType * baseType)1266 DwarfTypedefType::DwarfTypedefType(DwarfTypeContext* typeContext,
1267 	const BString& name, DIETypedef* entry, DwarfType* baseType)
1268 	:
1269 	DwarfType(typeContext, name, entry),
1270 	fEntry(entry),
1271 	fBaseType(baseType)
1272 {
1273 	fBaseType->AcquireReference();
1274 }
1275 
1276 
~DwarfTypedefType()1277 DwarfTypedefType::~DwarfTypedefType()
1278 {
1279 	fBaseType->ReleaseReference();
1280 }
1281 
1282 
1283 Type*
BaseType() const1284 DwarfTypedefType::BaseType() const
1285 {
1286 	return fBaseType;
1287 }
1288 
1289 
1290 DIEType*
GetDIEType() const1291 DwarfTypedefType::GetDIEType() const
1292 {
1293 	return fEntry;
1294 }
1295 
1296 
1297 // #pragma mark - DwarfAddressType
1298 
1299 
DwarfAddressType(DwarfTypeContext * typeContext,const BString & name,DIEAddressingType * entry,address_type_kind addressKind,DwarfType * baseType)1300 DwarfAddressType::DwarfAddressType(DwarfTypeContext* typeContext,
1301 	const BString& name, DIEAddressingType* entry,
1302 	address_type_kind addressKind, DwarfType* baseType)
1303 	:
1304 	DwarfType(typeContext, name, entry),
1305 	fEntry(entry),
1306 	fAddressKind(addressKind),
1307 	fBaseType(baseType)
1308 {
1309 	fBaseType->AcquireReference();
1310 }
1311 
1312 
~DwarfAddressType()1313 DwarfAddressType::~DwarfAddressType()
1314 {
1315 	fBaseType->ReleaseReference();
1316 }
1317 
1318 
1319 address_type_kind
AddressKind() const1320 DwarfAddressType::AddressKind() const
1321 {
1322 	return fAddressKind;
1323 }
1324 
1325 
1326 Type*
BaseType() const1327 DwarfAddressType::BaseType() const
1328 {
1329 	return fBaseType;
1330 }
1331 
1332 
1333 DIEType*
GetDIEType() const1334 DwarfAddressType::GetDIEType() const
1335 {
1336 	return fEntry;
1337 }
1338 
1339 
1340 // #pragma mark - DwarfEnumerationType
1341 
1342 
DwarfEnumerationType(DwarfTypeContext * typeContext,const BString & name,DIEEnumerationType * entry,DwarfType * baseType)1343 DwarfEnumerationType::DwarfEnumerationType(DwarfTypeContext* typeContext,
1344 	const BString& name, DIEEnumerationType* entry, DwarfType* baseType)
1345 	:
1346 	DwarfType(typeContext, name, entry),
1347 	fEntry(entry),
1348 	fBaseType(baseType)
1349 {
1350 	if (fBaseType != NULL)
1351 		fBaseType->AcquireReference();
1352 }
1353 
1354 
~DwarfEnumerationType()1355 DwarfEnumerationType::~DwarfEnumerationType()
1356 {
1357 	for (int32 i = 0; DwarfEnumeratorValue* value = fValues.ItemAt(i); i++)
1358 		value->ReleaseReference();
1359 
1360 	if (fBaseType != NULL)
1361 		fBaseType->ReleaseReference();
1362 }
1363 
1364 
1365 Type*
BaseType() const1366 DwarfEnumerationType::BaseType() const
1367 {
1368 	return fBaseType;
1369 }
1370 
1371 
1372 int32
CountValues() const1373 DwarfEnumerationType::CountValues() const
1374 {
1375 	return fValues.CountItems();
1376 }
1377 
1378 
1379 EnumeratorValue*
ValueAt(int32 index) const1380 DwarfEnumerationType::ValueAt(int32 index) const
1381 {
1382 	return fValues.ItemAt(index);
1383 }
1384 
1385 
1386 DIEType*
GetDIEType() const1387 DwarfEnumerationType::GetDIEType() const
1388 {
1389 	return fEntry;
1390 }
1391 
1392 
1393 bool
AddValue(DwarfEnumeratorValue * value)1394 DwarfEnumerationType::AddValue(DwarfEnumeratorValue* value)
1395 {
1396 	if (!fValues.AddItem(value))
1397 		return false;
1398 
1399 	value->AcquireReference();
1400 	return true;
1401 }
1402 
1403 
1404 // #pragma mark - DwarfSubrangeType
1405 
1406 
DwarfSubrangeType(DwarfTypeContext * typeContext,const BString & name,DIESubrangeType * entry,Type * baseType,const BVariant & lowerBound,const BVariant & upperBound)1407 DwarfSubrangeType::DwarfSubrangeType(DwarfTypeContext* typeContext,
1408 	const BString& name, DIESubrangeType* entry, Type* baseType,
1409 	const BVariant& lowerBound, const BVariant& upperBound)
1410 	:
1411 	DwarfType(typeContext, name, entry),
1412 	fEntry(entry),
1413 	fBaseType(baseType),
1414 	fLowerBound(lowerBound),
1415 	fUpperBound(upperBound)
1416 {
1417 	fBaseType->AcquireReference();
1418 }
1419 
1420 
~DwarfSubrangeType()1421 DwarfSubrangeType::~DwarfSubrangeType()
1422 {
1423 	fBaseType->ReleaseReference();
1424 }
1425 
1426 
1427 Type*
BaseType() const1428 DwarfSubrangeType::BaseType() const
1429 {
1430 	return fBaseType;
1431 }
1432 
1433 
1434 DIEType*
GetDIEType() const1435 DwarfSubrangeType::GetDIEType() const
1436 {
1437 	return fEntry;
1438 }
1439 
1440 
1441 BVariant
LowerBound() const1442 DwarfSubrangeType::LowerBound() const
1443 {
1444 	return fLowerBound;
1445 }
1446 
1447 
1448 BVariant
UpperBound() const1449 DwarfSubrangeType::UpperBound() const
1450 {
1451 	return fUpperBound;
1452 }
1453 
1454 
1455 // #pragma mark - DwarfUnspecifiedType
1456 
1457 
DwarfUnspecifiedType(DwarfTypeContext * typeContext,const BString & name,DIEUnspecifiedType * entry)1458 DwarfUnspecifiedType::DwarfUnspecifiedType(DwarfTypeContext* typeContext,
1459 	const BString& name, DIEUnspecifiedType* entry)
1460 	:
1461 	DwarfType(typeContext, name, entry),
1462 	fEntry(entry)
1463 {
1464 }
1465 
1466 
~DwarfUnspecifiedType()1467 DwarfUnspecifiedType::~DwarfUnspecifiedType()
1468 {
1469 }
1470 
1471 
1472 DIEType*
GetDIEType() const1473 DwarfUnspecifiedType::GetDIEType() const
1474 {
1475 	return fEntry;
1476 }
1477 
1478 
1479 // #pragma mark - DwarfFunctionType
1480 
1481 
DwarfFunctionType(DwarfTypeContext * typeContext,const BString & name,DIESubroutineType * entry,DwarfType * returnType)1482 DwarfFunctionType::DwarfFunctionType(DwarfTypeContext* typeContext,
1483 	const BString& name, DIESubroutineType* entry, DwarfType* returnType)
1484 	:
1485 	DwarfType(typeContext, name, entry),
1486 	fEntry(entry),
1487 	fReturnType(returnType),
1488 	fHasVariableArguments(false)
1489 {
1490 	if (fReturnType != NULL)
1491 		fReturnType->AcquireReference();
1492 }
1493 
1494 
~DwarfFunctionType()1495 DwarfFunctionType::~DwarfFunctionType()
1496 {
1497 	for (int32 i = 0;
1498 		DwarfFunctionParameter* parameter = fParameters.ItemAt(i); i++) {
1499 		parameter->ReleaseReference();
1500 	}
1501 
1502 	if (fReturnType != NULL)
1503 		fReturnType->ReleaseReference();
1504 }
1505 
1506 
1507 Type*
ReturnType() const1508 DwarfFunctionType::ReturnType() const
1509 {
1510 	return fReturnType;
1511 }
1512 
1513 
1514 int32
CountParameters() const1515 DwarfFunctionType::CountParameters() const
1516 {
1517 	return fParameters.CountItems();
1518 }
1519 
1520 
1521 FunctionParameter*
ParameterAt(int32 index) const1522 DwarfFunctionType::ParameterAt(int32 index) const
1523 {
1524 	return fParameters.ItemAt(index);
1525 }
1526 
1527 
1528 bool
HasVariableArguments() const1529 DwarfFunctionType::HasVariableArguments() const
1530 {
1531 	return fHasVariableArguments;
1532 }
1533 
1534 
1535 void
SetHasVariableArguments(bool hasVarArgs)1536 DwarfFunctionType::SetHasVariableArguments(bool hasVarArgs)
1537 {
1538 	fHasVariableArguments = hasVarArgs;
1539 }
1540 
1541 
1542 DIEType*
GetDIEType() const1543 DwarfFunctionType::GetDIEType() const
1544 {
1545 	return fEntry;
1546 }
1547 
1548 
1549 bool
AddParameter(DwarfFunctionParameter * parameter)1550 DwarfFunctionType::AddParameter(DwarfFunctionParameter* parameter)
1551 {
1552 	if (!fParameters.AddItem(parameter))
1553 		return false;
1554 
1555 	parameter->AcquireReference();
1556 	return true;
1557 }
1558 
1559 
1560 // #pragma mark - DwarfPointerToMemberType
1561 
1562 
DwarfPointerToMemberType(DwarfTypeContext * typeContext,const BString & name,DIEPointerToMemberType * entry,DwarfCompoundType * containingType,DwarfType * baseType)1563 DwarfPointerToMemberType::DwarfPointerToMemberType(
1564 	DwarfTypeContext* typeContext, const BString& name,
1565 	DIEPointerToMemberType* entry, DwarfCompoundType* containingType,
1566 	DwarfType* baseType)
1567 	:
1568 	DwarfType(typeContext, name, entry),
1569 	fEntry(entry),
1570 	fContainingType(containingType),
1571 	fBaseType(baseType)
1572 {
1573 	fContainingType->AcquireReference();
1574 	fBaseType->AcquireReference();
1575 }
1576 
1577 
~DwarfPointerToMemberType()1578 DwarfPointerToMemberType::~DwarfPointerToMemberType()
1579 {
1580 	fContainingType->ReleaseReference();
1581 	fBaseType->ReleaseReference();
1582 }
1583 
1584 
1585 CompoundType*
ContainingType() const1586 DwarfPointerToMemberType::ContainingType() const
1587 {
1588 	return fContainingType;
1589 }
1590 
1591 
1592 Type*
BaseType() const1593 DwarfPointerToMemberType::BaseType() const
1594 {
1595 	return fBaseType;
1596 }
1597 
1598 
1599 DIEType*
GetDIEType() const1600 DwarfPointerToMemberType::GetDIEType() const
1601 {
1602 	return fEntry;
1603 }
1604