xref: /haiku/src/kits/debugger/debug_info/DwarfImageDebugInfo.cpp (revision 3634f142352af2428aed187781fc9d75075e9140)
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,
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 
756 status_t
757 DwarfImageDebugInfo::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 
853 status_t
854 DwarfImageDebugInfo::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 
948 status_t
949 DwarfImageDebugInfo::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 
982 ssize_t
983 DwarfImageDebugInfo::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 
992 status_t
993 DwarfImageDebugInfo::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 
1013 status_t
1014 DwarfImageDebugInfo::_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 
1072 int32
1073 DwarfImageDebugInfo::_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 
1094 status_t
1095 DwarfImageDebugInfo::_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 
1171 status_t
1172 DwarfImageDebugInfo::_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 
1284 bool
1285 DwarfImageDebugInfo::_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 
1330 status_t
1331 DwarfImageDebugInfo::_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 
1373 status_t
1374 DwarfImageDebugInfo::_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 
1438 status_t
1439 DwarfImageDebugInfo::_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 
1479 status_t
1480 DwarfImageDebugInfo::_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 
1525 status_t
1526 DwarfImageDebugInfo::_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