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