1fce4895dSRene Gollent /*
2fce4895dSRene Gollent * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
39c9c24ceSRene Gollent * Copyright 2011-2016, Rene Gollent, rene@gollent.com.
4fce4895dSRene Gollent * Distributed under the terms of the MIT License.
5fce4895dSRene Gollent */
6fce4895dSRene Gollent
7fce4895dSRene Gollent
8fce4895dSRene Gollent #include "ArchitectureX86.h"
9fce4895dSRene Gollent
10fce4895dSRene Gollent #include <new>
11fce4895dSRene Gollent
12fce4895dSRene Gollent #include <String.h>
13fce4895dSRene Gollent
14fce4895dSRene Gollent #include <AutoDeleter.h>
15fce4895dSRene Gollent
16fce4895dSRene Gollent #include "CfaContext.h"
17fce4895dSRene Gollent #include "CpuStateX86.h"
18fce4895dSRene Gollent #include "DisassembledCode.h"
19fce4895dSRene Gollent #include "FunctionDebugInfo.h"
20fce4895dSRene Gollent #include "InstructionInfo.h"
21fce4895dSRene Gollent #include "NoOpStackFrameDebugInfo.h"
22fce4895dSRene Gollent #include "RegisterMap.h"
23fce4895dSRene Gollent #include "StackFrame.h"
24fce4895dSRene Gollent #include "Statement.h"
25fce4895dSRene Gollent #include "TeamMemory.h"
26fce4895dSRene Gollent #include "ValueLocation.h"
27fce4895dSRene Gollent #include "X86AssemblyLanguage.h"
28fce4895dSRene Gollent
29fce4895dSRene Gollent #include "disasm/DisassemblerX86.h"
30fce4895dSRene Gollent
31fce4895dSRene Gollent
32fce4895dSRene Gollent #define IA32_FEATURE_MMX (1 << 23)
33fce4895dSRene Gollent #define IA32_FEATURE_SSE (1 << 25)
34fce4895dSRene Gollent
35fce4895dSRene Gollent
36fce4895dSRene Gollent static const int32 kFromDwarfRegisters[] = {
37fce4895dSRene Gollent X86_REGISTER_EAX,
38fce4895dSRene Gollent X86_REGISTER_ECX,
39fce4895dSRene Gollent X86_REGISTER_EDX,
40fce4895dSRene Gollent X86_REGISTER_EBX,
41fce4895dSRene Gollent X86_REGISTER_ESP,
42fce4895dSRene Gollent X86_REGISTER_EBP,
43fce4895dSRene Gollent X86_REGISTER_ESI,
44fce4895dSRene Gollent X86_REGISTER_EDI,
45fce4895dSRene Gollent X86_REGISTER_EIP,
46fce4895dSRene Gollent -1, // eflags
47fce4895dSRene Gollent -1, // trap number
48fce4895dSRene Gollent X86_REGISTER_ST0,
49fce4895dSRene Gollent X86_REGISTER_ST1,
50fce4895dSRene Gollent X86_REGISTER_ST2,
51fce4895dSRene Gollent X86_REGISTER_ST3,
52fce4895dSRene Gollent X86_REGISTER_ST4,
53fce4895dSRene Gollent X86_REGISTER_ST5,
54fce4895dSRene Gollent X86_REGISTER_ST6,
55fce4895dSRene Gollent X86_REGISTER_ST7,
56fce4895dSRene Gollent -1, // ?
57fce4895dSRene Gollent -1, // ?
58fce4895dSRene Gollent X86_REGISTER_XMM0,
59fce4895dSRene Gollent X86_REGISTER_XMM1,
60fce4895dSRene Gollent X86_REGISTER_XMM2,
61fce4895dSRene Gollent X86_REGISTER_XMM3,
62fce4895dSRene Gollent X86_REGISTER_XMM4,
63fce4895dSRene Gollent X86_REGISTER_XMM5,
64fce4895dSRene Gollent X86_REGISTER_XMM6,
65fce4895dSRene Gollent X86_REGISTER_XMM7,
66fce4895dSRene Gollent X86_REGISTER_MM0,
67fce4895dSRene Gollent X86_REGISTER_MM1,
68fce4895dSRene Gollent X86_REGISTER_MM2,
69fce4895dSRene Gollent X86_REGISTER_MM3,
70fce4895dSRene Gollent X86_REGISTER_MM4,
71fce4895dSRene Gollent X86_REGISTER_MM5,
72fce4895dSRene Gollent X86_REGISTER_MM6,
73fce4895dSRene Gollent X86_REGISTER_MM7,
74fce4895dSRene Gollent };
75fce4895dSRene Gollent
76fce4895dSRene Gollent static const int32 kFromDwarfRegisterCount = sizeof(kFromDwarfRegisters) / 4;
77fce4895dSRene Gollent
78fce4895dSRene Gollent
79fce4895dSRene Gollent // #pragma mark - ToDwarfRegisterMap
80fce4895dSRene Gollent
81fce4895dSRene Gollent
82fce4895dSRene Gollent struct ArchitectureX86::ToDwarfRegisterMap : RegisterMap {
ToDwarfRegisterMapArchitectureX86::ToDwarfRegisterMap83fce4895dSRene Gollent ToDwarfRegisterMap()
84fce4895dSRene Gollent {
85fce4895dSRene Gollent // init the index array from the reverse map
86fce4895dSRene Gollent memset(fIndices, -1, sizeof(fIndices));
87fce4895dSRene Gollent for (int32 i = 0; i < kFromDwarfRegisterCount; i++) {
88fce4895dSRene Gollent if (kFromDwarfRegisters[i] >= 0)
89fce4895dSRene Gollent fIndices[kFromDwarfRegisters[i]] = i;
90fce4895dSRene Gollent }
91fce4895dSRene Gollent }
92fce4895dSRene Gollent
CountRegistersArchitectureX86::ToDwarfRegisterMap93fce4895dSRene Gollent virtual int32 CountRegisters() const
94fce4895dSRene Gollent {
95fce4895dSRene Gollent return X86_REGISTER_COUNT;
96fce4895dSRene Gollent }
97fce4895dSRene Gollent
MapRegisterIndexArchitectureX86::ToDwarfRegisterMap98fce4895dSRene Gollent virtual int32 MapRegisterIndex(int32 index) const
99fce4895dSRene Gollent {
100fce4895dSRene Gollent return index >= 0 && index < X86_REGISTER_COUNT ? fIndices[index] : -1;
101fce4895dSRene Gollent }
102fce4895dSRene Gollent
103fce4895dSRene Gollent private:
104fce4895dSRene Gollent int32 fIndices[X86_REGISTER_COUNT];
105fce4895dSRene Gollent };
106fce4895dSRene Gollent
107fce4895dSRene Gollent
108fce4895dSRene Gollent // #pragma mark - FromDwarfRegisterMap
109fce4895dSRene Gollent
110fce4895dSRene Gollent
111fce4895dSRene Gollent struct ArchitectureX86::FromDwarfRegisterMap : RegisterMap {
CountRegistersArchitectureX86::FromDwarfRegisterMap112fce4895dSRene Gollent virtual int32 CountRegisters() const
113fce4895dSRene Gollent {
114fce4895dSRene Gollent return kFromDwarfRegisterCount;
115fce4895dSRene Gollent }
116fce4895dSRene Gollent
MapRegisterIndexArchitectureX86::FromDwarfRegisterMap117fce4895dSRene Gollent virtual int32 MapRegisterIndex(int32 index) const
118fce4895dSRene Gollent {
119fce4895dSRene Gollent return index >= 0 && index < kFromDwarfRegisterCount
120fce4895dSRene Gollent ? kFromDwarfRegisters[index] : -1;
121fce4895dSRene Gollent }
122fce4895dSRene Gollent };
123fce4895dSRene Gollent
124fce4895dSRene Gollent
125fce4895dSRene Gollent // #pragma mark - ArchitectureX86
126fce4895dSRene Gollent
127fce4895dSRene Gollent
ArchitectureX86(TeamMemory * teamMemory)128fce4895dSRene Gollent ArchitectureX86::ArchitectureX86(TeamMemory* teamMemory)
129fce4895dSRene Gollent :
1309c9c24ceSRene Gollent Architecture(teamMemory, 4, sizeof(x86_debug_cpu_state), false),
131fce4895dSRene Gollent fFeatureFlags(0),
132fce4895dSRene Gollent fAssemblyLanguage(NULL),
133fce4895dSRene Gollent fToDwarfRegisterMap(NULL),
134fce4895dSRene Gollent fFromDwarfRegisterMap(NULL)
135fce4895dSRene Gollent {
136fce4895dSRene Gollent }
137fce4895dSRene Gollent
138fce4895dSRene Gollent
~ArchitectureX86()139fce4895dSRene Gollent ArchitectureX86::~ArchitectureX86()
140fce4895dSRene Gollent {
141fce4895dSRene Gollent if (fToDwarfRegisterMap != NULL)
142fce4895dSRene Gollent fToDwarfRegisterMap->ReleaseReference();
143fce4895dSRene Gollent if (fFromDwarfRegisterMap != NULL)
144fce4895dSRene Gollent fFromDwarfRegisterMap->ReleaseReference();
145fce4895dSRene Gollent if (fAssemblyLanguage != NULL)
146fce4895dSRene Gollent fAssemblyLanguage->ReleaseReference();
147fce4895dSRene Gollent }
148fce4895dSRene Gollent
149fce4895dSRene Gollent
150fce4895dSRene Gollent status_t
Init()151fce4895dSRene Gollent ArchitectureX86::Init()
152fce4895dSRene Gollent {
153fce4895dSRene Gollent fAssemblyLanguage = new(std::nothrow) X86AssemblyLanguage;
154fce4895dSRene Gollent if (fAssemblyLanguage == NULL)
155fce4895dSRene Gollent return B_NO_MEMORY;
156fce4895dSRene Gollent
157*5ffbe7d7SAugustin Cavalier #if defined(__i386__)
1589c9c24ceSRene Gollent // TODO: this needs to be determined/retrieved indirectly from the
1599c9c24ceSRene Gollent // target host interface, as in the remote case the CPU features may
1609c9c24ceSRene Gollent // differ from those of the local CPU.
161fce4895dSRene Gollent cpuid_info info;
162fce4895dSRene Gollent status_t error = get_cpuid(&info, 1, 0);
163fce4895dSRene Gollent if (error != B_OK)
164fce4895dSRene Gollent return error;
165fce4895dSRene Gollent
166fce4895dSRene Gollent if ((info.eax_1.features & IA32_FEATURE_MMX) != 0)
167fce4895dSRene Gollent fFeatureFlags |= X86_CPU_FEATURE_FLAG_MMX;
168fce4895dSRene Gollent
169fce4895dSRene Gollent if ((info.eax_1.features & IA32_FEATURE_SSE) != 0)
170fce4895dSRene Gollent fFeatureFlags |= X86_CPU_FEATURE_FLAG_SSE;
171fce4895dSRene Gollent
172fce4895dSRene Gollent #endif
173fce4895dSRene Gollent
174fce4895dSRene Gollent try {
175fce4895dSRene Gollent _AddIntegerRegister(X86_REGISTER_EIP, "eip", B_UINT32_TYPE,
176fce4895dSRene Gollent REGISTER_TYPE_INSTRUCTION_POINTER, false);
177fce4895dSRene Gollent _AddIntegerRegister(X86_REGISTER_ESP, "esp", B_UINT32_TYPE,
178fce4895dSRene Gollent REGISTER_TYPE_STACK_POINTER, true);
179fce4895dSRene Gollent _AddIntegerRegister(X86_REGISTER_EBP, "ebp", B_UINT32_TYPE,
180fce4895dSRene Gollent REGISTER_TYPE_GENERAL_PURPOSE, true);
181fce4895dSRene Gollent
182fce4895dSRene Gollent _AddIntegerRegister(X86_REGISTER_EAX, "eax", B_UINT32_TYPE,
183fce4895dSRene Gollent REGISTER_TYPE_GENERAL_PURPOSE, false);
184fce4895dSRene Gollent _AddIntegerRegister(X86_REGISTER_EBX, "ebx", B_UINT32_TYPE,
185fce4895dSRene Gollent REGISTER_TYPE_GENERAL_PURPOSE, true);
186fce4895dSRene Gollent _AddIntegerRegister(X86_REGISTER_ECX, "ecx", B_UINT32_TYPE,
187fce4895dSRene Gollent REGISTER_TYPE_GENERAL_PURPOSE, false);
188fce4895dSRene Gollent _AddIntegerRegister(X86_REGISTER_EDX, "edx", B_UINT32_TYPE,
189fce4895dSRene Gollent REGISTER_TYPE_GENERAL_PURPOSE, false);
190fce4895dSRene Gollent
191fce4895dSRene Gollent _AddIntegerRegister(X86_REGISTER_ESI, "esi", B_UINT32_TYPE,
192fce4895dSRene Gollent REGISTER_TYPE_GENERAL_PURPOSE, true);
193fce4895dSRene Gollent _AddIntegerRegister(X86_REGISTER_EDI, "edi", B_UINT32_TYPE,
194fce4895dSRene Gollent REGISTER_TYPE_GENERAL_PURPOSE, true);
195fce4895dSRene Gollent
196fce4895dSRene Gollent _AddIntegerRegister(X86_REGISTER_CS, "cs", B_UINT16_TYPE,
197fce4895dSRene Gollent REGISTER_TYPE_SPECIAL_PURPOSE, true);
198fce4895dSRene Gollent _AddIntegerRegister(X86_REGISTER_DS, "ds", B_UINT16_TYPE,
199fce4895dSRene Gollent REGISTER_TYPE_SPECIAL_PURPOSE, true);
200fce4895dSRene Gollent _AddIntegerRegister(X86_REGISTER_ES, "es", B_UINT16_TYPE,
201fce4895dSRene Gollent REGISTER_TYPE_SPECIAL_PURPOSE, true);
202fce4895dSRene Gollent _AddIntegerRegister(X86_REGISTER_FS, "fs", B_UINT16_TYPE,
203fce4895dSRene Gollent REGISTER_TYPE_SPECIAL_PURPOSE, true);
204fce4895dSRene Gollent _AddIntegerRegister(X86_REGISTER_GS, "gs", B_UINT16_TYPE,
205fce4895dSRene Gollent REGISTER_TYPE_SPECIAL_PURPOSE, true);
206fce4895dSRene Gollent _AddIntegerRegister(X86_REGISTER_SS, "ss", B_UINT16_TYPE,
207fce4895dSRene Gollent REGISTER_TYPE_SPECIAL_PURPOSE, true);
208fce4895dSRene Gollent
209fce4895dSRene Gollent _AddFPRegister(X86_REGISTER_ST0, "st0");
210fce4895dSRene Gollent _AddFPRegister(X86_REGISTER_ST1, "st1");
211fce4895dSRene Gollent _AddFPRegister(X86_REGISTER_ST2, "st2");
212fce4895dSRene Gollent _AddFPRegister(X86_REGISTER_ST3, "st3");
213fce4895dSRene Gollent _AddFPRegister(X86_REGISTER_ST4, "st4");
214fce4895dSRene Gollent _AddFPRegister(X86_REGISTER_ST5, "st5");
215fce4895dSRene Gollent _AddFPRegister(X86_REGISTER_ST6, "st6");
216fce4895dSRene Gollent _AddFPRegister(X86_REGISTER_ST7, "st7");
217fce4895dSRene Gollent
218fce4895dSRene Gollent if ((fFeatureFlags & X86_CPU_FEATURE_FLAG_MMX) != 0) {
219fce4895dSRene Gollent _AddSIMDRegister(X86_REGISTER_MM0, "mm0", sizeof(uint64));
220fce4895dSRene Gollent _AddSIMDRegister(X86_REGISTER_MM1, "mm1", sizeof(uint64));
221fce4895dSRene Gollent _AddSIMDRegister(X86_REGISTER_MM2, "mm2", sizeof(uint64));
222fce4895dSRene Gollent _AddSIMDRegister(X86_REGISTER_MM3, "mm3", sizeof(uint64));
223fce4895dSRene Gollent _AddSIMDRegister(X86_REGISTER_MM4, "mm4", sizeof(uint64));
224fce4895dSRene Gollent _AddSIMDRegister(X86_REGISTER_MM5, "mm5", sizeof(uint64));
225fce4895dSRene Gollent _AddSIMDRegister(X86_REGISTER_MM6, "mm6", sizeof(uint64));
226fce4895dSRene Gollent _AddSIMDRegister(X86_REGISTER_MM7, "mm7", sizeof(uint64));
227fce4895dSRene Gollent }
228fce4895dSRene Gollent
229fce4895dSRene Gollent if ((fFeatureFlags & X86_CPU_FEATURE_FLAG_SSE) != 0) {
230fce4895dSRene Gollent _AddSIMDRegister(X86_REGISTER_XMM0, "xmm0",
231fce4895dSRene Gollent sizeof(x86_xmm_register));
232fce4895dSRene Gollent _AddSIMDRegister(X86_REGISTER_XMM1, "xmm1",
233fce4895dSRene Gollent sizeof(x86_xmm_register));
234fce4895dSRene Gollent _AddSIMDRegister(X86_REGISTER_XMM2, "xmm2",
235fce4895dSRene Gollent sizeof(x86_xmm_register));
236fce4895dSRene Gollent _AddSIMDRegister(X86_REGISTER_XMM3, "xmm3",
237fce4895dSRene Gollent sizeof(x86_xmm_register));
238fce4895dSRene Gollent _AddSIMDRegister(X86_REGISTER_XMM4, "xmm4",
239fce4895dSRene Gollent sizeof(x86_xmm_register));
240fce4895dSRene Gollent _AddSIMDRegister(X86_REGISTER_XMM5, "xmm5",
241fce4895dSRene Gollent sizeof(x86_xmm_register));
242fce4895dSRene Gollent _AddSIMDRegister(X86_REGISTER_XMM6, "xmm6",
243fce4895dSRene Gollent sizeof(x86_xmm_register));
244fce4895dSRene Gollent _AddSIMDRegister(X86_REGISTER_XMM7, "xmm7",
245fce4895dSRene Gollent sizeof(x86_xmm_register));
246fce4895dSRene Gollent }
247fce4895dSRene Gollent
248b08627f3SMurai Takashi } catch (std::bad_alloc&) {
249fce4895dSRene Gollent return B_NO_MEMORY;
250fce4895dSRene Gollent }
251fce4895dSRene Gollent
252fce4895dSRene Gollent fToDwarfRegisterMap = new(std::nothrow) ToDwarfRegisterMap;
253fce4895dSRene Gollent fFromDwarfRegisterMap = new(std::nothrow) FromDwarfRegisterMap;
254fce4895dSRene Gollent
255fce4895dSRene Gollent if (fToDwarfRegisterMap == NULL || fFromDwarfRegisterMap == NULL)
256fce4895dSRene Gollent return B_NO_MEMORY;
257fce4895dSRene Gollent
258fce4895dSRene Gollent return B_OK;
259fce4895dSRene Gollent }
260fce4895dSRene Gollent
261fce4895dSRene Gollent
262fce4895dSRene Gollent int32
StackGrowthDirection() const263fce4895dSRene Gollent ArchitectureX86::StackGrowthDirection() const
264fce4895dSRene Gollent {
265fce4895dSRene Gollent return STACK_GROWTH_DIRECTION_NEGATIVE;
266fce4895dSRene Gollent }
267fce4895dSRene Gollent
268fce4895dSRene Gollent
269fce4895dSRene Gollent int32
CountRegisters() const270fce4895dSRene Gollent ArchitectureX86::CountRegisters() const
271fce4895dSRene Gollent {
272fce4895dSRene Gollent return fRegisters.Count();
273fce4895dSRene Gollent }
274fce4895dSRene Gollent
275fce4895dSRene Gollent
276fce4895dSRene Gollent const Register*
Registers() const277fce4895dSRene Gollent ArchitectureX86::Registers() const
278fce4895dSRene Gollent {
279fce4895dSRene Gollent return fRegisters.Elements();
280fce4895dSRene Gollent }
281fce4895dSRene Gollent
282fce4895dSRene Gollent
283fce4895dSRene Gollent
284fce4895dSRene Gollent status_t
InitRegisterRules(CfaContext & context) const285fce4895dSRene Gollent ArchitectureX86::InitRegisterRules(CfaContext& context) const
286fce4895dSRene Gollent {
287fce4895dSRene Gollent status_t error = Architecture::InitRegisterRules(context);
288fce4895dSRene Gollent if (error != B_OK)
289fce4895dSRene Gollent return error;
290fce4895dSRene Gollent
291fce4895dSRene Gollent // set up rule for EIP register
292fce4895dSRene Gollent context.RegisterRule(fToDwarfRegisterMap->MapRegisterIndex(
293fce4895dSRene Gollent X86_REGISTER_EIP))->SetToLocationOffset(-4);
294fce4895dSRene Gollent
295fce4895dSRene Gollent return B_OK;
296fce4895dSRene Gollent }
297fce4895dSRene Gollent
298fce4895dSRene Gollent
299fce4895dSRene Gollent status_t
GetDwarfRegisterMaps(RegisterMap ** _toDwarf,RegisterMap ** _fromDwarf) const300fce4895dSRene Gollent ArchitectureX86::GetDwarfRegisterMaps(RegisterMap** _toDwarf,
301fce4895dSRene Gollent RegisterMap** _fromDwarf) const
302fce4895dSRene Gollent {
303fce4895dSRene Gollent if (_toDwarf != NULL) {
304fce4895dSRene Gollent *_toDwarf = fToDwarfRegisterMap;
305fce4895dSRene Gollent fToDwarfRegisterMap->AcquireReference();
306fce4895dSRene Gollent }
307fce4895dSRene Gollent
308fce4895dSRene Gollent if (_fromDwarf != NULL) {
309fce4895dSRene Gollent *_fromDwarf = fFromDwarfRegisterMap;
310fce4895dSRene Gollent fFromDwarfRegisterMap->AcquireReference();
311fce4895dSRene Gollent }
312fce4895dSRene Gollent
313fce4895dSRene Gollent return B_OK;
314fce4895dSRene Gollent }
315fce4895dSRene Gollent
316fce4895dSRene Gollent
317fce4895dSRene Gollent status_t
GetCpuFeatures(uint32 & flags)318fce4895dSRene Gollent ArchitectureX86::GetCpuFeatures(uint32& flags)
319fce4895dSRene Gollent {
320fce4895dSRene Gollent flags = fFeatureFlags;
321fce4895dSRene Gollent
322fce4895dSRene Gollent return B_OK;
323fce4895dSRene Gollent }
324fce4895dSRene Gollent
325fce4895dSRene Gollent
326fce4895dSRene Gollent status_t
CreateCpuState(CpuState * & _state)327fce4895dSRene Gollent ArchitectureX86::CreateCpuState(CpuState*& _state)
328fce4895dSRene Gollent {
329fce4895dSRene Gollent CpuStateX86* state = new(std::nothrow) CpuStateX86;
330fce4895dSRene Gollent if (state == NULL)
331fce4895dSRene Gollent return B_NO_MEMORY;
332fce4895dSRene Gollent
333fce4895dSRene Gollent _state = state;
334fce4895dSRene Gollent return B_OK;
335fce4895dSRene Gollent }
336fce4895dSRene Gollent
337fce4895dSRene Gollent
338fce4895dSRene Gollent status_t
CreateCpuState(const void * cpuStateData,size_t size,CpuState * & _state)339fce4895dSRene Gollent ArchitectureX86::CreateCpuState(const void* cpuStateData, size_t size,
340fce4895dSRene Gollent CpuState*& _state)
341fce4895dSRene Gollent {
342fce4895dSRene Gollent if (size != sizeof(x86_debug_cpu_state))
343fce4895dSRene Gollent return B_BAD_VALUE;
344fce4895dSRene Gollent
345fce4895dSRene Gollent CpuStateX86* state = new(std::nothrow) CpuStateX86(
346fce4895dSRene Gollent *(const x86_debug_cpu_state*)cpuStateData);
347fce4895dSRene Gollent if (state == NULL)
348fce4895dSRene Gollent return B_NO_MEMORY;
349fce4895dSRene Gollent
350fce4895dSRene Gollent _state = state;
351fce4895dSRene Gollent return B_OK;
352fce4895dSRene Gollent }
353fce4895dSRene Gollent
354fce4895dSRene Gollent
355fce4895dSRene Gollent status_t
CreateStackFrame(Image * image,FunctionDebugInfo * function,CpuState * _cpuState,bool isTopFrame,StackFrame * & _frame,CpuState * & _previousCpuState)356fce4895dSRene Gollent ArchitectureX86::CreateStackFrame(Image* image, FunctionDebugInfo* function,
357fce4895dSRene Gollent CpuState* _cpuState, bool isTopFrame, StackFrame*& _frame,
358fce4895dSRene Gollent CpuState*& _previousCpuState)
359fce4895dSRene Gollent {
360fce4895dSRene Gollent CpuStateX86* cpuState = dynamic_cast<CpuStateX86*>(_cpuState);
361fce4895dSRene Gollent
362fce4895dSRene Gollent uint32 framePointer = cpuState->IntRegisterValue(X86_REGISTER_EBP);
363fce4895dSRene Gollent uint32 eip = cpuState->IntRegisterValue(X86_REGISTER_EIP);
364fce4895dSRene Gollent
365fce4895dSRene Gollent bool readStandardFrame = true;
366fce4895dSRene Gollent uint32 previousFramePointer = 0;
367fce4895dSRene Gollent uint32 returnAddress = 0;
368fce4895dSRene Gollent
369fce4895dSRene Gollent // check for syscall frames
370fce4895dSRene Gollent stack_frame_type frameType;
371fce4895dSRene Gollent bool hasPrologue = false;
372fce4895dSRene Gollent if (isTopFrame && cpuState->InterruptVector() == 99) {
373fce4895dSRene Gollent // The thread is performing a syscall. So this frame is not really the
374fce4895dSRene Gollent // top-most frame and we need to adjust the eip.
375fce4895dSRene Gollent frameType = STACK_FRAME_TYPE_SYSCALL;
376fce4895dSRene Gollent eip -= 2;
377fce4895dSRene Gollent // int 99, sysenter, and syscall all are 2 byte instructions
378fce4895dSRene Gollent
379fce4895dSRene Gollent // The syscall stubs are frameless, the return address is on top of the
380fce4895dSRene Gollent // stack.
381fce4895dSRene Gollent uint32 esp = cpuState->IntRegisterValue(X86_REGISTER_ESP);
382fce4895dSRene Gollent uint32 address;
383fce4895dSRene Gollent if (fTeamMemory->ReadMemory(esp, &address, 4) == 4) {
384fce4895dSRene Gollent returnAddress = address;
385fce4895dSRene Gollent previousFramePointer = framePointer;
386fce4895dSRene Gollent framePointer = 0;
387fce4895dSRene Gollent readStandardFrame = false;
388fce4895dSRene Gollent }
389fce4895dSRene Gollent } else {
390fce4895dSRene Gollent hasPrologue = _HasFunctionPrologue(function);
391fce4895dSRene Gollent if (hasPrologue)
392fce4895dSRene Gollent frameType = STACK_FRAME_TYPE_STANDARD;
393fce4895dSRene Gollent else
394fce4895dSRene Gollent frameType = STACK_FRAME_TYPE_FRAMELESS;
395fce4895dSRene Gollent // TODO: Handling for frameless functions. It's not trivial to find the
396fce4895dSRene Gollent // return address on the stack, though.
397fce4895dSRene Gollent
398fce4895dSRene Gollent // If the function is not frameless and we're at the top frame we need
399fce4895dSRene Gollent // to check whether the prologue has not been executed (completely) or
400fce4895dSRene Gollent // we're already after the epilogue.
401fce4895dSRene Gollent if (isTopFrame) {
402fce4895dSRene Gollent uint32 stack = 0;
403fce4895dSRene Gollent if (hasPrologue) {
404fce4895dSRene Gollent if (eip < function->Address() + 3) {
405fce4895dSRene Gollent // The prologue has not been executed yet, i.e. there's no
406fce4895dSRene Gollent // stack frame yet. Get the return address from the stack.
407fce4895dSRene Gollent stack = cpuState->IntRegisterValue(X86_REGISTER_ESP);
408fce4895dSRene Gollent if (eip > function->Address()) {
409fce4895dSRene Gollent // The "push %ebp" has already been executed.
410fce4895dSRene Gollent stack += 4;
411fce4895dSRene Gollent }
412fce4895dSRene Gollent } else {
413fce4895dSRene Gollent // Not in the function prologue, but maybe after the
414fce4895dSRene Gollent // epilogue. The epilogue is a single "pop %ebp", so we
415fce4895dSRene Gollent // check whether the current instruction is already a
416fce4895dSRene Gollent // "ret".
417fce4895dSRene Gollent uint8 code[1];
418fce4895dSRene Gollent if (fTeamMemory->ReadMemory(eip, &code, 1) == 1
419fce4895dSRene Gollent && code[0] == 0xc3) {
420fce4895dSRene Gollent stack = cpuState->IntRegisterValue(X86_REGISTER_ESP);
421fce4895dSRene Gollent }
422fce4895dSRene Gollent }
423fce4895dSRene Gollent } else {
424fce4895dSRene Gollent // Check if the instruction pointer is at a readable location.
425fce4895dSRene Gollent // If it isn't, then chances are we got here via a bogus
426fce4895dSRene Gollent // function pointer, and the prologue hasn't actually been
427fce4895dSRene Gollent // executed. In such a case, what we need is right at the top
428fce4895dSRene Gollent // of the stack.
429fce4895dSRene Gollent uint8 data[1];
430fce4895dSRene Gollent if (fTeamMemory->ReadMemory(eip, &data, 1) != 1)
431fce4895dSRene Gollent stack = cpuState->IntRegisterValue(X86_REGISTER_ESP);
432fce4895dSRene Gollent }
433fce4895dSRene Gollent
434fce4895dSRene Gollent if (stack != 0) {
435fce4895dSRene Gollent uint32 address;
436fce4895dSRene Gollent if (fTeamMemory->ReadMemory(stack, &address, 4) == 4) {
437fce4895dSRene Gollent returnAddress = address;
438fce4895dSRene Gollent previousFramePointer = framePointer;
439fce4895dSRene Gollent framePointer = 0;
440fce4895dSRene Gollent readStandardFrame = false;
441fce4895dSRene Gollent frameType = STACK_FRAME_TYPE_FRAMELESS;
442fce4895dSRene Gollent }
443fce4895dSRene Gollent }
444fce4895dSRene Gollent }
445fce4895dSRene Gollent }
446fce4895dSRene Gollent
447fce4895dSRene Gollent // create the stack frame
448fce4895dSRene Gollent StackFrameDebugInfo* stackFrameDebugInfo
449fce4895dSRene Gollent = new(std::nothrow) NoOpStackFrameDebugInfo;
450fce4895dSRene Gollent if (stackFrameDebugInfo == NULL)
451fce4895dSRene Gollent return B_NO_MEMORY;
452fce4895dSRene Gollent BReference<StackFrameDebugInfo> stackFrameDebugInfoReference(
453fce4895dSRene Gollent stackFrameDebugInfo, true);
454fce4895dSRene Gollent
455fce4895dSRene Gollent StackFrame* frame = new(std::nothrow) StackFrame(frameType, cpuState,
456fce4895dSRene Gollent framePointer, eip, stackFrameDebugInfo);
457fce4895dSRene Gollent if (frame == NULL)
458fce4895dSRene Gollent return B_NO_MEMORY;
459fce4895dSRene Gollent BReference<StackFrame> frameReference(frame, true);
460fce4895dSRene Gollent
461fce4895dSRene Gollent status_t error = frame->Init();
462fce4895dSRene Gollent if (error != B_OK)
463fce4895dSRene Gollent return error;
464fce4895dSRene Gollent
465fce4895dSRene Gollent // read the previous frame and return address, if this is a standard frame
466fce4895dSRene Gollent if (readStandardFrame) {
467fce4895dSRene Gollent uint32 frameData[2];
468fce4895dSRene Gollent if (framePointer != 0
469fce4895dSRene Gollent && fTeamMemory->ReadMemory(framePointer, frameData, 8) == 8) {
470fce4895dSRene Gollent previousFramePointer = frameData[0];
471fce4895dSRene Gollent returnAddress = frameData[1];
472fce4895dSRene Gollent }
473fce4895dSRene Gollent }
474fce4895dSRene Gollent
475fce4895dSRene Gollent // create the CPU state, if we have any info
476fce4895dSRene Gollent CpuStateX86* previousCpuState = NULL;
477fce4895dSRene Gollent if (returnAddress != 0) {
478fce4895dSRene Gollent // prepare the previous CPU state
479fce4895dSRene Gollent previousCpuState = new(std::nothrow) CpuStateX86;
480fce4895dSRene Gollent if (previousCpuState == NULL)
481fce4895dSRene Gollent return B_NO_MEMORY;
482fce4895dSRene Gollent
483fce4895dSRene Gollent previousCpuState->SetIntRegister(X86_REGISTER_EBP,
484fce4895dSRene Gollent previousFramePointer);
485fce4895dSRene Gollent previousCpuState->SetIntRegister(X86_REGISTER_EIP, returnAddress);
486fce4895dSRene Gollent frame->SetPreviousCpuState(previousCpuState);
487fce4895dSRene Gollent }
488fce4895dSRene Gollent
489fce4895dSRene Gollent frame->SetReturnAddress(returnAddress);
490fce4895dSRene Gollent
491fce4895dSRene Gollent _frame = frameReference.Detach();
492fce4895dSRene Gollent _previousCpuState = previousCpuState;
493fce4895dSRene Gollent return B_OK;
494fce4895dSRene Gollent }
495fce4895dSRene Gollent
496fce4895dSRene Gollent
497fce4895dSRene Gollent void
UpdateStackFrameCpuState(const StackFrame * frame,Image * previousImage,FunctionDebugInfo * previousFunction,CpuState * previousCpuState)498fce4895dSRene Gollent ArchitectureX86::UpdateStackFrameCpuState(const StackFrame* frame,
499fce4895dSRene Gollent Image* previousImage, FunctionDebugInfo* previousFunction,
500fce4895dSRene Gollent CpuState* previousCpuState)
501fce4895dSRene Gollent {
502fce4895dSRene Gollent // This is not a top frame, so we want to offset eip to the previous
503fce4895dSRene Gollent // (calling) instruction.
504fce4895dSRene Gollent CpuStateX86* cpuState = dynamic_cast<CpuStateX86*>(previousCpuState);
505fce4895dSRene Gollent
506fce4895dSRene Gollent // get eip
507fce4895dSRene Gollent uint32 eip = cpuState->IntRegisterValue(X86_REGISTER_EIP);
508fce4895dSRene Gollent if (previousFunction == NULL || eip <= previousFunction->Address())
509fce4895dSRene Gollent return;
510fce4895dSRene Gollent target_addr_t functionAddress = previousFunction->Address();
511fce4895dSRene Gollent
512fce4895dSRene Gollent // allocate a buffer for the function code to disassemble
513fce4895dSRene Gollent size_t bufferSize = eip - functionAddress;
514fce4895dSRene Gollent void* buffer = malloc(bufferSize);
515fce4895dSRene Gollent if (buffer == NULL)
516fce4895dSRene Gollent return;
517fce4895dSRene Gollent MemoryDeleter bufferDeleter(buffer);
518fce4895dSRene Gollent
519fce4895dSRene Gollent // read the code
520fce4895dSRene Gollent ssize_t bytesRead = fTeamMemory->ReadMemory(functionAddress, buffer,
521fce4895dSRene Gollent bufferSize);
522fce4895dSRene Gollent if (bytesRead != (ssize_t)bufferSize)
523fce4895dSRene Gollent return;
524fce4895dSRene Gollent
525fce4895dSRene Gollent // disassemble to get the previous instruction
526fce4895dSRene Gollent DisassemblerX86 disassembler;
527fce4895dSRene Gollent target_addr_t instructionAddress;
528fce4895dSRene Gollent target_size_t instructionSize;
529fce4895dSRene Gollent if (disassembler.Init(functionAddress, buffer, bufferSize) == B_OK
530fce4895dSRene Gollent && disassembler.GetPreviousInstruction(eip, instructionAddress,
531fce4895dSRene Gollent instructionSize) == B_OK) {
532fce4895dSRene Gollent eip -= instructionSize;
533fce4895dSRene Gollent cpuState->SetIntRegister(X86_REGISTER_EIP, eip);
534fce4895dSRene Gollent }
535fce4895dSRene Gollent }
536fce4895dSRene Gollent
537fce4895dSRene Gollent
538fce4895dSRene Gollent status_t
ReadValueFromMemory(target_addr_t address,uint32 valueType,BVariant & _value) const539fce4895dSRene Gollent ArchitectureX86::ReadValueFromMemory(target_addr_t address, uint32 valueType,
540fce4895dSRene Gollent BVariant& _value) const
541fce4895dSRene Gollent {
542fce4895dSRene Gollent uint8 buffer[64];
543fce4895dSRene Gollent size_t size = BVariant::SizeOfType(valueType);
544fce4895dSRene Gollent if (size == 0 || size > sizeof(buffer))
545fce4895dSRene Gollent return B_BAD_VALUE;
546fce4895dSRene Gollent
547fce4895dSRene Gollent ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer, size);
548fce4895dSRene Gollent if (bytesRead < 0)
549fce4895dSRene Gollent return bytesRead;
550fce4895dSRene Gollent if ((size_t)bytesRead != size)
551fce4895dSRene Gollent return B_ERROR;
552fce4895dSRene Gollent
553fce4895dSRene Gollent // TODO: We need to swap endianess, if the host is big endian!
554fce4895dSRene Gollent
555fce4895dSRene Gollent switch (valueType) {
556fce4895dSRene Gollent case B_INT8_TYPE:
557fce4895dSRene Gollent _value.SetTo(*(int8*)buffer);
558fce4895dSRene Gollent return B_OK;
559fce4895dSRene Gollent case B_UINT8_TYPE:
560fce4895dSRene Gollent _value.SetTo(*(uint8*)buffer);
561fce4895dSRene Gollent return B_OK;
562fce4895dSRene Gollent case B_INT16_TYPE:
563fce4895dSRene Gollent _value.SetTo(*(int16*)buffer);
564fce4895dSRene Gollent return B_OK;
565fce4895dSRene Gollent case B_UINT16_TYPE:
566fce4895dSRene Gollent _value.SetTo(*(uint16*)buffer);
567fce4895dSRene Gollent return B_OK;
568fce4895dSRene Gollent case B_INT32_TYPE:
569fce4895dSRene Gollent _value.SetTo(*(int32*)buffer);
570fce4895dSRene Gollent return B_OK;
571fce4895dSRene Gollent case B_UINT32_TYPE:
572fce4895dSRene Gollent _value.SetTo(*(uint32*)buffer);
573fce4895dSRene Gollent return B_OK;
574fce4895dSRene Gollent case B_INT64_TYPE:
575fce4895dSRene Gollent _value.SetTo(*(int64*)buffer);
576fce4895dSRene Gollent return B_OK;
577fce4895dSRene Gollent case B_UINT64_TYPE:
578fce4895dSRene Gollent _value.SetTo(*(uint64*)buffer);
579fce4895dSRene Gollent return B_OK;
580fce4895dSRene Gollent case B_FLOAT_TYPE:
581fce4895dSRene Gollent _value.SetTo(*(float*)buffer);
582fce4895dSRene Gollent // TODO: float on the host might work differently!
583fce4895dSRene Gollent return B_OK;
584fce4895dSRene Gollent case B_DOUBLE_TYPE:
585fce4895dSRene Gollent _value.SetTo(*(double*)buffer);
586fce4895dSRene Gollent // TODO: double on the host might work differently!
587fce4895dSRene Gollent return B_OK;
588fce4895dSRene Gollent default:
589fce4895dSRene Gollent return B_BAD_VALUE;
590fce4895dSRene Gollent }
591fce4895dSRene Gollent }
592fce4895dSRene Gollent
593fce4895dSRene Gollent
594fce4895dSRene Gollent status_t
ReadValueFromMemory(target_addr_t addressSpace,target_addr_t address,uint32 valueType,BVariant & _value) const595fce4895dSRene Gollent ArchitectureX86::ReadValueFromMemory(target_addr_t addressSpace,
596fce4895dSRene Gollent target_addr_t address, uint32 valueType, BVariant& _value) const
597fce4895dSRene Gollent {
598fce4895dSRene Gollent // n/a on this architecture
599fce4895dSRene Gollent return B_BAD_VALUE;
600fce4895dSRene Gollent }
601fce4895dSRene Gollent
602fce4895dSRene Gollent
603fce4895dSRene Gollent status_t
DisassembleCode(FunctionDebugInfo * function,const void * buffer,size_t bufferSize,DisassembledCode * & _sourceCode)604fce4895dSRene Gollent ArchitectureX86::DisassembleCode(FunctionDebugInfo* function,
605fce4895dSRene Gollent const void* buffer, size_t bufferSize, DisassembledCode*& _sourceCode)
606fce4895dSRene Gollent {
607fce4895dSRene Gollent DisassembledCode* source = new(std::nothrow) DisassembledCode(
608fce4895dSRene Gollent fAssemblyLanguage);
609fce4895dSRene Gollent if (source == NULL)
610fce4895dSRene Gollent return B_NO_MEMORY;
611fce4895dSRene Gollent BReference<DisassembledCode> sourceReference(source, true);
612fce4895dSRene Gollent
613fce4895dSRene Gollent // init disassembler
614fce4895dSRene Gollent DisassemblerX86 disassembler;
615fce4895dSRene Gollent status_t error = disassembler.Init(function->Address(), buffer, bufferSize);
616fce4895dSRene Gollent if (error != B_OK)
617fce4895dSRene Gollent return error;
618fce4895dSRene Gollent
619fce4895dSRene Gollent // add a function name line
620fce4895dSRene Gollent BString functionName(function->PrettyName());
621fce4895dSRene Gollent if (!source->AddCommentLine((functionName << ':').String()))
622fce4895dSRene Gollent return B_NO_MEMORY;
623fce4895dSRene Gollent
624fce4895dSRene Gollent // disassemble the instructions
625fce4895dSRene Gollent BString line;
626fce4895dSRene Gollent target_addr_t instructionAddress;
627fce4895dSRene Gollent target_size_t instructionSize;
628fce4895dSRene Gollent bool breakpointAllowed;
629fce4895dSRene Gollent while (disassembler.GetNextInstruction(line, instructionAddress,
630fce4895dSRene Gollent instructionSize, breakpointAllowed) == B_OK) {
631fce4895dSRene Gollent // TODO: Respect breakpointAllowed!
632fce4895dSRene Gollent if (!source->AddInstructionLine(line, instructionAddress,
633fce4895dSRene Gollent instructionSize)) {
634fce4895dSRene Gollent return B_NO_MEMORY;
635fce4895dSRene Gollent }
636fce4895dSRene Gollent }
637fce4895dSRene Gollent
638fce4895dSRene Gollent _sourceCode = sourceReference.Detach();
639fce4895dSRene Gollent return B_OK;
640fce4895dSRene Gollent }
641fce4895dSRene Gollent
642fce4895dSRene Gollent
643fce4895dSRene Gollent status_t
GetStatement(FunctionDebugInfo * function,target_addr_t address,Statement * & _statement)644fce4895dSRene Gollent ArchitectureX86::GetStatement(FunctionDebugInfo* function,
645fce4895dSRene Gollent target_addr_t address, Statement*& _statement)
646fce4895dSRene Gollent {
647fce4895dSRene Gollent // TODO: This is not architecture dependent anymore!
648fce4895dSRene Gollent // get the instruction info
649fce4895dSRene Gollent InstructionInfo info;
650fce4895dSRene Gollent status_t error = GetInstructionInfo(address, info, NULL);
651fce4895dSRene Gollent if (error != B_OK)
652fce4895dSRene Gollent return error;
653fce4895dSRene Gollent
654fce4895dSRene Gollent // create a statement
655fce4895dSRene Gollent ContiguousStatement* statement = new(std::nothrow) ContiguousStatement(
656fce4895dSRene Gollent SourceLocation(-1), TargetAddressRange(info.Address(), info.Size()));
657fce4895dSRene Gollent if (statement == NULL)
658fce4895dSRene Gollent return B_NO_MEMORY;
659fce4895dSRene Gollent
660fce4895dSRene Gollent _statement = statement;
661fce4895dSRene Gollent return B_OK;
662fce4895dSRene Gollent }
663fce4895dSRene Gollent
664fce4895dSRene Gollent
665fce4895dSRene Gollent status_t
GetInstructionInfo(target_addr_t address,InstructionInfo & _info,CpuState * state)666fce4895dSRene Gollent ArchitectureX86::GetInstructionInfo(target_addr_t address,
667fce4895dSRene Gollent InstructionInfo& _info, CpuState* state)
668fce4895dSRene Gollent {
669fce4895dSRene Gollent // read the code - maximum x86{-64} instruction size = 15 bytes
670fce4895dSRene Gollent uint8 buffer[16];
671fce4895dSRene Gollent ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer,
672fce4895dSRene Gollent sizeof(buffer));
673fce4895dSRene Gollent if (bytesRead < 0)
674fce4895dSRene Gollent return bytesRead;
675fce4895dSRene Gollent
676fce4895dSRene Gollent // init disassembler
677fce4895dSRene Gollent DisassemblerX86 disassembler;
678fce4895dSRene Gollent status_t error = disassembler.Init(address, buffer, bytesRead);
679fce4895dSRene Gollent if (error != B_OK)
680fce4895dSRene Gollent return error;
681fce4895dSRene Gollent
682fce4895dSRene Gollent return disassembler.GetNextInstructionInfo(_info, state);
683fce4895dSRene Gollent }
684fce4895dSRene Gollent
685fce4895dSRene Gollent
686fce4895dSRene Gollent status_t
ResolvePICFunctionAddress(target_addr_t instructionAddress,CpuState * state,target_addr_t & _targetAddress)687fce4895dSRene Gollent ArchitectureX86::ResolvePICFunctionAddress(target_addr_t instructionAddress,
688fce4895dSRene Gollent CpuState* state, target_addr_t& _targetAddress)
689fce4895dSRene Gollent {
690fce4895dSRene Gollent // if the function in question is position-independent, the call
691fce4895dSRene Gollent // will actually have taken us to its corresponding PLT slot.
692fce4895dSRene Gollent // in such a case, look at the disassembled jump to determine
693fce4895dSRene Gollent // where to find the actual function address.
694fce4895dSRene Gollent InstructionInfo info;
695fce4895dSRene Gollent if (GetInstructionInfo(instructionAddress, info, state) != B_OK) {
696fce4895dSRene Gollent return B_BAD_VALUE;
697fce4895dSRene Gollent }
698fce4895dSRene Gollent target_addr_t subroutineAddress = info.TargetAddress();
699fce4895dSRene Gollent
700fce4895dSRene Gollent ssize_t bytesRead = fTeamMemory->ReadMemory(info.TargetAddress(),
701fce4895dSRene Gollent &subroutineAddress, fAddressSize);
702fce4895dSRene Gollent
703fce4895dSRene Gollent if (bytesRead != fAddressSize)
704fce4895dSRene Gollent return B_BAD_VALUE;
705fce4895dSRene Gollent
706fce4895dSRene Gollent _targetAddress = subroutineAddress;
707fce4895dSRene Gollent return B_OK;
708fce4895dSRene Gollent }
709fce4895dSRene Gollent
710fce4895dSRene Gollent
711fce4895dSRene Gollent status_t
GetWatchpointDebugCapabilities(int32 & _maxRegisterCount,int32 & _maxBytesPerRegister,uint8 & _watchpointCapabilityFlags)712fce4895dSRene Gollent ArchitectureX86::GetWatchpointDebugCapabilities(int32& _maxRegisterCount,
713fce4895dSRene Gollent int32& _maxBytesPerRegister, uint8& _watchpointCapabilityFlags)
714fce4895dSRene Gollent {
715fce4895dSRene Gollent // while x86 technically has 4 hardware debug registers, one is reserved by
716fce4895dSRene Gollent // the kernel, and one is required for breakpoint support, which leaves
717fce4895dSRene Gollent // two available for watchpoints.
718fce4895dSRene Gollent _maxRegisterCount = 2;
719fce4895dSRene Gollent _maxBytesPerRegister = 4;
720fce4895dSRene Gollent
721fce4895dSRene Gollent // x86 only supports write and read/write watchpoints.
722fce4895dSRene Gollent _watchpointCapabilityFlags = WATCHPOINT_CAPABILITY_FLAG_WRITE
723fce4895dSRene Gollent | WATCHPOINT_CAPABILITY_FLAG_READ_WRITE;
724fce4895dSRene Gollent
725fce4895dSRene Gollent return B_OK;
726fce4895dSRene Gollent }
727fce4895dSRene Gollent
728fce4895dSRene Gollent
729fce4895dSRene Gollent status_t
GetReturnAddressLocation(StackFrame * frame,target_size_t valueSize,ValueLocation * & _location)730fce4895dSRene Gollent ArchitectureX86::GetReturnAddressLocation(StackFrame* frame,
731fce4895dSRene Gollent target_size_t valueSize, ValueLocation*& _location)
732fce4895dSRene Gollent {
733fce4895dSRene Gollent // for the calling conventions currently in use on Haiku,
734fce4895dSRene Gollent // the x86 rules for how values are returned are as follows:
735fce4895dSRene Gollent //
736fce4895dSRene Gollent // - 32 bits or smaller values are returned directly in EAX.
737fce4895dSRene Gollent // - 32-64 bit values are returned across EAX:EDX.
738fce4895dSRene Gollent // - > 64 bit values are returned on the stack.
739fce4895dSRene Gollent ValueLocation* location = new(std::nothrow) ValueLocation(
740fce4895dSRene Gollent IsBigEndian());
741fce4895dSRene Gollent if (location == NULL)
742fce4895dSRene Gollent return B_NO_MEMORY;
743fce4895dSRene Gollent BReference<ValueLocation> locationReference(location,
744fce4895dSRene Gollent true);
745fce4895dSRene Gollent
746fce4895dSRene Gollent if (valueSize <= 4) {
747fce4895dSRene Gollent ValuePieceLocation piece;
748fce4895dSRene Gollent piece.SetSize(valueSize);
749fce4895dSRene Gollent piece.SetToRegister(X86_REGISTER_EAX);
750fce4895dSRene Gollent if (!location->AddPiece(piece))
751fce4895dSRene Gollent return B_NO_MEMORY;
752fce4895dSRene Gollent } else if (valueSize <= 8) {
753fce4895dSRene Gollent ValuePieceLocation piece;
754fce4895dSRene Gollent piece.SetSize(4);
755fce4895dSRene Gollent piece.SetToRegister(X86_REGISTER_EAX);
756fce4895dSRene Gollent if (!location->AddPiece(piece))
757fce4895dSRene Gollent return B_NO_MEMORY;
758fce4895dSRene Gollent piece.SetToRegister(X86_REGISTER_EDX);
759fce4895dSRene Gollent piece.SetSize(valueSize - 4);
760fce4895dSRene Gollent if (!location->AddPiece(piece))
761fce4895dSRene Gollent return B_NO_MEMORY;
762fce4895dSRene Gollent } else {
763fce4895dSRene Gollent ValuePieceLocation piece;
764fce4895dSRene Gollent CpuStateX86* state = dynamic_cast<CpuStateX86*>(frame->GetCpuState());
765fce4895dSRene Gollent piece.SetToMemory(state->IntRegisterValue(X86_REGISTER_EAX));
766fce4895dSRene Gollent piece.SetSize(valueSize);
767fce4895dSRene Gollent if (!location->AddPiece(piece))
768fce4895dSRene Gollent return B_NO_MEMORY;
769fce4895dSRene Gollent }
770fce4895dSRene Gollent
771fce4895dSRene Gollent _location = locationReference.Detach();
772fce4895dSRene Gollent return B_OK;
773fce4895dSRene Gollent }
774fce4895dSRene Gollent
775fce4895dSRene Gollent
776fce4895dSRene Gollent void
_AddRegister(int32 index,const char * name,uint32 bitSize,uint32 valueType,register_type type,bool calleePreserved)777fce4895dSRene Gollent ArchitectureX86::_AddRegister(int32 index, const char* name,
778fce4895dSRene Gollent uint32 bitSize, uint32 valueType, register_type type, bool calleePreserved)
779fce4895dSRene Gollent {
780fce4895dSRene Gollent if (!fRegisters.Add(Register(index, name, bitSize, valueType, type,
781fce4895dSRene Gollent calleePreserved))) {
782fce4895dSRene Gollent throw std::bad_alloc();
783fce4895dSRene Gollent }
784fce4895dSRene Gollent }
785fce4895dSRene Gollent
786fce4895dSRene Gollent
787fce4895dSRene Gollent void
_AddIntegerRegister(int32 index,const char * name,uint32 valueType,register_type type,bool calleePreserved)788fce4895dSRene Gollent ArchitectureX86::_AddIntegerRegister(int32 index, const char* name,
789fce4895dSRene Gollent uint32 valueType, register_type type, bool calleePreserved)
790fce4895dSRene Gollent {
791fce4895dSRene Gollent _AddRegister(index, name, 8 * BVariant::SizeOfType(valueType), valueType,
792fce4895dSRene Gollent type, calleePreserved);
793fce4895dSRene Gollent }
794fce4895dSRene Gollent
795fce4895dSRene Gollent
796fce4895dSRene Gollent void
_AddFPRegister(int32 index,const char * name)797fce4895dSRene Gollent ArchitectureX86::_AddFPRegister(int32 index, const char* name)
798fce4895dSRene Gollent {
799fce4895dSRene Gollent _AddRegister(index, name, 8 * BVariant::SizeOfType(B_DOUBLE_TYPE),
800fce4895dSRene Gollent B_DOUBLE_TYPE, REGISTER_TYPE_GENERAL_PURPOSE, true);
801fce4895dSRene Gollent }
802fce4895dSRene Gollent
803fce4895dSRene Gollent
804fce4895dSRene Gollent void
_AddSIMDRegister(int32 index,const char * name,uint32 byteSize)805fce4895dSRene Gollent ArchitectureX86::_AddSIMDRegister(int32 index, const char* name,
806fce4895dSRene Gollent uint32 byteSize)
807fce4895dSRene Gollent {
808fce4895dSRene Gollent _AddRegister(index, name, byteSize * 8, B_RAW_TYPE,
809fce4895dSRene Gollent REGISTER_TYPE_GENERAL_PURPOSE, true);
810fce4895dSRene Gollent }
811fce4895dSRene Gollent
812fce4895dSRene Gollent
813fce4895dSRene Gollent bool
_HasFunctionPrologue(FunctionDebugInfo * function) const814fce4895dSRene Gollent ArchitectureX86::_HasFunctionPrologue(FunctionDebugInfo* function) const
815fce4895dSRene Gollent {
816fce4895dSRene Gollent if (function == NULL)
817fce4895dSRene Gollent return false;
818fce4895dSRene Gollent
819fce4895dSRene Gollent // check whether the function has the typical prologue
820fce4895dSRene Gollent if (function->Size() < 3)
821fce4895dSRene Gollent return false;
822fce4895dSRene Gollent
823fce4895dSRene Gollent uint8 buffer[3];
824fce4895dSRene Gollent if (fTeamMemory->ReadMemory(function->Address(), buffer, 3) != 3)
825fce4895dSRene Gollent return false;
826fce4895dSRene Gollent
827fce4895dSRene Gollent return buffer[0] == 0x55 && buffer[1] == 0x89 && buffer[2] == 0xe5;
828fce4895dSRene Gollent }
829