diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 59432d2776..082cfd0922 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -44,6 +44,7 @@ Application Debugger : CpuState.cpp InstructionInfo.cpp Register.cpp + RegisterMap.cpp # arch/x86 ArchitectureX86.cpp diff --git a/src/apps/debugger/arch/Architecture.cpp b/src/apps/debugger/arch/Architecture.cpp index b0eaf2e025..92c00ede8f 100644 --- a/src/apps/debugger/arch/Architecture.cpp +++ b/src/apps/debugger/arch/Architecture.cpp @@ -52,7 +52,6 @@ Architecture::CreateStackTrace(Team* team, return B_NO_MEMORY; ObjectDeleter stackTraceDeleter(stackTrace); - bool architectureFrame = false; StackFrame* frame = NULL; while (cpuState != NULL) { @@ -85,9 +84,10 @@ Architecture::CreateStackTrace(Team* team, Reference functionReference(function); teamLocker.Unlock(); - // If the last frame had been created by the architecture, we update the - // CPU state. - if (architectureFrame) { + // If the CPU state's instruction pointer is actually the return address + // of the next frame, we let the architecture fix that. + if (frame != NULL + && frame->ReturnAddress() == cpuState->InstructionPointer()) { UpdateStackFrameCpuState(frame, image, functionDebugInfo, cpuState); } @@ -109,9 +109,7 @@ Architecture::CreateStackTrace(Team* team, cpuState, frame == NULL, previousFrame, previousCpuState); if (error != B_OK) break; - architectureFrame = true; - } else - architectureFrame = false; + } cpuStateReference.SetTo(previousCpuState, true); diff --git a/src/apps/debugger/arch/Architecture.h b/src/apps/debugger/arch/Architecture.h index 6cf2167ee2..6d0170c353 100644 --- a/src/apps/debugger/arch/Architecture.h +++ b/src/apps/debugger/arch/Architecture.h @@ -5,9 +5,11 @@ #ifndef ARCHITECTURE_H #define ARCHITECTURE_H + #include #include +#include #include "Types.h" @@ -19,6 +21,7 @@ class Image; class ImageDebugInfoProvider; class InstructionInfo; class Register; +class RegisterMap; class StackFrame; class StackTrace; class Statement; @@ -36,6 +39,11 @@ public: virtual int32 CountRegisters() const = 0; virtual const Register* Registers() const = 0; + virtual status_t GetDwarfRegisterMaps(RegisterMap** _toDwarf, + RegisterMap** _fromDwarf) const = 0; + // returns references + + virtual status_t CreateCpuState(CpuState*& _state) = 0; virtual status_t CreateCpuState(const void* cpuStateData, size_t size, CpuState*& _state) = 0; virtual status_t CreateStackFrame(Image* image, @@ -55,6 +63,10 @@ public: // with the image/function corresponding // to the CPU state. + virtual status_t ReadValueFromMemory(target_addr_t address, + uint32 valueType, BVariant& _value) const + = 0; + virtual status_t DisassembleCode(FunctionDebugInfo* function, const void* buffer, size_t bufferSize, DisassembledCode*& _sourceCode) = 0; diff --git a/src/apps/debugger/arch/CpuState.h b/src/apps/debugger/arch/CpuState.h index 7f53d27fb9..4091b22ff3 100644 --- a/src/apps/debugger/arch/CpuState.h +++ b/src/apps/debugger/arch/CpuState.h @@ -22,7 +22,9 @@ public: virtual target_addr_t InstructionPointer() const = 0; virtual bool GetRegisterValue(const Register* reg, - BVariant& _value) = 0; + BVariant& _value) const = 0; + virtual bool SetRegisterValue(const Register* reg, + const BVariant& value) = 0; }; diff --git a/src/apps/debugger/arch/Register.cpp b/src/apps/debugger/arch/Register.cpp index 2f8449c566..af7d13cb2a 100644 --- a/src/apps/debugger/arch/Register.cpp +++ b/src/apps/debugger/arch/Register.cpp @@ -3,18 +3,41 @@ * Distributed under the terms of the MIT License. */ + #include "Register.h" +#include -Register::Register(int32 index, const char* name, register_format format, - uint32 bitSize, register_type type) + +Register::Register(int32 index, const char* name, uint32 bitSize, + uint32 valueType, register_type type, bool calleePreserved) : fIndex(index), fName(name), - fFormat(format), fBitSize(bitSize), - fType(type) + fValueType(valueType), + fType(type), + fCalleePreserved(calleePreserved) { + switch (fValueType) { + case B_INT8_TYPE: + case B_UINT8_TYPE: + case B_INT16_TYPE: + case B_UINT16_TYPE: + case B_INT32_TYPE: + case B_UINT32_TYPE: + case B_INT64_TYPE: + case B_UINT64_TYPE: + fFormat = REGISTER_FORMAT_INTEGER; + break; + case B_FLOAT_TYPE: + case B_DOUBLE_TYPE: + fFormat = REGISTER_FORMAT_FLOAT; + break; + default: + fFormat = 0; + break; + } } @@ -22,8 +45,10 @@ Register::Register(const Register& other) : fIndex(other.fIndex), fName(other.fName), - fFormat(other.fFormat), fBitSize(other.fBitSize), - fType(other.fType) + fValueType(other.fValueType), + fFormat(other.fFormat), + fType(other.fType), + fCalleePreserved(other.fCalleePreserved) { } diff --git a/src/apps/debugger/arch/Register.h b/src/apps/debugger/arch/Register.h index e69e700780..06ef5eb92a 100644 --- a/src/apps/debugger/arch/Register.h +++ b/src/apps/debugger/arch/Register.h @@ -5,6 +5,7 @@ #ifndef REGISTER_H #define REGISTER_H + #include @@ -25,23 +26,28 @@ enum register_type { class Register { public: Register(int32 index, const char* name, - register_format format, uint32 bitSize, - register_type type); + uint32 bitSize, uint32 valueType, + register_type type, bool calleePreserved); // name will not be cloned Register(const Register& other); - int32 Index() const { return fIndex; } - const char* Name() const { return fName; } - register_format Format() const { return fFormat; } - uint32 BitSize() const { return fBitSize; } - register_type Type() const { return fType; } + int32 Index() const { return fIndex; } + const char* Name() const { return fName; } + uint32 ValueType() const { return fValueType; } + register_format Format() const { return fFormat; } + uint32 BitSize() const { return fBitSize; } + register_type Type() const { return fType; } + bool IsCalleePreserved() const + { return fCalleePreserved; } private: int32 fIndex; const char* fName; - register_format fFormat; uint32 fBitSize; + uint32 fValueType; + register_format fFormat; register_type fType; + bool fCalleePreserved; }; diff --git a/src/apps/debugger/arch/RegisterMap.cpp b/src/apps/debugger/arch/RegisterMap.cpp new file mode 100644 index 0000000000..c0afc2a068 --- /dev/null +++ b/src/apps/debugger/arch/RegisterMap.cpp @@ -0,0 +1,12 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include "RegisterMap.h" + + +RegisterMap::~RegisterMap() +{ +} diff --git a/src/apps/debugger/arch/RegisterMap.h b/src/apps/debugger/arch/RegisterMap.h new file mode 100644 index 0000000000..81611a898e --- /dev/null +++ b/src/apps/debugger/arch/RegisterMap.h @@ -0,0 +1,21 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef REGISTER_MAP_H +#define REGISTER_MAP_H + + +#include + + +class RegisterMap : public Referenceable { +public: + virtual ~RegisterMap(); + + virtual int32 CountRegisters() const = 0; + virtual int32 MapRegisterIndex(int32 index) const = 0; +}; + + +#endif // REGISTER_MAP_H diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.cpp b/src/apps/debugger/arch/x86/ArchitectureX86.cpp index 8b93119636..6785a4ad29 100644 --- a/src/apps/debugger/arch/x86/ArchitectureX86.cpp +++ b/src/apps/debugger/arch/x86/ArchitectureX86.cpp @@ -3,6 +3,7 @@ * Distributed under the terms of the MIT License. */ + #include "ArchitectureX86.h" #include @@ -15,6 +16,7 @@ #include "DisassembledCode.h" #include "FunctionDebugInfo.h" #include "InstructionInfo.h" +#include "RegisterMap.h" #include "StackFrame.h" #include "Statement.h" #include "TeamMemory.h" @@ -22,15 +24,98 @@ #include "disasm/DisassemblerX86.h" +static const int32 kFromDwarfRegisters[] = { + X86_REGISTER_EAX, + X86_REGISTER_ECX, + X86_REGISTER_EDX, + X86_REGISTER_EBX, + X86_REGISTER_ESP, + X86_REGISTER_EBP, + X86_REGISTER_ESI, + X86_REGISTER_EDI, + X86_REGISTER_EIP, + -1, // eflags + -1, // trap number + -1, // st(0) + -1, // st(1) + -1, // st(2) + -1, // st(3) + -1, // st(4) + -1, // st(5) + -1, // st(6) + -1, // st(7) + -1, // ? + -1, // ? + -1, -1, -1, -1, -1, -1, -1, -1, // SSE + -1, -1, -1, -1, -1, -1, -1, -1 // MMX +}; +static const int32 kFromDwarfRegisterCount = sizeof(kFromDwarfRegisters) / 4; + + +// #pragma mark - ToDwarfRegisterMap + + +struct ArchitectureX86::ToDwarfRegisterMap : RegisterMap { + ToDwarfRegisterMap() + { + // init the index array from the reverse map + memset(fIndices, -1, sizeof(fIndices)); + for (int32 i = 0; i < kFromDwarfRegisterCount; i++) { + if (kFromDwarfRegisters[i] >= 0) + fIndices[kFromDwarfRegisters[i]] = i; + } + } + + virtual int32 CountRegisters() const + { + return X86_REGISTER_COUNT; + } + + virtual int32 MapRegisterIndex(int32 index) const + { + return index >= 0 && index < X86_REGISTER_COUNT ? fIndices[index] : -1; + } + +private: + int32 fIndices[X86_REGISTER_COUNT]; +}; + + +// #pragma mark - FromDwarfRegisterMap + + +struct ArchitectureX86::FromDwarfRegisterMap : RegisterMap { + virtual int32 CountRegisters() const + { + return kFromDwarfRegisterCount; + } + + virtual int32 MapRegisterIndex(int32 index) const + { + return index >= 0 && index < kFromDwarfRegisterCount + ? kFromDwarfRegisters[index] : -1; + } +}; + + +// #pragma mark - ArchitectureX86 + + ArchitectureX86::ArchitectureX86(TeamMemory* teamMemory) : - Architecture(teamMemory) + Architecture(teamMemory), + fToDwarfRegisterMap(NULL), + fFromDwarfRegisterMap(NULL) { } ArchitectureX86::~ArchitectureX86() { + if (fToDwarfRegisterMap != NULL) + fToDwarfRegisterMap->ReleaseReference(); + if (fFromDwarfRegisterMap != NULL) + fFromDwarfRegisterMap->ReleaseReference(); } @@ -38,43 +123,49 @@ status_t ArchitectureX86::Init() { try { - _AddIntegerRegister(X86_REGISTER_EIP, "eip", 32, - REGISTER_TYPE_INSTRUCTION_POINTER); - _AddIntegerRegister(X86_REGISTER_ESP, "esp", 32, - REGISTER_TYPE_STACK_POINTER); - _AddIntegerRegister(X86_REGISTER_EBP, "ebp", 32, - REGISTER_TYPE_GENERAL_PURPOSE); + _AddIntegerRegister(X86_REGISTER_EIP, "eip", B_UINT32_TYPE, + REGISTER_TYPE_INSTRUCTION_POINTER, false); + _AddIntegerRegister(X86_REGISTER_ESP, "esp", B_UINT32_TYPE, + REGISTER_TYPE_STACK_POINTER, true); + _AddIntegerRegister(X86_REGISTER_EBP, "ebp", B_UINT32_TYPE, + REGISTER_TYPE_GENERAL_PURPOSE, true); - _AddIntegerRegister(X86_REGISTER_EAX, "eax", 32, - REGISTER_TYPE_GENERAL_PURPOSE); - _AddIntegerRegister(X86_REGISTER_EBX, "ebx", 32, - REGISTER_TYPE_GENERAL_PURPOSE); - _AddIntegerRegister(X86_REGISTER_ECX, "ecx", 32, - REGISTER_TYPE_GENERAL_PURPOSE); - _AddIntegerRegister(X86_REGISTER_EDX, "edx", 32, - REGISTER_TYPE_GENERAL_PURPOSE); + _AddIntegerRegister(X86_REGISTER_EAX, "eax", B_UINT32_TYPE, + REGISTER_TYPE_GENERAL_PURPOSE, false); + _AddIntegerRegister(X86_REGISTER_EBX, "ebx", B_UINT32_TYPE, + REGISTER_TYPE_GENERAL_PURPOSE, true); + _AddIntegerRegister(X86_REGISTER_ECX, "ecx", B_UINT32_TYPE, + REGISTER_TYPE_GENERAL_PURPOSE, false); + _AddIntegerRegister(X86_REGISTER_EDX, "edx", B_UINT32_TYPE, + REGISTER_TYPE_GENERAL_PURPOSE, false); - _AddIntegerRegister(X86_REGISTER_ESI, "esi", 32, - REGISTER_TYPE_GENERAL_PURPOSE); - _AddIntegerRegister(X86_REGISTER_EDI, "edi", 32, - REGISTER_TYPE_GENERAL_PURPOSE); + _AddIntegerRegister(X86_REGISTER_ESI, "esi", B_UINT32_TYPE, + REGISTER_TYPE_GENERAL_PURPOSE, true); + _AddIntegerRegister(X86_REGISTER_EDI, "edi", B_UINT32_TYPE, + REGISTER_TYPE_GENERAL_PURPOSE, true); - _AddIntegerRegister(X86_REGISTER_CS, "cs", 16, - REGISTER_TYPE_SPECIAL_PURPOSE); - _AddIntegerRegister(X86_REGISTER_DS, "ds", 16, - REGISTER_TYPE_SPECIAL_PURPOSE); - _AddIntegerRegister(X86_REGISTER_ES, "es", 16, - REGISTER_TYPE_SPECIAL_PURPOSE); - _AddIntegerRegister(X86_REGISTER_FS, "fs", 16, - REGISTER_TYPE_SPECIAL_PURPOSE); - _AddIntegerRegister(X86_REGISTER_GS, "gs", 16, - REGISTER_TYPE_SPECIAL_PURPOSE); - _AddIntegerRegister(X86_REGISTER_SS, "ss", 16, - REGISTER_TYPE_SPECIAL_PURPOSE); + _AddIntegerRegister(X86_REGISTER_CS, "cs", B_UINT16_TYPE, + REGISTER_TYPE_SPECIAL_PURPOSE, true); + _AddIntegerRegister(X86_REGISTER_DS, "ds", B_UINT16_TYPE, + REGISTER_TYPE_SPECIAL_PURPOSE, true); + _AddIntegerRegister(X86_REGISTER_ES, "es", B_UINT16_TYPE, + REGISTER_TYPE_SPECIAL_PURPOSE, true); + _AddIntegerRegister(X86_REGISTER_FS, "fs", B_UINT16_TYPE, + REGISTER_TYPE_SPECIAL_PURPOSE, true); + _AddIntegerRegister(X86_REGISTER_GS, "gs", B_UINT16_TYPE, + REGISTER_TYPE_SPECIAL_PURPOSE, true); + _AddIntegerRegister(X86_REGISTER_SS, "ss", B_UINT16_TYPE, + REGISTER_TYPE_SPECIAL_PURPOSE, true); } catch (std::bad_alloc) { return B_NO_MEMORY; } + fToDwarfRegisterMap = new(std::nothrow) ToDwarfRegisterMap; + fFromDwarfRegisterMap = new(std::nothrow) FromDwarfRegisterMap; + + if (fToDwarfRegisterMap == NULL || fFromDwarfRegisterMap == NULL) + return B_NO_MEMORY; + return B_OK; } @@ -93,6 +184,36 @@ ArchitectureX86::Registers() const } +status_t +ArchitectureX86::GetDwarfRegisterMaps(RegisterMap** _toDwarf, + RegisterMap** _fromDwarf) const +{ + if (_toDwarf != NULL) { + *_toDwarf = fToDwarfRegisterMap; + fToDwarfRegisterMap->AcquireReference(); + } + + if (_fromDwarf != NULL) { + *_fromDwarf = fFromDwarfRegisterMap; + fFromDwarfRegisterMap->AcquireReference(); + } + + return B_OK; +} + + +status_t +ArchitectureX86::CreateCpuState(CpuState*& _state) +{ + CpuStateX86* state = new(std::nothrow) CpuStateX86; + if (state == NULL) + return B_NO_MEMORY; + + _state = state; + return B_OK; +} + + status_t ArchitectureX86::CreateCpuState(const void* cpuStateData, size_t size, CpuState*& _state) @@ -269,6 +390,62 @@ ArchitectureX86::UpdateStackFrameCpuState(const StackFrame* frame, } +status_t +ArchitectureX86::ReadValueFromMemory(target_addr_t address, uint32 valueType, + BVariant& _value) const +{ + uint8 buffer[64]; + size_t size = BVariant::SizeOfType(valueType); + if (size == 0 || size > sizeof(buffer)) + return B_BAD_VALUE; + + ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer, size); + if (bytesRead < 0) + return bytesRead; + if ((size_t)bytesRead != size) + return B_ERROR; + + // TODO: We need to swap endianess, if the host is big endian! + + switch (valueType) { + case B_INT8_TYPE: + _value.SetTo(*(int8*)buffer); + return B_OK; + case B_UINT8_TYPE: + _value.SetTo(*(uint8*)buffer); + return B_OK; + case B_INT16_TYPE: + _value.SetTo(*(int16*)buffer); + return B_OK; + case B_UINT16_TYPE: + _value.SetTo(*(uint16*)buffer); + return B_OK; + case B_INT32_TYPE: + _value.SetTo(*(int32*)buffer); + return B_OK; + case B_UINT32_TYPE: + _value.SetTo(*(uint32*)buffer); + return B_OK; + case B_INT64_TYPE: + _value.SetTo(*(int64*)buffer); + return B_OK; + case B_UINT64_TYPE: + _value.SetTo(*(uint64*)buffer); + return B_OK; + case B_FLOAT_TYPE: + _value.SetTo(*(float*)buffer); + // TODO: float on the host might work differently! + return B_OK; + case B_DOUBLE_TYPE: + _value.SetTo(*(double*)buffer); + // TODO: double on the host might work differently! + return B_OK; + default: + return B_BAD_VALUE; + } +} + + status_t ArchitectureX86::DisassembleCode(FunctionDebugInfo* function, const void* buffer, size_t bufferSize, DisassembledCode*& _sourceCode) @@ -382,18 +559,21 @@ ArchitectureX86::GetInstructionInfo(target_addr_t address, void ArchitectureX86::_AddRegister(int32 index, const char* name, - register_format format, uint32 bitSize, register_type type) + uint32 bitSize, uint32 valueType, register_type type, bool calleePreserved) { - if (!fRegisters.Add(Register(index, name, format, bitSize, type))) + if (!fRegisters.Add(Register(index, name, bitSize, valueType, type, + calleePreserved))) { throw std::bad_alloc(); + } } void ArchitectureX86::_AddIntegerRegister(int32 index, const char* name, - uint32 bitSize, register_type type) + uint32 valueType, register_type type, bool calleePreserved) { - _AddRegister(index, name, REGISTER_FORMAT_INTEGER, bitSize, type); + _AddRegister(index, name, 8 * BVariant::SizeOfType(valueType), valueType, + type, calleePreserved); } diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.h b/src/apps/debugger/arch/x86/ArchitectureX86.h index 3b31e8240f..f55c8da486 100644 --- a/src/apps/debugger/arch/x86/ArchitectureX86.h +++ b/src/apps/debugger/arch/x86/ArchitectureX86.h @@ -5,6 +5,7 @@ #ifndef ARCHITECTURE_X86_H #define ARCHITECTURE_X86_H + #include "Architecture.h" #include "Array.h" #include "Register.h" @@ -20,6 +21,10 @@ public: virtual int32 CountRegisters() const; virtual const Register* Registers() const; + virtual status_t GetDwarfRegisterMaps(RegisterMap** _toDwarf, + RegisterMap** _fromDwarf) const; + + virtual status_t CreateCpuState(CpuState*& _state); virtual status_t CreateCpuState(const void* cpuStateData, size_t size, CpuState*& _state); virtual status_t CreateStackFrame(Image* image, @@ -33,6 +38,9 @@ public: FunctionDebugInfo* previousFunction, CpuState* previousCpuState); + virtual status_t ReadValueFromMemory(target_addr_t address, + uint32 valueType, BVariant& _value) const; + virtual status_t DisassembleCode(FunctionDebugInfo* function, const void* buffer, size_t bufferSize, DisassembledCode*& _sourceCode); @@ -42,19 +50,25 @@ public: virtual status_t GetInstructionInfo(target_addr_t address, InstructionInfo& _info); +private: + struct ToDwarfRegisterMap; + struct FromDwarfRegisterMap; + private: void _AddRegister(int32 index, const char* name, - register_format format, uint32 bitSize, - register_type type); + uint32 bitSize, uint32 valueType, + register_type type, bool calleePreserved); void _AddIntegerRegister(int32 index, - const char* name, uint32 bitSize, - register_type type); + const char* name, uint32 valueType, + register_type type, bool calleePreserved); bool _HasFunctionPrologue( FunctionDebugInfo* function) const; private: Array fRegisters; + ToDwarfRegisterMap* fToDwarfRegisterMap; + FromDwarfRegisterMap* fFromDwarfRegisterMap; }; diff --git a/src/apps/debugger/arch/x86/CpuStateX86.cpp b/src/apps/debugger/arch/x86/CpuStateX86.cpp index a047bf1184..c0660be2df 100644 --- a/src/apps/debugger/arch/x86/CpuStateX86.cpp +++ b/src/apps/debugger/arch/x86/CpuStateX86.cpp @@ -55,7 +55,7 @@ CpuStateX86::InstructionPointer() const bool -CpuStateX86::GetRegisterValue(const Register* reg, BVariant& _value) +CpuStateX86::GetRegisterValue(const Register* reg, BVariant& _value) const { int32 index = reg->Index(); if (!IsRegisterSet(index)) @@ -73,6 +73,19 @@ CpuStateX86::GetRegisterValue(const Register* reg, BVariant& _value) } +bool +CpuStateX86::SetRegisterValue(const Register* reg, const BVariant& value) +{ + int32 index = reg->Index(); + if (index >= X86_INT_REGISTER_END) + return false; + + fIntRegisters[index] = value.ToUInt32(); + fSetRegisters[index] = 1; + return true; +} + + bool CpuStateX86::IsRegisterSet(int32 index) const { diff --git a/src/apps/debugger/arch/x86/CpuStateX86.h b/src/apps/debugger/arch/x86/CpuStateX86.h index 9fdab15109..d6befe95f8 100644 --- a/src/apps/debugger/arch/x86/CpuStateX86.h +++ b/src/apps/debugger/arch/x86/CpuStateX86.h @@ -48,7 +48,9 @@ public: virtual target_addr_t InstructionPointer() const; virtual bool GetRegisterValue(const Register* reg, - BVariant& _value); + BVariant& _value) const; + virtual bool SetRegisterValue(const Register* reg, + const BVariant& value); uint32 InterruptVector() const { return fInterruptVector; }