xref: /haiku/src/kits/debugger/debug_info/DwarfImageDebugInfo.cpp (revision c0936b5a0384bc6fe654d296ee54222a0f45d2b6)
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, true)
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 	TypeNameEntry* entry = fTypeNameTable->Clear(true);
366 	while (entry != NULL) {
367 		TypeNameEntry* next = entry->next;
368 		delete entry;
369 		entry = next;
370 	}
371 	delete fTypeNameTable;
372 }
373 
374 
375 status_t
376 DwarfImageDebugInfo::Init()
377 {
378 	status_t error = fLock.InitCheck();
379 	if (error != B_OK)
380 		return error;
381 
382 	fTextSegment = fFile->GetElfFile()->TextSegment();
383 	if (fTextSegment == NULL)
384 		return B_ENTRY_NOT_FOUND;
385 
386 	fRelocationDelta = fImageInfo.TextBase() - fTextSegment->LoadAddress();
387 
388 	ElfSection* section = fFile->GetElfFile()->FindSection(".text");
389 	if (section != NULL) {
390 		fTextSectionStart = section->LoadAddress() + fRelocationDelta;
391 		fTextSectionEnd = fTextSectionStart + section->Size();
392 	}
393 
394 	section = fFile->GetElfFile()->FindSection(".plt");
395 	if (section != NULL) {
396 		fPLTSectionStart = section->LoadAddress() + fRelocationDelta;
397 		fPLTSectionEnd = fPLTSectionStart + section->Size();
398 	}
399 
400 	return _BuildTypeNameTable();
401 }
402 
403 
404 status_t
405 DwarfImageDebugInfo::GetFunctions(const BObjectList<SymbolInfo>& symbols,
406 	BObjectList<FunctionDebugInfo>& functions)
407 {
408 	TRACE_IMAGES("DwarfImageDebugInfo::GetFunctions()\n");
409 	TRACE_IMAGES("  %" B_PRId32 " compilation units\n",
410 		fFile->CountCompilationUnits());
411 
412 	for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
413 			i++) {
414 		DIECompileUnitBase* unitEntry = unit->UnitEntry();
415 //		printf("  %s:\n", unitEntry->Name());
416 //		printf("    address ranges:\n");
417 //		TargetAddressRangeList* rangeList = unitEntry->AddressRanges();
418 //		if (rangeList != NULL) {
419 //			int32 count = rangeList->CountRanges();
420 //			for (int32 i = 0; i < count; i++) {
421 //				TargetAddressRange range = rangeList->RangeAt(i);
422 //				printf("      %#llx - %#llx\n", range.Start(), range.End());
423 //			}
424 //		} else {
425 //			printf("      %#llx - %#llx\n", (target_addr_t)unitEntry->LowPC(),
426 //				(target_addr_t)unitEntry->HighPC());
427 //		}
428 
429 //		printf("    functions:\n");
430 		for (DebugInfoEntryList::ConstIterator it
431 					= unitEntry->OtherChildren().GetIterator();
432 				DebugInfoEntry* entry = it.Next();) {
433 			if (entry->Tag() != DW_TAG_subprogram)
434 				continue;
435 
436 			DIESubprogram* subprogramEntry = static_cast<DIESubprogram*>(entry);
437 
438 			// ignore declarations and inlined functions
439 			if (subprogramEntry->IsDeclaration()
440 				|| subprogramEntry->Inline() == DW_INL_inlined
441 				|| subprogramEntry->Inline() == DW_INL_declared_inlined) {
442 				continue;
443 			}
444 
445 			// get the name
446 			BString name;
447 			DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry, name);
448 			if (name.Length() == 0)
449 				continue;
450 
451 			// get the address ranges
452 			TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit,
453 				subprogramEntry->AddressRangesOffset());
454 			if (rangeList == NULL) {
455 				target_addr_t lowPC = subprogramEntry->LowPC();
456 				target_addr_t highPC = subprogramEntry->HighPC();
457 				if (highPC <= lowPC)
458 					continue;
459 
460 				rangeList = new(std::nothrow) TargetAddressRangeList(
461 					TargetAddressRange(lowPC, highPC - lowPC));
462 				if (rangeList == NULL)
463 					return B_NO_MEMORY;
464 						// TODO: Clean up already added functions!
465 			}
466 			BReference<TargetAddressRangeList> rangeListReference(rangeList,
467 				true);
468 
469 			// get the source location
470 			const char* directoryPath = NULL;
471 			const char* fileName = NULL;
472 			int32 line = -1;
473 			int32 column = -1;
474 			DwarfUtils::GetDeclarationLocation(fFile, subprogramEntry,
475 				directoryPath, fileName, line, column);
476 
477 			LocatableFile* file = NULL;
478 			if (fileName != NULL) {
479 				file = fFileManager->GetSourceFile(directoryPath,
480 					fileName);
481 			}
482 			BReference<LocatableFile> fileReference(file, true);
483 
484 			// create and add the functions
485 			DwarfFunctionDebugInfo* function
486 				= new(std::nothrow) DwarfFunctionDebugInfo(this, unit,
487 					subprogramEntry, rangeList, name, file,
488 					SourceLocation(line, std::max(column, (int32)0)));
489 			if (function == NULL || !functions.AddItem(function)) {
490 				delete function;
491 				return B_NO_MEMORY;
492 					// TODO: Clean up already added functions!
493 			}
494 
495 //			BString name;
496 //			DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry, name);
497 //			printf("      subprogram entry: %p, name: %s, declaration: %d\n",
498 //				subprogramEntry, name.String(),
499 //				subprogramEntry->IsDeclaration());
500 //
501 //			rangeList = subprogramEntry->AddressRanges();
502 //			if (rangeList != NULL) {
503 //				int32 count = rangeList->CountRanges();
504 //				for (int32 i = 0; i < count; i++) {
505 //					TargetAddressRange range = rangeList->RangeAt(i);
506 //					printf("        %#llx - %#llx\n", range.Start(), range.End());
507 //				}
508 //			} else {
509 //				printf("        %#llx - %#llx\n",
510 //					(target_addr_t)subprogramEntry->LowPC(),
511 //					(target_addr_t)subprogramEntry->HighPC());
512 //			}
513 		}
514 	}
515 
516 	if (fFile->CountCompilationUnits() != 0)
517 		return B_OK;
518 
519 	// if we had no compilation units, fall back to providing basic
520 	// debug infos with DWARF-supported call frame unwinding,
521 	// if available.
522 	if (fFile->HasFrameInformation()) {
523 		return SpecificImageDebugInfo::GetFunctionsFromSymbols(symbols,
524 			functions, fDebuggerInterface, fImageInfo, this);
525 	}
526 
527 	return B_OK;
528 }
529 
530 
531 status_t
532 DwarfImageDebugInfo::GetType(GlobalTypeCache* cache, const BString& name,
533 	const TypeLookupConstraints& constraints, Type*& _type)
534 {
535 	TypeNameEntry* entry = fTypeNameTable->Lookup(name);
536 	if (entry == NULL)
537 		return B_ENTRY_NOT_FOUND;
538 
539 	for (int32 i = 0; TypeEntryInfo* info = entry->types.ItemAt(i); i++) {
540 		DIEType* typeEntry = info->type;
541 		if (constraints.HasTypeKind()) {
542 			if (dwarf_tag_to_type_kind(typeEntry->Tag())
543 				!= constraints.TypeKind()) {
544 				continue;
545 			}
546 
547 			if (!_EvaluateBaseTypeConstraints(typeEntry, constraints))
548 				continue;
549 		}
550 
551 		if (constraints.HasSubtypeKind()
552 			&& dwarf_tag_to_subtype_kind(typeEntry->Tag())
553 				!= constraints.SubtypeKind()) {
554 			continue;
555 		}
556 
557 		DwarfTypeContext* typeContext = new(std::nothrow)
558 			DwarfTypeContext(fArchitecture, fImageInfo.ImageID(), fFile,
559 				info->unit, NULL, 0, 0, fRelocationDelta, NULL, NULL);
560 		if (typeContext == NULL)
561 			return B_NO_MEMORY;
562 		BReference<DwarfTypeContext> typeContextReference(typeContext, true);
563 
564 		// create the type
565 		DwarfType* type;
566 		DwarfTypeFactory typeFactory(typeContext, fTypeLookup, cache);
567 		status_t error = typeFactory.CreateType(typeEntry, type);
568 		if (error != B_OK)
569 			continue;
570 
571 		_type = type;
572 		return B_OK;
573 	}
574 
575 	return B_ENTRY_NOT_FOUND;
576 }
577 
578 
579 bool
580 DwarfImageDebugInfo::HasType(const BString& name,
581 	const TypeLookupConstraints& constraints) const
582 {
583 	TypeNameEntry* entry = fTypeNameTable->Lookup(name);
584 	if (entry == NULL)
585 		return false;
586 
587 	for (int32 i = 0; TypeEntryInfo* info = entry->types.ItemAt(i); i++) {
588 		DIEType* typeEntry = info->type;
589 		if (constraints.HasTypeKind()) {
590 			if (dwarf_tag_to_type_kind(typeEntry->Tag())
591 				!= constraints.TypeKind()) {
592 				continue;
593 			}
594 
595 			if (!_EvaluateBaseTypeConstraints(typeEntry, constraints))
596 				continue;
597 		}
598 
599 		if (constraints.HasSubtypeKind()
600 			&& dwarf_tag_to_subtype_kind(typeEntry->Tag())
601 				!= constraints.SubtypeKind()) {
602 			continue;
603 		}
604 
605 		return true;
606 	}
607 
608 	return false;
609 }
610 
611 
612 AddressSectionType
613 DwarfImageDebugInfo::GetAddressSectionType(target_addr_t address)
614 {
615 	if (address >= fTextSectionStart && address < fTextSectionEnd)
616 		return ADDRESS_SECTION_TYPE_FUNCTION;
617 
618  	if (address >= fPLTSectionStart && address < fPLTSectionEnd)
619 		return ADDRESS_SECTION_TYPE_PLT;
620 
621 	return ADDRESS_SECTION_TYPE_UNKNOWN;
622 }
623 
624 
625 status_t
626 DwarfImageDebugInfo::CreateFrame(Image* image,
627 	FunctionInstance* functionInstance, CpuState* cpuState,
628 	bool getFullFrameInfo, ReturnValueInfoList* returnValueInfos,
629 	StackFrame*& _frame, CpuState*& _previousCpuState)
630 {
631 	DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>(
632 		functionInstance->GetFunctionDebugInfo());
633 
634 	FunctionID* functionID = functionInstance->GetFunctionID();
635 	BReference<FunctionID> functionIDReference;
636 	if (functionID != NULL)
637 		functionIDReference.SetTo(functionID, true);
638 
639 	DIESubprogram* entry = function != NULL
640 		? function->SubprogramEntry() : NULL;
641 
642 	TRACE_CFI("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p, "
643 		"function: %s\n", entry,
644 		functionID->FunctionName().String());
645 
646 	int32 registerCount = fArchitecture->CountRegisters();
647 	const Register* registers = fArchitecture->Registers();
648 
649 	// get the DWARF <-> architecture register maps
650 	RegisterMap* toDwarfMap;
651 	RegisterMap* fromDwarfMap;
652 	status_t error = fArchitecture->GetDwarfRegisterMaps(&toDwarfMap,
653 		&fromDwarfMap);
654 	if (error != B_OK)
655 		return error;
656 	BReference<RegisterMap> toDwarfMapReference(toDwarfMap, true);
657 	BReference<RegisterMap> fromDwarfMapReference(fromDwarfMap, true);
658 
659 	// create a clean CPU state for the previous frame
660 	CpuState* previousCpuState;
661 	error = fArchitecture->CreateCpuState(previousCpuState);
662 	if (error != B_OK)
663 		return error;
664 	BReference<CpuState> previousCpuStateReference(previousCpuState, true);
665 
666 	// create the target interfaces
667 	UnwindTargetInterface* inputInterface
668 		= new(std::nothrow) UnwindTargetInterface(registers, registerCount,
669 			fromDwarfMap, toDwarfMap, cpuState, fArchitecture,
670 			fDebuggerInterface);
671 	if (inputInterface == NULL)
672 		return B_NO_MEMORY;
673 	BReference<UnwindTargetInterface> inputInterfaceReference(inputInterface,
674 		true);
675 
676 	UnwindTargetInterface* outputInterface
677 		= new(std::nothrow) UnwindTargetInterface(registers, registerCount,
678 			fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture,
679 			fDebuggerInterface);
680 	if (outputInterface == NULL)
681 		return B_NO_MEMORY;
682 	BReference<UnwindTargetInterface> outputInterfaceReference(outputInterface,
683 		true);
684 
685 	// do the unwinding
686 	target_addr_t instructionPointer
687 		= cpuState->InstructionPointer() - fRelocationDelta;
688 	target_addr_t framePointer;
689 	CompilationUnit* unit = function != NULL ? function->GetCompilationUnit()
690 			: NULL;
691 	error = fFile->UnwindCallFrame(unit, fArchitecture->AddressSize(), entry,
692 		instructionPointer, inputInterface, outputInterface, framePointer);
693 
694 	if (error != B_OK) {
695 		TRACE_CFI("Failed to unwind call frame: %s\n", strerror(error));
696 		return B_UNSUPPORTED;
697 	}
698 
699 	TRACE_CFI_ONLY(
700 		TRACE_CFI("unwound registers:\n");
701 		for (int32 i = 0; i < registerCount; i++) {
702 			const Register* reg = registers + i;
703 			BVariant value;
704 			if (previousCpuState->GetRegisterValue(reg, value)) {
705 				TRACE_CFI("  %3s: %#" B_PRIx64 "\n", reg->Name(),
706 					value.ToUInt64());
707 			} else
708 				TRACE_CFI("  %3s: undefined\n", reg->Name());
709 		}
710 	)
711 
712 	// create the stack frame debug info
713 	DIESubprogram* subprogramEntry = function != NULL ?
714 		function->SubprogramEntry() : NULL;
715 	DwarfStackFrameDebugInfo* stackFrameDebugInfo
716 		= new(std::nothrow) DwarfStackFrameDebugInfo(fArchitecture,
717 			fImageInfo.ImageID(), fFile, unit, subprogramEntry, fTypeLookup,
718 			fTypeCache, instructionPointer, framePointer, fRelocationDelta,
719 			inputInterface, fromDwarfMap);
720 	if (stackFrameDebugInfo == NULL)
721 		return B_NO_MEMORY;
722 	BReference<DwarfStackFrameDebugInfo> stackFrameDebugInfoReference(
723 		stackFrameDebugInfo, true);
724 
725 	error = stackFrameDebugInfo->Init();
726 	if (error != B_OK)
727 		return error;
728 
729 	// create the stack frame
730 	StackFrame* frame = new(std::nothrow) StackFrame(STACK_FRAME_TYPE_STANDARD,
731 		cpuState, framePointer, cpuState->InstructionPointer(),
732 		stackFrameDebugInfo);
733 	if (frame == NULL)
734 		return B_NO_MEMORY;
735 	BReference<StackFrame> frameReference(frame, true);
736 
737 	error = frame->Init();
738 	if (error != B_OK)
739 		return error;
740 
741 	frame->SetReturnAddress(previousCpuState->InstructionPointer());
742 		// Note, this is correct, since we actually retrieved the return
743 		// address. Our caller will fix the IP for us.
744 
745 	// The subprogram entry may not be available since this may be a case
746 	// where .eh_frame was used to unwind the stack without other DWARF
747 	// info being available.
748 	if (subprogramEntry != NULL && getFullFrameInfo) {
749 		// create function parameter objects
750 		for (DebugInfoEntryList::ConstIterator it
751 			= subprogramEntry->Parameters().GetIterator();
752 			DebugInfoEntry* entry = it.Next();) {
753 			if (entry->Tag() != DW_TAG_formal_parameter)
754 				continue;
755 
756 			BString parameterName;
757 			DwarfUtils::GetDIEName(entry, parameterName);
758 			if (parameterName.Length() == 0)
759 				continue;
760 
761 			DIEFormalParameter* parameterEntry
762 				= dynamic_cast<DIEFormalParameter*>(entry);
763 			Variable* parameter;
764 			if (stackFrameDebugInfo->CreateParameter(functionID,
765 				parameterEntry, parameter) != B_OK) {
766 				continue;
767 			}
768 			BReference<Variable> parameterReference(parameter, true);
769 
770 			if (!frame->AddParameter(parameter))
771 				return B_NO_MEMORY;
772 		}
773 
774 		// create objects for the local variables
775 		_CreateLocalVariables(unit, frame, functionID, *stackFrameDebugInfo,
776 			instructionPointer, functionInstance->Address() - fRelocationDelta,
777 			subprogramEntry->Variables(), subprogramEntry->Blocks());
778 
779 		if (returnValueInfos != NULL && !returnValueInfos->IsEmpty()) {
780 			_CreateReturnValues(returnValueInfos, image, frame,
781 				*stackFrameDebugInfo);
782 		}
783 	}
784 
785 	_frame = frameReference.Detach();
786 	_previousCpuState = previousCpuStateReference.Detach();
787 
788 	frame->SetPreviousCpuState(_previousCpuState);
789 
790 	return B_OK;
791 }
792 
793 
794 status_t
795 DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function,
796 	target_addr_t address, Statement*& _statement)
797 {
798 	TRACE_CODE("DwarfImageDebugInfo::GetStatement(function: %p, address: %#"
799 		B_PRIx64 ")\n", _function, address);
800 
801 	DwarfFunctionDebugInfo* function
802 		= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
803 	if (function == NULL) {
804 		TRACE_LINES("  -> no dwarf function\n");
805 		// fall back to assembly
806 		return fArchitecture->GetStatement(function, address, _statement);
807 	}
808 
809 	AutoLocker<BLocker> locker(fLock);
810 
811 	// check whether we have the source code
812 	CompilationUnit* unit = function->GetCompilationUnit();
813 	LocatableFile* file = function->SourceFile();
814 	if (file == NULL) {
815 		TRACE_CODE("  -> no source file\n");
816 
817 		// no source code -- rather return the assembly statement
818 		return fArchitecture->GetStatement(function, address, _statement);
819 	}
820 
821 	SourceCode* sourceCode = NULL;
822 	status_t error = fSourceInfo->GetActiveSourceCode(_function, sourceCode);
823 	BReference<SourceCode> sourceReference(sourceCode, true);
824 	if (error != B_OK || dynamic_cast<DisassembledCode*>(sourceCode) != NULL) {
825 		// either no source code or disassembly is currently active (i.e.
826 		// due to failing to locate the source file on disk or the user
827 		// deliberately switching to disassembly view).
828 		// return the assembly statement.
829 		return fArchitecture->GetStatement(function, address, _statement);
830 	}
831 
832 	// get the index of the source file in the compilation unit for cheaper
833 	// comparison below
834 	int32 fileIndex = _GetSourceFileIndex(unit, file);
835 
836 	// Get the statement by executing the line number program for the
837 	// compilation unit.
838 	LineNumberProgram& program = unit->GetLineNumberProgram();
839 	if (!program.IsValid()) {
840 		TRACE_CODE("  -> no line number program\n");
841 		return B_BAD_DATA;
842 	}
843 
844 	// adjust address
845 	address -= fRelocationDelta;
846 
847 	LineNumberProgram::State state;
848 	program.GetInitialState(state);
849 
850 	target_addr_t statementAddress = 0;
851 	int32 statementLine = -1;
852 	int32 statementColumn = -1;
853 	while (program.GetNextRow(state)) {
854 		// skip statements of other files
855 		if (state.file != fileIndex)
856 			continue;
857 
858 		if (statementAddress != 0
859 			&& (state.isStatement || state.isSequenceEnd)) {
860 			target_addr_t endAddress = state.address;
861 			if (address >= statementAddress && address < endAddress) {
862 				ContiguousStatement* statement = new(std::nothrow)
863 					ContiguousStatement(
864 						SourceLocation(statementLine, statementColumn),
865 						TargetAddressRange(fRelocationDelta + statementAddress,
866 							endAddress - statementAddress));
867 				if (statement == NULL)
868 					return B_NO_MEMORY;
869 
870 				_statement = statement;
871 				return B_OK;
872 			}
873 
874 			statementAddress = 0;
875 		}
876 
877 		if (state.isStatement) {
878 			statementAddress = state.address;
879 			statementLine = state.line - 1;
880 			statementColumn = std::max(state.column - 1, (int32)0);
881 		}
882 	}
883 
884 	TRACE_CODE("  -> no line number program match\n");
885 	return B_ENTRY_NOT_FOUND;
886 }
887 
888 
889 status_t
890 DwarfImageDebugInfo::GetStatementAtSourceLocation(FunctionDebugInfo* _function,
891 	const SourceLocation& sourceLocation, Statement*& _statement)
892 {
893 	DwarfFunctionDebugInfo* function
894 		= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
895 	if (function == NULL)
896 		return B_BAD_VALUE;
897 
898 	target_addr_t functionStartAddress = function->Address() - fRelocationDelta;
899 	target_addr_t functionEndAddress = functionStartAddress + function->Size();
900 
901 	TRACE_LINES2("DwarfImageDebugInfo::GetStatementAtSourceLocation(%p, "
902 		"(%" B_PRId32 ", %" B_PRId32 ")): function range: %#" B_PRIx64 " - %#"
903 		B_PRIx64 "\n", function, sourceLocation.Line(), sourceLocation.Column(),
904 		functionStartAddress, functionEndAddress);
905 
906 	AutoLocker<BLocker> locker(fLock);
907 
908 	// get the source file
909 	LocatableFile* file = function->SourceFile();
910 	if (file == NULL)
911 		return B_ENTRY_NOT_FOUND;
912 
913 	CompilationUnit* unit = function->GetCompilationUnit();
914 
915 	// get the index of the source file in the compilation unit for cheaper
916 	// comparison below
917 	int32 fileIndex = _GetSourceFileIndex(unit, file);
918 
919 	// Get the statement by executing the line number program for the
920 	// compilation unit.
921 	LineNumberProgram& program = unit->GetLineNumberProgram();
922 	if (!program.IsValid())
923 		return B_BAD_DATA;
924 
925 	LineNumberProgram::State state;
926 	program.GetInitialState(state);
927 
928 	target_addr_t statementAddress = 0;
929 	int32 statementLine = -1;
930 	int32 statementColumn = -1;
931 	while (program.GetNextRow(state)) {
932 		bool isOurFile = state.file == fileIndex;
933 
934 		if (statementAddress != 0
935 			&& (!isOurFile || state.isStatement || state.isSequenceEnd)) {
936 			target_addr_t endAddress = state.address;
937 
938 			if (statementAddress < endAddress) {
939 				TRACE_LINES2("  statement: %#" B_PRIx64 " - %#" B_PRIx64
940 					", location: (%" B_PRId32 ", %" B_PRId32 ")\n",
941 					statementAddress, endAddress, statementLine,
942 				 	statementColumn);
943 			}
944 
945 			if (statementAddress < endAddress
946 				&& statementAddress >= functionStartAddress
947 				&& statementAddress < functionEndAddress
948 				&& statementLine == (int32)sourceLocation.Line()
949 				&& statementColumn == (int32)sourceLocation.Column()) {
950 				TRACE_LINES2("  -> found statement!\n");
951 
952 				ContiguousStatement* statement = new(std::nothrow)
953 					ContiguousStatement(
954 						SourceLocation(statementLine, statementColumn),
955 						TargetAddressRange(fRelocationDelta + statementAddress,
956 							endAddress - statementAddress));
957 				if (statement == NULL)
958 					return B_NO_MEMORY;
959 
960 				_statement = statement;
961 				return B_OK;
962 			}
963 
964 			statementAddress = 0;
965 		}
966 
967 		// skip statements of other files
968 		if (!isOurFile)
969 			continue;
970 
971 		if (state.isStatement) {
972 			statementAddress = state.address;
973 			statementLine = state.line - 1;
974 			statementColumn = std::max(state.column - 1, (int32)0);
975 		}
976 	}
977 
978 	return B_ENTRY_NOT_FOUND;
979 }
980 
981 
982 status_t
983 DwarfImageDebugInfo::GetSourceLanguage(FunctionDebugInfo* _function,
984 	SourceLanguage*& _language)
985 {
986 	DwarfFunctionDebugInfo* function
987 		= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
988 	if (function == NULL)
989 		return B_BAD_VALUE;
990 
991 	SourceLanguage* language;
992 	CompilationUnit* unit = function->GetCompilationUnit();
993 	switch (unit->UnitEntry()->Language()) {
994 		case DW_LANG_C89:
995 		case DW_LANG_C:
996 		case DW_LANG_C99:
997 			language = new(std::nothrow) CLanguage;
998 			break;
999 		case DW_LANG_C_plus_plus:
1000 			language = new(std::nothrow) CppLanguage;
1001 			break;
1002 		case 0:
1003 		default:
1004 			language = new(std::nothrow) UnsupportedLanguage;
1005 			break;
1006 	}
1007 
1008 	if (language == NULL)
1009 		return B_NO_MEMORY;
1010 
1011 	_language = language;
1012 	return B_OK;
1013 }
1014 
1015 
1016 ssize_t
1017 DwarfImageDebugInfo::ReadCode(target_addr_t address, void* buffer, size_t size)
1018 {
1019 	target_addr_t offset = address - fRelocationDelta
1020 		- fTextSegment->LoadAddress() + fTextSegment->FileOffset();
1021 	ssize_t bytesRead = pread(fFile->GetElfFile()->FD(), buffer, size, offset);
1022 	return bytesRead >= 0 ? bytesRead : errno;
1023 }
1024 
1025 
1026 status_t
1027 DwarfImageDebugInfo::AddSourceCodeInfo(LocatableFile* file,
1028 	FileSourceCode* sourceCode)
1029 {
1030 	bool addedAny = false;
1031 	for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
1032 			i++) {
1033 		int32 fileIndex = _GetSourceFileIndex(unit, file);
1034 		if (fileIndex < 0)
1035 			continue;
1036 
1037 		status_t error = _AddSourceCodeInfo(unit, sourceCode, fileIndex);
1038 		if (error == B_NO_MEMORY)
1039 			return error;
1040 		addedAny |= error == B_OK;
1041 	}
1042 
1043 	return addedAny ? B_OK : B_ENTRY_NOT_FOUND;
1044 }
1045 
1046 
1047 status_t
1048 DwarfImageDebugInfo::_AddSourceCodeInfo(CompilationUnit* unit,
1049 	FileSourceCode* sourceCode, int32 fileIndex)
1050 {
1051 	// Get the statements by executing the line number program for the
1052 	// compilation unit and filtering the rows for our source file.
1053 	LineNumberProgram& program = unit->GetLineNumberProgram();
1054 	if (!program.IsValid())
1055 		return B_BAD_DATA;
1056 
1057 	LineNumberProgram::State state;
1058 	program.GetInitialState(state);
1059 
1060 	target_addr_t statementAddress = 0;
1061 	int32 statementLine = -1;
1062 	int32 statementColumn = -1;
1063 	while (program.GetNextRow(state)) {
1064 		TRACE_LINES2("  %#" B_PRIx64 "  (%" B_PRId32 ", %" B_PRId32 ", %"
1065 			B_PRId32 ")  %d\n", state.address, state.file, state.line,
1066 			state.column, state.isStatement);
1067 
1068 		bool isOurFile = state.file == fileIndex;
1069 
1070 		if (statementAddress != 0
1071 			&& (!isOurFile || state.isStatement || state.isSequenceEnd)) {
1072 			target_addr_t endAddress = state.address;
1073 			if (endAddress > statementAddress) {
1074 				// add the statement
1075 				status_t error = sourceCode->AddSourceLocation(
1076 					SourceLocation(statementLine, statementColumn));
1077 				if (error != B_OK)
1078 					return error;
1079 
1080 				TRACE_LINES2("  -> statement: %#" B_PRIx64 " - %#" B_PRIx64
1081 					", source location: (%" B_PRId32 ", %" B_PRId32 ")\n",
1082 					statementAddress, endAddress, statementLine,
1083 				 	statementColumn);
1084 			}
1085 
1086 			statementAddress = 0;
1087 		}
1088 
1089 		// skip statements of other files
1090 		if (!isOurFile)
1091 			continue;
1092 
1093 		if (state.isStatement) {
1094 			statementAddress = state.address;
1095 			statementLine = state.line - 1;
1096 			statementColumn = std::max(state.column - 1, (int32)0);
1097 		}
1098 	}
1099 
1100 	return B_OK;
1101 }
1102 
1103 
1104 int32
1105 DwarfImageDebugInfo::_GetSourceFileIndex(CompilationUnit* unit,
1106 	LocatableFile* sourceFile) const
1107 {
1108 	// get the index of the source file in the compilation unit for cheaper
1109 	// comparison below
1110 	const char* directory;
1111 	for (int32 i = 0; const char* fileName = unit->FileAt(i, &directory); i++) {
1112 		LocatableFile* file = fFileManager->GetSourceFile(directory, fileName);
1113 		if (file != NULL) {
1114 			BReference<LocatableFile> fileReference(file, true);
1115 			if (file == sourceFile) {
1116 				return i + 1;
1117 					// indices are one-based
1118 			}
1119 		}
1120 	}
1121 
1122 	return -1;
1123 }
1124 
1125 
1126 status_t
1127 DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit,
1128 	StackFrame* frame, FunctionID* functionID,
1129 	DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer,
1130 	target_addr_t lowPC, const EntryListWrapper& variableEntries,
1131 	const EntryListWrapper& blockEntries)
1132 {
1133 	TRACE_LOCALS("DwarfImageDebugInfo::_CreateLocalVariables(): ip: %#" B_PRIx64
1134 		", low PC: %#" B_PRIx64 "\n", instructionPointer, lowPC);
1135 
1136 	// iterate through the variables and add the ones in scope
1137 	for (DebugInfoEntryList::ConstIterator it
1138 			= variableEntries.list.GetIterator();
1139 		DIEVariable* variableEntry = dynamic_cast<DIEVariable*>(it.Next());) {
1140 
1141 		TRACE_LOCALS("  variableEntry %p, scope start: %" B_PRIu64 "\n",
1142 			variableEntry, variableEntry->StartScope());
1143 
1144 		// check the variable's scope
1145 		if (instructionPointer < lowPC + variableEntry->StartScope())
1146 			continue;
1147 
1148 		// add the variable
1149 		Variable* variable;
1150 		if (factory.CreateLocalVariable(functionID, variableEntry, variable)
1151 				!= B_OK) {
1152 			continue;
1153 		}
1154 		BReference<Variable> variableReference(variable, true);
1155 
1156 		if (!frame->AddLocalVariable(variable))
1157 			return B_NO_MEMORY;
1158 	}
1159 
1160 	// iterate through the blocks and find the one we're currently in (if any)
1161 	for (DebugInfoEntryList::ConstIterator it = blockEntries.list.GetIterator();
1162 		DIELexicalBlock* block = dynamic_cast<DIELexicalBlock*>(it.Next());) {
1163 
1164 		TRACE_LOCALS("  lexical block: %p\n", block);
1165 
1166 		// check whether the block has low/high PC attributes
1167 		if (block->LowPC() != 0) {
1168 			TRACE_LOCALS("    has lowPC\n");
1169 
1170 			// yep, compare with the instruction pointer
1171 			if (instructionPointer < block->LowPC()
1172 				|| instructionPointer >= block->HighPC()) {
1173 				continue;
1174 			}
1175 		} else {
1176 			TRACE_LOCALS("    no lowPC\n");
1177 
1178 			// check the address ranges instead
1179 			TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit,
1180 				block->AddressRangesOffset());
1181 			if (rangeList == NULL) {
1182 				TRACE_LOCALS("    failed to get ranges\n");
1183 				continue;
1184 			}
1185 			BReference<TargetAddressRangeList> rangeListReference(rangeList,
1186 				true);
1187 
1188 			if (!rangeList->Contains(instructionPointer)) {
1189 				TRACE_LOCALS("    ranges don't contain IP\n");
1190 				continue;
1191 			}
1192 		}
1193 
1194 		// found a block -- recurse
1195 		return _CreateLocalVariables(unit, frame, functionID, factory,
1196 			instructionPointer, lowPC, block->Variables(), block->Blocks());
1197 	}
1198 
1199 	return B_OK;
1200 }
1201 
1202 
1203 status_t
1204 DwarfImageDebugInfo::_CreateReturnValues(ReturnValueInfoList* returnValueInfos,
1205 	Image* image, StackFrame* frame, DwarfStackFrameDebugInfo& factory)
1206 {
1207 	for (int32 i = 0; i < returnValueInfos->CountItems(); i++) {
1208 		Image* targetImage = image;
1209 		ReturnValueInfo* valueInfo = returnValueInfos->ItemAt(i);
1210 		target_addr_t subroutineAddress = valueInfo->SubroutineAddress();
1211 		CpuState* subroutineState = valueInfo->State();
1212 		if (!targetImage->ContainsAddress(subroutineAddress)) {
1213 			// our current image doesn't contain the target function,
1214 			// locate the one which does.
1215 			targetImage = image->GetTeam()->ImageByAddress(subroutineAddress);
1216 			if (targetImage == NULL) {
1217 				// nothing we can do, try the next entry (if any)
1218 				continue;
1219 			}
1220 		}
1221 
1222 		status_t result = B_OK;
1223 		ImageDebugInfo* imageInfo = targetImage->GetImageDebugInfo();
1224 		if (imageInfo == NULL) {
1225 			// the subroutine may have resolved to a different image
1226 			// that doesn't have debug information available.
1227 			continue;
1228 		}
1229 
1230 		FunctionInstance* targetFunction;
1231 		if (imageInfo->GetAddressSectionType(subroutineAddress)
1232 				== ADDRESS_SECTION_TYPE_PLT) {
1233 			result = fArchitecture->ResolvePICFunctionAddress(
1234 				subroutineAddress, subroutineState, subroutineAddress);
1235 			if (result != B_OK)
1236 				continue;
1237 			if (!targetImage->ContainsAddress(subroutineAddress)) {
1238 				// the PLT entry doesn't necessarily point to a function
1239 				// in the same image; as such we may need to try to
1240 				// resolve the target address again.
1241 				targetImage = image->GetTeam()->ImageByAddress(
1242 					subroutineAddress);
1243 				if (targetImage == NULL)
1244 					continue;
1245 				imageInfo = targetImage->GetImageDebugInfo();
1246 				if (imageInfo == NULL) {
1247 					// As above, since the indirection here may have
1248 					// landed us in an entirely different image, there is
1249 					// no guarantee that debug info is available,
1250 					// depending on which image it was.
1251 					continue;
1252 				}
1253 
1254 			}
1255 		}
1256 
1257 		targetFunction = imageInfo->FunctionAtAddress(subroutineAddress);
1258 		if (targetFunction != NULL) {
1259 			DwarfFunctionDebugInfo* targetInfo =
1260 				dynamic_cast<DwarfFunctionDebugInfo*>(
1261 					targetFunction->GetFunctionDebugInfo());
1262 			if (targetInfo != NULL) {
1263 				DIESubprogram* subProgram = targetInfo->SubprogramEntry();
1264 				DIEType* returnType = subProgram->ReturnType();
1265 				if (returnType == NULL) {
1266 					// check if we have a specification, and if so, if that has
1267 					// a return type
1268 					subProgram = dynamic_cast<DIESubprogram*>(
1269 						subProgram->Specification());
1270 					if (subProgram != NULL)
1271 						returnType = subProgram->ReturnType();
1272 
1273 					// function doesn't return a value, we're done.
1274 					if (returnType == NULL)
1275 						return B_OK;
1276 				}
1277 
1278 				uint32 byteSize = 0;
1279 				if (returnType->ByteSize() == NULL) {
1280 					if (dynamic_cast<DIEAddressingType*>(returnType) != NULL)
1281 						byteSize = fArchitecture->AddressSize();
1282 				} else
1283 					byteSize = returnType->ByteSize()->constant;
1284 
1285 				// if we were unable to determine a size for the type,
1286 				// simply default to the architecture's register width.
1287 				if (byteSize == 0)
1288 					byteSize = fArchitecture->AddressSize();
1289 
1290 				ValueLocation* location;
1291 				result = fArchitecture->GetReturnAddressLocation(frame,
1292 					byteSize, location);
1293 				if (result != B_OK)
1294 					return result;
1295 
1296 				BReference<ValueLocation> locationReference(location, true);
1297 				Variable* variable = NULL;
1298 				BReference<FunctionID> idReference(
1299 					targetFunction->GetFunctionID(), true);
1300 				result = factory.CreateReturnValue(idReference, returnType,
1301 					location, subroutineState, variable);
1302 				if (result != B_OK)
1303 					return result;
1304 
1305 				BReference<Variable> variableReference(variable, true);
1306 				if (!frame->AddLocalVariable(variable))
1307 					return B_NO_MEMORY;
1308 			}
1309 		}
1310 	}
1311 
1312 	return B_OK;
1313 }
1314 
1315 
1316 bool
1317 DwarfImageDebugInfo::_EvaluateBaseTypeConstraints(DIEType* type,
1318 	const TypeLookupConstraints& constraints) const
1319 {
1320 	if (constraints.HasBaseTypeName()) {
1321 		BString baseEntryName;
1322 		DIEType* baseTypeOwnerEntry = NULL;
1323 
1324 		switch (constraints.TypeKind()) {
1325 			case TYPE_ADDRESS:
1326 			{
1327 				DIEAddressingType* addressType =
1328 					dynamic_cast<DIEAddressingType*>(type);
1329 				if (addressType != NULL) {
1330 					baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate(
1331 						addressType, HasTypePredicate<DIEAddressingType>());
1332 				}
1333 				break;
1334 			}
1335 			case TYPE_ARRAY:
1336 			{
1337 				DIEArrayType* arrayType =
1338 					dynamic_cast<DIEArrayType*>(type);
1339 				if (arrayType != NULL) {
1340 					baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate(
1341 						arrayType, HasTypePredicate<DIEArrayType>());
1342 				}
1343 				break;
1344 			}
1345 			default:
1346 				break;
1347 		}
1348 
1349 		if (baseTypeOwnerEntry != NULL) {
1350 			DwarfUtils::GetFullyQualifiedDIEName(baseTypeOwnerEntry,
1351 				baseEntryName);
1352 
1353 			if (baseEntryName != constraints.BaseTypeName())
1354 				return false;
1355 		}
1356 	}
1357 
1358 	return true;
1359 }
1360 
1361 
1362 status_t
1363 DwarfImageDebugInfo::_BuildTypeNameTable()
1364 {
1365 	fTypeNameTable = new(std::nothrow) TypeNameTable;
1366 	if (fTypeNameTable == NULL)
1367 		return B_NO_MEMORY;
1368 
1369 	status_t error = fTypeNameTable->Init();
1370 	if (error != B_OK)
1371 		return error;
1372 
1373 	// iterate through all compilation units
1374 	for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
1375 		i++) {
1376 
1377 		// iterate through all types of the compilation unit
1378 		for (DebugInfoEntryList::ConstIterator it
1379 				= unit->UnitEntry()->Types().GetIterator();
1380 			DIEType* typeEntry = dynamic_cast<DIEType*>(it.Next());) {
1381 			if (typeEntry->IsDeclaration())
1382 				continue;
1383 
1384 			BString typeEntryName;
1385 			DwarfUtils::GetFullyQualifiedDIEName(typeEntry, typeEntryName);
1386 
1387 			TypeNameEntry* entry = fTypeNameTable->Lookup(typeEntryName);
1388 			if (entry == NULL) {
1389 				entry = new(std::nothrow) TypeNameEntry(typeEntryName);
1390 				if (entry == NULL)
1391 					return B_NO_MEMORY;
1392 
1393 				error = fTypeNameTable->Insert(entry);
1394 				if (error != B_OK)
1395 					return error;
1396 			}
1397 
1398 			TypeEntryInfo* info = new(std::nothrow) TypeEntryInfo(typeEntry,
1399 				unit);
1400 			if (info == NULL)
1401 				return B_NO_MEMORY;
1402 
1403 			if (!entry->types.AddItem(info)) {
1404 				delete info;
1405 				return B_NO_MEMORY;
1406 			}
1407 		}
1408 	}
1409 
1410 	return B_OK;
1411 }
1412