Debugger: Add dedicated functions for global {un}init.
[haiku.git] / src / apps / debugger / arch / Architecture.cpp
blob162002466bc31819b9b1795483114f102f79387c
1 /*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
6 #include "Architecture.h"
8 #include <new>
10 #include <AutoDeleter.h>
11 #include <AutoLocker.h>
13 #include "CfaContext.h"
14 #include "CpuState.h"
15 #include "FunctionInstance.h"
16 #include "Image.h"
17 #include "ImageDebugInfo.h"
18 #include "ImageDebugInfoProvider.h"
19 #include "Register.h"
20 #include "RegisterMap.h"
21 #include "SpecificImageDebugInfo.h"
22 #include "StackTrace.h"
23 #include "Team.h"
26 Architecture::Architecture(TeamMemory* teamMemory, uint8 addressSize,
27 bool bigEndian)
29 fTeamMemory(teamMemory),
30 fAddressSize(addressSize),
31 fBigEndian(bigEndian)
36 Architecture::~Architecture()
41 status_t
42 Architecture::Init()
44 return B_OK;
48 status_t
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
56 // or all columns."
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);
64 if (result != B_OK)
65 return result;
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)
71 continue;
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);
80 break;
82 default:
84 context.RegisterRule(dwarfReg)->SetToSameValue();
85 break;
90 return result;
94 status_t
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;
108 else {
109 // create the object
110 stackTrace = new(std::nothrow) StackTrace;
111 if (stackTrace == NULL)
112 return B_NO_MEMORY;
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);
131 teamLocker.Unlock();
133 // get the image debug info
134 ImageDebugInfo* imageDebugInfo = NULL;
135 if (image != NULL)
136 imageInfoProvider->GetImageDebugInfo(image, imageDebugInfo);
137 BReference<ImageDebugInfo> imageDebugInfoReference(imageDebugInfo,
138 true);
140 // get the function
141 teamLocker.Lock();
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);
150 teamLocker.Unlock();
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,
166 nextFrame == NULL
167 ? returnValueInfos : NULL, frame,
168 previousCpuState);
169 if (error != B_OK && error != B_UNSUPPORTED)
170 break;
173 // If we have no frame yet, let the architecture create it.
174 if (frame == NULL) {
175 status_t error = CreateStackFrame(image, functionDebugInfo,
176 cpuState, nextFrame == NULL, frame, previousCpuState);
177 if (error != B_OK)
178 break;
181 cpuStateReference.SetTo(previousCpuState, true);
183 frame->SetImage(image);
184 frame->SetFunction(function);
186 if (!stackTrace->AddFrame(frame)) {
187 delete frame;
188 return B_NO_MEMORY;
191 nextFrame = frame;
192 cpuState = previousCpuState;
193 if (--maxStackDepth == 0)
194 break;
197 if (stackTrace->CountFrames() == 0)
198 return B_ERROR;
200 stackTraceDeleter.Detach();
201 _stackTrace = stackTrace;
202 return B_OK;