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