2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2016, Rene Gollent, rene@gollent.com.
4 * Distributed under the terms of the MIT License.
7 #include "Architecture.h"
11 #include <AutoDeleter.h>
12 #include <AutoLocker.h>
14 #include "CfaContext.h"
16 #include "FunctionInstance.h"
18 #include "ImageDebugInfo.h"
19 #include "ImageDebugInfoProvider.h"
21 #include "RegisterMap.h"
22 #include "SpecificImageDebugInfo.h"
23 #include "StackTrace.h"
27 Architecture::Architecture(TeamMemory
* teamMemory
, uint8 addressSize
,
28 size_t debugCpuStateSize
, bool bigEndian
)
30 fTeamMemory(teamMemory
),
31 fAddressSize(addressSize
),
32 fDebugCpuStateSize(debugCpuStateSize
),
38 Architecture::~Architecture()
51 Architecture::InitRegisterRules(CfaContext
& context
) const
53 // Init the initial register rules. The DWARF 3 specs on the
54 // matter: "The default rule for all columns before
55 // interpretation of the initial instructions is the undefined
56 // rule. However, an ABI authoring body or a compilation system
57 // authoring body may specify an alternate default value for any
59 // GCC's assumes the "same value" rule for all callee preserved
60 // registers. We set them respectively.
61 // the stack pointer is initialized to
62 // CFA offset 0 by default.
63 const Register
* registers
= Registers();
64 RegisterMap
* toDwarf
= NULL
;
65 status_t result
= GetDwarfRegisterMaps(&toDwarf
, NULL
);
69 BReference
<RegisterMap
> toDwarfMapReference(toDwarf
, true);
70 for (int32 i
= 0; i
< CountRegisters(); i
++) {
71 int32 dwarfReg
= toDwarf
->MapRegisterIndex(i
);
72 if (dwarfReg
< 0 || dwarfReg
> CountRegisters() - 1)
75 // TODO: on CPUs that have a return address register
76 // a default rule should be set up to use that to
77 // extract the instruction pointer
78 switch (registers
[i
].Type()) {
79 case REGISTER_TYPE_STACK_POINTER
:
81 context
.RegisterRule(dwarfReg
)->SetToValueOffset(0);
86 context
.RegisterRule(dwarfReg
)->SetToSameValue();
97 Architecture::CreateStackTrace(Team
* team
,
98 ImageDebugInfoProvider
* imageInfoProvider
, CpuState
* cpuState
,
99 StackTrace
*& _stackTrace
, ReturnValueInfoList
* returnValueInfos
,
100 int32 maxStackDepth
, bool useExistingTrace
, bool getFullFrameInfo
)
102 BReference
<CpuState
> cpuStateReference(cpuState
);
104 StackTrace
* stackTrace
= NULL
;
105 ObjectDeleter
<StackTrace
> stackTraceDeleter
;
106 StackFrame
* nextFrame
= NULL
;
108 if (useExistingTrace
)
109 stackTrace
= _stackTrace
;
112 stackTrace
= new(std::nothrow
) StackTrace
;
113 if (stackTrace
== NULL
)
115 stackTraceDeleter
.SetTo(stackTrace
);
118 // if we're passed an already existing partial stack trace,
119 // attempt to continue building it from where it left off.
120 if (stackTrace
->CountFrames() > 0) {
121 nextFrame
= stackTrace
->FrameAt(stackTrace
->CountFrames() - 1);
122 cpuState
= nextFrame
->PreviousCpuState();
125 while (cpuState
!= NULL
) {
126 // get the instruction pointer
127 target_addr_t instructionPointer
= cpuState
->InstructionPointer();
129 // get the image for the instruction pointer
130 AutoLocker
<Team
> teamLocker(team
);
131 Image
* image
= team
->ImageByAddress(instructionPointer
);
132 BReference
<Image
> imageReference(image
);
135 // get the image debug info
136 ImageDebugInfo
* imageDebugInfo
= NULL
;
138 imageInfoProvider
->GetImageDebugInfo(image
, imageDebugInfo
);
139 BReference
<ImageDebugInfo
> imageDebugInfoReference(imageDebugInfo
,
144 FunctionInstance
* function
= NULL
;
145 FunctionDebugInfo
* functionDebugInfo
= NULL
;
146 if (imageDebugInfo
!= NULL
) {
147 function
= imageDebugInfo
->FunctionAtAddress(instructionPointer
);
148 if (function
!= NULL
)
149 functionDebugInfo
= function
->GetFunctionDebugInfo();
151 BReference
<FunctionInstance
> functionReference(function
);
154 // If the CPU state's instruction pointer is actually the return address
155 // of the next frame, we let the architecture fix that.
156 if (nextFrame
!= NULL
157 && nextFrame
->ReturnAddress() == cpuState
->InstructionPointer()) {
158 UpdateStackFrameCpuState(nextFrame
, image
,
159 functionDebugInfo
, cpuState
);
162 // create the frame using the debug info
163 StackFrame
* frame
= NULL
;
164 CpuState
* previousCpuState
= NULL
;
165 if (function
!= NULL
) {
166 status_t error
= functionDebugInfo
->GetSpecificImageDebugInfo()
167 ->CreateFrame(image
, function
, cpuState
, getFullFrameInfo
,
169 ? returnValueInfos
: NULL
, frame
,
171 if (error
!= B_OK
&& error
!= B_UNSUPPORTED
)
175 // If we have no frame yet, let the architecture create it.
177 status_t error
= CreateStackFrame(image
, functionDebugInfo
,
178 cpuState
, nextFrame
== NULL
, frame
, previousCpuState
);
183 cpuStateReference
.SetTo(previousCpuState
, true);
185 frame
->SetImage(image
);
186 frame
->SetFunction(function
);
188 if (!stackTrace
->AddFrame(frame
)) {
194 cpuState
= previousCpuState
;
195 if (--maxStackDepth
== 0)
199 if (stackTrace
->CountFrames() == 0)
202 stackTraceDeleter
.Detach();
203 _stackTrace
= stackTrace
;