vfs: check userland buffers before reading them.
[haiku.git] / src / kits / debugger / arch / Architecture.cpp
blobdf7b2d51aca6ad4059cd65b30d28ba3e1f56e5f6
1 /*
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.
5 */
7 #include "Architecture.h"
9 #include <new>
11 #include <AutoDeleter.h>
12 #include <AutoLocker.h>
14 #include "CfaContext.h"
15 #include "CpuState.h"
16 #include "FunctionInstance.h"
17 #include "Image.h"
18 #include "ImageDebugInfo.h"
19 #include "ImageDebugInfoProvider.h"
20 #include "Register.h"
21 #include "RegisterMap.h"
22 #include "SpecificImageDebugInfo.h"
23 #include "StackTrace.h"
24 #include "Team.h"
27 Architecture::Architecture(TeamMemory* teamMemory, uint8 addressSize,
28 size_t debugCpuStateSize, bool bigEndian)
30 fTeamMemory(teamMemory),
31 fAddressSize(addressSize),
32 fDebugCpuStateSize(debugCpuStateSize),
33 fBigEndian(bigEndian)
38 Architecture::~Architecture()
43 status_t
44 Architecture::Init()
46 return B_OK;
50 status_t
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
58 // or all columns."
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);
66 if (result != B_OK)
67 return result;
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)
73 continue;
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);
82 break;
84 default:
86 context.RegisterRule(dwarfReg)->SetToSameValue();
87 break;
92 return result;
96 status_t
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;
110 else {
111 // create the object
112 stackTrace = new(std::nothrow) StackTrace;
113 if (stackTrace == NULL)
114 return B_NO_MEMORY;
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);
133 teamLocker.Unlock();
135 // get the image debug info
136 ImageDebugInfo* imageDebugInfo = NULL;
137 if (image != NULL)
138 imageInfoProvider->GetImageDebugInfo(image, imageDebugInfo);
139 BReference<ImageDebugInfo> imageDebugInfoReference(imageDebugInfo,
140 true);
142 // get the function
143 teamLocker.Lock();
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);
152 teamLocker.Unlock();
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,
168 nextFrame == NULL
169 ? returnValueInfos : NULL, frame,
170 previousCpuState);
171 if (error != B_OK && error != B_UNSUPPORTED)
172 break;
175 // If we have no frame yet, let the architecture create it.
176 if (frame == NULL) {
177 status_t error = CreateStackFrame(image, functionDebugInfo,
178 cpuState, nextFrame == NULL, frame, previousCpuState);
179 if (error != B_OK)
180 break;
183 cpuStateReference.SetTo(previousCpuState, true);
185 frame->SetImage(image);
186 frame->SetFunction(function);
188 if (!stackTrace->AddFrame(frame)) {
189 delete frame;
190 return B_NO_MEMORY;
193 nextFrame = frame;
194 cpuState = previousCpuState;
195 if (--maxStackDepth == 0)
196 break;
199 if (stackTrace->CountFrames() == 0)
200 return B_ERROR;
202 stackTraceDeleter.Detach();
203 _stackTrace = stackTrace;
204 return B_OK;