Commit c1cd0e4f authored by Aleksey R.'s avatar Aleksey R.

add: arm support

parent b45fb034
......@@ -47,7 +47,8 @@ enum CPUType {
CPU_I386 = 0,
CPU_AMD64 = 1,
CPU_ARM64 = 2,
CPU_MAX = 3
CPU_ARM = 3,
CPU_MAX = 4
};
enum CPURegType {
......
......@@ -131,6 +131,7 @@ enum MachineTypes {
machine_I386 = 0x014c,
machine_AMD64 = 0x8664,
machine_ARM64 = 0xaa64,
machine_ARM = 0x01c4,
};
////////////////////////////////////////////////////////////////////////////////
......
......@@ -37,6 +37,12 @@ const DiaRegToRegRelativeBase g_DiaRegToRegRelativeArm64 {
{ CV_ARM64_SP, rriStackPointer },
};
const DiaRegToRegRelativeBase g_DiaRegToRegRelativeArm {
{ CV_ARM_PC, rriInstructionPointer },
{ CV_ARM_R11, rriStackFrame },
{ CV_ARM_SP, rriStackPointer },
};
} // end nameless namespace
///////////////////////////////////////////////////////////////////////////////
......@@ -428,6 +434,8 @@ ULONG DiaSymbol::getRegRealativeId()
return getRegRealativeIdImpl(g_DiaRegToRegRelativeI386);
case IMAGE_FILE_MACHINE_ARM64:
return getRegRealativeIdImpl(g_DiaRegToRegRelativeArm64);
case IMAGE_FILE_MACHINE_ARMNT:
return getRegRealativeIdImpl(g_DiaRegToRegRelativeArm);
}
throw DiaException(L"Unsupported machine type");
}
......
......@@ -474,6 +474,7 @@ public:
case IMAGE_FILE_MACHINE_I386: return machine_I386;
case IMAGE_FILE_MACHINE_AMD64: return machine_AMD64;
case IMAGE_FILE_MACHINE_ARM64: return machine_ARM64;
case IMAGE_FILE_MACHINE_ARMNT: return machine_ARM;
}
throw SymbolException(L"Unkonw machine type");
......@@ -522,7 +523,8 @@ private:
m_moduleBase = moduleBase;
if ( m_machineType == IMAGE_FILE_MACHINE_I386 )
if ( m_machineType == IMAGE_FILE_MACHINE_I386 ||
m_machineType == IMAGE_FILE_MACHINE_ARMNT )
{
GetExport<IMAGE_NT_HEADERS32>( moduleBase );
return;
......
......@@ -72,6 +72,10 @@
<ClCompile Include="win\autoswitch.cpp" />
<ClCompile Include="win\breakpoint.cpp" />
<ClCompile Include="win\cpucontext.cpp" />
<ClCompile Include="win\cpucontextamd64.cpp" />
<ClCompile Include="win\cpucontextarm.cpp" />
<ClCompile Include="win\cpucontextarm64.cpp" />
<ClCompile Include="win\cpucontexti386.cpp" />
<ClCompile Include="win\dbgeng.cpp" />
<ClCompile Include="win\dbgmem.cpp" />
<ClCompile Include="win\dbgmgr.cpp" />
......
......@@ -143,6 +143,10 @@
<ClCompile Include="fnmatch.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="win\cpucontextamd64.cpp" />
<ClCompile Include="win\cpucontextarm.cpp" />
<ClCompile Include="win\cpucontextarm64.cpp" />
<ClCompile Include="win\cpucontexti386.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h" />
......
......@@ -121,6 +121,7 @@ size_t getPointerSizeByMachine(const SymbolPtr &symbol)
switch (machineType)
{
case machine_I386:
case machine_ARM:
return 4;
case machine_AMD64:
......
This diff is collapsed.
This diff is collapsed.
#include "stdafx.h"
#include <cvconst.h>
#include "kdlib/dbgengine.h"
#include "kdlib/exceptions.h"
#include "kdlib/memaccess.h"
#include "stackimpl.h"
#include "cpucontextimpl.h"
#include "dbgmgr.h"
namespace kdlib {
///////////////////////////////////////////////////////////////////////////////
NumVariant CPUContextArm::getRegisterByIndex(unsigned long index)
{
switch (index)
{
case CV_ARM_R0:
return NumVariant(m_context.R0);
case CV_ARM_R1:
return NumVariant(m_context.R1);
case CV_ARM_R2:
return NumVariant(m_context.R2);
case CV_ARM_R3:
return NumVariant(m_context.R3);
case CV_ARM_R4:
return NumVariant(m_context.R4);
case CV_ARM_R5:
return NumVariant(m_context.R5);
case CV_ARM_R6:
return NumVariant(m_context.R6);
case CV_ARM_R7:
return NumVariant(m_context.R7);
case CV_ARM_R8:
return NumVariant(m_context.R8);
case CV_ARM_R9:
return NumVariant(m_context.R9);
case CV_ARM_R10:
return NumVariant(m_context.R10);
case CV_ARM_R11:
return NumVariant(m_context.R11);
case CV_ARM_R12:
return NumVariant(m_context.R12);
case CV_ARM_SP:
return NumVariant(m_context.Sp);
case CV_ARM_LR:
return NumVariant(m_context.Lr);
case CV_ARM_PC:
return NumVariant(m_context.Pc);
case CV_ARM_CPSR:
return NumVariant(m_context.Cpsr);
case CV_ARM_FPSCR:
return NumVariant(m_context.Fpscr);
case CV_ARM_ND0:
return NumVariant(m_context.D[0]);
case CV_ARM_ND1:
return NumVariant(m_context.D[1]);
case CV_ARM_ND2:
return NumVariant(m_context.D[2]);
case CV_ARM_ND3:
return NumVariant(m_context.D[3]);
case CV_ARM_ND4:
return NumVariant(m_context.D[4]);
case CV_ARM_ND5:
return NumVariant(m_context.D[5]);
case CV_ARM_ND6:
return NumVariant(m_context.D[6]);
case CV_ARM_ND7:
return NumVariant(m_context.D[7]);
case CV_ARM_ND8:
return NumVariant(m_context.D[8]);
case CV_ARM_ND9:
return NumVariant(m_context.D[9]);
case CV_ARM_ND10:
return NumVariant(m_context.D[10]);
case CV_ARM_ND11:
return NumVariant(m_context.D[11]);
case CV_ARM_ND12:
return NumVariant(m_context.D[12]);
case CV_ARM_ND13:
return NumVariant(m_context.D[13]);
case CV_ARM_ND14:
return NumVariant(m_context.D[14]);
case CV_ARM_ND15:
return NumVariant(m_context.D[15]);
case CV_ARM_ND16:
return NumVariant(m_context.D[16]);
case CV_ARM_ND17:
return NumVariant(m_context.D[17]);
case CV_ARM_ND18:
return NumVariant(m_context.D[18]);
case CV_ARM_ND19:
return NumVariant(m_context.D[19]);
case CV_ARM_ND20:
return NumVariant(m_context.D[20]);
case CV_ARM_ND21:
return NumVariant(m_context.D[21]);
case CV_ARM_ND22:
return NumVariant(m_context.D[22]);
case CV_ARM_ND23:
return NumVariant(m_context.D[23]);
case CV_ARM_ND24:
return NumVariant(m_context.D[24]);
case CV_ARM_ND25:
return NumVariant(m_context.D[25]);
case CV_ARM_ND26:
return NumVariant(m_context.D[26]);
case CV_ARM_ND27:
return NumVariant(m_context.D[27]);
case CV_ARM_ND28:
return NumVariant(m_context.D[28]);
case CV_ARM_ND29:
return NumVariant(m_context.D[29]);
case CV_ARM_ND30:
return NumVariant(m_context.D[30]);
case CV_ARM_ND31:
return NumVariant(m_context.D[31]);
/* NumVariant can not provide 128-bit registers :( */
// CV_ARM_NQ0 ... CV_ARM_NQ15
}
std::stringstream sstr;
sstr << "ARM context: unsupported register index " << std::dec << index;
throw DbgException(sstr.str());
}
///////////////////////////////////////////////////////////////////////////////
std::wstring CPUContextArm::getRegisterName(unsigned long index)
{
switch (index)
{
case CV_ARM_R0:
return L"r0";
case CV_ARM_R1:
return L"r1";
case CV_ARM_R2:
return L"r2";
case CV_ARM_R3:
return L"r3";
case CV_ARM_R4:
return L"r4";
case CV_ARM_R5:
return L"r5";
case CV_ARM_R6:
return L"r6";
case CV_ARM_R7:
return L"r7";
case CV_ARM_R8:
return L"r8";
case CV_ARM_R9:
return L"r9";
case CV_ARM_R10:
return L"r10";
case CV_ARM_R11:
return L"r11";
case CV_ARM_R12:
return L"r12";
case CV_ARM_SP:
return L"sp";
case CV_ARM_LR:
return L"lr";
case CV_ARM_PC:
return L"pc";
case CV_ARM_CPSR:
return L"psr";
case CV_ARM_FPSCR:
return L"fpscr";
case CV_ARM_ND0:
return L"d0";
case CV_ARM_ND1:
return L"d1";
case CV_ARM_ND2:
return L"d2";
case CV_ARM_ND3:
return L"d3";
case CV_ARM_ND4:
return L"d4";
case CV_ARM_ND5:
return L"d5";
case CV_ARM_ND6:
return L"d6";
case CV_ARM_ND7:
return L"d7";
case CV_ARM_ND8:
return L"d8";
case CV_ARM_ND9:
return L"d9";
case CV_ARM_ND10:
return L"d10";
case CV_ARM_ND11:
return L"d11";
case CV_ARM_ND12:
return L"d12";
case CV_ARM_ND13:
return L"d13";
case CV_ARM_ND14:
return L"d14";
case CV_ARM_ND15:
return L"d15";
case CV_ARM_ND16:
return L"d16";
case CV_ARM_ND17:
return L"d17";
case CV_ARM_ND18:
return L"d18";
case CV_ARM_ND19:
return L"d19";
case CV_ARM_ND20:
return L"d20";
case CV_ARM_ND21:
return L"d21";
case CV_ARM_ND22:
return L"d22";
case CV_ARM_ND23:
return L"d23";
case CV_ARM_ND24:
return L"d24";
case CV_ARM_ND25:
return L"d25";
case CV_ARM_ND26:
return L"d26";
case CV_ARM_ND27:
return L"d27";
case CV_ARM_ND28:
return L"d28";
case CV_ARM_ND29:
return L"d29";
case CV_ARM_ND30:
return L"d30";
case CV_ARM_ND31:
return L"d31";
case CV_ARM_NQ0:
return L"q0";
case CV_ARM_NQ1:
return L"q1";
case CV_ARM_NQ2:
return L"q2";
case CV_ARM_NQ3:
return L"q3";
case CV_ARM_NQ4:
return L"q4";
case CV_ARM_NQ5:
return L"q5";
case CV_ARM_NQ6:
return L"q6";
case CV_ARM_NQ7:
return L"q7";
case CV_ARM_NQ8:
return L"q8";
case CV_ARM_NQ9:
return L"q9";
case CV_ARM_NQ10:
return L"q10";
case CV_ARM_NQ11:
return L"q11";
case CV_ARM_NQ12:
return L"q12";
case CV_ARM_NQ13:
return L"q13";
case CV_ARM_NQ14:
return L"q14";
case CV_ARM_NQ15:
return L"q15";
}
std::stringstream sstr;
sstr << "ARM context: unsupported register index " << std::dec << index;
throw DbgException(sstr.str());
}
///////////////////////////////////////////////////////////////////////////////
} // kdlib namespace end
///////////////////////////////////////////////////////////////////////////////
This diff is collapsed.
#include "stdafx.h"
#include <cvconst.h>
#include "kdlib/dbgengine.h"
#include "kdlib/exceptions.h"
#include "kdlib/memaccess.h"
#include "stackimpl.h"
#include "cpucontextimpl.h"
#include "dbgmgr.h"
namespace kdlib {
///////////////////////////////////////////////////////////////////////////////
NumVariant CPUContextI386::getRegisterByIndex(unsigned long index)
{
switch (index)
{
case CV_REG_AL:
return NumVariant(static_cast<unsigned char>(m_context.Eax & 0xFF));
case CV_REG_CL:
return NumVariant(static_cast<unsigned char>(m_context.Ecx & 0xFF));
case CV_REG_DL:
return NumVariant(static_cast<unsigned char>(m_context.Edx & 0xFF));
case CV_REG_BL:
return NumVariant(static_cast<unsigned char>(m_context.Ebx & 0xFF));
case CV_REG_AH:
return NumVariant(static_cast<unsigned char>((m_context.Eax & 0xFF00) >> 8));
case CV_REG_CH:
return NumVariant(static_cast<unsigned char>((m_context.Ecx & 0xFF00) >> 8));
case CV_REG_DH:
return NumVariant(static_cast<unsigned char>((m_context.Edx & 0xFF00) >> 8));
case CV_REG_BH:
return NumVariant(static_cast<unsigned char>((m_context.Ebx & 0xFF00) >> 8));
case CV_REG_AX:
return NumVariant(static_cast<unsigned short>(m_context.Eax & 0xFFFF));
case CV_REG_CX:
return NumVariant(static_cast<unsigned short>(m_context.Ecx & 0xFFFF));
case CV_REG_DX:
return NumVariant(static_cast<unsigned short>(m_context.Edx & 0xFFFF));
case CV_REG_BX:
return NumVariant(static_cast<unsigned short>(m_context.Ebx & 0xFFFF));
case CV_REG_SP:
return NumVariant(static_cast<unsigned short>(m_context.Esp & 0xFFFF));
case CV_REG_BP:
return NumVariant(static_cast<unsigned short>(m_context.Ebp & 0xFFFF));
case CV_REG_SI:
return NumVariant(static_cast<unsigned short>(m_context.Esi & 0xFFFF));
case CV_REG_DI:
return NumVariant(static_cast<unsigned short>(m_context.Edi & 0xFFFF));
case CV_REG_EAX:
return NumVariant(m_context.Eax);
case CV_REG_ECX:
return NumVariant(m_context.Ecx);
case CV_REG_EDX:
return NumVariant(m_context.Edx);
case CV_REG_EBX:
return NumVariant(m_context.Ebx);
case CV_REG_ESP:
return NumVariant(m_context.Esp);
case CV_REG_EBP:
return NumVariant(m_context.Ebp);
case CV_REG_ESI:
return NumVariant(m_context.Esi);
case CV_REG_EDI:
return NumVariant(m_context.Edi);
case CV_REG_ES:
return NumVariant(m_context.SegEs);
case CV_REG_CS:
return NumVariant(m_context.SegCs);
case CV_REG_SS:
return NumVariant(m_context.SegSs);
case CV_REG_DS:
return NumVariant(m_context.SegDs);
case CV_REG_FS:
return NumVariant(m_context.SegFs);
case CV_REG_GS:
return NumVariant(m_context.SegGs);
case CV_REG_IP:
return NumVariant(static_cast<unsigned short>(m_context.Eip & 0xFFFF));
case CV_REG_FLAGS:
return NumVariant(static_cast<unsigned short>(m_context.EFlags & 0xFFFF));
case CV_REG_EIP:
return NumVariant(m_context.Eip);
case CV_REG_EFLAGS:
return NumVariant(m_context.EFlags);
}
std::stringstream sstr;
sstr << "I386 context: unsupported register index " << std::dec << index;
throw DbgException(sstr.str());
}
///////////////////////////////////////////////////////////////////////////////
std::wstring CPUContextI386::getRegisterName(unsigned long index)
{
switch (index)
{
case CV_REG_AL:
return L"al";
case CV_REG_CL:
return L"cl";
case CV_REG_DL:
return L"dl";
case CV_REG_BL:
return L"bl";
case CV_REG_AH:
return L"ah";
case CV_REG_CH:
return L"ch";
case CV_REG_DH:
return L"dh";
case CV_REG_BH:
return L"bh";
case CV_REG_AX:
return L"ax";
case CV_REG_CX:
return L"cx";
case CV_REG_DX:
return L"dx";
case CV_REG_BX:
return L"bx";
case CV_REG_SP:
return L"sp";
case CV_REG_BP:
return L"bp";
case CV_REG_SI:
return L"si";
case CV_REG_DI:
return L"di";
case CV_REG_EAX:
return L"eax";
case CV_REG_ECX:
return L"ecx";
case CV_REG_EDX:
return L"edx";
case CV_REG_EBX:
return L"ebx";
case CV_REG_ESP:
return L"esp";
case CV_REG_EBP:
return L"ebp";
case CV_REG_ESI:
return L"esi";
case CV_REG_EDI:
return L"edi";
case CV_REG_ES:
return L"es";
case CV_REG_CS:
return L"cs";
case CV_REG_SS:
return L"ss";
case CV_REG_DS:
return L"ds";
case CV_REG_FS:
return L"fs";
case CV_REG_GS:
return L"gs";
case CV_REG_IP:
return L"ip";
case CV_REG_FLAGS:
return L"flags";
case CV_REG_EIP:
return L"eip";
case CV_REG_EFLAGS:
return L"eflags";
}
std::stringstream sstr;
sstr << "I386 context: unsupported register index " << std::dec << index;
throw DbgException(sstr.str());
}
///////////////////////////////////////////////////////////////////////////////
} // kdlib namespace end
///////////////////////////////////////////////////////////////////////////////
......@@ -213,4 +213,37 @@ public:
///////////////////////////////////////////////////////////////////////////////
class CPUContextArm : public CPUContextImpl<CONTEXT_ARM>
{
typedef CPUContextImpl<CONTEXT_ARM> Base;
public:
CPUContextArm() :
Base{ CPU_ARM, CPU_ARM }
{
}
explicit CPUContextArm(const CONTEXT_ARM &context) :
Base{ CPU_ARM, CPU_ARM, &context }
{
}
virtual NumVariant getRegisterByIndex(unsigned long index);
virtual std::wstring getRegisterName(unsigned long index);
virtual MEMOFFSET_64 getIP() {
return m_context.Pc;
}
virtual MEMOFFSET_64 getSP() {
return m_context.Sp;
}
virtual MEMOFFSET_64 getFP() {
return m_context.R11;
}
};
///////////////////////////////////////////////////////////////////////////////
} // namespace kdlib
......@@ -1549,6 +1549,7 @@ void setInstructionOffset(MEMOFFSET_64 offset)
break;
case CPU_ARM64:
case CPU_ARM:
regIndex = getRegisterIndex(L"pc");
break;
......@@ -1578,6 +1579,7 @@ void setStackOffset(MEMOFFSET_64 offset)
break;
case CPU_ARM64:
case CPU_ARM:
regIndex = getRegisterIndex(L"sp");
break;
......@@ -1610,6 +1612,10 @@ void setFrameOffset(MEMOFFSET_64 offset)
regIndex = getRegisterIndex(L"fp");
break;
case CPU_ARM:
regIndex = getRegisterIndex(L"r11");
break;
default:
throw DbgException( "Unknown processor type" );
}
......@@ -1632,6 +1638,9 @@ MEMOFFSET_64 getReturnReg()
case CPU_ARM64:
return static_cast<MEMOFFSET_64>(getRegisterByName(L"x0").asULongLong());
case CPU_ARM:
return static_cast<MEMOFFSET_64>(static_cast<MEMOFFSET_64>(getRegisterByName(L"r0").asULong()));
}
throw DbgException( "Unknown processor type" );
......@@ -1971,6 +1980,9 @@ CPUType getCPUType()
case IMAGE_FILE_MACHINE_ARM64:
return CPU_ARM64;
case IMAGE_FILE_MACHINE_ARMNT:
return CPU_ARM;
}
throw DbgException( "Unknown processor type" );
......@@ -1997,6 +2009,9 @@ CPUType getCPUMode()
case IMAGE_FILE_MACHINE_ARM64:
return CPU_ARM64;
case IMAGE_FILE_MACHINE_ARMNT:
return CPU_ARM;
}
throw DbgException( "Unknown processor type" );
......@@ -2023,6 +2038,10 @@ void setCPUMode(CPUType mode )
processorMode = IMAGE_FILE_MACHINE_ARM64;
break;
case CPU_ARM:
processorMode = IMAGE_FILE_MACHINE_ARMNT;
break;
default:
DbgException( "Unknown processor type" );
}
......
......@@ -29,6 +29,7 @@ MEMOFFSET_64 addr64( MEMOFFSET_64 offset )
switch( processorMode )
{
case IMAGE_FILE_MACHINE_I386:
case IMAGE_FILE_MACHINE_ARMNT:
if ( *( (ULONG*)&offset + 1 ) == 0 )
return (ULONG64)(LONG)offset;
......
......@@ -234,7 +234,8 @@ bool isModuleManaged( MEMOFFSET_64 baseOffset )
ULONG64 ntHeaderOffset = baseOffset + ptrDWord( baseOffset + 0x3c );
if ( machineType == IMAGE_FILE_MACHINE_I386 )
if ( machineType == IMAGE_FILE_MACHINE_I386 ||
machineType == IMAGE_FILE_MACHINE_ARMNT )
{
IMAGE_NT_HEADERS32 ntHeader;
readMemory( ntHeaderOffset, &ntHeader, sizeof(ntHeader) );
......
......@@ -380,6 +380,76 @@ static_assert(FIELD_OFFSET(CONTEXT_ARM64, Wvr) == 0x380, "FIELD_OFFSET(CONTEXT_A
///////////////////////////////////////////////////////////////////////////////
#define ARM_MAX_BREAKPOINTS 8
#define ARM_MAX_WATCHPOINTS 1
typedef struct _ARM_NEON128 {
ULONGLONG Low;
LONGLONG High;
} ARM_NEON128;
typedef struct DECLSPEC_ALIGN(8) _CONTEXT_ARM {
//
// Control flags.
//
ULONG ContextFlags;
//
// Integer registers
//
ULONG R0;
ULONG R1;
ULONG R2;
ULONG R3;
ULONG R4;
ULONG R5;
ULONG R6;
ULONG R7;
ULONG R8;
ULONG R9;
ULONG R10;