2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2012-2016, Rene Gollent, rene@gollent.com.
4 * Distributed under the terms of the MIT License.
8 #include "DwarfImageDebugInfo.h"
17 #include <AutoDeleter.h>
18 #include <AutoLocker.h>
20 #include "Architecture.h"
21 #include "BasicFunctionDebugInfo.h"
22 #include "CLanguage.h"
23 #include "CompilationUnit.h"
24 #include "CppLanguage.h"
26 #include "DebuggerInterface.h"
27 #include "DebugInfoEntries.h"
28 #include "Demangler.h"
29 #include "DisassembledCode.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"
39 #include "FileManager.h"
40 #include "FileSourceCode.h"
41 #include "FunctionID.h"
42 #include "FunctionInstance.h"
43 #include "GlobalTypeLookup.h"
45 #include "ImageDebugInfo.h"
46 #include "InstructionInfo.h"
47 #include "LocatableFile.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"
57 #include "TeamFunctionSourceInformation.h"
58 #include "TeamMemory.h"
60 #include "TypeLookupConstraints.h"
61 #include "UnsupportedLanguage.h"
63 #include "ValueLocation.h"
69 // #pragma mark - HasTypePredicate
72 template<typename EntryType
>
73 struct HasTypePredicate
{
74 inline bool operator()(EntryType
* entry
) const
76 return entry
->GetType() != NULL
;
83 // #pragma mark - BasicTargetInterface
86 struct DwarfImageDebugInfo::BasicTargetInterface
: DwarfTargetInterface
{
87 BasicTargetInterface(const Register
* registers
, int32 registerCount
,
88 RegisterMap
* fromDwarfMap
, Architecture
* architecture
,
89 TeamMemory
* teamMemory
)
91 fRegisters(registers
),
92 fRegisterCount(registerCount
),
93 fFromDwarfMap(fromDwarfMap
),
94 fArchitecture(architecture
),
95 fTeamMemory(teamMemory
)
97 fFromDwarfMap
->AcquireReference();
100 ~BasicTargetInterface()
102 fFromDwarfMap
->ReleaseReference();
105 virtual uint32
CountRegisters() const
107 return fRegisterCount
;
110 virtual uint32
RegisterValueType(uint32 index
) const
112 const Register
* reg
= _RegisterAt(index
);
113 return reg
!= NULL
? reg
->ValueType() : 0;
116 virtual bool GetRegisterValue(uint32 index
, BVariant
& _value
) const
121 virtual bool SetRegisterValue(uint32 index
, const BVariant
& value
)
126 virtual bool IsCalleePreservedRegister(uint32 index
) const
128 const Register
* reg
= _RegisterAt(index
);
129 return reg
!= NULL
&& reg
->IsCalleePreserved();
132 virtual status_t
InitRegisterRules(CfaContext
& context
) const
134 return fArchitecture
->InitRegisterRules(context
);
137 virtual bool ReadMemory(target_addr_t address
, void* buffer
,
140 ssize_t bytesRead
= fTeamMemory
->ReadMemory(address
, buffer
, size
);
141 return bytesRead
>= 0 && (size_t)bytesRead
== size
;
144 virtual bool ReadValueFromMemory(target_addr_t address
,
145 uint32 valueType
, BVariant
& _value
) const
147 return fArchitecture
->ReadValueFromMemory(address
, valueType
, _value
)
151 virtual bool ReadValueFromMemory(target_addr_t addressSpace
,
152 target_addr_t address
, uint32 valueType
, BVariant
& _value
) const
154 return fArchitecture
->ReadValueFromMemory(addressSpace
, address
,
155 valueType
, _value
) == B_OK
;
159 const Register
* _RegisterAt(uint32 dwarfIndex
) const
161 int32 index
= fFromDwarfMap
->MapRegisterIndex(dwarfIndex
);
162 return index
>= 0 && index
< fRegisterCount
? fRegisters
+ index
: NULL
;
166 const Register
* fRegisters
;
167 int32 fRegisterCount
;
168 RegisterMap
* fFromDwarfMap
;
169 Architecture
* fArchitecture
;
170 TeamMemory
* fTeamMemory
;
174 // #pragma mark - UnwindTargetInterface
177 struct DwarfImageDebugInfo::UnwindTargetInterface
: BasicTargetInterface
{
178 UnwindTargetInterface(const Register
* registers
, int32 registerCount
,
179 RegisterMap
* fromDwarfMap
, RegisterMap
* toDwarfMap
, CpuState
* cpuState
,
180 Architecture
* architecture
, TeamMemory
* teamMemory
)
182 BasicTargetInterface(registers
, registerCount
, fromDwarfMap
,
183 architecture
, teamMemory
),
184 fToDwarfMap(toDwarfMap
),
187 fToDwarfMap
->AcquireReference();
188 fCpuState
->AcquireReference();
191 ~UnwindTargetInterface()
193 fToDwarfMap
->ReleaseReference();
194 fCpuState
->ReleaseReference();
197 virtual bool GetRegisterValue(uint32 index
, BVariant
& _value
) const
199 const Register
* reg
= _RegisterAt(index
);
202 return fCpuState
->GetRegisterValue(reg
, _value
);
205 virtual bool SetRegisterValue(uint32 index
, const BVariant
& value
)
207 const Register
* reg
= _RegisterAt(index
);
210 return fCpuState
->SetRegisterValue(reg
, value
);
214 RegisterMap
* fToDwarfMap
;
219 // #pragma mark - EntryListWrapper
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.
225 struct DwarfImageDebugInfo::EntryListWrapper
{
226 const DebugInfoEntryList
& list
;
228 EntryListWrapper(const DebugInfoEntryList
& list
)
236 // #pragma mark - DwarfImageDebugInfo::TypeNameKey
239 struct DwarfImageDebugInfo::TypeNameKey
{
242 TypeNameKey(const BString
& typeName
)
248 uint32
HashValue() const
250 return StringUtils::HashValue(typeName
);
253 bool operator==(const TypeNameKey
& other
) const
255 return typeName
== other
.typeName
;
260 // #pragma mark - DwarfImageDebugInfo::TypeNameEntry
263 struct DwarfImageDebugInfo::TypeNameEntry
: TypeNameKey
{
267 TypeNameEntry(const BString
& name
)
281 // #pragma mark - DwarfImageDebugInfo::TypeNameEntryHashDefinition
284 struct DwarfImageDebugInfo::TypeNameEntryHashDefinition
{
285 typedef TypeNameKey KeyType
;
286 typedef TypeNameEntry ValueType
;
288 size_t HashKey(const TypeNameKey
& key
) const
290 return key
.HashValue();
293 size_t Hash(const TypeNameEntry
* value
) const
295 return value
->HashValue();
298 bool Compare(const TypeNameKey
& key
,
299 const TypeNameEntry
* value
) const
301 return key
== *value
;
304 TypeNameEntry
*& GetLink(TypeNameEntry
* value
) const
311 // #pragma mark - DwarfImageDebugInfo::TypeEntryInfo
314 struct DwarfImageDebugInfo::TypeEntryInfo
{
316 CompilationUnit
* unit
;
318 TypeEntryInfo(DIEType
* type
, CompilationUnit
* unit
)
327 // #pragma mark - DwarfImageDebugInfo
330 DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo
& imageInfo
,
331 DebuggerInterface
* interface
, Architecture
* architecture
,
332 FileManager
* fileManager
, GlobalTypeLookup
* typeLookup
,
333 GlobalTypeCache
* typeCache
, TeamFunctionSourceInformation
* sourceInfo
,
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
),
348 fTextSectionStart(0),
353 fDebuggerInterface
->AcquireReference();
354 fFile
->AcquireReference();
355 fTypeCache
->AcquireReference();
359 DwarfImageDebugInfo::~DwarfImageDebugInfo()
361 fDebuggerInterface
->ReleaseReference();
362 fFile
->ReleaseReference();
363 fTypeCache
->ReleaseReference();
365 TypeNameEntry
* entry
= fTypeNameTable
->Clear(true);
366 while (entry
!= NULL
) {
367 TypeNameEntry
* next
= entry
->next
;
371 delete fTypeNameTable
;
376 DwarfImageDebugInfo::Init()
378 status_t error
= fLock
.InitCheck();
382 fTextSegment
= fFile
->GetElfFile()->TextSegment();
383 if (fTextSegment
== NULL
)
384 return B_ENTRY_NOT_FOUND
;
386 fRelocationDelta
= fImageInfo
.TextBase() - fTextSegment
->LoadAddress();
388 ElfSection
* section
= fFile
->GetElfFile()->FindSection(".text");
389 if (section
!= NULL
) {
390 fTextSectionStart
= section
->LoadAddress() + fRelocationDelta
;
391 fTextSectionEnd
= fTextSectionStart
+ section
->Size();
394 section
= fFile
->GetElfFile()->FindSection(".plt");
395 if (section
!= NULL
) {
396 fPLTSectionStart
= section
->LoadAddress() + fRelocationDelta
;
397 fPLTSectionEnd
= fPLTSectionStart
+ section
->Size();
400 return _BuildTypeNameTable();
405 DwarfImageDebugInfo::GetFunctions(const BObjectList
<SymbolInfo
>& symbols
,
406 BObjectList
<FunctionDebugInfo
>& functions
)
408 TRACE_IMAGES("DwarfImageDebugInfo::GetFunctions()\n");
409 TRACE_IMAGES(" %" B_PRId32
" compilation units\n",
410 fFile
->CountCompilationUnits());
412 for (int32 i
= 0; CompilationUnit
* unit
= fFile
->CompilationUnitAt(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());
425 // printf(" %#llx - %#llx\n", (target_addr_t)unitEntry->LowPC(),
426 // (target_addr_t)unitEntry->HighPC());
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
)
436 DIESubprogram
* subprogramEntry
= static_cast<DIESubprogram
*>(entry
);
438 // ignore declarations and inlined functions
439 if (subprogramEntry
->IsDeclaration()
440 || subprogramEntry
->Inline() == DW_INL_inlined
441 || subprogramEntry
->Inline() == DW_INL_declared_inlined
) {
447 DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry
, name
);
448 if (name
.Length() == 0)
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();
460 rangeList
= new(std::nothrow
) TargetAddressRangeList(
461 TargetAddressRange(lowPC
, highPC
- lowPC
));
462 if (rangeList
== NULL
)
464 // TODO: Clean up already added functions!
466 BReference
<TargetAddressRangeList
> rangeListReference(rangeList
,
469 // get the source location
470 const char* directoryPath
= NULL
;
471 const char* fileName
= NULL
;
474 DwarfUtils::GetDeclarationLocation(fFile
, subprogramEntry
,
475 directoryPath
, fileName
, line
, column
);
477 LocatableFile
* file
= NULL
;
478 if (fileName
!= NULL
) {
479 file
= fFileManager
->GetSourceFile(directoryPath
,
482 BReference
<LocatableFile
> fileReference(file
, true);
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
)) {
492 // TODO: Clean up already added functions!
496 // DwarfUtils::GetFullyQualifiedDIEName(subprogramEntry, name);
497 // printf(" subprogram entry: %p, name: %s, declaration: %d\n",
498 // subprogramEntry, name.String(),
499 // subprogramEntry->IsDeclaration());
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());
509 // printf(" %#llx - %#llx\n",
510 // (target_addr_t)subprogramEntry->LowPC(),
511 // (target_addr_t)subprogramEntry->HighPC());
516 if (fFile
->CountCompilationUnits() != 0)
519 // if we had no compilation units, fall back to providing basic
520 // debug infos with DWARF-supported call frame unwinding,
522 if (fFile
->HasFrameInformation()) {
523 return SpecificImageDebugInfo::GetFunctionsFromSymbols(symbols
,
524 functions
, fDebuggerInterface
, fImageInfo
, this);
532 DwarfImageDebugInfo::GetType(GlobalTypeCache
* cache
, const BString
& name
,
533 const TypeLookupConstraints
& constraints
, Type
*& _type
)
535 TypeNameEntry
* entry
= fTypeNameTable
->Lookup(name
);
537 return B_ENTRY_NOT_FOUND
;
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()) {
547 if (!_EvaluateBaseTypeConstraints(typeEntry
, constraints
))
551 if (constraints
.HasSubtypeKind()
552 && dwarf_tag_to_subtype_kind(typeEntry
->Tag())
553 != constraints
.SubtypeKind()) {
557 DwarfTypeContext
* typeContext
= new(std::nothrow
)
558 DwarfTypeContext(fArchitecture
, fImageInfo
.ImageID(), fFile
,
559 info
->unit
, NULL
, 0, 0, fRelocationDelta
, NULL
, NULL
);
560 if (typeContext
== NULL
)
562 BReference
<DwarfTypeContext
> typeContextReference(typeContext
, true);
566 DwarfTypeFactory
typeFactory(typeContext
, fTypeLookup
, cache
);
567 status_t error
= typeFactory
.CreateType(typeEntry
, type
);
575 return B_ENTRY_NOT_FOUND
;
580 DwarfImageDebugInfo::HasType(const BString
& name
,
581 const TypeLookupConstraints
& constraints
) const
583 TypeNameEntry
* entry
= fTypeNameTable
->Lookup(name
);
587 for (int32 i
= 0; TypeEntryInfo
* info
= entry
->types
.ItemAt(i
); i
++) {
588 DIEType
* typeEntry
= info
->type
;
589 if (constraints
.HasTypeKind()) {
590 if (dwarf_tag_to_type_kind(typeEntry
->Tag())
591 != constraints
.TypeKind()) {
595 if (!_EvaluateBaseTypeConstraints(typeEntry
, constraints
))
599 if (constraints
.HasSubtypeKind()
600 && dwarf_tag_to_subtype_kind(typeEntry
->Tag())
601 != constraints
.SubtypeKind()) {
613 DwarfImageDebugInfo::GetAddressSectionType(target_addr_t address
)
615 if (address
>= fTextSectionStart
&& address
< fTextSectionEnd
)
616 return ADDRESS_SECTION_TYPE_FUNCTION
;
618 if (address
>= fPLTSectionStart
&& address
< fPLTSectionEnd
)
619 return ADDRESS_SECTION_TYPE_PLT
;
621 return ADDRESS_SECTION_TYPE_UNKNOWN
;
626 DwarfImageDebugInfo::CreateFrame(Image
* image
,
627 FunctionInstance
* functionInstance
, CpuState
* cpuState
,
628 bool getFullFrameInfo
, ReturnValueInfoList
* returnValueInfos
,
629 StackFrame
*& _frame
, CpuState
*& _previousCpuState
)
631 DwarfFunctionDebugInfo
* function
= dynamic_cast<DwarfFunctionDebugInfo
*>(
632 functionInstance
->GetFunctionDebugInfo());
634 FunctionID
* functionID
= functionInstance
->GetFunctionID();
635 BReference
<FunctionID
> functionIDReference
;
636 if (functionID
!= NULL
)
637 functionIDReference
.SetTo(functionID
, true);
639 DIESubprogram
* entry
= function
!= NULL
640 ? function
->SubprogramEntry() : NULL
;
642 TRACE_CFI("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p, "
643 "function: %s\n", entry
,
644 functionID
->FunctionName().String());
646 int32 registerCount
= fArchitecture
->CountRegisters();
647 const Register
* registers
= fArchitecture
->Registers();
649 // get the DWARF <-> architecture register maps
650 RegisterMap
* toDwarfMap
;
651 RegisterMap
* fromDwarfMap
;
652 status_t error
= fArchitecture
->GetDwarfRegisterMaps(&toDwarfMap
,
656 BReference
<RegisterMap
> toDwarfMapReference(toDwarfMap
, true);
657 BReference
<RegisterMap
> fromDwarfMapReference(fromDwarfMap
, true);
659 // create a clean CPU state for the previous frame
660 CpuState
* previousCpuState
;
661 error
= fArchitecture
->CreateCpuState(previousCpuState
);
664 BReference
<CpuState
> previousCpuStateReference(previousCpuState
, true);
666 // create the target interfaces
667 UnwindTargetInterface
* inputInterface
668 = new(std::nothrow
) UnwindTargetInterface(registers
, registerCount
,
669 fromDwarfMap
, toDwarfMap
, cpuState
, fArchitecture
,
671 if (inputInterface
== NULL
)
673 BReference
<UnwindTargetInterface
> inputInterfaceReference(inputInterface
,
676 UnwindTargetInterface
* outputInterface
677 = new(std::nothrow
) UnwindTargetInterface(registers
, registerCount
,
678 fromDwarfMap
, toDwarfMap
, previousCpuState
, fArchitecture
,
680 if (outputInterface
== NULL
)
682 BReference
<UnwindTargetInterface
> outputInterfaceReference(outputInterface
,
686 target_addr_t instructionPointer
687 = cpuState
->InstructionPointer() - fRelocationDelta
;
688 target_addr_t framePointer
;
689 CompilationUnit
* unit
= function
!= NULL
? function
->GetCompilationUnit()
691 error
= fFile
->UnwindCallFrame(unit
, fArchitecture
->AddressSize(), entry
,
692 instructionPointer
, inputInterface
, outputInterface
, framePointer
);
695 TRACE_CFI("Failed to unwind call frame: %s\n", strerror(error
));
696 return B_UNSUPPORTED
;
700 TRACE_CFI("unwound registers:\n");
701 for (int32 i
= 0; i
< registerCount
; i
++) {
702 const Register
* reg
= registers
+ i
;
704 if (previousCpuState
->GetRegisterValue(reg
, value
)) {
705 TRACE_CFI(" %3s: %#" B_PRIx64
"\n", reg
->Name(),
708 TRACE_CFI(" %3s: undefined\n", reg
->Name());
712 // create the stack frame debug info
713 DIESubprogram
* subprogramEntry
= function
!= NULL
?
714 function
->SubprogramEntry() : NULL
;
715 DwarfStackFrameDebugInfo
* stackFrameDebugInfo
716 = new(std::nothrow
) DwarfStackFrameDebugInfo(fArchitecture
,
717 fImageInfo
.ImageID(), fFile
, unit
, subprogramEntry
, fTypeLookup
,
718 fTypeCache
, instructionPointer
, framePointer
, fRelocationDelta
,
719 inputInterface
, fromDwarfMap
);
720 if (stackFrameDebugInfo
== NULL
)
722 BReference
<DwarfStackFrameDebugInfo
> stackFrameDebugInfoReference(
723 stackFrameDebugInfo
, true);
725 error
= stackFrameDebugInfo
->Init();
729 // create the stack frame
730 StackFrame
* frame
= new(std::nothrow
) StackFrame(STACK_FRAME_TYPE_STANDARD
,
731 cpuState
, framePointer
, cpuState
->InstructionPointer(),
732 stackFrameDebugInfo
);
735 BReference
<StackFrame
> frameReference(frame
, true);
737 error
= frame
->Init();
741 frame
->SetReturnAddress(previousCpuState
->InstructionPointer());
742 // Note, this is correct, since we actually retrieved the return
743 // address. Our caller will fix the IP for us.
745 // The subprogram entry may not be available since this may be a case
746 // where .eh_frame was used to unwind the stack without other DWARF
747 // info being available.
748 if (subprogramEntry
!= NULL
&& getFullFrameInfo
) {
749 // create function parameter objects
750 for (DebugInfoEntryList::ConstIterator it
751 = subprogramEntry
->Parameters().GetIterator();
752 DebugInfoEntry
* entry
= it
.Next();) {
753 if (entry
->Tag() != DW_TAG_formal_parameter
)
756 BString parameterName
;
757 DwarfUtils::GetDIEName(entry
, parameterName
);
758 if (parameterName
.Length() == 0)
761 DIEFormalParameter
* parameterEntry
762 = dynamic_cast<DIEFormalParameter
*>(entry
);
764 if (stackFrameDebugInfo
->CreateParameter(functionID
,
765 parameterEntry
, parameter
) != B_OK
) {
768 BReference
<Variable
> parameterReference(parameter
, true);
770 if (!frame
->AddParameter(parameter
))
774 // create objects for the local variables
775 _CreateLocalVariables(unit
, frame
, functionID
, *stackFrameDebugInfo
,
776 instructionPointer
, functionInstance
->Address() - fRelocationDelta
,
777 subprogramEntry
->Variables(), subprogramEntry
->Blocks());
779 if (returnValueInfos
!= NULL
&& !returnValueInfos
->IsEmpty()) {
780 _CreateReturnValues(returnValueInfos
, image
, frame
,
781 *stackFrameDebugInfo
);
785 _frame
= frameReference
.Detach();
786 _previousCpuState
= previousCpuStateReference
.Detach();
788 frame
->SetPreviousCpuState(_previousCpuState
);
795 DwarfImageDebugInfo::GetStatement(FunctionDebugInfo
* _function
,
796 target_addr_t address
, Statement
*& _statement
)
798 TRACE_CODE("DwarfImageDebugInfo::GetStatement(function: %p, address: %#"
799 B_PRIx64
")\n", _function
, address
);
801 DwarfFunctionDebugInfo
* function
802 = dynamic_cast<DwarfFunctionDebugInfo
*>(_function
);
803 if (function
== NULL
) {
804 TRACE_LINES(" -> no dwarf function\n");
805 // fall back to assembly
806 return fArchitecture
->GetStatement(function
, address
, _statement
);
809 AutoLocker
<BLocker
> locker(fLock
);
811 // check whether we have the source code
812 CompilationUnit
* unit
= function
->GetCompilationUnit();
813 LocatableFile
* file
= function
->SourceFile();
815 TRACE_CODE(" -> no source file\n");
817 // no source code -- rather return the assembly statement
818 return fArchitecture
->GetStatement(function
, address
, _statement
);
821 SourceCode
* sourceCode
= NULL
;
822 status_t error
= fSourceInfo
->GetActiveSourceCode(_function
, sourceCode
);
823 BReference
<SourceCode
> sourceReference(sourceCode
, true);
824 if (error
!= B_OK
|| dynamic_cast<DisassembledCode
*>(sourceCode
) != NULL
) {
825 // either no source code or disassembly is currently active (i.e.
826 // due to failing to locate the source file on disk or the user
827 // deliberately switching to disassembly view).
828 // return the assembly statement.
829 return fArchitecture
->GetStatement(function
, address
, _statement
);
832 // get the index of the source file in the compilation unit for cheaper
834 int32 fileIndex
= _GetSourceFileIndex(unit
, file
);
836 // Get the statement by executing the line number program for the
838 LineNumberProgram
& program
= unit
->GetLineNumberProgram();
839 if (!program
.IsValid()) {
840 TRACE_CODE(" -> no line number program\n");
845 address
-= fRelocationDelta
;
847 LineNumberProgram::State state
;
848 program
.GetInitialState(state
);
850 target_addr_t statementAddress
= 0;
851 int32 statementLine
= -1;
852 int32 statementColumn
= -1;
853 while (program
.GetNextRow(state
)) {
854 // skip statements of other files
855 if (state
.file
!= fileIndex
)
858 if (statementAddress
!= 0
859 && (state
.isStatement
|| state
.isSequenceEnd
)) {
860 target_addr_t endAddress
= state
.address
;
861 if (address
>= statementAddress
&& address
< endAddress
) {
862 ContiguousStatement
* statement
= new(std::nothrow
)
864 SourceLocation(statementLine
, statementColumn
),
865 TargetAddressRange(fRelocationDelta
+ statementAddress
,
866 endAddress
- statementAddress
));
867 if (statement
== NULL
)
870 _statement
= statement
;
874 statementAddress
= 0;
877 if (state
.isStatement
) {
878 statementAddress
= state
.address
;
879 statementLine
= state
.line
- 1;
880 statementColumn
= std::max(state
.column
- 1, (int32
)0);
884 TRACE_CODE(" -> no line number program match\n");
885 return B_ENTRY_NOT_FOUND
;
890 DwarfImageDebugInfo::GetStatementAtSourceLocation(FunctionDebugInfo
* _function
,
891 const SourceLocation
& sourceLocation
, Statement
*& _statement
)
893 DwarfFunctionDebugInfo
* function
894 = dynamic_cast<DwarfFunctionDebugInfo
*>(_function
);
895 if (function
== NULL
)
898 target_addr_t functionStartAddress
= function
->Address() - fRelocationDelta
;
899 target_addr_t functionEndAddress
= functionStartAddress
+ function
->Size();
901 TRACE_LINES2("DwarfImageDebugInfo::GetStatementAtSourceLocation(%p, "
902 "(%" B_PRId32
", %" B_PRId32
")): function range: %#" B_PRIx64
" - %#"
903 B_PRIx64
"\n", function
, sourceLocation
.Line(), sourceLocation
.Column(),
904 functionStartAddress
, functionEndAddress
);
906 AutoLocker
<BLocker
> locker(fLock
);
908 // get the source file
909 LocatableFile
* file
= function
->SourceFile();
911 return B_ENTRY_NOT_FOUND
;
913 CompilationUnit
* unit
= function
->GetCompilationUnit();
915 // get the index of the source file in the compilation unit for cheaper
917 int32 fileIndex
= _GetSourceFileIndex(unit
, file
);
919 // Get the statement by executing the line number program for the
921 LineNumberProgram
& program
= unit
->GetLineNumberProgram();
922 if (!program
.IsValid())
925 LineNumberProgram::State state
;
926 program
.GetInitialState(state
);
928 target_addr_t statementAddress
= 0;
929 int32 statementLine
= -1;
930 int32 statementColumn
= -1;
931 while (program
.GetNextRow(state
)) {
932 bool isOurFile
= state
.file
== fileIndex
;
934 if (statementAddress
!= 0
935 && (!isOurFile
|| state
.isStatement
|| state
.isSequenceEnd
)) {
936 target_addr_t endAddress
= state
.address
;
938 if (statementAddress
< endAddress
) {
939 TRACE_LINES2(" statement: %#" B_PRIx64
" - %#" B_PRIx64
940 ", location: (%" B_PRId32
", %" B_PRId32
")\n",
941 statementAddress
, endAddress
, statementLine
,
945 if (statementAddress
< endAddress
946 && statementAddress
>= functionStartAddress
947 && statementAddress
< functionEndAddress
948 && statementLine
== (int32
)sourceLocation
.Line()
949 && statementColumn
== (int32
)sourceLocation
.Column()) {
950 TRACE_LINES2(" -> found statement!\n");
952 ContiguousStatement
* statement
= new(std::nothrow
)
954 SourceLocation(statementLine
, statementColumn
),
955 TargetAddressRange(fRelocationDelta
+ statementAddress
,
956 endAddress
- statementAddress
));
957 if (statement
== NULL
)
960 _statement
= statement
;
964 statementAddress
= 0;
967 // skip statements of other files
971 if (state
.isStatement
) {
972 statementAddress
= state
.address
;
973 statementLine
= state
.line
- 1;
974 statementColumn
= std::max(state
.column
- 1, (int32
)0);
978 return B_ENTRY_NOT_FOUND
;
983 DwarfImageDebugInfo::GetSourceLanguage(FunctionDebugInfo
* _function
,
984 SourceLanguage
*& _language
)
986 DwarfFunctionDebugInfo
* function
987 = dynamic_cast<DwarfFunctionDebugInfo
*>(_function
);
988 if (function
== NULL
)
991 SourceLanguage
* language
;
992 CompilationUnit
* unit
= function
->GetCompilationUnit();
993 switch (unit
->UnitEntry()->Language()) {
997 language
= new(std::nothrow
) CLanguage
;
999 case DW_LANG_C_plus_plus
:
1000 language
= new(std::nothrow
) CppLanguage
;
1004 language
= new(std::nothrow
) UnsupportedLanguage
;
1008 if (language
== NULL
)
1011 _language
= language
;
1017 DwarfImageDebugInfo::ReadCode(target_addr_t address
, void* buffer
, size_t size
)
1019 target_addr_t offset
= address
- fRelocationDelta
1020 - fTextSegment
->LoadAddress() + fTextSegment
->FileOffset();
1021 ssize_t bytesRead
= pread(fFile
->GetElfFile()->FD(), buffer
, size
, offset
);
1022 return bytesRead
>= 0 ? bytesRead
: errno
;
1027 DwarfImageDebugInfo::AddSourceCodeInfo(LocatableFile
* file
,
1028 FileSourceCode
* sourceCode
)
1030 bool addedAny
= false;
1031 for (int32 i
= 0; CompilationUnit
* unit
= fFile
->CompilationUnitAt(i
);
1033 int32 fileIndex
= _GetSourceFileIndex(unit
, file
);
1037 status_t error
= _AddSourceCodeInfo(unit
, sourceCode
, fileIndex
);
1038 if (error
== B_NO_MEMORY
)
1040 addedAny
|= error
== B_OK
;
1043 return addedAny
? B_OK
: B_ENTRY_NOT_FOUND
;
1048 DwarfImageDebugInfo::_AddSourceCodeInfo(CompilationUnit
* unit
,
1049 FileSourceCode
* sourceCode
, int32 fileIndex
)
1051 // Get the statements by executing the line number program for the
1052 // compilation unit and filtering the rows for our source file.
1053 LineNumberProgram
& program
= unit
->GetLineNumberProgram();
1054 if (!program
.IsValid())
1057 LineNumberProgram::State state
;
1058 program
.GetInitialState(state
);
1060 target_addr_t statementAddress
= 0;
1061 int32 statementLine
= -1;
1062 int32 statementColumn
= -1;
1063 while (program
.GetNextRow(state
)) {
1064 TRACE_LINES2(" %#" B_PRIx64
" (%" B_PRId32
", %" B_PRId32
", %"
1065 B_PRId32
") %d\n", state
.address
, state
.file
, state
.line
,
1066 state
.column
, state
.isStatement
);
1068 bool isOurFile
= state
.file
== fileIndex
;
1070 if (statementAddress
!= 0
1071 && (!isOurFile
|| state
.isStatement
|| state
.isSequenceEnd
)) {
1072 target_addr_t endAddress
= state
.address
;
1073 if (endAddress
> statementAddress
) {
1074 // add the statement
1075 status_t error
= sourceCode
->AddSourceLocation(
1076 SourceLocation(statementLine
, statementColumn
));
1080 TRACE_LINES2(" -> statement: %#" B_PRIx64
" - %#" B_PRIx64
1081 ", source location: (%" B_PRId32
", %" B_PRId32
")\n",
1082 statementAddress
, endAddress
, statementLine
,
1086 statementAddress
= 0;
1089 // skip statements of other files
1093 if (state
.isStatement
) {
1094 statementAddress
= state
.address
;
1095 statementLine
= state
.line
- 1;
1096 statementColumn
= std::max(state
.column
- 1, (int32
)0);
1105 DwarfImageDebugInfo::_GetSourceFileIndex(CompilationUnit
* unit
,
1106 LocatableFile
* sourceFile
) const
1108 // get the index of the source file in the compilation unit for cheaper
1110 const char* directory
;
1111 for (int32 i
= 0; const char* fileName
= unit
->FileAt(i
, &directory
); i
++) {
1112 LocatableFile
* file
= fFileManager
->GetSourceFile(directory
, fileName
);
1114 file
->ReleaseReference();
1115 if (file
== sourceFile
) {
1117 // indices are one-based
1127 DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit
* unit
,
1128 StackFrame
* frame
, FunctionID
* functionID
,
1129 DwarfStackFrameDebugInfo
& factory
, target_addr_t instructionPointer
,
1130 target_addr_t lowPC
, const EntryListWrapper
& variableEntries
,
1131 const EntryListWrapper
& blockEntries
)
1133 TRACE_LOCALS("DwarfImageDebugInfo::_CreateLocalVariables(): ip: %#" B_PRIx64
1134 ", low PC: %#" B_PRIx64
"\n", instructionPointer
, lowPC
);
1136 // iterate through the variables and add the ones in scope
1137 for (DebugInfoEntryList::ConstIterator it
1138 = variableEntries
.list
.GetIterator();
1139 DIEVariable
* variableEntry
= dynamic_cast<DIEVariable
*>(it
.Next());) {
1141 TRACE_LOCALS(" variableEntry %p, scope start: %" B_PRIu64
"\n",
1142 variableEntry
, variableEntry
->StartScope());
1144 // check the variable's scope
1145 if (instructionPointer
< lowPC
+ variableEntry
->StartScope())
1150 if (factory
.CreateLocalVariable(functionID
, variableEntry
, variable
)
1154 BReference
<Variable
> variableReference(variable
, true);
1156 if (!frame
->AddLocalVariable(variable
))
1160 // iterate through the blocks and find the one we're currently in (if any)
1161 for (DebugInfoEntryList::ConstIterator it
= blockEntries
.list
.GetIterator();
1162 DIELexicalBlock
* block
= dynamic_cast<DIELexicalBlock
*>(it
.Next());) {
1164 TRACE_LOCALS(" lexical block: %p\n", block
);
1166 // check whether the block has low/high PC attributes
1167 if (block
->LowPC() != 0) {
1168 TRACE_LOCALS(" has lowPC\n");
1170 // yep, compare with the instruction pointer
1171 if (instructionPointer
< block
->LowPC()
1172 || instructionPointer
>= block
->HighPC()) {
1176 TRACE_LOCALS(" no lowPC\n");
1178 // check the address ranges instead
1179 TargetAddressRangeList
* rangeList
= fFile
->ResolveRangeList(unit
,
1180 block
->AddressRangesOffset());
1181 if (rangeList
== NULL
) {
1182 TRACE_LOCALS(" failed to get ranges\n");
1185 BReference
<TargetAddressRangeList
> rangeListReference(rangeList
,
1188 if (!rangeList
->Contains(instructionPointer
)) {
1189 TRACE_LOCALS(" ranges don't contain IP\n");
1194 // found a block -- recurse
1195 return _CreateLocalVariables(unit
, frame
, functionID
, factory
,
1196 instructionPointer
, lowPC
, block
->Variables(), block
->Blocks());
1204 DwarfImageDebugInfo::_CreateReturnValues(ReturnValueInfoList
* returnValueInfos
,
1205 Image
* image
, StackFrame
* frame
, DwarfStackFrameDebugInfo
& factory
)
1207 for (int32 i
= 0; i
< returnValueInfos
->CountItems(); i
++) {
1208 Image
* targetImage
= image
;
1209 ReturnValueInfo
* valueInfo
= returnValueInfos
->ItemAt(i
);
1210 target_addr_t subroutineAddress
= valueInfo
->SubroutineAddress();
1211 CpuState
* subroutineState
= valueInfo
->State();
1212 if (!targetImage
->ContainsAddress(subroutineAddress
)) {
1213 // our current image doesn't contain the target function,
1214 // locate the one which does.
1215 targetImage
= image
->GetTeam()->ImageByAddress(subroutineAddress
);
1216 if (targetImage
== NULL
) {
1217 // nothing we can do, try the next entry (if any)
1222 status_t result
= B_OK
;
1223 ImageDebugInfo
* imageInfo
= targetImage
->GetImageDebugInfo();
1224 if (imageInfo
== NULL
) {
1225 // the subroutine may have resolved to a different image
1226 // that doesn't have debug information available.
1230 FunctionInstance
* targetFunction
;
1231 if (imageInfo
->GetAddressSectionType(subroutineAddress
)
1232 == ADDRESS_SECTION_TYPE_PLT
) {
1233 result
= fArchitecture
->ResolvePICFunctionAddress(
1234 subroutineAddress
, subroutineState
, subroutineAddress
);
1237 if (!targetImage
->ContainsAddress(subroutineAddress
)) {
1238 // the PLT entry doesn't necessarily point to a function
1239 // in the same image; as such we may need to try to
1240 // resolve the target address again.
1241 targetImage
= image
->GetTeam()->ImageByAddress(
1243 if (targetImage
== NULL
)
1245 imageInfo
= targetImage
->GetImageDebugInfo();
1246 if (imageInfo
== NULL
) {
1247 // As above, since the indirection here may have
1248 // landed us in an entirely different image, there is
1249 // no guarantee that debug info is available,
1250 // depending on which image it was.
1257 targetFunction
= imageInfo
->FunctionAtAddress(subroutineAddress
);
1258 if (targetFunction
!= NULL
) {
1259 DwarfFunctionDebugInfo
* targetInfo
=
1260 dynamic_cast<DwarfFunctionDebugInfo
*>(
1261 targetFunction
->GetFunctionDebugInfo());
1262 if (targetInfo
!= NULL
) {
1263 DIESubprogram
* subProgram
= targetInfo
->SubprogramEntry();
1264 DIEType
* returnType
= subProgram
->ReturnType();
1265 if (returnType
== NULL
) {
1266 // check if we have a specification, and if so, if that has
1268 subProgram
= dynamic_cast<DIESubprogram
*>(
1269 subProgram
->Specification());
1270 if (subProgram
!= NULL
)
1271 returnType
= subProgram
->ReturnType();
1273 // function doesn't return a value, we're done.
1274 if (returnType
== NULL
)
1278 uint32 byteSize
= 0;
1279 if (returnType
->ByteSize() == NULL
) {
1280 if (dynamic_cast<DIEAddressingType
*>(returnType
) != NULL
)
1281 byteSize
= fArchitecture
->AddressSize();
1283 byteSize
= returnType
->ByteSize()->constant
;
1285 // if we were unable to determine a size for the type,
1286 // simply default to the architecture's register width.
1288 byteSize
= fArchitecture
->AddressSize();
1290 ValueLocation
* location
;
1291 result
= fArchitecture
->GetReturnAddressLocation(frame
,
1292 byteSize
, location
);
1296 BReference
<ValueLocation
> locationReference(location
, true);
1297 Variable
* variable
= NULL
;
1298 BReference
<FunctionID
> idReference(
1299 targetFunction
->GetFunctionID(), true);
1300 result
= factory
.CreateReturnValue(idReference
, returnType
,
1301 location
, subroutineState
, variable
);
1305 BReference
<Variable
> variableReference(variable
, true);
1306 if (!frame
->AddLocalVariable(variable
))
1317 DwarfImageDebugInfo::_EvaluateBaseTypeConstraints(DIEType
* type
,
1318 const TypeLookupConstraints
& constraints
) const
1320 if (constraints
.HasBaseTypeName()) {
1321 BString baseEntryName
;
1322 DIEType
* baseTypeOwnerEntry
= NULL
;
1324 switch (constraints
.TypeKind()) {
1327 DIEAddressingType
* addressType
=
1328 dynamic_cast<DIEAddressingType
*>(type
);
1329 if (addressType
!= NULL
) {
1330 baseTypeOwnerEntry
= DwarfUtils::GetDIEByPredicate(
1331 addressType
, HasTypePredicate
<DIEAddressingType
>());
1337 DIEArrayType
* arrayType
=
1338 dynamic_cast<DIEArrayType
*>(type
);
1339 if (arrayType
!= NULL
) {
1340 baseTypeOwnerEntry
= DwarfUtils::GetDIEByPredicate(
1341 arrayType
, HasTypePredicate
<DIEArrayType
>());
1349 if (baseTypeOwnerEntry
!= NULL
) {
1350 DwarfUtils::GetFullyQualifiedDIEName(baseTypeOwnerEntry
,
1353 if (baseEntryName
!= constraints
.BaseTypeName())
1363 DwarfImageDebugInfo::_BuildTypeNameTable()
1365 fTypeNameTable
= new(std::nothrow
) TypeNameTable
;
1366 if (fTypeNameTable
== NULL
)
1369 status_t error
= fTypeNameTable
->Init();
1373 // iterate through all compilation units
1374 for (int32 i
= 0; CompilationUnit
* unit
= fFile
->CompilationUnitAt(i
);
1377 // iterate through all types of the compilation unit
1378 for (DebugInfoEntryList::ConstIterator it
1379 = unit
->UnitEntry()->Types().GetIterator();
1380 DIEType
* typeEntry
= dynamic_cast<DIEType
*>(it
.Next());) {
1381 if (typeEntry
->IsDeclaration())
1384 BString typeEntryName
;
1385 DwarfUtils::GetFullyQualifiedDIEName(typeEntry
, typeEntryName
);
1387 TypeNameEntry
* entry
= fTypeNameTable
->Lookup(typeEntryName
);
1388 if (entry
== NULL
) {
1389 entry
= new(std::nothrow
) TypeNameEntry(typeEntryName
);
1393 error
= fTypeNameTable
->Insert(entry
);
1398 TypeEntryInfo
* info
= new(std::nothrow
) TypeEntryInfo(typeEntry
,
1403 if (!entry
->types
.AddItem(info
)) {