xref: /haiku/src/kits/debugger/debug_info/DwarfImageDebugInfo.cpp (revision f7c507c3a6fbf3a44c59500543926a9088724968)
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 			statementColumn = std::max(state.column - 1, (int32)0);
841 		}
842 	}
843 
844 	TRACE_CODE("  -> no line number program match\n");
845 	return B_ENTRY_NOT_FOUND;
846 }
847 
848 
849 status_t
850 DwarfImageDebugInfo::GetStatementAtSourceLocation(FunctionDebugInfo* _function,
851 	const SourceLocation& sourceLocation, Statement*& _statement)
852 {
853 	DwarfFunctionDebugInfo* function
854 		= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
855 	if (function == NULL)
856 		return B_BAD_VALUE;
857 
858 	target_addr_t functionStartAddress = function->Address() - fRelocationDelta;
859 	target_addr_t functionEndAddress = functionStartAddress + function->Size();
860 
861 	TRACE_LINES2("DwarfImageDebugInfo::GetStatementAtSourceLocation(%p, "
862 		"(%" B_PRId32 ", %" B_PRId32 ")): function range: %#" B_PRIx64 " - %#"
863 		B_PRIx64 "\n", function, sourceLocation.Line(), sourceLocation.Column(),
864 		functionStartAddress, functionEndAddress);
865 
866 	AutoLocker<BLocker> locker(fLock);
867 
868 	// get the source file
869 	LocatableFile* file = function->SourceFile();
870 	if (file == NULL)
871 		return B_ENTRY_NOT_FOUND;
872 
873 	CompilationUnit* unit = function->GetCompilationUnit();
874 
875 	// get the index of the source file in the compilation unit for cheaper
876 	// comparison below
877 	int32 fileIndex = _GetSourceFileIndex(unit, file);
878 
879 	// Get the statement by executing the line number program for the
880 	// compilation unit.
881 	LineNumberProgram& program = unit->GetLineNumberProgram();
882 	if (!program.IsValid())
883 		return B_BAD_DATA;
884 
885 	LineNumberProgram::State state;
886 	program.GetInitialState(state);
887 
888 	target_addr_t statementAddress = 0;
889 	int32 statementLine = -1;
890 	int32 statementColumn = -1;
891 	while (program.GetNextRow(state)) {
892 		bool isOurFile = state.file == fileIndex;
893 
894 		if (statementAddress != 0
895 			&& (!isOurFile || state.isStatement || state.isSequenceEnd)) {
896 			target_addr_t endAddress = state.address;
897 
898 			if (statementAddress < endAddress) {
899 				TRACE_LINES2("  statement: %#" B_PRIx64 " - %#" B_PRIx64
900 					", location: (%" B_PRId32 ", %" B_PRId32 ")\n",
901 					statementAddress, endAddress, statementLine,
902 				 	statementColumn);
903 			}
904 
905 			if (statementAddress < endAddress
906 				&& statementAddress >= functionStartAddress
907 				&& statementAddress < functionEndAddress
908 				&& statementLine == (int32)sourceLocation.Line()
909 				&& statementColumn == (int32)sourceLocation.Column()) {
910 				TRACE_LINES2("  -> found statement!\n");
911 
912 				ContiguousStatement* statement = new(std::nothrow)
913 					ContiguousStatement(
914 						SourceLocation(statementLine, statementColumn),
915 						TargetAddressRange(fRelocationDelta + statementAddress,
916 							endAddress - statementAddress));
917 				if (statement == NULL)
918 					return B_NO_MEMORY;
919 
920 				_statement = statement;
921 				return B_OK;
922 			}
923 
924 			statementAddress = 0;
925 		}
926 
927 		// skip statements of other files
928 		if (!isOurFile)
929 			continue;
930 
931 		if (state.isStatement) {
932 			statementAddress = state.address;
933 			statementLine = state.line - 1;
934 			statementColumn = std::max(state.column - 1, (int32)0);
935 		}
936 	}
937 
938 	return B_ENTRY_NOT_FOUND;
939 }
940 
941 
942 status_t
943 DwarfImageDebugInfo::GetSourceLanguage(FunctionDebugInfo* _function,
944 	SourceLanguage*& _language)
945 {
946 	DwarfFunctionDebugInfo* function
947 		= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
948 	if (function == NULL)
949 		return B_BAD_VALUE;
950 
951 	SourceLanguage* language;
952 	CompilationUnit* unit = function->GetCompilationUnit();
953 	switch (unit->UnitEntry()->Language()) {
954 		case DW_LANG_C89:
955 		case DW_LANG_C:
956 		case DW_LANG_C99:
957 			language = new(std::nothrow) CLanguage;
958 			break;
959 		case DW_LANG_C_plus_plus:
960 			language = new(std::nothrow) CppLanguage;
961 			break;
962 		case 0:
963 		default:
964 			language = new(std::nothrow) UnsupportedLanguage;
965 			break;
966 	}
967 
968 	if (language == NULL)
969 		return B_NO_MEMORY;
970 
971 	_language = language;
972 	return B_OK;
973 }
974 
975 
976 ssize_t
977 DwarfImageDebugInfo::ReadCode(target_addr_t address, void* buffer, size_t size)
978 {
979 	target_addr_t offset = address - fRelocationDelta
980 		- fTextSegment->LoadAddress() + fTextSegment->FileOffset();
981 	ssize_t bytesRead = pread(fFile->GetElfFile()->FD(), buffer, size, offset);
982 	return bytesRead >= 0 ? bytesRead : errno;
983 }
984 
985 
986 status_t
987 DwarfImageDebugInfo::AddSourceCodeInfo(LocatableFile* file,
988 	FileSourceCode* sourceCode)
989 {
990 	bool addedAny = false;
991 	for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
992 			i++) {
993 		int32 fileIndex = _GetSourceFileIndex(unit, file);
994 		if (fileIndex < 0)
995 			continue;
996 
997 		status_t error = _AddSourceCodeInfo(unit, sourceCode, fileIndex);
998 		if (error == B_NO_MEMORY)
999 			return error;
1000 		addedAny |= error == B_OK;
1001 	}
1002 
1003 	return addedAny ? B_OK : B_ENTRY_NOT_FOUND;
1004 }
1005 
1006 
1007 status_t
1008 DwarfImageDebugInfo::_AddSourceCodeInfo(CompilationUnit* unit,
1009 	FileSourceCode* sourceCode, int32 fileIndex)
1010 {
1011 	// Get the statements by executing the line number program for the
1012 	// compilation unit and filtering the rows for our source file.
1013 	LineNumberProgram& program = unit->GetLineNumberProgram();
1014 	if (!program.IsValid())
1015 		return B_BAD_DATA;
1016 
1017 	LineNumberProgram::State state;
1018 	program.GetInitialState(state);
1019 
1020 	target_addr_t statementAddress = 0;
1021 	int32 statementLine = -1;
1022 	int32 statementColumn = -1;
1023 	while (program.GetNextRow(state)) {
1024 		TRACE_LINES2("  %#" B_PRIx64 "  (%" B_PRId32 ", %" B_PRId32 ", %"
1025 			B_PRId32 ")  %d\n", state.address, state.file, state.line,
1026 			state.column, state.isStatement);
1027 
1028 		bool isOurFile = state.file == fileIndex;
1029 
1030 		if (statementAddress != 0
1031 			&& (!isOurFile || state.isStatement || state.isSequenceEnd)) {
1032 			target_addr_t endAddress = state.address;
1033 			if (endAddress > statementAddress) {
1034 				// add the statement
1035 				status_t error = sourceCode->AddSourceLocation(
1036 					SourceLocation(statementLine, statementColumn));
1037 				if (error != B_OK)
1038 					return error;
1039 
1040 				TRACE_LINES2("  -> statement: %#" B_PRIx64 " - %#" B_PRIx64
1041 					", source location: (%" B_PRId32 ", %" B_PRId32 ")\n",
1042 					statementAddress, endAddress, statementLine,
1043 				 	statementColumn);
1044 			}
1045 
1046 			statementAddress = 0;
1047 		}
1048 
1049 		// skip statements of other files
1050 		if (!isOurFile)
1051 			continue;
1052 
1053 		if (state.isStatement) {
1054 			statementAddress = state.address;
1055 			statementLine = state.line - 1;
1056 			statementColumn = std::max(state.column - 1, (int32)0);
1057 		}
1058 	}
1059 
1060 	return B_OK;
1061 }
1062 
1063 
1064 int32
1065 DwarfImageDebugInfo::_GetSourceFileIndex(CompilationUnit* unit,
1066 	LocatableFile* sourceFile) const
1067 {
1068 	// get the index of the source file in the compilation unit for cheaper
1069 	// comparison below
1070 	const char* directory;
1071 	for (int32 i = 0; const char* fileName = unit->FileAt(i, &directory); i++) {
1072 		LocatableFile* file = fFileManager->GetSourceFile(directory, fileName);
1073 		if (file != NULL) {
1074 			BReference<LocatableFile> fileReference(file, true);
1075 			if (file == sourceFile) {
1076 				return i + 1;
1077 					// indices are one-based
1078 			}
1079 		}
1080 	}
1081 
1082 	return -1;
1083 }
1084 
1085 
1086 status_t
1087 DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit,
1088 	StackFrame* frame, FunctionID* functionID,
1089 	DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer,
1090 	target_addr_t lowPC, const EntryListWrapper& variableEntries,
1091 	const EntryListWrapper& blockEntries)
1092 {
1093 	TRACE_LOCALS("DwarfImageDebugInfo::_CreateLocalVariables(): ip: %#" B_PRIx64
1094 		", low PC: %#" B_PRIx64 "\n", instructionPointer, lowPC);
1095 
1096 	// iterate through the variables and add the ones in scope
1097 	for (DebugInfoEntryList::ConstIterator it
1098 			= variableEntries.list.GetIterator();
1099 		DIEVariable* variableEntry = dynamic_cast<DIEVariable*>(it.Next());) {
1100 
1101 		TRACE_LOCALS("  variableEntry %p, scope start: %" B_PRIu64 "\n",
1102 			variableEntry, variableEntry->StartScope());
1103 
1104 		// check the variable's scope
1105 		if (instructionPointer < lowPC + variableEntry->StartScope())
1106 			continue;
1107 
1108 		// add the variable
1109 		Variable* variable;
1110 		if (factory.CreateLocalVariable(functionID, variableEntry, variable)
1111 				!= B_OK) {
1112 			continue;
1113 		}
1114 		BReference<Variable> variableReference(variable, true);
1115 
1116 		if (!frame->AddLocalVariable(variable))
1117 			return B_NO_MEMORY;
1118 	}
1119 
1120 	// iterate through the blocks and find the one we're currently in (if any)
1121 	for (DebugInfoEntryList::ConstIterator it = blockEntries.list.GetIterator();
1122 		DIELexicalBlock* block = dynamic_cast<DIELexicalBlock*>(it.Next());) {
1123 
1124 		TRACE_LOCALS("  lexical block: %p\n", block);
1125 
1126 		// check whether the block has low/high PC attributes
1127 		if (block->LowPC() != 0) {
1128 			TRACE_LOCALS("    has lowPC\n");
1129 
1130 			// yep, compare with the instruction pointer
1131 			if (instructionPointer < block->LowPC()
1132 				|| instructionPointer >= block->HighPC()) {
1133 				continue;
1134 			}
1135 		} else {
1136 			TRACE_LOCALS("    no lowPC\n");
1137 
1138 			// check the address ranges instead
1139 			TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit,
1140 				block->AddressRangesOffset());
1141 			if (rangeList == NULL) {
1142 				TRACE_LOCALS("    failed to get ranges\n");
1143 				continue;
1144 			}
1145 			BReference<TargetAddressRangeList> rangeListReference(rangeList,
1146 				true);
1147 
1148 			if (!rangeList->Contains(instructionPointer)) {
1149 				TRACE_LOCALS("    ranges don't contain IP\n");
1150 				continue;
1151 			}
1152 		}
1153 
1154 		// found a block -- recurse
1155 		return _CreateLocalVariables(unit, frame, functionID, factory,
1156 			instructionPointer, lowPC, block->Variables(), block->Blocks());
1157 	}
1158 
1159 	return B_OK;
1160 }
1161 
1162 
1163 status_t
1164 DwarfImageDebugInfo::_CreateReturnValues(ReturnValueInfoList* returnValueInfos,
1165 	Image* image, StackFrame* frame, DwarfStackFrameDebugInfo& factory)
1166 {
1167 	for (int32 i = 0; i < returnValueInfos->CountItems(); i++) {
1168 		Image* targetImage = image;
1169 		ReturnValueInfo* valueInfo = returnValueInfos->ItemAt(i);
1170 		target_addr_t subroutineAddress = valueInfo->SubroutineAddress();
1171 		CpuState* subroutineState = valueInfo->State();
1172 		if (!targetImage->ContainsAddress(subroutineAddress)) {
1173 			// our current image doesn't contain the target function,
1174 			// locate the one which does.
1175 			targetImage = image->GetTeam()->ImageByAddress(subroutineAddress);
1176 			if (targetImage == NULL) {
1177 				// nothing we can do, try the next entry (if any)
1178 				continue;
1179 			}
1180 		}
1181 
1182 		status_t result = B_OK;
1183 		ImageDebugInfo* imageInfo = targetImage->GetImageDebugInfo();
1184 		if (imageInfo == NULL) {
1185 			// the subroutine may have resolved to a different image
1186 			// that doesn't have debug information available.
1187 			continue;
1188 		}
1189 
1190 		FunctionInstance* targetFunction;
1191 		if (imageInfo->GetAddressSectionType(subroutineAddress)
1192 				== ADDRESS_SECTION_TYPE_PLT) {
1193 			result = fArchitecture->ResolvePICFunctionAddress(
1194 				subroutineAddress, subroutineState, subroutineAddress);
1195 			if (result != B_OK)
1196 				continue;
1197 			if (!targetImage->ContainsAddress(subroutineAddress)) {
1198 				// the PLT entry doesn't necessarily point to a function
1199 				// in the same image; as such we may need to try to
1200 				// resolve the target address again.
1201 				targetImage = image->GetTeam()->ImageByAddress(
1202 					subroutineAddress);
1203 				if (targetImage == NULL)
1204 					continue;
1205 				imageInfo = targetImage->GetImageDebugInfo();
1206 				if (imageInfo == NULL) {
1207 					// As above, since the indirection here may have
1208 					// landed us in an entirely different image, there is
1209 					// no guarantee that debug info is available,
1210 					// depending on which image it was.
1211 					continue;
1212 				}
1213 
1214 			}
1215 		}
1216 
1217 		targetFunction = imageInfo->FunctionAtAddress(subroutineAddress);
1218 		if (targetFunction != NULL) {
1219 			DwarfFunctionDebugInfo* targetInfo =
1220 				dynamic_cast<DwarfFunctionDebugInfo*>(
1221 					targetFunction->GetFunctionDebugInfo());
1222 			if (targetInfo != NULL) {
1223 				DIESubprogram* subProgram = targetInfo->SubprogramEntry();
1224 				DIEType* returnType = subProgram->ReturnType();
1225 				if (returnType == NULL) {
1226 					// check if we have a specification, and if so, if that has
1227 					// a return type
1228 					subProgram = dynamic_cast<DIESubprogram*>(
1229 						subProgram->Specification());
1230 					if (subProgram != NULL)
1231 						returnType = subProgram->ReturnType();
1232 
1233 					// function doesn't return a value, we're done.
1234 					if (returnType == NULL)
1235 						return B_OK;
1236 				}
1237 
1238 				uint32 byteSize = 0;
1239 				if (returnType->ByteSize() == NULL) {
1240 					if (dynamic_cast<DIEAddressingType*>(returnType) != NULL)
1241 						byteSize = fArchitecture->AddressSize();
1242 				} else
1243 					byteSize = returnType->ByteSize()->constant;
1244 
1245 				// if we were unable to determine a size for the type,
1246 				// simply default to the architecture's register width.
1247 				if (byteSize == 0)
1248 					byteSize = fArchitecture->AddressSize();
1249 
1250 				ValueLocation* location;
1251 				result = fArchitecture->GetReturnAddressLocation(frame,
1252 					byteSize, location);
1253 				if (result != B_OK)
1254 					return result;
1255 
1256 				BReference<ValueLocation> locationReference(location, true);
1257 				Variable* variable = NULL;
1258 				BReference<FunctionID> idReference(
1259 					targetFunction->GetFunctionID(), true);
1260 				result = factory.CreateReturnValue(idReference, returnType,
1261 					location, subroutineState, variable);
1262 				if (result != B_OK)
1263 					return result;
1264 
1265 				BReference<Variable> variableReference(variable, true);
1266 				if (!frame->AddLocalVariable(variable))
1267 					return B_NO_MEMORY;
1268 			}
1269 		}
1270 	}
1271 
1272 	return B_OK;
1273 }
1274 
1275 
1276 bool
1277 DwarfImageDebugInfo::_EvaluateBaseTypeConstraints(DIEType* type,
1278 	const TypeLookupConstraints& constraints) const
1279 {
1280 	if (constraints.HasBaseTypeName()) {
1281 		BString baseEntryName;
1282 		DIEType* baseTypeOwnerEntry = NULL;
1283 
1284 		switch (constraints.TypeKind()) {
1285 			case TYPE_ADDRESS:
1286 			{
1287 				DIEAddressingType* addressType =
1288 					dynamic_cast<DIEAddressingType*>(type);
1289 				if (addressType != NULL) {
1290 					baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate(
1291 						addressType, HasTypePredicate<DIEAddressingType>());
1292 				}
1293 				break;
1294 			}
1295 			case TYPE_ARRAY:
1296 			{
1297 				DIEArrayType* arrayType =
1298 					dynamic_cast<DIEArrayType*>(type);
1299 				if (arrayType != NULL) {
1300 					baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate(
1301 						arrayType, HasTypePredicate<DIEArrayType>());
1302 				}
1303 				break;
1304 			}
1305 			default:
1306 				break;
1307 		}
1308 
1309 		if (baseTypeOwnerEntry != NULL) {
1310 			DwarfUtils::GetFullyQualifiedDIEName(baseTypeOwnerEntry,
1311 				baseEntryName);
1312 
1313 			if (baseEntryName != constraints.BaseTypeName())
1314 				return false;
1315 		}
1316 	}
1317 
1318 	return true;
1319 }
1320 
1321 
1322 status_t
1323 DwarfImageDebugInfo::_RecursiveTraverseNamespaceForFunctions(
1324 	DIENamespace* nsEntry, CompilationUnit* unit,
1325 	BObjectList<FunctionDebugInfo>& functions)
1326 {
1327 	status_t error = B_OK;
1328 	for (DebugInfoEntryList::ConstIterator it
1329 				= nsEntry->Children().GetIterator();
1330 			DebugInfoEntry* entry = it.Next();) {
1331 		if (entry->Tag() == DW_TAG_subprogram) {
1332 			DIESubprogram* subprogramEntry
1333 				= static_cast<DIESubprogram*>(entry);
1334 			error = _AddFunction(subprogramEntry, unit, functions);
1335 			if (error != B_OK)
1336 				return error;
1337 		}
1338 
1339 		DIENamespace* nsEntry = dynamic_cast<DIENamespace*>(entry);
1340 		if (nsEntry != NULL) {
1341 			error = _RecursiveTraverseNamespaceForFunctions(nsEntry, unit,
1342 				functions);
1343 			if (error != B_OK)
1344 				return error;
1345 			continue;
1346 		}
1347 
1348 		DIEClassBaseType* classEntry = dynamic_cast<DIEClassBaseType*>(entry);
1349 		if (classEntry != NULL) {
1350 			for (DebugInfoEntryList::ConstIterator it
1351 						= classEntry->MemberFunctions().GetIterator();
1352 					DebugInfoEntry* memberEntry = it.Next();) {
1353 				error = _AddFunction(static_cast<DIESubprogram*>(memberEntry),
1354 					unit, functions);
1355 				if (error != B_OK)
1356 					return error;
1357 			}
1358 		}
1359 	}
1360 
1361 	return B_OK;
1362 }
1363 
1364 
1365 status_t
1366 DwarfImageDebugInfo::_AddFunction(DIESubprogram* subprogramEntry,
1367 	CompilationUnit* unit, BObjectList<FunctionDebugInfo>& functions)
1368 {
1369 	// ignore declarations and inlined functions
1370 	if (subprogramEntry->IsDeclaration()
1371 		|| subprogramEntry->Inline() == DW_INL_inlined
1372 		|| subprogramEntry->Inline() == DW_INL_declared_inlined) {
1373 		return B_OK;
1374 	}
1375 
1376 	// get the name
1377 	BString name;
1378 	DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry, name);
1379 	if (name.Length() == 0)
1380 		return B_OK;
1381 
1382 	// get the address ranges
1383 	TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit,
1384 		subprogramEntry->AddressRangesOffset());
1385 	if (rangeList == NULL) {
1386 		target_addr_t lowPC = subprogramEntry->LowPC();
1387 		target_addr_t highPC = subprogramEntry->HighPC();
1388 		if (highPC <= lowPC)
1389 			return B_OK;
1390 
1391 		rangeList = new(std::nothrow) TargetAddressRangeList(
1392 			TargetAddressRange(lowPC, highPC - lowPC));
1393 		if (rangeList == NULL)
1394 			return B_NO_MEMORY;
1395 				// TODO: Clean up already added functions!
1396 	}
1397 	BReference<TargetAddressRangeList> rangeListReference(rangeList,
1398 		true);
1399 
1400 	// get the source location
1401 	const char* directoryPath = NULL;
1402 	const char* fileName = NULL;
1403 	int32 line = -1;
1404 	int32 column = -1;
1405 	DwarfUtils::GetDeclarationLocation(fFile, subprogramEntry,
1406 		directoryPath, fileName, line, column);
1407 
1408 	LocatableFile* file = NULL;
1409 	if (fileName != NULL) {
1410 		file = fFileManager->GetSourceFile(directoryPath,
1411 			fileName);
1412 	}
1413 	BReference<LocatableFile> fileReference(file, true);
1414 
1415 	// create and add the functions
1416 	DwarfFunctionDebugInfo* function
1417 		= new(std::nothrow) DwarfFunctionDebugInfo(this, unit,
1418 			subprogramEntry, rangeList, name, file,
1419 			SourceLocation(line, std::max(column, (int32)0)));
1420 	if (function == NULL || !functions.AddItem(function)) {
1421 		delete function;
1422 		return B_NO_MEMORY;
1423 			// TODO: Clean up already added functions!
1424 	}
1425 
1426 	return B_OK;
1427 }
1428 
1429 
1430 status_t
1431 DwarfImageDebugInfo::_BuildTypeNameTable()
1432 {
1433 	fTypeNameTable = new(std::nothrow) TypeNameTable;
1434 	if (fTypeNameTable == NULL)
1435 		return B_NO_MEMORY;
1436 
1437 	status_t error = fTypeNameTable->Init();
1438 	if (error != B_OK)
1439 		return error;
1440 
1441 	// iterate through all compilation units
1442 	for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
1443 		i++) {
1444 		// iterate through all types of the compilation unit
1445 		for (DebugInfoEntryList::ConstIterator it
1446 				= unit->UnitEntry()->Types().GetIterator();
1447 			DIEType* typeEntry = dynamic_cast<DIEType*>(it.Next());) {
1448 
1449 			if (_RecursiveAddTypeNames(typeEntry, unit) != B_OK)
1450 				return B_NO_MEMORY;
1451 		}
1452 
1453 		for (DebugInfoEntryList::ConstIterator it
1454 			= unit->UnitEntry()->OtherChildren().GetIterator();
1455 			DebugInfoEntry* child = it.Next();) {
1456 			DIENamespace* namespaceEntry = dynamic_cast<DIENamespace*>(child);
1457 			if (namespaceEntry == NULL)
1458 				continue;
1459 
1460 			if (_RecursiveTraverseNamespaceForTypes(namespaceEntry, unit)
1461 					!= B_OK) {
1462 				return B_NO_MEMORY;
1463 			}
1464 		}
1465 	}
1466 
1467 	return B_OK;
1468 }
1469 
1470 
1471 status_t
1472 DwarfImageDebugInfo::_RecursiveAddTypeNames(DIEType* type, CompilationUnit* unit)
1473 {
1474 	if (type->IsDeclaration())
1475 		return B_OK;
1476 
1477 	BString typeEntryName;
1478 	DwarfUtils::GetFullyQualifiedDIEName(type, typeEntryName);
1479 
1480 	status_t error = B_OK;
1481 	TypeNameEntry* entry = fTypeNameTable->Lookup(typeEntryName);
1482 	if (entry == NULL) {
1483 		entry = new(std::nothrow) TypeNameEntry(typeEntryName);
1484 		if (entry == NULL)
1485 			return B_NO_MEMORY;
1486 
1487 		error = fTypeNameTable->Insert(entry);
1488 		if (error != B_OK)
1489 			return error;
1490 	}
1491 
1492 	TypeEntryInfo* info = new(std::nothrow) TypeEntryInfo(type,	unit);
1493 	if (info == NULL)
1494 		return B_NO_MEMORY;
1495 
1496 	if (!entry->types.AddItem(info)) {
1497 		delete info;
1498 		return B_NO_MEMORY;
1499 	}
1500 
1501 	DIEClassBaseType* classType = dynamic_cast<DIEClassBaseType*>(type);
1502 	if (classType == NULL)
1503 		return B_OK;
1504 
1505 	for (DebugInfoEntryList::ConstIterator it
1506 			= classType->InnerTypes().GetIterator();
1507 		DIEType* innerType = dynamic_cast<DIEType*>(it.Next());) {
1508 		error = _RecursiveAddTypeNames(innerType, unit);
1509 		if (error != B_OK)
1510 			return error;
1511 	}
1512 
1513 	return B_OK;
1514 }
1515 
1516 
1517 status_t
1518 DwarfImageDebugInfo::_RecursiveTraverseNamespaceForTypes(DIENamespace* nsEntry,
1519 	CompilationUnit* unit)
1520 {
1521 	for (DebugInfoEntryList::ConstIterator it
1522 				= nsEntry->Children().GetIterator();
1523 			DebugInfoEntry* child = it.Next();) {
1524 
1525 		if (child->IsType()) {
1526 			DIEType* type = dynamic_cast<DIEType*>(child);
1527 			if (_RecursiveAddTypeNames(type, unit) != B_OK)
1528 				return B_NO_MEMORY;
1529 		} else {
1530 			DIENamespace* nameSpace = dynamic_cast<DIENamespace*>(child);
1531 			if (nameSpace == NULL)
1532 				continue;
1533 
1534 			status_t error = _RecursiveTraverseNamespaceForTypes(nameSpace,
1535 				unit);
1536 			if (error != B_OK)
1537 				return error;
1538 			continue;
1539 		}
1540 	}
1541 
1542 	return B_OK;
1543 }
1544