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