2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
6 #include "Architecture.h"
10 #include <AutoDeleter.h>
11 #include <AutoLocker.h>
13 #include "CfaContext.h"
15 #include "FunctionInstance.h"
17 #include "ImageDebugInfo.h"
18 #include "ImageDebugInfoProvider.h"
20 #include "RegisterMap.h"
21 #include "SpecificImageDebugInfo.h"
22 #include "StackTrace.h"
26 Architecture::Architecture(TeamMemory
* teamMemory
, uint8 addressSize
,
29 fTeamMemory(teamMemory
),
30 fAddressSize(addressSize
),
36 Architecture::~Architecture()
49 Architecture::InitRegisterRules(CfaContext
& context
) const
51 // Init the initial register rules. The DWARF 3 specs on the
52 // matter: "The default rule for all columns before
53 // interpretation of the initial instructions is the undefined
54 // rule. However, an ABI authoring body or a compilation system
55 // authoring body may specify an alternate default value for any
57 // GCC's assumes the "same value" rule for all callee preserved
58 // registers. We set them respectively.
59 // the stack pointer is initialized to
60 // CFA offset 0 by default.
61 const Register
* registers
= Registers();
62 RegisterMap
* toDwarf
= NULL
;
63 status_t result
= GetDwarfRegisterMaps(&toDwarf
, NULL
);
67 BReference
<RegisterMap
> toDwarfMapReference(toDwarf
, true);
68 for (int32 i
= 0; i
< CountRegisters(); i
++) {
69 int32 dwarfReg
= toDwarf
->MapRegisterIndex(i
);
70 if (dwarfReg
< 0 || dwarfReg
> CountRegisters() - 1)
73 // TODO: on CPUs that have a return address register
74 // a default rule should be set up to use that to
75 // extract the instruction pointer
76 switch (registers
[i
].Type()) {
77 case REGISTER_TYPE_STACK_POINTER
:
79 context
.RegisterRule(dwarfReg
)->SetToValueOffset(0);
84 context
.RegisterRule(dwarfReg
)->SetToSameValue();
95 Architecture::CreateStackTrace(Team
* team
,
96 ImageDebugInfoProvider
* imageInfoProvider
, CpuState
* cpuState
,
97 StackTrace
*& _stackTrace
, ReturnValueInfoList
* returnValueInfos
,
98 int32 maxStackDepth
, bool useExistingTrace
, bool getFullFrameInfo
)
100 BReference
<CpuState
> cpuStateReference(cpuState
);
102 StackTrace
* stackTrace
= NULL
;
103 ObjectDeleter
<StackTrace
> stackTraceDeleter
;
104 StackFrame
* nextFrame
= NULL
;
106 if (useExistingTrace
)
107 stackTrace
= _stackTrace
;
110 stackTrace
= new(std::nothrow
) StackTrace
;
111 if (stackTrace
== NULL
)
113 stackTraceDeleter
.SetTo(stackTrace
);
116 // if we're passed an already existing partial stack trace,
117 // attempt to continue building it from where it left off.
118 if (stackTrace
->CountFrames() > 0) {
119 nextFrame
= stackTrace
->FrameAt(stackTrace
->CountFrames() - 1);
120 cpuState
= nextFrame
->PreviousCpuState();
123 while (cpuState
!= NULL
) {
124 // get the instruction pointer
125 target_addr_t instructionPointer
= cpuState
->InstructionPointer();
127 // get the image for the instruction pointer
128 AutoLocker
<Team
> teamLocker(team
);
129 Image
* image
= team
->ImageByAddress(instructionPointer
);
130 BReference
<Image
> imageReference(image
);
133 // get the image debug info
134 ImageDebugInfo
* imageDebugInfo
= NULL
;
136 imageInfoProvider
->GetImageDebugInfo(image
, imageDebugInfo
);
137 BReference
<ImageDebugInfo
> imageDebugInfoReference(imageDebugInfo
,
142 FunctionInstance
* function
= NULL
;
143 FunctionDebugInfo
* functionDebugInfo
= NULL
;
144 if (imageDebugInfo
!= NULL
) {
145 function
= imageDebugInfo
->FunctionAtAddress(instructionPointer
);
146 if (function
!= NULL
)
147 functionDebugInfo
= function
->GetFunctionDebugInfo();
149 BReference
<FunctionInstance
> functionReference(function
);
152 // If the CPU state's instruction pointer is actually the return address
153 // of the next frame, we let the architecture fix that.
154 if (nextFrame
!= NULL
155 && nextFrame
->ReturnAddress() == cpuState
->InstructionPointer()) {
156 UpdateStackFrameCpuState(nextFrame
, image
,
157 functionDebugInfo
, cpuState
);
160 // create the frame using the debug info
161 StackFrame
* frame
= NULL
;
162 CpuState
* previousCpuState
= NULL
;
163 if (function
!= NULL
) {
164 status_t error
= functionDebugInfo
->GetSpecificImageDebugInfo()
165 ->CreateFrame(image
, function
, cpuState
, getFullFrameInfo
,
167 ? returnValueInfos
: NULL
, frame
,
169 if (error
!= B_OK
&& error
!= B_UNSUPPORTED
)
173 // If we have no frame yet, let the architecture create it.
175 status_t error
= CreateStackFrame(image
, functionDebugInfo
,
176 cpuState
, nextFrame
== NULL
, frame
, previousCpuState
);
181 cpuStateReference
.SetTo(previousCpuState
, true);
183 frame
->SetImage(image
);
184 frame
->SetFunction(function
);
186 if (!stackTrace
->AddFrame(frame
)) {
192 cpuState
= previousCpuState
;
193 if (--maxStackDepth
== 0)
197 if (stackTrace
->CountFrames() == 0)
200 stackTraceDeleter
.Detach();
201 _stackTrace
= stackTrace
;