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