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