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
66namespace {
67
68
69// #pragma mark - HasTypePredicate
70
71
72template<typename EntryType>
73struct 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
86struct 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
158protected:
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
165protected:
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
177struct 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
213private:
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*/
225struct 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
239struct 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
263struct 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
284struct 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
314struct 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
330DwarfImageDebugInfo::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
359DwarfImageDebugInfo::~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
375status_t
376DwarfImageDebugInfo::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
404status_t
405DwarfImageDebugInfo::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
467status_t
468DwarfImageDebugInfo::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
539bool
540DwarfImageDebugInfo::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
572AddressSectionType
573DwarfImageDebugInfo::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
585status_t
586DwarfImageDebugInfo::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,
652		fArchitecture->AddressSize(), fArchitecture->IsBigEndian(),
653		entry, instructionPointer, inputInterface, outputInterface,
654		framePointer);
655
656	if (error != B_OK) {
657		TRACE_CFI("Failed to unwind call frame: %s\n", strerror(error));
658		return B_UNSUPPORTED;
659	}
660
661	TRACE_CFI_ONLY(
662		TRACE_CFI("unwound registers:\n");
663		for (int32 i = 0; i < registerCount; i++) {
664			const Register* reg = registers + i;
665			BVariant value;
666			if (previousCpuState->GetRegisterValue(reg, value)) {
667				TRACE_CFI("  %3s: %#" B_PRIx64 "\n", reg->Name(),
668					value.ToUInt64());
669			} else
670				TRACE_CFI("  %3s: undefined\n", reg->Name());
671		}
672	)
673
674	// create the stack frame debug info
675	DIESubprogram* subprogramEntry = function != NULL ?
676		function->SubprogramEntry() : NULL;
677	DwarfStackFrameDebugInfo* stackFrameDebugInfo
678		= new(std::nothrow) DwarfStackFrameDebugInfo(fArchitecture,
679			fImageInfo.ImageID(), fFile, unit, subprogramEntry, fTypeLookup,
680			fTypeCache, instructionPointer, framePointer, fRelocationDelta,
681			inputInterface, fromDwarfMap);
682	if (stackFrameDebugInfo == NULL)
683		return B_NO_MEMORY;
684	BReference<DwarfStackFrameDebugInfo> stackFrameDebugInfoReference(
685		stackFrameDebugInfo, true);
686
687	error = stackFrameDebugInfo->Init();
688	if (error != B_OK)
689		return error;
690
691	// create the stack frame
692	StackFrame* frame = new(std::nothrow) StackFrame(STACK_FRAME_TYPE_STANDARD,
693		cpuState, framePointer, cpuState->InstructionPointer(),
694		stackFrameDebugInfo);
695	if (frame == NULL)
696		return B_NO_MEMORY;
697	BReference<StackFrame> frameReference(frame, true);
698
699	error = frame->Init();
700	if (error != B_OK)
701		return error;
702
703	frame->SetReturnAddress(previousCpuState->InstructionPointer());
704		// Note, this is correct, since we actually retrieved the return
705		// address. Our caller will fix the IP for us.
706
707	// The subprogram entry may not be available since this may be a case
708	// where .eh_frame was used to unwind the stack without other DWARF
709	// info being available.
710	if (subprogramEntry != NULL && getFullFrameInfo) {
711		// create function parameter objects
712		for (DebugInfoEntryList::ConstIterator it
713			= subprogramEntry->Parameters().GetIterator();
714			DebugInfoEntry* entry = it.Next();) {
715			if (entry->Tag() != DW_TAG_formal_parameter)
716				continue;
717
718			BString parameterName;
719			DwarfUtils::GetDIEName(entry, parameterName);
720			if (parameterName.Length() == 0)
721				continue;
722
723			DIEFormalParameter* parameterEntry
724				= dynamic_cast<DIEFormalParameter*>(entry);
725			Variable* parameter;
726			if (stackFrameDebugInfo->CreateParameter(functionID,
727				parameterEntry, parameter) != B_OK) {
728				continue;
729			}
730			BReference<Variable> parameterReference(parameter, true);
731
732			if (!frame->AddParameter(parameter))
733				return B_NO_MEMORY;
734		}
735
736		// create objects for the local variables
737		_CreateLocalVariables(unit, frame, functionID, *stackFrameDebugInfo,
738			instructionPointer, functionInstance->Address() - fRelocationDelta,
739			subprogramEntry->Variables(), subprogramEntry->Blocks());
740
741		if (returnValueInfos != NULL && !returnValueInfos->IsEmpty()) {
742			_CreateReturnValues(returnValueInfos, image, frame,
743				*stackFrameDebugInfo);
744		}
745	}
746
747	_frame = frameReference.Detach();
748	_previousCpuState = previousCpuStateReference.Detach();
749
750	frame->SetPreviousCpuState(_previousCpuState);
751
752	return B_OK;
753}
754
755
756status_t
757DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function,
758	target_addr_t address, Statement*& _statement)
759{
760	TRACE_CODE("DwarfImageDebugInfo::GetStatement(function: %p, address: %#"
761		B_PRIx64 ")\n", _function, address);
762
763	DwarfFunctionDebugInfo* function
764		= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
765	if (function == NULL) {
766		TRACE_LINES("  -> no dwarf function\n");
767		// fall back to assembly
768		return fArchitecture->GetStatement(function, address, _statement);
769	}
770
771	AutoLocker<BLocker> locker(fLock);
772
773	// check whether we have the source code
774	CompilationUnit* unit = function->GetCompilationUnit();
775	LocatableFile* file = function->SourceFile();
776	if (file == NULL) {
777		TRACE_CODE("  -> no source file\n");
778
779		// no source code -- rather return the assembly statement
780		return fArchitecture->GetStatement(function, address, _statement);
781	}
782
783	SourceCode* sourceCode = NULL;
784	status_t error = fSourceInfo->GetActiveSourceCode(_function, sourceCode);
785	BReference<SourceCode> sourceReference(sourceCode, true);
786	if (error != B_OK || dynamic_cast<DisassembledCode*>(sourceCode) != NULL) {
787		// either no source code or disassembly is currently active (i.e.
788		// due to failing to locate the source file on disk or the user
789		// deliberately switching to disassembly view).
790		// return the assembly statement.
791		return fArchitecture->GetStatement(function, address, _statement);
792	}
793
794	// get the index of the source file in the compilation unit for cheaper
795	// comparison below
796	int32 fileIndex = _GetSourceFileIndex(unit, file);
797
798	// Get the statement by executing the line number program for the
799	// compilation unit.
800	LineNumberProgram& program = unit->GetLineNumberProgram();
801	if (!program.IsValid()) {
802		TRACE_CODE("  -> no line number program\n");
803		return B_BAD_DATA;
804	}
805
806	// adjust address
807	address -= fRelocationDelta;
808
809	LineNumberProgram::State state;
810	program.GetInitialState(state);
811
812	target_addr_t statementAddress = 0;
813	int32 statementLine = -1;
814	int32 statementColumn = -1;
815	while (program.GetNextRow(state)) {
816		// skip statements of other files
817		if (state.file != fileIndex)
818			continue;
819
820		if (statementAddress != 0
821			&& (state.isStatement || state.isSequenceEnd)) {
822			target_addr_t endAddress = state.address;
823			if (address >= statementAddress && address < endAddress) {
824				ContiguousStatement* statement = new(std::nothrow)
825					ContiguousStatement(
826						SourceLocation(statementLine, statementColumn),
827						TargetAddressRange(fRelocationDelta + statementAddress,
828							endAddress - statementAddress));
829				if (statement == NULL)
830					return B_NO_MEMORY;
831
832				_statement = statement;
833				return B_OK;
834			}
835
836			statementAddress = 0;
837		}
838
839		if (state.isStatement) {
840			statementAddress = state.address;
841			statementLine = state.line - 1;
842			// discard column info until proper support is implemented
843			// statementColumn = std::max(state.column - 1, (int32)0);
844			statementColumn = 0;
845		}
846	}
847
848	TRACE_CODE("  -> no line number program match\n");
849	return B_ENTRY_NOT_FOUND;
850}
851
852
853status_t
854DwarfImageDebugInfo::GetStatementAtSourceLocation(FunctionDebugInfo* _function,
855	const SourceLocation& sourceLocation, Statement*& _statement)
856{
857	DwarfFunctionDebugInfo* function
858		= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
859	if (function == NULL)
860		return B_BAD_VALUE;
861
862	target_addr_t functionStartAddress = function->Address() - fRelocationDelta;
863	target_addr_t functionEndAddress = functionStartAddress + function->Size();
864
865	TRACE_LINES2("DwarfImageDebugInfo::GetStatementAtSourceLocation(%p, "
866		"(%" B_PRId32 ", %" B_PRId32 ")): function range: %#" B_PRIx64 " - %#"
867		B_PRIx64 "\n", function, sourceLocation.Line(), sourceLocation.Column(),
868		functionStartAddress, functionEndAddress);
869
870	AutoLocker<BLocker> locker(fLock);
871
872	// get the source file
873	LocatableFile* file = function->SourceFile();
874	if (file == NULL)
875		return B_ENTRY_NOT_FOUND;
876
877	CompilationUnit* unit = function->GetCompilationUnit();
878
879	// get the index of the source file in the compilation unit for cheaper
880	// comparison below
881	int32 fileIndex = _GetSourceFileIndex(unit, file);
882
883	// Get the statement by executing the line number program for the
884	// compilation unit.
885	LineNumberProgram& program = unit->GetLineNumberProgram();
886	if (!program.IsValid())
887		return B_BAD_DATA;
888
889	LineNumberProgram::State state;
890	program.GetInitialState(state);
891
892	target_addr_t statementAddress = 0;
893	int32 statementLine = -1;
894	int32 statementColumn = -1;
895	while (program.GetNextRow(state)) {
896		bool isOurFile = state.file == fileIndex;
897
898		if (statementAddress != 0
899			&& (!isOurFile || state.isStatement || state.isSequenceEnd)) {
900			target_addr_t endAddress = state.address;
901
902			if (statementAddress < endAddress) {
903				TRACE_LINES2("  statement: %#" B_PRIx64 " - %#" B_PRIx64
904					", location: (%" B_PRId32 ", %" B_PRId32 ")\n",
905					statementAddress, endAddress, statementLine,
906				 	statementColumn);
907			}
908
909			if (statementAddress < endAddress
910				&& statementAddress >= functionStartAddress
911				&& statementAddress < functionEndAddress
912				&& statementLine == (int32)sourceLocation.Line()
913				&& statementColumn == (int32)sourceLocation.Column()) {
914				TRACE_LINES2("  -> found statement!\n");
915
916				ContiguousStatement* statement = new(std::nothrow)
917					ContiguousStatement(
918						SourceLocation(statementLine, statementColumn),
919						TargetAddressRange(fRelocationDelta + statementAddress,
920							endAddress - statementAddress));
921				if (statement == NULL)
922					return B_NO_MEMORY;
923
924				_statement = statement;
925				return B_OK;
926			}
927
928			statementAddress = 0;
929		}
930
931		// skip statements of other files
932		if (!isOurFile)
933			continue;
934
935		if (state.isStatement) {
936			statementAddress = state.address;
937			statementLine = state.line - 1;
938			// discard column info until proper support is implemented
939			// statementColumn = std::max(state.column - 1, (int32)0);
940			statementColumn = 0;
941		}
942	}
943
944	return B_ENTRY_NOT_FOUND;
945}
946
947
948status_t
949DwarfImageDebugInfo::GetSourceLanguage(FunctionDebugInfo* _function,
950	SourceLanguage*& _language)
951{
952	DwarfFunctionDebugInfo* function
953		= dynamic_cast<DwarfFunctionDebugInfo*>(_function);
954	if (function == NULL)
955		return B_BAD_VALUE;
956
957	SourceLanguage* language;
958	CompilationUnit* unit = function->GetCompilationUnit();
959	switch (unit->UnitEntry()->Language()) {
960		case DW_LANG_C89:
961		case DW_LANG_C:
962		case DW_LANG_C99:
963			language = new(std::nothrow) CLanguage;
964			break;
965		case DW_LANG_C_plus_plus:
966			language = new(std::nothrow) CppLanguage;
967			break;
968		case 0:
969		default:
970			language = new(std::nothrow) UnsupportedLanguage;
971			break;
972	}
973
974	if (language == NULL)
975		return B_NO_MEMORY;
976
977	_language = language;
978	return B_OK;
979}
980
981
982ssize_t
983DwarfImageDebugInfo::ReadCode(target_addr_t address, void* buffer, size_t size)
984{
985	target_addr_t offset = address - fRelocationDelta
986		- fTextSegment->LoadAddress() + fTextSegment->FileOffset();
987	ssize_t bytesRead = pread(fFile->GetElfFile()->FD(), buffer, size, offset);
988	return bytesRead >= 0 ? bytesRead : errno;
989}
990
991
992status_t
993DwarfImageDebugInfo::AddSourceCodeInfo(LocatableFile* file,
994	FileSourceCode* sourceCode)
995{
996	bool addedAny = false;
997	for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
998			i++) {
999		int32 fileIndex = _GetSourceFileIndex(unit, file);
1000		if (fileIndex < 0)
1001			continue;
1002
1003		status_t error = _AddSourceCodeInfo(unit, sourceCode, fileIndex);
1004		if (error == B_NO_MEMORY)
1005			return error;
1006		addedAny |= error == B_OK;
1007	}
1008
1009	return addedAny ? B_OK : B_ENTRY_NOT_FOUND;
1010}
1011
1012
1013status_t
1014DwarfImageDebugInfo::_AddSourceCodeInfo(CompilationUnit* unit,
1015	FileSourceCode* sourceCode, int32 fileIndex)
1016{
1017	// Get the statements by executing the line number program for the
1018	// compilation unit and filtering the rows for our source file.
1019	LineNumberProgram& program = unit->GetLineNumberProgram();
1020	if (!program.IsValid())
1021		return B_BAD_DATA;
1022
1023	LineNumberProgram::State state;
1024	program.GetInitialState(state);
1025
1026	target_addr_t statementAddress = 0;
1027	int32 statementLine = -1;
1028	int32 statementColumn = -1;
1029	while (program.GetNextRow(state)) {
1030		TRACE_LINES2("  %#" B_PRIx64 "  (%" B_PRId32 ", %" B_PRId32 ", %"
1031			B_PRId32 ")  %d\n", state.address, state.file, state.line,
1032			state.column, state.isStatement);
1033
1034		bool isOurFile = state.file == fileIndex;
1035
1036		if (statementAddress != 0
1037			&& (!isOurFile || state.isStatement || state.isSequenceEnd)) {
1038			target_addr_t endAddress = state.address;
1039			if (endAddress > statementAddress) {
1040				// add the statement
1041				status_t error = sourceCode->AddSourceLocation(
1042					SourceLocation(statementLine, statementColumn));
1043				if (error != B_OK)
1044					return error;
1045
1046				TRACE_LINES2("  -> statement: %#" B_PRIx64 " - %#" B_PRIx64
1047					", source location: (%" B_PRId32 ", %" B_PRId32 ")\n",
1048					statementAddress, endAddress, statementLine,
1049				 	statementColumn);
1050			}
1051
1052			statementAddress = 0;
1053		}
1054
1055		// skip statements of other files
1056		if (!isOurFile)
1057			continue;
1058
1059		if (state.isStatement) {
1060			statementAddress = state.address;
1061			statementLine = state.line - 1;
1062			// discard column info until proper support is implemented
1063			// statementColumn = std::max(state.column - 1, (int32)0);
1064			statementColumn = 0;
1065		}
1066	}
1067
1068	return B_OK;
1069}
1070
1071
1072int32
1073DwarfImageDebugInfo::_GetSourceFileIndex(CompilationUnit* unit,
1074	LocatableFile* sourceFile) const
1075{
1076	// get the index of the source file in the compilation unit for cheaper
1077	// comparison below
1078	const char* directory;
1079	for (int32 i = 0; const char* fileName = unit->FileAt(i, &directory); i++) {
1080		LocatableFile* file = fFileManager->GetSourceFile(directory, fileName);
1081		if (file != NULL) {
1082			BReference<LocatableFile> fileReference(file, true);
1083			if (file == sourceFile) {
1084				return i + 1;
1085					// indices are one-based
1086			}
1087		}
1088	}
1089
1090	return -1;
1091}
1092
1093
1094status_t
1095DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit,
1096	StackFrame* frame, FunctionID* functionID,
1097	DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer,
1098	target_addr_t lowPC, const EntryListWrapper& variableEntries,
1099	const EntryListWrapper& blockEntries)
1100{
1101	TRACE_LOCALS("DwarfImageDebugInfo::_CreateLocalVariables(): ip: %#" B_PRIx64
1102		", low PC: %#" B_PRIx64 "\n", instructionPointer, lowPC);
1103
1104	// iterate through the variables and add the ones in scope
1105	for (DebugInfoEntryList::ConstIterator it
1106			= variableEntries.list.GetIterator();
1107		DIEVariable* variableEntry = dynamic_cast<DIEVariable*>(it.Next());) {
1108
1109		TRACE_LOCALS("  variableEntry %p, scope start: %" B_PRIu64 "\n",
1110			variableEntry, variableEntry->StartScope());
1111
1112		// check the variable's scope
1113		if (instructionPointer < lowPC + variableEntry->StartScope())
1114			continue;
1115
1116		// add the variable
1117		Variable* variable;
1118		if (factory.CreateLocalVariable(functionID, variableEntry, variable)
1119				!= B_OK) {
1120			continue;
1121		}
1122		BReference<Variable> variableReference(variable, true);
1123
1124		if (!frame->AddLocalVariable(variable))
1125			return B_NO_MEMORY;
1126	}
1127
1128	// iterate through the blocks and find the one we're currently in (if any)
1129	for (DebugInfoEntryList::ConstIterator it = blockEntries.list.GetIterator();
1130		DIELexicalBlock* block = dynamic_cast<DIELexicalBlock*>(it.Next());) {
1131
1132		TRACE_LOCALS("  lexical block: %p\n", block);
1133
1134		// check whether the block has low/high PC attributes
1135		if (block->LowPC() != 0) {
1136			TRACE_LOCALS("    has lowPC\n");
1137
1138			// yep, compare with the instruction pointer
1139			if (instructionPointer < block->LowPC()
1140				|| instructionPointer >= block->HighPC()) {
1141				continue;
1142			}
1143		} else {
1144			TRACE_LOCALS("    no lowPC\n");
1145
1146			// check the address ranges instead
1147			TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit,
1148				block->AddressRangesOffset());
1149			if (rangeList == NULL) {
1150				TRACE_LOCALS("    failed to get ranges\n");
1151				continue;
1152			}
1153			BReference<TargetAddressRangeList> rangeListReference(rangeList,
1154				true);
1155
1156			if (!rangeList->Contains(instructionPointer)) {
1157				TRACE_LOCALS("    ranges don't contain IP\n");
1158				continue;
1159			}
1160		}
1161
1162		// found a block -- recurse
1163		return _CreateLocalVariables(unit, frame, functionID, factory,
1164			instructionPointer, lowPC, block->Variables(), block->Blocks());
1165	}
1166
1167	return B_OK;
1168}
1169
1170
1171status_t
1172DwarfImageDebugInfo::_CreateReturnValues(ReturnValueInfoList* returnValueInfos,
1173	Image* image, StackFrame* frame, DwarfStackFrameDebugInfo& factory)
1174{
1175	for (int32 i = 0; i < returnValueInfos->CountItems(); i++) {
1176		Image* targetImage = image;
1177		ReturnValueInfo* valueInfo = returnValueInfos->ItemAt(i);
1178		target_addr_t subroutineAddress = valueInfo->SubroutineAddress();
1179		CpuState* subroutineState = valueInfo->State();
1180		if (!targetImage->ContainsAddress(subroutineAddress)) {
1181			// our current image doesn't contain the target function,
1182			// locate the one which does.
1183			targetImage = image->GetTeam()->ImageByAddress(subroutineAddress);
1184			if (targetImage == NULL) {
1185				// nothing we can do, try the next entry (if any)
1186				continue;
1187			}
1188		}
1189
1190		status_t result = B_OK;
1191		ImageDebugInfo* imageInfo = targetImage->GetImageDebugInfo();
1192		if (imageInfo == NULL) {
1193			// the subroutine may have resolved to a different image
1194			// that doesn't have debug information available.
1195			continue;
1196		}
1197
1198		FunctionInstance* targetFunction;
1199		if (imageInfo->GetAddressSectionType(subroutineAddress)
1200				== ADDRESS_SECTION_TYPE_PLT) {
1201			result = fArchitecture->ResolvePICFunctionAddress(
1202				subroutineAddress, subroutineState, subroutineAddress);
1203			if (result != B_OK)
1204				continue;
1205			if (!targetImage->ContainsAddress(subroutineAddress)) {
1206				// the PLT entry doesn't necessarily point to a function
1207				// in the same image; as such we may need to try to
1208				// resolve the target address again.
1209				targetImage = image->GetTeam()->ImageByAddress(
1210					subroutineAddress);
1211				if (targetImage == NULL)
1212					continue;
1213				imageInfo = targetImage->GetImageDebugInfo();
1214				if (imageInfo == NULL) {
1215					// As above, since the indirection here may have
1216					// landed us in an entirely different image, there is
1217					// no guarantee that debug info is available,
1218					// depending on which image it was.
1219					continue;
1220				}
1221
1222			}
1223		}
1224
1225		targetFunction = imageInfo->FunctionAtAddress(subroutineAddress);
1226		if (targetFunction != NULL) {
1227			DwarfFunctionDebugInfo* targetInfo =
1228				dynamic_cast<DwarfFunctionDebugInfo*>(
1229					targetFunction->GetFunctionDebugInfo());
1230			if (targetInfo != NULL) {
1231				DIESubprogram* subProgram = targetInfo->SubprogramEntry();
1232				DIEType* returnType = subProgram->ReturnType();
1233				if (returnType == NULL) {
1234					// check if we have a specification, and if so, if that has
1235					// a return type
1236					subProgram = dynamic_cast<DIESubprogram*>(
1237						subProgram->Specification());
1238					if (subProgram != NULL)
1239						returnType = subProgram->ReturnType();
1240
1241					// function doesn't return a value, we're done.
1242					if (returnType == NULL)
1243						return B_OK;
1244				}
1245
1246				uint32 byteSize = 0;
1247				if (returnType->ByteSize() == NULL) {
1248					if (dynamic_cast<DIEAddressingType*>(returnType) != NULL)
1249						byteSize = fArchitecture->AddressSize();
1250				} else
1251					byteSize = returnType->ByteSize()->constant;
1252
1253				// if we were unable to determine a size for the type,
1254				// simply default to the architecture's register width.
1255				if (byteSize == 0)
1256					byteSize = fArchitecture->AddressSize();
1257
1258				ValueLocation* location;
1259				result = fArchitecture->GetReturnAddressLocation(frame,
1260					byteSize, location);
1261				if (result != B_OK)
1262					return result;
1263
1264				BReference<ValueLocation> locationReference(location, true);
1265				Variable* variable = NULL;
1266				BReference<FunctionID> idReference(
1267					targetFunction->GetFunctionID(), true);
1268				result = factory.CreateReturnValue(idReference, returnType,
1269					location, subroutineState, variable);
1270				if (result != B_OK)
1271					return result;
1272
1273				BReference<Variable> variableReference(variable, true);
1274				if (!frame->AddLocalVariable(variable))
1275					return B_NO_MEMORY;
1276			}
1277		}
1278	}
1279
1280	return B_OK;
1281}
1282
1283
1284bool
1285DwarfImageDebugInfo::_EvaluateBaseTypeConstraints(DIEType* type,
1286	const TypeLookupConstraints& constraints) const
1287{
1288	if (constraints.HasBaseTypeName()) {
1289		BString baseEntryName;
1290		DIEType* baseTypeOwnerEntry = NULL;
1291
1292		switch (constraints.TypeKind()) {
1293			case TYPE_ADDRESS:
1294			{
1295				DIEAddressingType* addressType =
1296					dynamic_cast<DIEAddressingType*>(type);
1297				if (addressType != NULL) {
1298					baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate(
1299						addressType, HasTypePredicate<DIEAddressingType>());
1300				}
1301				break;
1302			}
1303			case TYPE_ARRAY:
1304			{
1305				DIEArrayType* arrayType =
1306					dynamic_cast<DIEArrayType*>(type);
1307				if (arrayType != NULL) {
1308					baseTypeOwnerEntry = DwarfUtils::GetDIEByPredicate(
1309						arrayType, HasTypePredicate<DIEArrayType>());
1310				}
1311				break;
1312			}
1313			default:
1314				break;
1315		}
1316
1317		if (baseTypeOwnerEntry != NULL) {
1318			DwarfUtils::GetFullyQualifiedDIEName(baseTypeOwnerEntry,
1319				baseEntryName);
1320
1321			if (baseEntryName != constraints.BaseTypeName())
1322				return false;
1323		}
1324	}
1325
1326	return true;
1327}
1328
1329
1330status_t
1331DwarfImageDebugInfo::_RecursiveTraverseNamespaceForFunctions(
1332	DIENamespace* nsEntry, CompilationUnit* unit,
1333	BObjectList<FunctionDebugInfo>& functions)
1334{
1335	status_t error = B_OK;
1336	for (DebugInfoEntryList::ConstIterator it
1337				= nsEntry->Children().GetIterator();
1338			DebugInfoEntry* entry = it.Next();) {
1339		if (entry->Tag() == DW_TAG_subprogram) {
1340			DIESubprogram* subprogramEntry
1341				= static_cast<DIESubprogram*>(entry);
1342			error = _AddFunction(subprogramEntry, unit, functions);
1343			if (error != B_OK)
1344				return error;
1345		}
1346
1347		DIENamespace* nsEntry = dynamic_cast<DIENamespace*>(entry);
1348		if (nsEntry != NULL) {
1349			error = _RecursiveTraverseNamespaceForFunctions(nsEntry, unit,
1350				functions);
1351			if (error != B_OK)
1352				return error;
1353			continue;
1354		}
1355
1356		DIEClassBaseType* classEntry = dynamic_cast<DIEClassBaseType*>(entry);
1357		if (classEntry != NULL) {
1358			for (DebugInfoEntryList::ConstIterator it
1359						= classEntry->MemberFunctions().GetIterator();
1360					DebugInfoEntry* memberEntry = it.Next();) {
1361				error = _AddFunction(static_cast<DIESubprogram*>(memberEntry),
1362					unit, functions);
1363				if (error != B_OK)
1364					return error;
1365			}
1366		}
1367	}
1368
1369	return B_OK;
1370}
1371
1372
1373status_t
1374DwarfImageDebugInfo::_AddFunction(DIESubprogram* subprogramEntry,
1375	CompilationUnit* unit, BObjectList<FunctionDebugInfo>& functions)
1376{
1377	// ignore declarations and inlined functions
1378	if (subprogramEntry->IsDeclaration()
1379		|| subprogramEntry->Inline() == DW_INL_inlined
1380		|| subprogramEntry->Inline() == DW_INL_declared_inlined) {
1381		return B_OK;
1382	}
1383
1384	// get the name
1385	BString name;
1386	DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry, name);
1387	if (name.Length() == 0)
1388		return B_OK;
1389
1390	// get the address ranges
1391	TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit,
1392		subprogramEntry->AddressRangesOffset());
1393	if (rangeList == NULL) {
1394		target_addr_t lowPC = subprogramEntry->LowPC();
1395		target_addr_t highPC = subprogramEntry->HighPC();
1396		if (highPC <= lowPC)
1397			return B_OK;
1398
1399		rangeList = new(std::nothrow) TargetAddressRangeList(
1400			TargetAddressRange(lowPC, highPC - lowPC));
1401		if (rangeList == NULL)
1402			return B_NO_MEMORY;
1403				// TODO: Clean up already added functions!
1404	}
1405	BReference<TargetAddressRangeList> rangeListReference(rangeList,
1406		true);
1407
1408	// get the source location
1409	const char* directoryPath = NULL;
1410	const char* fileName = NULL;
1411	int32 line = -1;
1412	int32 column = -1;
1413	DwarfUtils::GetDeclarationLocation(fFile, subprogramEntry,
1414		directoryPath, fileName, line, column);
1415
1416	LocatableFile* file = NULL;
1417	if (fileName != NULL) {
1418		file = fFileManager->GetSourceFile(directoryPath,
1419			fileName);
1420	}
1421	BReference<LocatableFile> fileReference(file, true);
1422
1423	// create and add the functions
1424	DwarfFunctionDebugInfo* function
1425		= new(std::nothrow) DwarfFunctionDebugInfo(this, unit,
1426			subprogramEntry, rangeList, name, file,
1427			SourceLocation(line, std::max(column, (int32)0)));
1428	if (function == NULL || !functions.AddItem(function)) {
1429		delete function;
1430		return B_NO_MEMORY;
1431			// TODO: Clean up already added functions!
1432	}
1433
1434	return B_OK;
1435}
1436
1437
1438status_t
1439DwarfImageDebugInfo::_BuildTypeNameTable()
1440{
1441	fTypeNameTable = new(std::nothrow) TypeNameTable;
1442	if (fTypeNameTable == NULL)
1443		return B_NO_MEMORY;
1444
1445	status_t error = fTypeNameTable->Init();
1446	if (error != B_OK)
1447		return error;
1448
1449	// iterate through all compilation units
1450	for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i);
1451		i++) {
1452		// iterate through all types of the compilation unit
1453		for (DebugInfoEntryList::ConstIterator it
1454				= unit->UnitEntry()->Types().GetIterator();
1455			DIEType* typeEntry = dynamic_cast<DIEType*>(it.Next());) {
1456
1457			if (_RecursiveAddTypeNames(typeEntry, unit) != B_OK)
1458				return B_NO_MEMORY;
1459		}
1460
1461		for (DebugInfoEntryList::ConstIterator it
1462			= unit->UnitEntry()->OtherChildren().GetIterator();
1463			DebugInfoEntry* child = it.Next();) {
1464			DIENamespace* namespaceEntry = dynamic_cast<DIENamespace*>(child);
1465			if (namespaceEntry == NULL)
1466				continue;
1467
1468			if (_RecursiveTraverseNamespaceForTypes(namespaceEntry, unit)
1469					!= B_OK) {
1470				return B_NO_MEMORY;
1471			}
1472		}
1473	}
1474
1475	return B_OK;
1476}
1477
1478
1479status_t
1480DwarfImageDebugInfo::_RecursiveAddTypeNames(DIEType* type, CompilationUnit* unit)
1481{
1482	if (type->IsDeclaration())
1483		return B_OK;
1484
1485	BString typeEntryName;
1486	DwarfUtils::GetFullyQualifiedDIEName(type, typeEntryName);
1487
1488	status_t error = B_OK;
1489	TypeNameEntry* entry = fTypeNameTable->Lookup(typeEntryName);
1490	if (entry == NULL) {
1491		entry = new(std::nothrow) TypeNameEntry(typeEntryName);
1492		if (entry == NULL)
1493			return B_NO_MEMORY;
1494
1495		error = fTypeNameTable->Insert(entry);
1496		if (error != B_OK)
1497			return error;
1498	}
1499
1500	TypeEntryInfo* info = new(std::nothrow) TypeEntryInfo(type,	unit);
1501	if (info == NULL)
1502		return B_NO_MEMORY;
1503
1504	if (!entry->types.AddItem(info)) {
1505		delete info;
1506		return B_NO_MEMORY;
1507	}
1508
1509	DIEClassBaseType* classType = dynamic_cast<DIEClassBaseType*>(type);
1510	if (classType == NULL)
1511		return B_OK;
1512
1513	for (DebugInfoEntryList::ConstIterator it
1514			= classType->InnerTypes().GetIterator();
1515		DIEType* innerType = dynamic_cast<DIEType*>(it.Next());) {
1516		error = _RecursiveAddTypeNames(innerType, unit);
1517		if (error != B_OK)
1518			return error;
1519	}
1520
1521	return B_OK;
1522}
1523
1524
1525status_t
1526DwarfImageDebugInfo::_RecursiveTraverseNamespaceForTypes(DIENamespace* nsEntry,
1527	CompilationUnit* unit)
1528{
1529	for (DebugInfoEntryList::ConstIterator it
1530				= nsEntry->Children().GetIterator();
1531			DebugInfoEntry* child = it.Next();) {
1532
1533		if (child->IsType()) {
1534			DIEType* type = dynamic_cast<DIEType*>(child);
1535			if (_RecursiveAddTypeNames(type, unit) != B_OK)
1536				return B_NO_MEMORY;
1537		} else {
1538			DIENamespace* nameSpace = dynamic_cast<DIENamespace*>(child);
1539			if (nameSpace == NULL)
1540				continue;
1541
1542			status_t error = _RecursiveTraverseNamespaceForTypes(nameSpace,
1543				unit);
1544			if (error != B_OK)
1545				return error;
1546			continue;
1547		}
1548	}
1549
1550	return B_OK;
1551}
1552