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 { 83fce4895dSRene 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 93fce4895dSRene Gollent virtual int32 CountRegisters() const 94fce4895dSRene Gollent { 95fce4895dSRene Gollent return X86_REGISTER_COUNT; 96fce4895dSRene Gollent } 97fce4895dSRene Gollent 98fce4895dSRene 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 { 112fce4895dSRene Gollent virtual int32 CountRegisters() const 113fce4895dSRene Gollent { 114fce4895dSRene Gollent return kFromDwarfRegisterCount; 115fce4895dSRene Gollent } 116fce4895dSRene Gollent 117fce4895dSRene 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 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 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 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 157fce4895dSRene Gollent #if defined(__INTEL__) 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 248*b08627f3SMurai 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 263fce4895dSRene Gollent ArchitectureX86::StackGrowthDirection() const 264fce4895dSRene Gollent { 265fce4895dSRene Gollent return STACK_GROWTH_DIRECTION_NEGATIVE; 266fce4895dSRene Gollent } 267fce4895dSRene Gollent 268fce4895dSRene Gollent 269fce4895dSRene Gollent int32 270fce4895dSRene Gollent ArchitectureX86::CountRegisters() const 271fce4895dSRene Gollent { 272fce4895dSRene Gollent return fRegisters.Count(); 273fce4895dSRene Gollent } 274fce4895dSRene Gollent 275fce4895dSRene Gollent 276fce4895dSRene Gollent const Register* 277fce4895dSRene Gollent ArchitectureX86::Registers() const 278fce4895dSRene Gollent { 279fce4895dSRene Gollent return fRegisters.Elements(); 280fce4895dSRene Gollent } 281fce4895dSRene Gollent 282fce4895dSRene Gollent 283fce4895dSRene Gollent 284fce4895dSRene Gollent status_t 285fce4895dSRene 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 300fce4895dSRene 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 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 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 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 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 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 539fce4895dSRene 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 595fce4895dSRene 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 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 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 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 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 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 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 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 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 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 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 814fce4895dSRene 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