2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2011-2015, Rene Gollent, rene@gollent.com.
4 * Distributed under the terms of the MIT License.
8 #include "ArchitectureX86.h"
14 #include <AutoDeleter.h>
16 #include "CfaContext.h"
17 #include "CpuStateX86.h"
18 #include "DisassembledCode.h"
19 #include "FunctionDebugInfo.h"
20 #include "InstructionInfo.h"
21 #include "NoOpStackFrameDebugInfo.h"
22 #include "RegisterMap.h"
23 #include "StackFrame.h"
24 #include "Statement.h"
25 #include "TeamMemory.h"
26 #include "ValueLocation.h"
27 #include "X86AssemblyLanguage.h"
29 #include "disasm/DisassemblerX86.h"
32 #define IA32_FEATURE_MMX (1 << 23)
33 #define IA32_FEATURE_SSE (1 << 25)
36 static const int32 kFromDwarfRegisters
[] = {
76 static const int32 kFromDwarfRegisterCount
= sizeof(kFromDwarfRegisters
) / 4;
79 // #pragma mark - ToDwarfRegisterMap
82 struct ArchitectureX86::ToDwarfRegisterMap
: RegisterMap
{
85 // init the index array from the reverse map
86 memset(fIndices
, -1, sizeof(fIndices
));
87 for (int32 i
= 0; i
< kFromDwarfRegisterCount
; i
++) {
88 if (kFromDwarfRegisters
[i
] >= 0)
89 fIndices
[kFromDwarfRegisters
[i
]] = i
;
93 virtual int32
CountRegisters() const
95 return X86_REGISTER_COUNT
;
98 virtual int32
MapRegisterIndex(int32 index
) const
100 return index
>= 0 && index
< X86_REGISTER_COUNT
? fIndices
[index
] : -1;
104 int32 fIndices
[X86_REGISTER_COUNT
];
108 // #pragma mark - FromDwarfRegisterMap
111 struct ArchitectureX86::FromDwarfRegisterMap
: RegisterMap
{
112 virtual int32
CountRegisters() const
114 return kFromDwarfRegisterCount
;
117 virtual int32
MapRegisterIndex(int32 index
) const
119 return index
>= 0 && index
< kFromDwarfRegisterCount
120 ? kFromDwarfRegisters
[index
] : -1;
125 // #pragma mark - ArchitectureX86
128 ArchitectureX86::ArchitectureX86(TeamMemory
* teamMemory
)
130 Architecture(teamMemory
, 4, false),
132 fAssemblyLanguage(NULL
),
133 fToDwarfRegisterMap(NULL
),
134 fFromDwarfRegisterMap(NULL
)
139 ArchitectureX86::~ArchitectureX86()
141 if (fToDwarfRegisterMap
!= NULL
)
142 fToDwarfRegisterMap
->ReleaseReference();
143 if (fFromDwarfRegisterMap
!= NULL
)
144 fFromDwarfRegisterMap
->ReleaseReference();
145 if (fAssemblyLanguage
!= NULL
)
146 fAssemblyLanguage
->ReleaseReference();
151 ArchitectureX86::Init()
153 fAssemblyLanguage
= new(std::nothrow
) X86AssemblyLanguage
;
154 if (fAssemblyLanguage
== NULL
)
157 #if defined(__INTEL__)
159 status_t error
= get_cpuid(&info
, 1, 0);
163 if ((info
.eax_1
.features
& IA32_FEATURE_MMX
) != 0)
164 fFeatureFlags
|= X86_CPU_FEATURE_FLAG_MMX
;
166 if ((info
.eax_1
.features
& IA32_FEATURE_SSE
) != 0)
167 fFeatureFlags
|= X86_CPU_FEATURE_FLAG_SSE
;
172 _AddIntegerRegister(X86_REGISTER_EIP
, "eip", B_UINT32_TYPE
,
173 REGISTER_TYPE_INSTRUCTION_POINTER
, false);
174 _AddIntegerRegister(X86_REGISTER_ESP
, "esp", B_UINT32_TYPE
,
175 REGISTER_TYPE_STACK_POINTER
, true);
176 _AddIntegerRegister(X86_REGISTER_EBP
, "ebp", B_UINT32_TYPE
,
177 REGISTER_TYPE_GENERAL_PURPOSE
, true);
179 _AddIntegerRegister(X86_REGISTER_EAX
, "eax", B_UINT32_TYPE
,
180 REGISTER_TYPE_GENERAL_PURPOSE
, false);
181 _AddIntegerRegister(X86_REGISTER_EBX
, "ebx", B_UINT32_TYPE
,
182 REGISTER_TYPE_GENERAL_PURPOSE
, true);
183 _AddIntegerRegister(X86_REGISTER_ECX
, "ecx", B_UINT32_TYPE
,
184 REGISTER_TYPE_GENERAL_PURPOSE
, false);
185 _AddIntegerRegister(X86_REGISTER_EDX
, "edx", B_UINT32_TYPE
,
186 REGISTER_TYPE_GENERAL_PURPOSE
, false);
188 _AddIntegerRegister(X86_REGISTER_ESI
, "esi", B_UINT32_TYPE
,
189 REGISTER_TYPE_GENERAL_PURPOSE
, true);
190 _AddIntegerRegister(X86_REGISTER_EDI
, "edi", B_UINT32_TYPE
,
191 REGISTER_TYPE_GENERAL_PURPOSE
, true);
193 _AddIntegerRegister(X86_REGISTER_CS
, "cs", B_UINT16_TYPE
,
194 REGISTER_TYPE_SPECIAL_PURPOSE
, true);
195 _AddIntegerRegister(X86_REGISTER_DS
, "ds", B_UINT16_TYPE
,
196 REGISTER_TYPE_SPECIAL_PURPOSE
, true);
197 _AddIntegerRegister(X86_REGISTER_ES
, "es", B_UINT16_TYPE
,
198 REGISTER_TYPE_SPECIAL_PURPOSE
, true);
199 _AddIntegerRegister(X86_REGISTER_FS
, "fs", B_UINT16_TYPE
,
200 REGISTER_TYPE_SPECIAL_PURPOSE
, true);
201 _AddIntegerRegister(X86_REGISTER_GS
, "gs", B_UINT16_TYPE
,
202 REGISTER_TYPE_SPECIAL_PURPOSE
, true);
203 _AddIntegerRegister(X86_REGISTER_SS
, "ss", B_UINT16_TYPE
,
204 REGISTER_TYPE_SPECIAL_PURPOSE
, true);
206 _AddFPRegister(X86_REGISTER_ST0
, "st0");
207 _AddFPRegister(X86_REGISTER_ST1
, "st1");
208 _AddFPRegister(X86_REGISTER_ST2
, "st2");
209 _AddFPRegister(X86_REGISTER_ST3
, "st3");
210 _AddFPRegister(X86_REGISTER_ST4
, "st4");
211 _AddFPRegister(X86_REGISTER_ST5
, "st5");
212 _AddFPRegister(X86_REGISTER_ST6
, "st6");
213 _AddFPRegister(X86_REGISTER_ST7
, "st7");
215 if ((fFeatureFlags
& X86_CPU_FEATURE_FLAG_MMX
) != 0) {
216 _AddSIMDRegister(X86_REGISTER_MM0
, "mm0", sizeof(uint64
));
217 _AddSIMDRegister(X86_REGISTER_MM1
, "mm1", sizeof(uint64
));
218 _AddSIMDRegister(X86_REGISTER_MM2
, "mm2", sizeof(uint64
));
219 _AddSIMDRegister(X86_REGISTER_MM3
, "mm3", sizeof(uint64
));
220 _AddSIMDRegister(X86_REGISTER_MM4
, "mm4", sizeof(uint64
));
221 _AddSIMDRegister(X86_REGISTER_MM5
, "mm5", sizeof(uint64
));
222 _AddSIMDRegister(X86_REGISTER_MM6
, "mm6", sizeof(uint64
));
223 _AddSIMDRegister(X86_REGISTER_MM7
, "mm7", sizeof(uint64
));
226 if ((fFeatureFlags
& X86_CPU_FEATURE_FLAG_SSE
) != 0) {
227 _AddSIMDRegister(X86_REGISTER_XMM0
, "xmm0",
228 sizeof(x86_xmm_register
));
229 _AddSIMDRegister(X86_REGISTER_XMM1
, "xmm1",
230 sizeof(x86_xmm_register
));
231 _AddSIMDRegister(X86_REGISTER_XMM2
, "xmm2",
232 sizeof(x86_xmm_register
));
233 _AddSIMDRegister(X86_REGISTER_XMM3
, "xmm3",
234 sizeof(x86_xmm_register
));
235 _AddSIMDRegister(X86_REGISTER_XMM4
, "xmm4",
236 sizeof(x86_xmm_register
));
237 _AddSIMDRegister(X86_REGISTER_XMM5
, "xmm5",
238 sizeof(x86_xmm_register
));
239 _AddSIMDRegister(X86_REGISTER_XMM6
, "xmm6",
240 sizeof(x86_xmm_register
));
241 _AddSIMDRegister(X86_REGISTER_XMM7
, "xmm7",
242 sizeof(x86_xmm_register
));
245 } catch (std::bad_alloc
) {
249 fToDwarfRegisterMap
= new(std::nothrow
) ToDwarfRegisterMap
;
250 fFromDwarfRegisterMap
= new(std::nothrow
) FromDwarfRegisterMap
;
252 if (fToDwarfRegisterMap
== NULL
|| fFromDwarfRegisterMap
== NULL
)
260 ArchitectureX86::StackGrowthDirection() const
262 return STACK_GROWTH_DIRECTION_NEGATIVE
;
267 ArchitectureX86::CountRegisters() const
269 return fRegisters
.Count();
274 ArchitectureX86::Registers() const
276 return fRegisters
.Elements();
282 ArchitectureX86::InitRegisterRules(CfaContext
& context
) const
284 status_t error
= Architecture::InitRegisterRules(context
);
288 // set up rule for EIP register
289 context
.RegisterRule(fToDwarfRegisterMap
->MapRegisterIndex(
290 X86_REGISTER_EIP
))->SetToLocationOffset(-4);
297 ArchitectureX86::GetDwarfRegisterMaps(RegisterMap
** _toDwarf
,
298 RegisterMap
** _fromDwarf
) const
300 if (_toDwarf
!= NULL
) {
301 *_toDwarf
= fToDwarfRegisterMap
;
302 fToDwarfRegisterMap
->AcquireReference();
305 if (_fromDwarf
!= NULL
) {
306 *_fromDwarf
= fFromDwarfRegisterMap
;
307 fFromDwarfRegisterMap
->AcquireReference();
315 ArchitectureX86::GetCpuFeatures(uint32
& flags
)
317 flags
= fFeatureFlags
;
324 ArchitectureX86::CreateCpuState(CpuState
*& _state
)
326 CpuStateX86
* state
= new(std::nothrow
) CpuStateX86
;
336 ArchitectureX86::CreateCpuState(const void* cpuStateData
, size_t size
,
339 if (size
!= sizeof(x86_debug_cpu_state
))
342 CpuStateX86
* state
= new(std::nothrow
) CpuStateX86(
343 *(const x86_debug_cpu_state
*)cpuStateData
);
353 ArchitectureX86::CreateStackFrame(Image
* image
, FunctionDebugInfo
* function
,
354 CpuState
* _cpuState
, bool isTopFrame
, StackFrame
*& _frame
,
355 CpuState
*& _previousCpuState
)
357 CpuStateX86
* cpuState
= dynamic_cast<CpuStateX86
*>(_cpuState
);
359 uint32 framePointer
= cpuState
->IntRegisterValue(X86_REGISTER_EBP
);
360 uint32 eip
= cpuState
->IntRegisterValue(X86_REGISTER_EIP
);
362 bool readStandardFrame
= true;
363 uint32 previousFramePointer
= 0;
364 uint32 returnAddress
= 0;
366 // check for syscall frames
367 stack_frame_type frameType
;
368 bool hasPrologue
= false;
369 if (isTopFrame
&& cpuState
->InterruptVector() == 99) {
370 // The thread is performing a syscall. So this frame is not really the
371 // top-most frame and we need to adjust the eip.
372 frameType
= STACK_FRAME_TYPE_SYSCALL
;
374 // int 99, sysenter, and syscall all are 2 byte instructions
376 // The syscall stubs are frameless, the return address is on top of the
378 uint32 esp
= cpuState
->IntRegisterValue(X86_REGISTER_ESP
);
380 if (fTeamMemory
->ReadMemory(esp
, &address
, 4) == 4) {
381 returnAddress
= address
;
382 previousFramePointer
= framePointer
;
384 readStandardFrame
= false;
387 hasPrologue
= _HasFunctionPrologue(function
);
389 frameType
= STACK_FRAME_TYPE_STANDARD
;
391 frameType
= STACK_FRAME_TYPE_FRAMELESS
;
392 // TODO: Handling for frameless functions. It's not trivial to find the
393 // return address on the stack, though.
395 // If the function is not frameless and we're at the top frame we need
396 // to check whether the prologue has not been executed (completely) or
397 // we're already after the epilogue.
401 if (eip
< function
->Address() + 3) {
402 // The prologue has not been executed yet, i.e. there's no
403 // stack frame yet. Get the return address from the stack.
404 stack
= cpuState
->IntRegisterValue(X86_REGISTER_ESP
);
405 if (eip
> function
->Address()) {
406 // The "push %ebp" has already been executed.
410 // Not in the function prologue, but maybe after the
411 // epilogue. The epilogue is a single "pop %ebp", so we
412 // check whether the current instruction is already a
415 if (fTeamMemory
->ReadMemory(eip
, &code
, 1) == 1
416 && code
[0] == 0xc3) {
417 stack
= cpuState
->IntRegisterValue(X86_REGISTER_ESP
);
421 // Check if the instruction pointer is at a readable location.
422 // If it isn't, then chances are we got here via a bogus
423 // function pointer, and the prologue hasn't actually been
424 // executed. In such a case, what we need is right at the top
427 if (fTeamMemory
->ReadMemory(eip
, &data
, 1) != 1)
428 stack
= cpuState
->IntRegisterValue(X86_REGISTER_ESP
);
433 if (fTeamMemory
->ReadMemory(stack
, &address
, 4) == 4) {
434 returnAddress
= address
;
435 previousFramePointer
= framePointer
;
437 readStandardFrame
= false;
438 frameType
= STACK_FRAME_TYPE_FRAMELESS
;
444 // create the stack frame
445 StackFrameDebugInfo
* stackFrameDebugInfo
446 = new(std::nothrow
) NoOpStackFrameDebugInfo
;
447 if (stackFrameDebugInfo
== NULL
)
449 BReference
<StackFrameDebugInfo
> stackFrameDebugInfoReference(
450 stackFrameDebugInfo
, true);
452 StackFrame
* frame
= new(std::nothrow
) StackFrame(frameType
, cpuState
,
453 framePointer
, eip
, stackFrameDebugInfo
);
456 BReference
<StackFrame
> frameReference(frame
, true);
458 status_t error
= frame
->Init();
462 // read the previous frame and return address, if this is a standard frame
463 if (readStandardFrame
) {
465 if (framePointer
!= 0
466 && fTeamMemory
->ReadMemory(framePointer
, frameData
, 8) == 8) {
467 previousFramePointer
= frameData
[0];
468 returnAddress
= frameData
[1];
472 // create the CPU state, if we have any info
473 CpuStateX86
* previousCpuState
= NULL
;
474 if (returnAddress
!= 0) {
475 // prepare the previous CPU state
476 previousCpuState
= new(std::nothrow
) CpuStateX86
;
477 if (previousCpuState
== NULL
)
480 previousCpuState
->SetIntRegister(X86_REGISTER_EBP
,
481 previousFramePointer
);
482 previousCpuState
->SetIntRegister(X86_REGISTER_EIP
, returnAddress
);
483 frame
->SetPreviousCpuState(previousCpuState
);
486 frame
->SetReturnAddress(returnAddress
);
488 _frame
= frameReference
.Detach();
489 _previousCpuState
= previousCpuState
;
495 ArchitectureX86::UpdateStackFrameCpuState(const StackFrame
* frame
,
496 Image
* previousImage
, FunctionDebugInfo
* previousFunction
,
497 CpuState
* previousCpuState
)
499 // This is not a top frame, so we want to offset eip to the previous
500 // (calling) instruction.
501 CpuStateX86
* cpuState
= dynamic_cast<CpuStateX86
*>(previousCpuState
);
504 uint32 eip
= cpuState
->IntRegisterValue(X86_REGISTER_EIP
);
505 if (previousFunction
== NULL
|| eip
<= previousFunction
->Address())
507 target_addr_t functionAddress
= previousFunction
->Address();
509 // allocate a buffer for the function code to disassemble
510 size_t bufferSize
= eip
- functionAddress
;
511 void* buffer
= malloc(bufferSize
);
514 MemoryDeleter
bufferDeleter(buffer
);
517 ssize_t bytesRead
= fTeamMemory
->ReadMemory(functionAddress
, buffer
,
519 if (bytesRead
!= (ssize_t
)bufferSize
)
522 // disassemble to get the previous instruction
523 DisassemblerX86 disassembler
;
524 target_addr_t instructionAddress
;
525 target_size_t instructionSize
;
526 if (disassembler
.Init(functionAddress
, buffer
, bufferSize
) == B_OK
527 && disassembler
.GetPreviousInstruction(eip
, instructionAddress
,
528 instructionSize
) == B_OK
) {
529 eip
-= instructionSize
;
530 cpuState
->SetIntRegister(X86_REGISTER_EIP
, eip
);
536 ArchitectureX86::ReadValueFromMemory(target_addr_t address
, uint32 valueType
,
537 BVariant
& _value
) const
540 size_t size
= BVariant::SizeOfType(valueType
);
541 if (size
== 0 || size
> sizeof(buffer
))
544 ssize_t bytesRead
= fTeamMemory
->ReadMemory(address
, buffer
, size
);
547 if ((size_t)bytesRead
!= size
)
550 // TODO: We need to swap endianess, if the host is big endian!
554 _value
.SetTo(*(int8
*)buffer
);
557 _value
.SetTo(*(uint8
*)buffer
);
560 _value
.SetTo(*(int16
*)buffer
);
563 _value
.SetTo(*(uint16
*)buffer
);
566 _value
.SetTo(*(int32
*)buffer
);
569 _value
.SetTo(*(uint32
*)buffer
);
572 _value
.SetTo(*(int64
*)buffer
);
575 _value
.SetTo(*(uint64
*)buffer
);
578 _value
.SetTo(*(float*)buffer
);
579 // TODO: float on the host might work differently!
582 _value
.SetTo(*(double*)buffer
);
583 // TODO: double on the host might work differently!
592 ArchitectureX86::ReadValueFromMemory(target_addr_t addressSpace
,
593 target_addr_t address
, uint32 valueType
, BVariant
& _value
) const
595 // n/a on this architecture
601 ArchitectureX86::DisassembleCode(FunctionDebugInfo
* function
,
602 const void* buffer
, size_t bufferSize
, DisassembledCode
*& _sourceCode
)
604 DisassembledCode
* source
= new(std::nothrow
) DisassembledCode(
608 BReference
<DisassembledCode
> sourceReference(source
, true);
611 DisassemblerX86 disassembler
;
612 status_t error
= disassembler
.Init(function
->Address(), buffer
, bufferSize
);
616 // add a function name line
617 BString
functionName(function
->PrettyName());
618 if (!source
->AddCommentLine((functionName
<< ':').String()))
621 // disassemble the instructions
623 target_addr_t instructionAddress
;
624 target_size_t instructionSize
;
625 bool breakpointAllowed
;
626 while (disassembler
.GetNextInstruction(line
, instructionAddress
,
627 instructionSize
, breakpointAllowed
) == B_OK
) {
628 // TODO: Respect breakpointAllowed!
629 if (!source
->AddInstructionLine(line
, instructionAddress
,
635 _sourceCode
= sourceReference
.Detach();
641 ArchitectureX86::GetStatement(FunctionDebugInfo
* function
,
642 target_addr_t address
, Statement
*& _statement
)
644 // TODO: This is not architecture dependent anymore!
645 // get the instruction info
646 InstructionInfo info
;
647 status_t error
= GetInstructionInfo(address
, info
, NULL
);
651 // create a statement
652 ContiguousStatement
* statement
= new(std::nothrow
) ContiguousStatement(
653 SourceLocation(-1), TargetAddressRange(info
.Address(), info
.Size()));
654 if (statement
== NULL
)
657 _statement
= statement
;
663 ArchitectureX86::GetInstructionInfo(target_addr_t address
,
664 InstructionInfo
& _info
, CpuState
* state
)
666 // read the code - maximum x86{-64} instruction size = 15 bytes
668 ssize_t bytesRead
= fTeamMemory
->ReadMemory(address
, buffer
,
674 DisassemblerX86 disassembler
;
675 status_t error
= disassembler
.Init(address
, buffer
, bytesRead
);
679 return disassembler
.GetNextInstructionInfo(_info
, state
);
684 ArchitectureX86::ResolvePICFunctionAddress(target_addr_t instructionAddress
,
685 CpuState
* state
, target_addr_t
& _targetAddress
)
687 // if the function in question is position-independent, the call
688 // will actually have taken us to its corresponding PLT slot.
689 // in such a case, look at the disassembled jump to determine
690 // where to find the actual function address.
691 InstructionInfo info
;
692 if (GetInstructionInfo(instructionAddress
, info
, state
) != B_OK
) {
695 target_addr_t subroutineAddress
= info
.TargetAddress();
697 ssize_t bytesRead
= fTeamMemory
->ReadMemory(info
.TargetAddress(),
698 &subroutineAddress
, fAddressSize
);
700 if (bytesRead
!= fAddressSize
)
703 _targetAddress
= subroutineAddress
;
709 ArchitectureX86::GetWatchpointDebugCapabilities(int32
& _maxRegisterCount
,
710 int32
& _maxBytesPerRegister
, uint8
& _watchpointCapabilityFlags
)
712 // while x86 technically has 4 hardware debug registers, one is reserved by
713 // the kernel, and one is required for breakpoint support, which leaves
714 // two available for watchpoints.
715 _maxRegisterCount
= 2;
716 _maxBytesPerRegister
= 4;
718 // x86 only supports write and read/write watchpoints.
719 _watchpointCapabilityFlags
= WATCHPOINT_CAPABILITY_FLAG_WRITE
720 | WATCHPOINT_CAPABILITY_FLAG_READ_WRITE
;
727 ArchitectureX86::GetReturnAddressLocation(StackFrame
* frame
,
728 target_size_t valueSize
, ValueLocation
*& _location
)
730 // for the calling conventions currently in use on Haiku,
731 // the x86 rules for how values are returned are as follows:
733 // - 32 bits or smaller values are returned directly in EAX.
734 // - 32-64 bit values are returned across EAX:EDX.
735 // - > 64 bit values are returned on the stack.
736 ValueLocation
* location
= new(std::nothrow
) ValueLocation(
738 if (location
== NULL
)
740 BReference
<ValueLocation
> locationReference(location
,
743 if (valueSize
<= 4) {
744 ValuePieceLocation piece
;
745 piece
.SetSize(valueSize
);
746 piece
.SetToRegister(X86_REGISTER_EAX
);
747 if (!location
->AddPiece(piece
))
749 } else if (valueSize
<= 8) {
750 ValuePieceLocation piece
;
752 piece
.SetToRegister(X86_REGISTER_EAX
);
753 if (!location
->AddPiece(piece
))
755 piece
.SetToRegister(X86_REGISTER_EDX
);
756 piece
.SetSize(valueSize
- 4);
757 if (!location
->AddPiece(piece
))
760 ValuePieceLocation piece
;
761 CpuStateX86
* state
= dynamic_cast<CpuStateX86
*>(frame
->GetCpuState());
762 piece
.SetToMemory(state
->IntRegisterValue(X86_REGISTER_EAX
));
763 piece
.SetSize(valueSize
);
764 if (!location
->AddPiece(piece
))
768 _location
= locationReference
.Detach();
774 ArchitectureX86::_AddRegister(int32 index
, const char* name
,
775 uint32 bitSize
, uint32 valueType
, register_type type
, bool calleePreserved
)
777 if (!fRegisters
.Add(Register(index
, name
, bitSize
, valueType
, type
,
779 throw std::bad_alloc();
785 ArchitectureX86::_AddIntegerRegister(int32 index
, const char* name
,
786 uint32 valueType
, register_type type
, bool calleePreserved
)
788 _AddRegister(index
, name
, 8 * BVariant::SizeOfType(valueType
), valueType
,
789 type
, calleePreserved
);
794 ArchitectureX86::_AddFPRegister(int32 index
, const char* name
)
796 _AddRegister(index
, name
, 8 * BVariant::SizeOfType(B_DOUBLE_TYPE
),
797 B_DOUBLE_TYPE
, REGISTER_TYPE_GENERAL_PURPOSE
, true);
802 ArchitectureX86::_AddSIMDRegister(int32 index
, const char* name
,
805 _AddRegister(index
, name
, byteSize
* 8, B_RAW_TYPE
,
806 REGISTER_TYPE_GENERAL_PURPOSE
, true);
811 ArchitectureX86::_HasFunctionPrologue(FunctionDebugInfo
* function
) const
813 if (function
== NULL
)
816 // check whether the function has the typical prologue
817 if (function
->Size() < 3)
821 if (fTeamMemory
->ReadMemory(function
->Address(), buffer
, 3) != 3)
824 return buffer
[0] == 0x55 && buffer
[1] == 0x89 && buffer
[2] == 0xe5;