xref: /haiku/src/kits/debugger/debug_info/DwarfImageDebugInfo.cpp (revision 5e7964b0a929555415798dea3373db9ac4611caa)
1 /*
2  * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2012-2016, Rene Gollent, rene@gollent.com.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include "DwarfImageDebugInfo.h"
9 
10 #include <errno.h>
11 #include <stdio.h>
12 #include <unistd.h>
13 
14 #include <algorithm>
15 #include <new>
16 
17 #include <AutoDeleter.h>
18 #include <AutoLocker.h>
19 
20 #include "Architecture.h"
21 #include "BasicFunctionDebugInfo.h"
22 #include "CLanguage.h"
23 #include "CompilationUnit.h"
24 #include "CppLanguage.h"
25 #include "CpuState.h"
26 #include "DebuggerInterface.h"
27 #include "DebugInfoEntries.h"
28 #include "Demangler.h"
29 #include "DisassembledCode.h"
30 #include "Dwarf.h"
31 #include "DwarfFile.h"
32 #include "DwarfFunctionDebugInfo.h"
33 #include "DwarfStackFrameDebugInfo.h"
34 #include "DwarfTargetInterface.h"
35 #include "DwarfTypeFactory.h"
36 #include "DwarfTypes.h"
37 #include "DwarfUtils.h"
38 #include "ElfFile.h"
39 #include "FileManager.h"
40 #include "FileSourceCode.h"
41 #include "FunctionID.h"
42 #include "FunctionInstance.h"
43 #include "GlobalTypeLookup.h"
44 #include "Image.h"
45 #include "ImageDebugInfo.h"
46 #include "InstructionInfo.h"
47 #include "LocatableFile.h"
48 #include "Register.h"
49 #include "RegisterMap.h"
50 #include "SourceFile.h"
51 #include "StackFrame.h"
52 #include "Statement.h"
53 #include "StringUtils.h"
54 #include "SymbolInfo.h"
55 #include "TargetAddressRangeList.h"
56 #include "Team.h"
57 #include "TeamFunctionSourceInformation.h"
58 #include "TeamMemory.h"
59 #include "Tracing.h"
60 #include "TypeLookupConstraints.h"
61 #include "UnsupportedLanguage.h"
62 #include "Variable.h"
63 #include "ValueLocation.h"
64 
65 
66 namespace {
67 
68 
69 // #pragma mark - HasTypePredicate
70 
71 
72 template<typename EntryType>
73 struct HasTypePredicate {
74 	inline bool operator()(EntryType* entry) const
75 	{
76 		return entry->GetType() != NULL;
77 	}
78 };
79 
80 }
81 
82 
83 // #pragma mark - BasicTargetInterface
84 
85 
86 struct DwarfImageDebugInfo::BasicTargetInterface : DwarfTargetInterface {
87 	BasicTargetInterface(const Register* registers, int32 registerCount,
88 		RegisterMap* fromDwarfMap, Architecture* architecture,
89 		TeamMemory* teamMemory)
90 		:
91 		fRegisters(registers),
92 		fRegisterCount(registerCount),
93 		fFromDwarfMap(fromDwarfMap),
94 		fArchitecture(architecture),
95 		fTeamMemory(teamMemory)
96 	{
97 		fFromDwarfMap->AcquireReference();
98 	}
99 
100 	~BasicTargetInterface()
101 	{
102 		fFromDwarfMap->ReleaseReference();
103 	}
104 
105 	virtual uint32 CountRegisters() const
106 	{
107 		return fRegisterCount;
108 	}
109 
110 	virtual uint32 RegisterValueType(uint32 index) const
111 	{
112 		const Register* reg = _RegisterAt(index);
113 		return reg != NULL ? reg->ValueType() : 0;
114 	}
115 
116 	virtual bool GetRegisterValue(uint32 index, BVariant& _value) const
117 	{
118 		return false;
119 	}
120 
121 	virtual bool SetRegisterValue(uint32 index, const BVariant& value)
122 	{
123 		return false;
124 	}
125 
126 	virtual bool IsCalleePreservedRegister(uint32 index) const
127 	{
128 		const Register* reg = _RegisterAt(index);
129 		return reg != NULL && reg->IsCalleePreserved();
130 	}
131 
132 	virtual status_t InitRegisterRules(CfaContext& context) const
133 	{
134 		return fArchitecture->InitRegisterRules(context);
135 	}
136 
137 	virtual bool ReadMemory(target_addr_t address, void* buffer,
138 		size_t size) const
139 	{
140 		ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer, size);
141 		return bytesRead >= 0 && (size_t)bytesRead == size;
142 	}
143 
144 	virtual bool ReadValueFromMemory(target_addr_t address,
145 		uint32 valueType, BVariant& _value) const
146 	{
147 		return fArchitecture->ReadValueFromMemory(address, valueType, _value)
148 			== B_OK;
149 	}
150 
151 	virtual bool ReadValueFromMemory(target_addr_t addressSpace,
152 		target_addr_t address, uint32 valueType, BVariant& _value) const
153 	{
154 		return fArchitecture->ReadValueFromMemory(addressSpace, address,
155 			valueType, _value) == B_OK;
156 	}
157 
158 protected:
159 	const Register* _RegisterAt(uint32 dwarfIndex) const
160 	{
161 		int32 index = fFromDwarfMap->MapRegisterIndex(dwarfIndex);
162 		return index >= 0 && index < fRegisterCount ? fRegisters + index : NULL;
163 	}
164 
165 protected:
166 	const Register*	fRegisters;
167 	int32			fRegisterCount;
168 	RegisterMap*	fFromDwarfMap;
169 	Architecture*	fArchitecture;
170 	TeamMemory*		fTeamMemory;
171 };
172 
173 
174 // #pragma mark - UnwindTargetInterface
175 
176 
177 struct DwarfImageDebugInfo::UnwindTargetInterface : BasicTargetInterface {
178 	UnwindTargetInterface(const Register* registers, int32 registerCount,
179 		RegisterMap* fromDwarfMap, RegisterMap* toDwarfMap, CpuState* cpuState,
180 		Architecture* architecture, TeamMemory* teamMemory)
181 		:
182 		BasicTargetInterface(registers, registerCount, fromDwarfMap,
183 			architecture, teamMemory),
184 		fToDwarfMap(toDwarfMap),
185 		fCpuState(cpuState)
186 	{
187 		fToDwarfMap->AcquireReference();
188 		fCpuState->AcquireReference();
189 	}
190 
191 	~UnwindTargetInterface()
192 	{
193 		fToDwarfMap->ReleaseReference();
194 		fCpuState->ReleaseReference();
195 	}
196 
197 	virtual bool GetRegisterValue(uint32 index, BVariant& _value) const
198 	{
199 		const Register* reg = _RegisterAt(index);
200 		if (reg == NULL)
201 			return false;
202 		return fCpuState->GetRegisterValue(reg, _value);
203 	}
204 
205 	virtual bool SetRegisterValue(uint32 index, const BVariant& value)
206 	{
207 		const Register* reg = _RegisterAt(index);
208 		if (reg == NULL)
209 			return false;
210 		return fCpuState->SetRegisterValue(reg, value);
211 	}
212 
213 private:
214 	RegisterMap*	fToDwarfMap;
215 	CpuState*		fCpuState;
216 };
217 
218 
219 // #pragma mark - EntryListWrapper
220 
221 
222 /*!	Wraps a DebugInfoEntryList, which is a typedef and thus cannot appear in
223 	the header, since our policy disallows us to include DWARF headers there.
224 */
225 struct DwarfImageDebugInfo::EntryListWrapper {
226 	const DebugInfoEntryList&	list;
227 
228 	EntryListWrapper(const DebugInfoEntryList& list)
229 		:
230 		list(list)
231 	{
232 	}
233 };
234 
235 
236 // #pragma mark - DwarfImageDebugInfo::TypeNameKey
237 
238 
239 struct DwarfImageDebugInfo::TypeNameKey {
240 	BString			typeName;
241 
242 	TypeNameKey(const BString& typeName)
243 		:
244 		typeName(typeName)
245 	{
246 	}
247 
248 	uint32 HashValue() const
249 	{
250 		return StringUtils::HashValue(typeName);
251 	}
252 
253 	bool operator==(const TypeNameKey& other) const
254 	{
255 		return typeName == other.typeName;
256 	}
257 };
258 
259 
260 // #pragma mark - DwarfImageDebugInfo::TypeNameEntry
261 
262 
263 struct DwarfImageDebugInfo::TypeNameEntry : TypeNameKey {
264 	TypeNameEntry* next;
265 	TypeEntryList types;
266 
267 	TypeNameEntry(const BString& name)
268 		:
269 		TypeNameKey(name),
270 		types(10, false)
271 	{
272 	}
273 
274 	~TypeNameEntry()
275 	{
276 	}
277 
278 };
279 
280 
281 // #pragma mark - DwarfImageDebugInfo::TypeNameEntryHashDefinition
282 
283 
284 struct DwarfImageDebugInfo::TypeNameEntryHashDefinition {
285 	typedef TypeNameKey		KeyType;
286 	typedef	TypeNameEntry	ValueType;
287 
288 	size_t HashKey(const TypeNameKey& key) const
289 	{
290 		return key.HashValue();
291 	}
292 
293 	size_t Hash(const TypeNameEntry* value) const
294 	{
295 		return value->HashValue();
296 	}
297 
298 	bool Compare(const TypeNameKey& key,
299 		const TypeNameEntry* value) const
300 	{
301 		return key == *value;
302 	}
303 
304 	TypeNameEntry*& GetLink(TypeNameEntry* value) const
305 	{
306 		return value->next;
307 	}
308 };
309 
310 
311 // #pragma mark - DwarfImageDebugInfo::TypeEntryInfo
312 
313 
314 struct DwarfImageDebugInfo::TypeEntryInfo {
315 	DIEType* type;
316 	CompilationUnit* unit;
317 
318 	TypeEntryInfo(DIEType* type, CompilationUnit* unit)
319 		:
320 		type(type),
321 		unit(unit)
322 	{
323 	}
324 };
325 
326 
327 // #pragma mark - DwarfImageDebugInfo
328 
329 
330 DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
331 	DebuggerInterface* interface, Architecture* architecture,
332 	FileManager* fileManager, GlobalTypeLookup* typeLookup,
333 	GlobalTypeCache* typeCache, TeamFunctionSourceInformation* sourceInfo,
334 	DwarfFile* file)
335 	:
336 	fLock("dwarf image debug info"),
337 	fImageInfo(imageInfo),
338 	fDebuggerInterface(interface),
339 	fArchitecture(architecture),
340 	fFileManager(fileManager),
341 	fTypeLookup(typeLookup),
342 	fTypeCache(typeCache),
343 	fSourceInfo(sourceInfo),
344 	fTypeNameTable(NULL),
345 	fFile(file),
346 	fTextSegment(NULL),
347 	fRelocationDelta(0),
348 	fTextSectionStart(0),
349 	fTextSectionEnd(0),
350 	fPLTSectionStart(0),
351 	fPLTSectionEnd(0)
352 {
353 	fDebuggerInterface->AcquireReference();
354 	fFile->AcquireReference();
355 	fTypeCache->AcquireReference();
356 }
357 
358 
359 DwarfImageDebugInfo::~DwarfImageDebugInfo()
360 {
361 	fDebuggerInterface->ReleaseReference();
362 	fFile->ReleaseReference();
363 	fTypeCache->ReleaseReference();
364 
365 	delete fTypeNameTable;
366 }
367 
368 
369 status_t
370 DwarfImageDebugInfo::Init()
371 {
372 	status_t error = fLock.InitCheck();
373 	if (error != B_OK)
374 		return error;
375 
376 	fTextSegment = fFile->GetElfFile()->TextSegment();
377 	if (fTextSegment == NULL)
378 		return B_ENTRY_NOT_FOUND;
379 
380 	fRelocationDelta = fImageInfo.TextBase() - fTextSegment->LoadAddress();
381 
382 	ElfSection* section = fFile->GetElfFile()->FindSection(".text");
383 	if (section != NULL) {
384 		fTextSectionStart = section->LoadAddress() + fRelocationDelta;
385 		fTextSectionEnd = fTextSectionStart + section->Size();
386 	}
387 
388 	section = fFile->GetElfFile()->FindSection(".plt");
389 	if (section != NULL) {
390 		fPLTSectionStart = section->LoadAddress() + fRelocationDelta;
391 		fPLTSectionEnd = fPLTSectionStart + section->Size();
392 	}
393 
394 	return _BuildTypeNameTable();
395 }
396 
397 
398 status_t
399 DwarfImageDebugInfo::GetFunctions(const BObjectList<SymbolInfo>& symbols,
400 	BObjectList<FunctionDebugInfo>& functions)
401 {
402 	TRACE_IMAGES("DwarfImageDebugInfo::GetFunctions()\n");
403 	TRACE_IMAGES("  %" B_PRId32 " compilation units\n",
404 		fFile->CountCompilationUnits());
405 
406 	for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
407 			i++) {
408 		DIECompileUnitBase* unitEntry = unit->UnitEntry();
409 //		printf("  %s:\n", unitEntry->Name());
410 //		printf("    address ranges:\n");
411 //		TargetAddressRangeList* rangeList = unitEntry->AddressRanges();
412 //		if (rangeList != NULL) {
413 //			int32 count = rangeList->CountRanges();
414 //			for (int32 i = 0; i < count; i++) {
415 //				TargetAddressRange range = rangeList->RangeAt(i);
416 //				printf("      %#llx - %#llx\n", range.Start(), range.End());
417 //			}
418 //		} else {
419 //			printf("      %#llx - %#llx\n", (target_addr_t)unitEntry->LowPC(),
420 //				(target_addr_t)unitEntry->HighPC());
421 //		}
422 
423 //		printf("    functions:\n");
424 		for (DebugInfoEntryList::ConstIterator it
425 					= unitEntry->OtherChildren().GetIterator();
426 				DebugInfoEntry* entry = it.Next();) {
427 			if (entry->Tag() != DW_TAG_subprogram)
428 				continue;
429 
430 			DIESubprogram* subprogramEntry = static_cast<DIESubprogram*>(entry);
431 
432 			// ignore declarations and inlined functions
433 			if (subprogramEntry->IsDeclaration()
434 				|| subprogramEntry->Inline() == DW_INL_inlined
435 				|| subprogramEntry->Inline() == DW_INL_declared_inlined) {
436 				continue;
437 			}
438 
439 			// get the name
440 			BString name;
441 			DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry, name);
442 			if (name.Length() == 0)
443 				continue;
444 
445 			// get the address ranges
446 			TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit,
447 				subprogramEntry->AddressRangesOffset());
448 			if (rangeList == NULL) {
449 				target_addr_t lowPC = subprogramEntry->LowPC();
450 				target_addr_t highPC = subprogramEntry->HighPC();
451 				if (highPC <= lowPC)
452 					continue;
453 
454 				rangeList = new(std::nothrow) TargetAddressRangeList(
455 					TargetAddressRange(lowPC, highPC - lowPC));
456 				if (rangeList == NULL)
457 					return B_NO_MEMORY;
458 						// TODO: Clean up already added functions!
459 			}
460 			BReference<TargetAddressRangeList> rangeListReference(rangeList,
461 				true);
462 
463 			// get the source location
464 			const char* directoryPath = NULL;
465 			const char* fileName = NULL;
466 			int32 line = -1;
467 			int32 column = -1;
468 			DwarfUtils::GetDeclarationLocation(fFile, subprogramEntry,
469 				directoryPath, fileName, line, column);
470 
471 			LocatableFile* file = NULL;
472 			if (fileName != NULL) {
473 				file = fFileManager->GetSourceFile(directoryPath,
474 					fileName);
475 			}
476 			BReference<LocatableFile> fileReference(file, true);
477 
478 			// create and add the functions
479 			DwarfFunctionDebugInfo* function
480 				= new(std::nothrow) DwarfFunctionDebugInfo(this, unit,
481 					subprogramEntry, rangeList, name, file,
482 					SourceLocation(line, std::max(column, (int32)0)));
483 			if (function == NULL || !functions.AddItem(function)) {
484 				delete function;
485 				return B_NO_MEMORY;
486 					// TODO: Clean up already added functions!
487 			}
488 
489 //			BString name;
490 //			DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry, name);
491 //			printf("      subprogram entry: %p, name: %s, declaration: %d\n",
492 //				subprogramEntry, name.String(),
493 //				subprogramEntry->IsDeclaration());
494 //
495 //			rangeList = subprogramEntry->AddressRanges();
496 //			if (rangeList != NULL) {
497 //				int32 count = rangeList->CountRanges();
498 //				for (int32 i = 0; i < count; i++) {
499 //					TargetAddressRange range = rangeList->RangeAt(i);
500 //					printf("        %#llx - %#llx\n", range.Start(), range.End());
501 //				}
502 //			} else {
503 //				printf("        %#llx - %#llx\n",
504 //					(target_addr_t)subprogramEntry->LowPC(),
505 //					(target_addr_t)subprogramEntry->HighPC());
506 //			}
507 		}
508 	}
509 
510 	if (fFile->CountCompilationUnits() != 0)
511 		return B_OK;
512 
513 	// if we had no compilation units, fall back to providing basic
514 	// debug infos with DWARF-supported call frame unwinding,
515 	// if available.
516 	if (fFile->HasFrameInformation()) {
517 		return SpecificImageDebugInfo::GetFunctionsFromSymbols(symbols,
518 			functions, fDebuggerInterface, fImageInfo, this);
519 	}
520 
521 	return B_OK;
522 }
523 
524 
525 status_t
526 DwarfImageDebugInfo::GetType(GlobalTypeCache* cache, const BString& name,
527 	const TypeLookupConstraints& constraints, Type*& _type)
528 {
529 	TypeNameEntry* entry = fTypeNameTable->Lookup(name);
530 	if (entry == NULL)
531 		return B_ENTRY_NOT_FOUND;
532 
533 	for (int32 i = 0; TypeEntryInfo* info = entry->types.ItemAt(i); i++) {
534 		DIEType* typeEntry = info->type;
535 		if (constraints.HasTypeKind()) {
536 			if (dwarf_tag_to_type_kind(typeEntry->Tag())
537 				!= constraints.TypeKind()) {
538 				continue;
539 			}
540 
541 			if (!_EvaluateBaseTypeConstraints(typeEntry, constraints))
542 				continue;
543 		}
544 
545 		if (constraints.HasSubtypeKind()
546 			&& dwarf_tag_to_subtype_kind(typeEntry->Tag())
547 				!= constraints.SubtypeKind()) {
548 			continue;
549 		}
550 
551 		DwarfTypeContext* typeContext = new(std::nothrow)
552 			DwarfTypeContext(fArchitecture, fImageInfo.ImageID(), fFile,
553 				info->unit, NULL, 0, 0, fRelocationDelta, NULL, NULL);
554 		if (typeContext == NULL)
555 			return B_NO_MEMORY;
556 		BReference<DwarfTypeContext> typeContextReference(typeContext, true);
557 
558 		// create the type
559 		DwarfType* type;
560 		DwarfTypeFactory typeFactory(typeContext, fTypeLookup, cache);
561 		status_t error = typeFactory.CreateType(typeEntry, type);
562 		if (error != B_OK)
563 			continue;
564 
565 		_type = type;
566 		return B_OK;
567 	}
568 
569 	return B_ENTRY_NOT_FOUND;
570 }
571 
572 
573 bool
574 DwarfImageDebugInfo::HasType(const BString& name,
575 	const TypeLookupConstraints& constraints) const
576 {
577 	TypeNameEntry* entry = fTypeNameTable->Lookup(name);
578 	if (entry == NULL)
579 		return false;
580 
581 	for (int32 i = 0; TypeEntryInfo* info = entry->types.ItemAt(i); i++) {
582 		DIEType* typeEntry = info->type;
583 		if (constraints.HasTypeKind()) {
584 			if (dwarf_tag_to_type_kind(typeEntry->Tag())
585 				!= constraints.TypeKind()) {
586 				continue;
587 			}
588 
589 			if (!_EvaluateBaseTypeConstraints(typeEntry, constraints))
590 				continue;
591 		}
592 
593 		if (constraints.HasSubtypeKind()
594 			&& dwarf_tag_to_subtype_kind(typeEntry->Tag())
595 				!= constraints.SubtypeKind()) {
596 			continue;
597 		}
598 
599 		return true;
600 	}
601 
602 	return false;
603 }
604 
605 
606 AddressSectionType
607 DwarfImageDebugInfo::GetAddressSectionType(target_addr_t address)
608 {
609 	if (address >= fTextSectionStart && address < fTextSectionEnd)
610 		return ADDRESS_SECTION_TYPE_FUNCTION;
611 
612  	if (address >= fPLTSectionStart && address < fPLTSectionEnd)
613 		return ADDRESS_SECTION_TYPE_PLT;
614 
615 	return ADDRESS_SECTION_TYPE_UNKNOWN;
616 }
617 
618 
619 status_t
620 DwarfImageDebugInfo::CreateFrame(Image* image,
621 	FunctionInstance* functionInstance, CpuState* cpuState,
622 	bool getFullFrameInfo, ReturnValueInfoList* returnValueInfos,
623 	StackFrame*& _frame, CpuState*& _previousCpuState)
624 {
625 	DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>(
626 		functionInstance->GetFunctionDebugInfo());
627 
628 	FunctionID* functionID = functionInstance->GetFunctionID();
629 	BReference<FunctionID> functionIDReference;
630 	if (functionID != NULL)
631 		functionIDReference.SetTo(functionID, true);
632 
633 	DIESubprogram* entry = function != NULL
634 		? function->SubprogramEntry() : NULL;
635 
636 	TRACE_CFI("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p, "
637 		"function: %s\n", entry,
638 		functionID->FunctionName().String());
639 
640 	int32 registerCount = fArchitecture->CountRegisters();
641 	const Register* registers = fArchitecture->Registers();
642 
643 	// get the DWARF <-> architecture register maps
644 	RegisterMap* toDwarfMap;
645 	RegisterMap* fromDwarfMap;
646 	status_t error = fArchitecture->GetDwarfRegisterMaps(&toDwarfMap,
647 		&fromDwarfMap);
648 	if (error != B_OK)
649 		return error;
650 	BReference<RegisterMap> toDwarfMapReference(toDwarfMap, true);
651 	BReference<RegisterMap> fromDwarfMapReference(fromDwarfMap, true);
652 
653 	// create a clean CPU state for the previous frame
654 	CpuState* previousCpuState;
655 	error = fArchitecture->CreateCpuState(previousCpuState);
656 	if (error != B_OK)
657 		return error;
658 	BReference<CpuState> previousCpuStateReference(previousCpuState, true);
659 
660 	// create the target interfaces
661 	UnwindTargetInterface* inputInterface
662 		= new(std::nothrow) UnwindTargetInterface(registers, registerCount,
663 			fromDwarfMap, toDwarfMap, cpuState, fArchitecture,
664 			fDebuggerInterface);
665 	if (inputInterface == NULL)
666 		return B_NO_MEMORY;
667 	BReference<UnwindTargetInterface> inputInterfaceReference(inputInterface,
668 		true);
669 
670 	UnwindTargetInterface* outputInterface
671 		= new(std::nothrow) UnwindTargetInterface(registers, registerCount,
672 			fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture,
673 			fDebuggerInterface);
674 	if (outputInterface == NULL)
675 		return B_NO_MEMORY;
676 	BReference<UnwindTargetInterface> outputInterfaceReference(outputInterface,
677 		true);
678 
679 	// do the unwinding
680 	target_addr_t instructionPointer
681 		= cpuState->InstructionPointer() - fRelocationDelta;
682 	target_addr_t framePointer;
683 	CompilationUnit* unit = function != NULL ? function->GetCompilationUnit()
684 			: NULL;
685 	error = fFile->UnwindCallFrame(unit, fArchitecture->AddressSize(), entry,
686 		instructionPointer, inputInterface, outputInterface, framePointer);
687 
688 	if (error != B_OK) {
689 		TRACE_CFI("Failed to unwind call frame: %s\n", strerror(error));
690 		return B_UNSUPPORTED;
691 	}
692 
693 	TRACE_CFI_ONLY(
694 		TRACE_CFI("unwound registers:\n");
695 		for (int32 i = 0; i < registerCount; i++) {
696 			const Register* reg = registers + i;
697 			BVariant value;
698 			if (previousCpuState->GetRegisterValue(reg, value)) {
699 				TRACE_CFI("  %3s: %#" B_PRIx64 "\n", reg->Name(),
700 					value.ToUInt64());
701 			} else
702 				TRACE_CFI("  %3s: undefined\n", reg->Name());
703 		}
704 	)
705 
706 	// create the stack frame debug info
707 	DIESubprogram* subprogramEntry = function != NULL ?
708 		function->SubprogramEntry() : NULL;
709 	DwarfStackFrameDebugInfo* stackFrameDebugInfo
710 		= new(std::nothrow) DwarfStackFrameDebugInfo(fArchitecture,
711 			fImageInfo.ImageID(), fFile, unit, subprogramEntry, fTypeLookup,
712 			fTypeCache, instructionPointer, framePointer, fRelocationDelta,
713 			inputInterface, fromDwarfMap);
714 	if (stackFrameDebugInfo == NULL)
715 		return B_NO_MEMORY;
716 	BReference<DwarfStackFrameDebugInfo> stackFrameDebugInfoReference(
717 		stackFrameDebugInfo, true);
718 
719 	error = stackFrameDebugInfo->Init();
720 	if (error != B_OK)
721 		return error;
722 
723 	// create the stack frame
724 	StackFrame* frame = new(std::nothrow) StackFrame(STACK_FRAME_TYPE_STANDARD,
725 		cpuState, framePointer, cpuState->InstructionPointer(),
726 		stackFrameDebugInfo);
727 	if (frame == NULL)
728 		return B_NO_MEMORY;
729 	BReference<StackFrame> frameReference(frame, true);
730 
731 	error = frame->Init();
732 	if (error != B_OK)
733 		return error;
734 
735 	frame->SetReturnAddress(previousCpuState->InstructionPointer());
736 		// Note, this is correct, since we actually retrieved the return
737 		// address. Our caller will fix the IP for us.
738 
739 	// The subprogram entry may not be available since this may be a case
740 	// where .eh_frame was used to unwind the stack without other DWARF
741 	// info being available.
742 	if (subprogramEntry != NULL && getFullFrameInfo) {
743 		// create function parameter objects
744 		for (DebugInfoEntryList::ConstIterator it
745 			= subprogramEntry->Parameters().GetIterator();
746 			DebugInfoEntry* entry = it.Next();) {
747 			if (entry->Tag() != DW_TAG_formal_parameter)
748 				continue;
749 
750 			BString parameterName;
751 			DwarfUtils::GetDIEName(entry, parameterName);
752 			if (parameterName.Length() == 0)
753 				continue;
754 
755 			DIEFormalParameter* parameterEntry
756 				= dynamic_cast<DIEFormalParameter*>(entry);
757 			Variable* parameter;
758 			if (stackFrameDebugInfo->CreateParameter(functionID,
759 				parameterEntry, parameter) != B_OK) {
760 				continue;
761 			}
762 			BReference<Variable> parameterReference(parameter, true);
763 
764 			if (!frame->AddParameter(parameter))
765 				return B_NO_MEMORY;
766 		}
767 
768 		// create objects for the local variables
769 		_CreateLocalVariables(unit, frame, functionID, *stackFrameDebugInfo,
770 			instructionPointer, functionInstance->Address() - fRelocationDelta,
771 			subprogramEntry->Variables(), subprogramEntry->Blocks());
772 
773 		if (returnValueInfos != NULL && !returnValueInfos->IsEmpty()) {
774 			_CreateReturnValues(returnValueInfos, image, frame,
775 				*stackFrameDebugInfo);
776 		}
777 	}
778 
779 	_frame = frameReference.Detach();
780 	_previousCpuState = previousCpuStateReference.Detach();
781 
782 	frame->SetPreviousCpuState(_previousCpuState);
783 
784 	return B_OK;
785 }
786 
787 
788 status_t
789 DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function,
790 	target_addr_t address, Statement*& _statement)
791 {
792 	TRACE_CODE("DwarfImageDebugInfo::GetStatement(function: %p, address: %#"
793 		B_PRIx64 ")\n", _function, address);
794 
795 	DwarfFunctionDebugInfo* function
796 		= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
797 	if (function == NULL) {
798 		TRACE_LINES("  -> no dwarf function\n");
799 		// fall back to assembly
800 		return fArchitecture->GetStatement(function, address, _statement);
801 	}
802 
803 	AutoLocker<BLocker> locker(fLock);
804 
805 	// check whether we have the source code
806 	CompilationUnit* unit = function->GetCompilationUnit();
807 	LocatableFile* file = function->SourceFile();
808 	if (file == NULL) {
809 		TRACE_CODE("  -> no source file\n");
810 
811 		// no source code -- rather return the assembly statement
812 		return fArchitecture->GetStatement(function, address, _statement);
813 	}
814 
815 	SourceCode* sourceCode = NULL;
816 	status_t error = fSourceInfo->GetActiveSourceCode(_function, sourceCode);
817 	BReference<SourceCode> sourceReference(sourceCode, true);
818 	if (error != B_OK || dynamic_cast<DisassembledCode*>(sourceCode) != NULL) {
819 		// either no source code or disassembly is currently active (i.e.
820 		// due to failing to locate the source file on disk or the user
821 		// deliberately switching to disassembly view).
822 		// return the assembly statement.
823 		return fArchitecture->GetStatement(function, address, _statement);
824 	}
825 
826 	// get the index of the source file in the compilation unit for cheaper
827 	// comparison below
828 	int32 fileIndex = _GetSourceFileIndex(unit, file);
829 
830 	// Get the statement by executing the line number program for the
831 	// compilation unit.
832 	LineNumberProgram& program = unit->GetLineNumberProgram();
833 	if (!program.IsValid()) {
834 		TRACE_CODE("  -> no line number program\n");
835 		return B_BAD_DATA;
836 	}
837 
838 	// adjust address
839 	address -= fRelocationDelta;
840 
841 	LineNumberProgram::State state;
842 	program.GetInitialState(state);
843 
844 	target_addr_t statementAddress = 0;
845 	int32 statementLine = -1;
846 	int32 statementColumn = -1;
847 	while (program.GetNextRow(state)) {
848 		// skip statements of other files
849 		if (state.file != fileIndex)
850 			continue;
851 
852 		if (statementAddress != 0
853 			&& (state.isStatement || state.isSequenceEnd)) {
854 			target_addr_t endAddress = state.address;
855 			if (address >= statementAddress && address < endAddress) {
856 				ContiguousStatement* statement = new(std::nothrow)
857 					ContiguousStatement(
858 						SourceLocation(statementLine, statementColumn),
859 						TargetAddressRange(fRelocationDelta + statementAddress,
860 							endAddress - statementAddress));
861 				if (statement == NULL)
862 					return B_NO_MEMORY;
863 
864 				_statement = statement;
865 				return B_OK;
866 			}
867 
868 			statementAddress = 0;
869 		}
870 
871 		if (state.isStatement) {
872 			statementAddress = state.address;
873 			statementLine = state.line - 1;
874 			statementColumn = std::max(state.column - 1, (int32)0);
875 		}
876 	}
877 
878 	TRACE_CODE("  -> no line number program match\n");
879 	return B_ENTRY_NOT_FOUND;
880 }
881 
882 
883 status_t
884 DwarfImageDebugInfo::GetStatementAtSourceLocation(FunctionDebugInfo* _function,
885 	const SourceLocation& sourceLocation, Statement*& _statement)
886 {
887 	DwarfFunctionDebugInfo* function
888 		= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
889 	if (function == NULL)
890 		return B_BAD_VALUE;
891 
892 	target_addr_t functionStartAddress = function->Address() - fRelocationDelta;
893 	target_addr_t functionEndAddress = functionStartAddress + function->Size();
894 
895 	TRACE_LINES2("DwarfImageDebugInfo::GetStatementAtSourceLocation(%p, "
896 		"(%" B_PRId32 ", %" B_PRId32 ")): function range: %#" B_PRIx64 " - %#"
897 		B_PRIx64 "\n", function, sourceLocation.Line(), sourceLocation.Column(),
898 		functionStartAddress, functionEndAddress);
899 
900 	AutoLocker<BLocker> locker(fLock);
901 
902 	// get the source file
903 	LocatableFile* file = function->SourceFile();
904 	if (file == NULL)
905 		return B_ENTRY_NOT_FOUND;
906 
907 	CompilationUnit* unit = function->GetCompilationUnit();
908 
909 	// get the index of the source file in the compilation unit for cheaper
910 	// comparison below
911 	int32 fileIndex = _GetSourceFileIndex(unit, file);
912 
913 	// Get the statement by executing the line number program for the
914 	// compilation unit.
915 	LineNumberProgram& program = unit->GetLineNumberProgram();
916 	if (!program.IsValid())
917 		return B_BAD_DATA;
918 
919 	LineNumberProgram::State state;
920 	program.GetInitialState(state);
921 
922 	target_addr_t statementAddress = 0;
923 	int32 statementLine = -1;
924 	int32 statementColumn = -1;
925 	while (program.GetNextRow(state)) {
926 		bool isOurFile = state.file == fileIndex;
927 
928 		if (statementAddress != 0
929 			&& (!isOurFile || state.isStatement || state.isSequenceEnd)) {
930 			target_addr_t endAddress = state.address;
931 
932 			if (statementAddress < endAddress) {
933 				TRACE_LINES2("  statement: %#" B_PRIx64 " - %#" B_PRIx64
934 					", location: (%" B_PRId32 ", %" B_PRId32 ")\n",
935 					statementAddress, endAddress, statementLine,
936 				 	statementColumn);
937 			}
938 
939 			if (statementAddress < endAddress
940 				&& statementAddress >= functionStartAddress
941 				&& statementAddress < functionEndAddress
942 				&& statementLine == (int32)sourceLocation.Line()
943 				&& statementColumn == (int32)sourceLocation.Column()) {
944 				TRACE_LINES2("  -> found statement!\n");
945 
946 				ContiguousStatement* statement = new(std::nothrow)
947 					ContiguousStatement(
948 						SourceLocation(statementLine, statementColumn),
949 						TargetAddressRange(fRelocationDelta + statementAddress,
950 							endAddress - statementAddress));
951 				if (statement == NULL)
952 					return B_NO_MEMORY;
953 
954 				_statement = statement;
955 				return B_OK;
956 			}
957 
958 			statementAddress = 0;
959 		}
960 
961 		// skip statements of other files
962 		if (!isOurFile)
963 			continue;
964 
965 		if (state.isStatement) {
966 			statementAddress = state.address;
967 			statementLine = state.line - 1;
968 			statementColumn = std::max(state.column - 1, (int32)0);
969 		}
970 	}
971 
972 	return B_ENTRY_NOT_FOUND;
973 }
974 
975 
976 status_t
977 DwarfImageDebugInfo::GetSourceLanguage(FunctionDebugInfo* _function,
978 	SourceLanguage*& _language)
979 {
980 	DwarfFunctionDebugInfo* function
981 		= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
982 	if (function == NULL)
983 		return B_BAD_VALUE;
984 
985 	SourceLanguage* language;
986 	CompilationUnit* unit = function->GetCompilationUnit();
987 	switch (unit->UnitEntry()->Language()) {
988 		case DW_LANG_C89:
989 		case DW_LANG_C:
990 		case DW_LANG_C99:
991 			language = new(std::nothrow) CLanguage;
992 			break;
993 		case DW_LANG_C_plus_plus:
994 			language = new(std::nothrow) CppLanguage;
995 			break;
996 		case 0:
997 		default:
998 			language = new(std::nothrow) UnsupportedLanguage;
999 			break;
1000 	}
1001 
1002 	if (language == NULL)
1003 		return B_NO_MEMORY;
1004 
1005 	_language = language;
1006 	return B_OK;
1007 }
1008 
1009 
1010 ssize_t
1011 DwarfImageDebugInfo::ReadCode(target_addr_t address, void* buffer, size_t size)
1012 {
1013 	target_addr_t offset = address - fRelocationDelta
1014 		- fTextSegment->LoadAddress() + fTextSegment->FileOffset();
1015 	ssize_t bytesRead = pread(fFile->GetElfFile()->FD(), buffer, size, offset);
1016 	return bytesRead >= 0 ? bytesRead : errno;
1017 }
1018 
1019 
1020 status_t
1021 DwarfImageDebugInfo::AddSourceCodeInfo(LocatableFile* file,
1022 	FileSourceCode* sourceCode)
1023 {
1024 	bool addedAny = false;
1025 	for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
1026 			i++) {
1027 		int32 fileIndex = _GetSourceFileIndex(unit, file);
1028 		if (fileIndex < 0)
1029 			continue;
1030 
1031 		status_t error = _AddSourceCodeInfo(unit, sourceCode, fileIndex);
1032 		if (error == B_NO_MEMORY)
1033 			return error;
1034 		addedAny |= error == B_OK;
1035 	}
1036 
1037 	return addedAny ? B_OK : B_ENTRY_NOT_FOUND;
1038 }
1039 
1040 
1041 status_t
1042 DwarfImageDebugInfo::_AddSourceCodeInfo(CompilationUnit* unit,
1043 	FileSourceCode* sourceCode, int32 fileIndex)
1044 {
1045 	// Get the statements by executing the line number program for the
1046 	// compilation unit and filtering the rows for our source file.
1047 	LineNumberProgram& program = unit->GetLineNumberProgram();
1048 	if (!program.IsValid())
1049 		return B_BAD_DATA;
1050 
1051 	LineNumberProgram::State state;
1052 	program.GetInitialState(state);
1053 
1054 	target_addr_t statementAddress = 0;
1055 	int32 statementLine = -1;
1056 	int32 statementColumn = -1;
1057 	while (program.GetNextRow(state)) {
1058 		TRACE_LINES2("  %#" B_PRIx64 "  (%" B_PRId32 ", %" B_PRId32 ", %"
1059 			B_PRId32 ")  %d\n", state.address, state.file, state.line,
1060 			state.column, state.isStatement);
1061 
1062 		bool isOurFile = state.file == fileIndex;
1063 
1064 		if (statementAddress != 0
1065 			&& (!isOurFile || state.isStatement || state.isSequenceEnd)) {
1066 			target_addr_t endAddress = state.address;
1067 			if (endAddress > statementAddress) {
1068 				// add the statement
1069 				status_t error = sourceCode->AddSourceLocation(
1070 					SourceLocation(statementLine, statementColumn));
1071 				if (error != B_OK)
1072 					return error;
1073 
1074 				TRACE_LINES2("  -> statement: %#" B_PRIx64 " - %#" B_PRIx64
1075 					", source location: (%" B_PRId32 ", %" B_PRId32 ")\n",
1076 					statementAddress, endAddress, statementLine,
1077 				 	statementColumn);
1078 			}
1079 
1080 			statementAddress = 0;
1081 		}
1082 
1083 		// skip statements of other files
1084 		if (!isOurFile)
1085 			continue;
1086 
1087 		if (state.isStatement) {
1088 			statementAddress = state.address;
1089 			statementLine = state.line - 1;
1090 			statementColumn = std::max(state.column - 1, (int32)0);
1091 		}
1092 	}
1093 
1094 	return B_OK;
1095 }
1096 
1097 
1098 int32
1099 DwarfImageDebugInfo::_GetSourceFileIndex(CompilationUnit* unit,
1100 	LocatableFile* sourceFile) const
1101 {
1102 	// get the index of the source file in the compilation unit for cheaper
1103 	// comparison below
1104 	const char* directory;
1105 	for (int32 i = 0; const char* fileName = unit->FileAt(i, &directory); i++) {
1106 		LocatableFile* file = fFileManager->GetSourceFile(directory, fileName);
1107 		if (file != NULL) {
1108 			file->ReleaseReference();
1109 			if (file == sourceFile) {
1110 				return i + 1;
1111 					// indices are one-based
1112 			}
1113 		}
1114 	}
1115 
1116 	return -1;
1117 }
1118 
1119 
1120 status_t
1121 DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit,
1122 	StackFrame* frame, FunctionID* functionID,
1123 	DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer,
1124 	target_addr_t lowPC, const EntryListWrapper& variableEntries,
1125 	const EntryListWrapper& blockEntries)
1126 {
1127 	TRACE_LOCALS("DwarfImageDebugInfo::_CreateLocalVariables(): ip: %#" B_PRIx64
1128 		", low PC: %#" B_PRIx64 "\n", instructionPointer, lowPC);
1129 
1130 	// iterate through the variables and add the ones in scope
1131 	for (DebugInfoEntryList::ConstIterator it
1132 			= variableEntries.list.GetIterator();
1133 		DIEVariable* variableEntry = dynamic_cast<DIEVariable*>(it.Next());) {
1134 
1135 		TRACE_LOCALS("  variableEntry %p, scope start: %" B_PRIu64 "\n",
1136 			variableEntry, variableEntry->StartScope());
1137 
1138 		// check the variable's scope
1139 		if (instructionPointer < lowPC + variableEntry->StartScope())
1140 			continue;
1141 
1142 		// add the variable
1143 		Variable* variable;
1144 		if (factory.CreateLocalVariable(functionID, variableEntry, variable)
1145 				!= B_OK) {
1146 			continue;
1147 		}
1148 		BReference<Variable> variableReference(variable, true);
1149 
1150 		if (!frame->AddLocalVariable(variable))
1151 			return B_NO_MEMORY;
1152 	}
1153 
1154 	// iterate through the blocks and find the one we're currently in (if any)
1155 	for (DebugInfoEntryList::ConstIterator it = blockEntries.list.GetIterator();
1156 		DIELexicalBlock* block = dynamic_cast<DIELexicalBlock*>(it.Next());) {
1157 
1158 		TRACE_LOCALS("  lexical block: %p\n", block);
1159 
1160 		// check whether the block has low/high PC attributes
1161 		if (block->LowPC() != 0) {
1162 			TRACE_LOCALS("    has lowPC\n");
1163 
1164 			// yep, compare with the instruction pointer
1165 			if (instructionPointer < block->LowPC()
1166 				|| instructionPointer >= block->HighPC()) {
1167 				continue;
1168 			}
1169 		} else {
1170 			TRACE_LOCALS("    no lowPC\n");
1171 
1172 			// check the address ranges instead
1173 			TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit,
1174 				block->AddressRangesOffset());
1175 			if (rangeList == NULL) {
1176 				TRACE_LOCALS("    failed to get ranges\n");
1177 				continue;
1178 			}
1179 			BReference<TargetAddressRangeList> rangeListReference(rangeList,
1180 				true);
1181 
1182 			if (!rangeList->Contains(instructionPointer)) {
1183 				TRACE_LOCALS("    ranges don't contain IP\n");
1184 				continue;
1185 			}
1186 		}
1187 
1188 		// found a block -- recurse
1189 		return _CreateLocalVariables(unit, frame, functionID, factory,
1190 			instructionPointer, lowPC, block->Variables(), block->Blocks());
1191 	}
1192 
1193 	return B_OK;
1194 }
1195 
1196 
1197 status_t
1198 DwarfImageDebugInfo::_CreateReturnValues(ReturnValueInfoList* returnValueInfos,
1199 	Image* image, StackFrame* frame, DwarfStackFrameDebugInfo& factory)
1200 {
1201 	for (int32 i = 0; i < returnValueInfos->CountItems(); i++) {
1202 		Image* targetImage = image;
1203 		ReturnValueInfo* valueInfo = returnValueInfos->ItemAt(i);
1204 		target_addr_t subroutineAddress = valueInfo->SubroutineAddress();
1205 		CpuState* subroutineState = valueInfo->State();
1206 		if (!targetImage->ContainsAddress(subroutineAddress)) {
1207 			// our current image doesn't contain the target function,
1208 			// locate the one which does.
1209 			targetImage = image->GetTeam()->ImageByAddress(subroutineAddress);
1210 			if (targetImage == NULL) {
1211 				// nothing we can do, try the next entry (if any)
1212 				continue;
1213 			}
1214 		}
1215 
1216 		status_t result = B_OK;
1217 		ImageDebugInfo* imageInfo = targetImage->GetImageDebugInfo();
1218 		if (imageInfo == NULL) {
1219 			// the subroutine may have resolved to a different image
1220 			// that doesn't have debug information available.
1221 			continue;
1222 		}
1223 
1224 		FunctionInstance* targetFunction;
1225 		if (imageInfo->GetAddressSectionType(subroutineAddress)
1226 				== ADDRESS_SECTION_TYPE_PLT) {
1227 			result = fArchitecture->ResolvePICFunctionAddress(
1228 				subroutineAddress, subroutineState, subroutineAddress);
1229 			if (result != B_OK)
1230 				continue;
1231 			if (!targetImage->ContainsAddress(subroutineAddress)) {
1232 				// the PLT entry doesn't necessarily point to a function
1233 				// in the same image; as such we may need to try to
1234 				// resolve the target address again.
1235 				targetImage = image->GetTeam()->ImageByAddress(
1236 					subroutineAddress);
1237 				if (targetImage == NULL)
1238 					continue;
1239 				imageInfo = targetImage->GetImageDebugInfo();
1240 				if (imageInfo == NULL) {
1241 					// As above, since the indirection here may have
1242 					// landed us in an entirely different image, there is
1243 					// no guarantee that debug info is available,
1244 					// depending on which image it was.
1245 					continue;
1246 				}
1247 
1248 			}
1249 		}
1250 
1251 		targetFunction = imageInfo->FunctionAtAddress(subroutineAddress);
1252 		if (targetFunction != NULL) {
1253 			DwarfFunctionDebugInfo* targetInfo =
1254 				dynamic_cast<DwarfFunctionDebugInfo*>(
1255 					targetFunction->GetFunctionDebugInfo());
1256 			if (targetInfo != NULL) {
1257 				DIESubprogram* subProgram = targetInfo->SubprogramEntry();
1258 				DIEType* returnType = subProgram->ReturnType();
1259 				if (returnType == NULL) {
1260 					// check if we have a specification, and if so, if that has
1261 					// a return type
1262 					subProgram = dynamic_cast<DIESubprogram*>(
1263 						subProgram->Specification());
1264 					if (subProgram != NULL)
1265 						returnType = subProgram->ReturnType();
1266 
1267 					// function doesn't return a value, we're done.
1268 					if (returnType == NULL)
1269 						return B_OK;
1270 				}
1271 
1272 				uint32 byteSize = 0;
1273 				if (returnType->ByteSize() == NULL) {
1274 					if (dynamic_cast<DIEAddressingType*>(returnType) != NULL)
1275 						byteSize = fArchitecture->AddressSize();
1276 				} else
1277 					byteSize = returnType->ByteSize()->constant;
1278 
1279 				// if we were unable to determine a size for the type,
1280 				// simply default to the architecture's register width.
1281 				if (byteSize == 0)
1282 					byteSize = fArchitecture->AddressSize();
1283 
1284 				ValueLocation* location;
1285 				result = fArchitecture->GetReturnAddressLocation(frame,
1286 					byteSize, location);
1287 				if (result != B_OK)
1288 					return result;
1289 
1290 				BReference<ValueLocation> locationReference(location, true);
1291 				Variable* variable = NULL;
1292 				BReference<FunctionID> idReference(
1293 					targetFunction->GetFunctionID(), true);
1294 				result = factory.CreateReturnValue(idReference, returnType,
1295 					location, subroutineState, variable);
1296 				if (result != B_OK)
1297 					return result;
1298 
1299 				BReference<Variable> variableReference(variable, true);
1300 				if (!frame->AddLocalVariable(variable))
1301 					return B_NO_MEMORY;
1302 			}
1303 		}
1304 	}
1305 
1306 	return B_OK;
1307 }
1308 
1309 
1310 bool
1311 DwarfImageDebugInfo::_EvaluateBaseTypeConstraints(DIEType* type,
1312 	const TypeLookupConstraints& constraints) const
1313 {
1314 	if (constraints.HasBaseTypeName()) {
1315 		BString baseEntryName;
1316 		DIEType* baseTypeOwnerEntry = NULL;
1317 
1318 		switch (constraints.TypeKind()) {
1319 			case TYPE_ADDRESS:
1320 			{
1321 				DIEAddressingType* addressType =
1322 					dynamic_cast<DIEAddressingType*>(type);
1323 				if (addressType != NULL) {
1324 					baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate(
1325 						addressType, HasTypePredicate<DIEAddressingType>());
1326 				}
1327 				break;
1328 			}
1329 			case TYPE_ARRAY:
1330 			{
1331 				DIEArrayType* arrayType =
1332 					dynamic_cast<DIEArrayType*>(type);
1333 				if (arrayType != NULL) {
1334 					baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate(
1335 						arrayType, HasTypePredicate<DIEArrayType>());
1336 				}
1337 				break;
1338 			}
1339 			default:
1340 				break;
1341 		}
1342 
1343 		if (baseTypeOwnerEntry != NULL) {
1344 			DwarfUtils::GetFullyQualifiedDIEName(baseTypeOwnerEntry,
1345 				baseEntryName);
1346 
1347 			if (baseEntryName != constraints.BaseTypeName())
1348 				return false;
1349 		}
1350 	}
1351 
1352 	return true;
1353 }
1354 
1355 
1356 status_t
1357 DwarfImageDebugInfo::_BuildTypeNameTable()
1358 {
1359 	fTypeNameTable = new(std::nothrow) TypeNameTable;
1360 	if (fTypeNameTable == NULL)
1361 		return B_NO_MEMORY;
1362 
1363 	status_t error = fTypeNameTable->Init();
1364 	if (error != B_OK)
1365 		return error;
1366 
1367 	// iterate through all compilation units
1368 	for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
1369 		i++) {
1370 
1371 		// iterate through all types of the compilation unit
1372 		for (DebugInfoEntryList::ConstIterator it
1373 				= unit->UnitEntry()->Types().GetIterator();
1374 			DIEType* typeEntry = dynamic_cast<DIEType*>(it.Next());) {
1375 			if (typeEntry->IsDeclaration())
1376 				continue;
1377 
1378 			BString typeEntryName;
1379 			DwarfUtils::GetFullyQualifiedDIEName(typeEntry, typeEntryName);
1380 
1381 			TypeNameEntry* entry = fTypeNameTable->Lookup(typeEntryName);
1382 			if (entry == NULL) {
1383 				entry = new(std::nothrow) TypeNameEntry(typeEntryName);
1384 				if (entry == NULL)
1385 					return B_NO_MEMORY;
1386 
1387 				error = fTypeNameTable->Insert(entry);
1388 				if (error != B_OK)
1389 					return error;
1390 			}
1391 
1392 			TypeEntryInfo* info = new(std::nothrow) TypeEntryInfo(typeEntry,
1393 				unit);
1394 			if (info == NULL)
1395 				return B_NO_MEMORY;
1396 
1397 			if (!entry->types.AddItem(info)) {
1398 				delete info;
1399 				return B_NO_MEMORY;
1400 			}
1401 		}
1402 	}
1403 
1404 	return B_OK;
1405 }
1406