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