Started adding x86_64 support to Debugger.
Stack tracing doesn't work yet, nor does single stepping (somehow manages to completely freeze the system).
This commit is contained in:
@@ -23,8 +23,8 @@ SYSTEM_BIN = "[" addattr base64 basename bash beep cal cat catattr checkfs
|
|||||||
zmore znew
|
zmore znew
|
||||||
;
|
;
|
||||||
|
|
||||||
SYSTEM_APPS = AboutSystem ActivityMonitor DriveSetup Installer NetworkStatus
|
SYSTEM_APPS = AboutSystem ActivityMonitor Debugger DriveSetup Installer
|
||||||
ProcessController StyledEdit Terminal
|
NetworkStatus ProcessController StyledEdit Terminal
|
||||||
;
|
;
|
||||||
|
|
||||||
SYSTEM_PREFERENCES = Appearance Backgrounds <preference>Deskbar FileTypes
|
SYSTEM_PREFERENCES = Appearance Backgrounds <preference>Deskbar FileTypes
|
||||||
|
|||||||
@@ -682,6 +682,8 @@ if [ IsOptionalHaikuImagePackageAdded Development ] {
|
|||||||
: : true ;
|
: : true ;
|
||||||
}
|
}
|
||||||
} else if $(TARGET_ARCH) = x86_64 {
|
} else if $(TARGET_ARCH) = x86_64 {
|
||||||
|
AddSymlinkToHaikuImage home config settings deskbar Applications
|
||||||
|
: /boot/system/apps/Debugger : Debugger ;
|
||||||
InstallOptionalHaikuImagePackage
|
InstallOptionalHaikuImagePackage
|
||||||
autoconf-2.69-x86_64-2012-08-17.zip
|
autoconf-2.69-x86_64-2012-08-17.zip
|
||||||
: $(baseURL)/autoconf-2.69-x86_64-2012-08-17.zip
|
: $(baseURL)/autoconf-2.69-x86_64-2012-08-17.zip
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ UsePrivateSystemHeaders ;
|
|||||||
|
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86 ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86 ] ;
|
||||||
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86_64 ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) controllers ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) controllers ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_managers ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_managers ] ;
|
||||||
@@ -71,6 +72,10 @@ Application Debugger :
|
|||||||
ArchitectureX86.cpp
|
ArchitectureX86.cpp
|
||||||
CpuStateX86.cpp
|
CpuStateX86.cpp
|
||||||
|
|
||||||
|
# arch/x86_64
|
||||||
|
ArchitectureX8664.cpp
|
||||||
|
CpuStateX8664.cpp
|
||||||
|
|
||||||
# controllers
|
# controllers
|
||||||
DebugReportGenerator.cpp
|
DebugReportGenerator.cpp
|
||||||
TeamDebugger.cpp
|
TeamDebugger.cpp
|
||||||
@@ -305,6 +310,7 @@ Application Debugger :
|
|||||||
:
|
:
|
||||||
<nogrist>Debugger_demangler.o
|
<nogrist>Debugger_demangler.o
|
||||||
<nogrist>Debugger_disasm_x86.o
|
<nogrist>Debugger_disasm_x86.o
|
||||||
|
<nogrist>Debugger_disasm_x86_64.o
|
||||||
<nogrist>Debugger_dwarf.o
|
<nogrist>Debugger_dwarf.o
|
||||||
<nogrist>DebugAnalyzer_gui_table.o
|
<nogrist>DebugAnalyzer_gui_table.o
|
||||||
|
|
||||||
@@ -325,5 +331,6 @@ Application Debugger :
|
|||||||
;
|
;
|
||||||
|
|
||||||
HaikuSubInclude arch x86 disasm ;
|
HaikuSubInclude arch x86 disasm ;
|
||||||
|
HaikuSubInclude arch x86_64 disasm ;
|
||||||
HaikuSubInclude demangler ;
|
HaikuSubInclude demangler ;
|
||||||
HaikuSubInclude dwarf ;
|
HaikuSubInclude dwarf ;
|
||||||
|
|||||||
@@ -0,0 +1,522 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Alex Smith, [email protected].
|
||||||
|
* Copyright 2009-2012, Ingo Weinhold, [email protected].
|
||||||
|
* Copyright 2011-2012, Rene Gollent, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ArchitectureX8664.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
#include "CfaContext.h"
|
||||||
|
#include "CpuStateX8664.h"
|
||||||
|
#include "DisassembledCode.h"
|
||||||
|
#include "FunctionDebugInfo.h"
|
||||||
|
#include "InstructionInfo.h"
|
||||||
|
#include "NoOpStackFrameDebugInfo.h"
|
||||||
|
#include "RegisterMap.h"
|
||||||
|
#include "StackFrame.h"
|
||||||
|
#include "Statement.h"
|
||||||
|
#include "TeamMemory.h"
|
||||||
|
#include "X86AssemblyLanguage.h"
|
||||||
|
|
||||||
|
#include "disasm/DisassemblerX8664.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const int32 kFromDwarfRegisters[] = {
|
||||||
|
X86_64_REGISTER_RAX,
|
||||||
|
X86_64_REGISTER_RDX,
|
||||||
|
X86_64_REGISTER_RCX,
|
||||||
|
X86_64_REGISTER_RBX,
|
||||||
|
X86_64_REGISTER_RSI,
|
||||||
|
X86_64_REGISTER_RDI,
|
||||||
|
X86_64_REGISTER_RBP,
|
||||||
|
X86_64_REGISTER_RSP,
|
||||||
|
X86_64_REGISTER_R8,
|
||||||
|
X86_64_REGISTER_R9,
|
||||||
|
X86_64_REGISTER_R10,
|
||||||
|
X86_64_REGISTER_R11,
|
||||||
|
X86_64_REGISTER_R12,
|
||||||
|
X86_64_REGISTER_R13,
|
||||||
|
X86_64_REGISTER_R14,
|
||||||
|
X86_64_REGISTER_R15,
|
||||||
|
-1
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, // xmm0-xmm7
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, // xmm8-xmm15
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, // st0-st7
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, // mm0-mm7
|
||||||
|
-1, // rflags
|
||||||
|
X86_64_REGISTER_ES,
|
||||||
|
X86_64_REGISTER_CS,
|
||||||
|
X86_64_REGISTER_SS,
|
||||||
|
X86_64_REGISTER_DS,
|
||||||
|
X86_64_REGISTER_FS,
|
||||||
|
X86_64_REGISTER_GS,
|
||||||
|
};
|
||||||
|
static const int32 kFromDwarfRegisterCount = sizeof(kFromDwarfRegisters) / 4;
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - ToDwarfRegisterMap
|
||||||
|
|
||||||
|
|
||||||
|
struct ArchitectureX8664::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_64_REGISTER_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int32 MapRegisterIndex(int32 index) const
|
||||||
|
{
|
||||||
|
return index >= 0 && index < X86_64_REGISTER_COUNT ? fIndices[index] : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32 fIndices[X86_64_REGISTER_COUNT];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - FromDwarfRegisterMap
|
||||||
|
|
||||||
|
|
||||||
|
struct ArchitectureX8664::FromDwarfRegisterMap : RegisterMap {
|
||||||
|
virtual int32 CountRegisters() const
|
||||||
|
{
|
||||||
|
return kFromDwarfRegisterCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int32 MapRegisterIndex(int32 index) const
|
||||||
|
{
|
||||||
|
return index >= 0 && index < kFromDwarfRegisterCount
|
||||||
|
? kFromDwarfRegisters[index] : -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - ArchitectureX8664
|
||||||
|
|
||||||
|
|
||||||
|
ArchitectureX8664::ArchitectureX8664(TeamMemory* teamMemory)
|
||||||
|
:
|
||||||
|
Architecture(teamMemory, 8, false),
|
||||||
|
fAssemblyLanguage(NULL),
|
||||||
|
fToDwarfRegisterMap(NULL),
|
||||||
|
fFromDwarfRegisterMap(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ArchitectureX8664::~ArchitectureX8664()
|
||||||
|
{
|
||||||
|
if (fToDwarfRegisterMap != NULL)
|
||||||
|
fToDwarfRegisterMap->ReleaseReference();
|
||||||
|
if (fFromDwarfRegisterMap != NULL)
|
||||||
|
fFromDwarfRegisterMap->ReleaseReference();
|
||||||
|
if (fAssemblyLanguage != NULL)
|
||||||
|
fAssemblyLanguage->ReleaseReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ArchitectureX8664::Init()
|
||||||
|
{
|
||||||
|
fAssemblyLanguage = new(std::nothrow) X86AssemblyLanguage;
|
||||||
|
if (fAssemblyLanguage == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
try {
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_RIP, "rip", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_INSTRUCTION_POINTER, false);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_RSP, "rsp", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_STACK_POINTER, true);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_RBP, "rbp", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE, true);
|
||||||
|
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_RAX, "rax", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE, false);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_RBX, "rbx", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE, true);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_RCX, "rcx", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE, false);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_RDX, "rdx", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE, false);
|
||||||
|
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_RSI, "rsi", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE, true);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_RDI, "rdi", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE, true);
|
||||||
|
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_R8, "r8", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE, true);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_R9, "r9", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE, true);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_R10, "r10", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE, true);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_R11, "r11", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE, true);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_R12, "r12", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE, true);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_R13, "r13", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE, true);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_R14, "r14", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE, true);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_R15, "r15", B_UINT64_TYPE,
|
||||||
|
REGISTER_TYPE_GENERAL_PURPOSE, true);
|
||||||
|
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_CS, "cs", B_UINT16_TYPE,
|
||||||
|
REGISTER_TYPE_SPECIAL_PURPOSE, true);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_DS, "ds", B_UINT16_TYPE,
|
||||||
|
REGISTER_TYPE_SPECIAL_PURPOSE, true);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_ES, "es", B_UINT16_TYPE,
|
||||||
|
REGISTER_TYPE_SPECIAL_PURPOSE, true);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_FS, "fs", B_UINT16_TYPE,
|
||||||
|
REGISTER_TYPE_SPECIAL_PURPOSE, true);
|
||||||
|
_AddIntegerRegister(X86_64_REGISTER_GS, "gs", B_UINT16_TYPE,
|
||||||
|
REGISTER_TYPE_SPECIAL_PURPOSE, true);
|
||||||
|
_AddIntegerRegister(X86_64_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
ArchitectureX8664::StackGrowthDirection() const
|
||||||
|
{
|
||||||
|
return STACK_GROWTH_DIRECTION_NEGATIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
ArchitectureX8664::CountRegisters() const
|
||||||
|
{
|
||||||
|
return fRegisters.Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Register*
|
||||||
|
ArchitectureX8664::Registers() const
|
||||||
|
{
|
||||||
|
return fRegisters.Elements();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ArchitectureX8664::InitRegisterRules(CfaContext& context) const
|
||||||
|
{
|
||||||
|
status_t error = Architecture::InitRegisterRules(context);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// set up rule for EIP register
|
||||||
|
// FIXME: Huh? x86_64's DWARF spec doesn't seem to include RIP in the
|
||||||
|
// register mapping? Does this matter?
|
||||||
|
//context.RegisterRule(fToDwarfRegisterMap->MapRegisterIndex(
|
||||||
|
// X86_REGISTER_EIP))->SetToLocationOffset(-4);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ArchitectureX8664::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
|
||||||
|
ArchitectureX8664::CreateCpuState(CpuState*& _state)
|
||||||
|
{
|
||||||
|
CpuStateX8664* state = new(std::nothrow) CpuStateX8664;
|
||||||
|
if (state == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
_state = state;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ArchitectureX8664::CreateCpuState(const void* cpuStateData, size_t size,
|
||||||
|
CpuState*& _state)
|
||||||
|
{
|
||||||
|
if (size != sizeof(x86_64_debug_cpu_state))
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
CpuStateX8664* state = new(std::nothrow) CpuStateX8664(
|
||||||
|
*(const x86_64_debug_cpu_state*)cpuStateData);
|
||||||
|
if (state == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
_state = state;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ArchitectureX8664::CreateStackFrame(Image* image, FunctionDebugInfo* function,
|
||||||
|
CpuState* _cpuState, bool isTopFrame, StackFrame*& _frame,
|
||||||
|
CpuState*& _previousCpuState)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ArchitectureX8664::CreateStackFrame: TODO\n");
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ArchitectureX8664::UpdateStackFrameCpuState(const StackFrame* frame,
|
||||||
|
Image* previousImage, FunctionDebugInfo* previousFunction,
|
||||||
|
CpuState* previousCpuState)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ArchitectureX8664::UpdateStackFrameCpuState: TODO\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ArchitectureX8664::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
|
||||||
|
ArchitectureX8664::ReadValueFromMemory(target_addr_t addressSpace,
|
||||||
|
target_addr_t address, uint32 valueType, BVariant& _value) const
|
||||||
|
{
|
||||||
|
// n/a on this architecture
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ArchitectureX8664::DisassembleCode(FunctionDebugInfo* function,
|
||||||
|
const void* buffer, size_t bufferSize, DisassembledCode*& _sourceCode)
|
||||||
|
{
|
||||||
|
DisassembledCode* source = new(std::nothrow) DisassembledCode(
|
||||||
|
fAssemblyLanguage);
|
||||||
|
if (source == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
BReference<DisassembledCode> sourceReference(source, true);
|
||||||
|
|
||||||
|
// init disassembler
|
||||||
|
DisassemblerX8664 disassembler;
|
||||||
|
status_t error = disassembler.Init(function->Address(), buffer, bufferSize);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// add a function name line
|
||||||
|
BString functionName(function->PrettyName());
|
||||||
|
if (!source->AddCommentLine((functionName << ':').String()))
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
// disassemble the instructions
|
||||||
|
BString line;
|
||||||
|
target_addr_t instructionAddress;
|
||||||
|
target_size_t instructionSize;
|
||||||
|
bool breakpointAllowed;
|
||||||
|
while (disassembler.GetNextInstruction(line, instructionAddress,
|
||||||
|
instructionSize, breakpointAllowed) == B_OK) {
|
||||||
|
// TODO: Respect breakpointAllowed!
|
||||||
|
if (!source->AddInstructionLine(line, instructionAddress,
|
||||||
|
instructionSize)) {
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_sourceCode = sourceReference.Detach();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ArchitectureX8664::GetStatement(FunctionDebugInfo* function,
|
||||||
|
target_addr_t address, Statement*& _statement)
|
||||||
|
{
|
||||||
|
// TODO: This is not architecture dependent anymore!
|
||||||
|
// get the instruction info
|
||||||
|
InstructionInfo info;
|
||||||
|
status_t error = GetInstructionInfo(address, info);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// create a statement
|
||||||
|
ContiguousStatement* statement = new(std::nothrow) ContiguousStatement(
|
||||||
|
SourceLocation(-1), TargetAddressRange(info.Address(), info.Size()));
|
||||||
|
if (statement == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
_statement = statement;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ArchitectureX8664::GetInstructionInfo(target_addr_t address,
|
||||||
|
InstructionInfo& _info)
|
||||||
|
{
|
||||||
|
// read the code
|
||||||
|
uint8 buffer[16];
|
||||||
|
// TODO: What's the maximum instruction size?
|
||||||
|
ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer,
|
||||||
|
sizeof(buffer));
|
||||||
|
if (bytesRead < 0)
|
||||||
|
return bytesRead;
|
||||||
|
|
||||||
|
// init disassembler
|
||||||
|
DisassemblerX8664 disassembler;
|
||||||
|
status_t error = disassembler.Init(address, buffer, bytesRead);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// disassemble the instruction
|
||||||
|
BString line;
|
||||||
|
target_addr_t instructionAddress;
|
||||||
|
target_size_t instructionSize;
|
||||||
|
bool breakpointAllowed;
|
||||||
|
error = disassembler.GetNextInstruction(line, instructionAddress,
|
||||||
|
instructionSize, breakpointAllowed);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// FIXME: Is this correct for x86_64? I'm not entirely sure.
|
||||||
|
instruction_type instructionType = INSTRUCTION_TYPE_OTHER;
|
||||||
|
if (buffer[0] == 0xff && (buffer[1] & 0x34) == 0x10) {
|
||||||
|
// absolute call with r/m32
|
||||||
|
instructionType = INSTRUCTION_TYPE_SUBROUTINE_CALL;
|
||||||
|
} else if (buffer[0] == 0xe8 && instructionSize == 5) {
|
||||||
|
// relative call with rel32 -- don't categorize the call with 0 as
|
||||||
|
// subroutine call, since it is only used to get the address of the GOT
|
||||||
|
if (buffer[1] != 0 || buffer[2] != 0 || buffer[3] != 0
|
||||||
|
|| buffer[4] != 0) {
|
||||||
|
instructionType = INSTRUCTION_TYPE_SUBROUTINE_CALL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_info.SetTo(instructionAddress, instructionSize, instructionType,
|
||||||
|
breakpointAllowed, line)) {
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ArchitectureX8664::GetWatchpointDebugCapabilities(int32& _maxRegisterCount,
|
||||||
|
int32& _maxBytesPerRegister, uint8& _watchpointCapabilityFlags)
|
||||||
|
{
|
||||||
|
// Have 4 debug registers, 1 is required for breakpoint support, which
|
||||||
|
// leaves 3 available for watchpoints.
|
||||||
|
_maxRegisterCount = 3;
|
||||||
|
_maxBytesPerRegister = 8;
|
||||||
|
|
||||||
|
// x86 only supports write and read/write watchpoints.
|
||||||
|
_watchpointCapabilityFlags = WATCHPOINT_CAPABILITY_FLAG_WRITE
|
||||||
|
| WATCHPOINT_CAPABILITY_FLAG_READ_WRITE;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ArchitectureX8664::_AddRegister(int32 index, const char* name,
|
||||||
|
uint32 bitSize, uint32 valueType, register_type type, bool calleePreserved)
|
||||||
|
{
|
||||||
|
if (!fRegisters.Add(Register(index, name, bitSize, valueType, type,
|
||||||
|
calleePreserved))) {
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ArchitectureX8664::_AddIntegerRegister(int32 index, const char* name,
|
||||||
|
uint32 valueType, register_type type, bool calleePreserved)
|
||||||
|
{
|
||||||
|
_AddRegister(index, name, 8 * BVariant::SizeOfType(valueType), valueType,
|
||||||
|
type, calleePreserved);
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Alex Smith, [email protected].
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Copyright 2011-2012, Rene Gollent, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef ARCHITECTURE_X86_64_H
|
||||||
|
#define ARCHITECTURE_X86_64_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Array.h>
|
||||||
|
|
||||||
|
#include "Architecture.h"
|
||||||
|
#include "Register.h"
|
||||||
|
|
||||||
|
|
||||||
|
class SourceLanguage;
|
||||||
|
|
||||||
|
|
||||||
|
class ArchitectureX8664 : public Architecture {
|
||||||
|
public:
|
||||||
|
ArchitectureX8664(TeamMemory* teamMemory);
|
||||||
|
virtual ~ArchitectureX8664();
|
||||||
|
|
||||||
|
virtual status_t Init();
|
||||||
|
|
||||||
|
virtual int32 StackGrowthDirection() const;
|
||||||
|
|
||||||
|
virtual int32 CountRegisters() const;
|
||||||
|
virtual const Register* Registers() const;
|
||||||
|
virtual status_t InitRegisterRules(CfaContext& context) 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,
|
||||||
|
FunctionDebugInfo* function,
|
||||||
|
CpuState* cpuState, bool isTopFrame,
|
||||||
|
StackFrame*& _previousFrame,
|
||||||
|
CpuState*& _previousCpuState);
|
||||||
|
virtual void UpdateStackFrameCpuState(
|
||||||
|
const StackFrame* frame,
|
||||||
|
Image* previousImage,
|
||||||
|
FunctionDebugInfo* previousFunction,
|
||||||
|
CpuState* previousCpuState);
|
||||||
|
|
||||||
|
virtual status_t ReadValueFromMemory(target_addr_t address,
|
||||||
|
uint32 valueType, BVariant& _value) const;
|
||||||
|
virtual status_t ReadValueFromMemory(target_addr_t addressSpace,
|
||||||
|
target_addr_t address, uint32 valueType,
|
||||||
|
BVariant& _value) const;
|
||||||
|
|
||||||
|
virtual status_t DisassembleCode(FunctionDebugInfo* function,
|
||||||
|
const void* buffer, size_t bufferSize,
|
||||||
|
DisassembledCode*& _sourceCode);
|
||||||
|
virtual status_t GetStatement(FunctionDebugInfo* function,
|
||||||
|
target_addr_t address,
|
||||||
|
Statement*& _statement);
|
||||||
|
virtual status_t GetInstructionInfo(target_addr_t address,
|
||||||
|
InstructionInfo& _info);
|
||||||
|
|
||||||
|
virtual status_t GetWatchpointDebugCapabilities(
|
||||||
|
int32& _maxRegisterCount,
|
||||||
|
int32& _maxBytesPerRegister,
|
||||||
|
uint8& _watchpointCapabilityFlags);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct ToDwarfRegisterMap;
|
||||||
|
struct FromDwarfRegisterMap;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _AddRegister(int32 index, const char* name,
|
||||||
|
uint32 bitSize, uint32 valueType,
|
||||||
|
register_type type, bool calleePreserved);
|
||||||
|
void _AddIntegerRegister(int32 index,
|
||||||
|
const char* name, uint32 valueType,
|
||||||
|
register_type type, bool calleePreserved);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Array<Register> fRegisters;
|
||||||
|
SourceLanguage* fAssemblyLanguage;
|
||||||
|
ToDwarfRegisterMap* fToDwarfRegisterMap;
|
||||||
|
FromDwarfRegisterMap* fFromDwarfRegisterMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ARCHITECTURE_X86_64_H
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Alex Smith, [email protected].
|
||||||
|
* Copyright 2009-2012, Ingo Weinhold, [email protected].
|
||||||
|
* Copyright 2011, Rene Gollent, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CpuStateX8664.h"
|
||||||
|
|
||||||
|
#include "Register.h"
|
||||||
|
|
||||||
|
|
||||||
|
CpuStateX8664::CpuStateX8664()
|
||||||
|
:
|
||||||
|
fSetRegisters()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CpuStateX8664::CpuStateX8664(const x86_64_debug_cpu_state& state)
|
||||||
|
:
|
||||||
|
fSetRegisters()
|
||||||
|
{
|
||||||
|
SetIntRegister(X86_64_REGISTER_RIP, state.rip);
|
||||||
|
SetIntRegister(X86_64_REGISTER_RSP, state.rsp);
|
||||||
|
SetIntRegister(X86_64_REGISTER_RBP, state.rbp);
|
||||||
|
SetIntRegister(X86_64_REGISTER_RAX, state.rax);
|
||||||
|
SetIntRegister(X86_64_REGISTER_RBX, state.rbx);
|
||||||
|
SetIntRegister(X86_64_REGISTER_RCX, state.rcx);
|
||||||
|
SetIntRegister(X86_64_REGISTER_RDX, state.rdx);
|
||||||
|
SetIntRegister(X86_64_REGISTER_RSI, state.rsi);
|
||||||
|
SetIntRegister(X86_64_REGISTER_RDI, state.rdi);
|
||||||
|
SetIntRegister(X86_64_REGISTER_R8, state.r8);
|
||||||
|
SetIntRegister(X86_64_REGISTER_R9, state.r9);
|
||||||
|
SetIntRegister(X86_64_REGISTER_R10, state.r10);
|
||||||
|
SetIntRegister(X86_64_REGISTER_R11, state.r11);
|
||||||
|
SetIntRegister(X86_64_REGISTER_R12, state.r12);
|
||||||
|
SetIntRegister(X86_64_REGISTER_R13, state.r13);
|
||||||
|
SetIntRegister(X86_64_REGISTER_R14, state.r14);
|
||||||
|
SetIntRegister(X86_64_REGISTER_R15, state.r15);
|
||||||
|
SetIntRegister(X86_64_REGISTER_CS, state.cs);
|
||||||
|
SetIntRegister(X86_64_REGISTER_DS, state.ds);
|
||||||
|
SetIntRegister(X86_64_REGISTER_ES, state.es);
|
||||||
|
SetIntRegister(X86_64_REGISTER_FS, state.fs);
|
||||||
|
SetIntRegister(X86_64_REGISTER_GS, state.gs);
|
||||||
|
SetIntRegister(X86_64_REGISTER_SS, state.ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CpuStateX8664::~CpuStateX8664()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
target_addr_t
|
||||||
|
CpuStateX8664::InstructionPointer() const
|
||||||
|
{
|
||||||
|
return IsRegisterSet(X86_64_REGISTER_RIP)
|
||||||
|
? IntRegisterValue(X86_64_REGISTER_RIP) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
target_addr_t
|
||||||
|
CpuStateX8664::StackFramePointer() const
|
||||||
|
{
|
||||||
|
return IsRegisterSet(X86_64_REGISTER_RBP)
|
||||||
|
? IntRegisterValue(X86_64_REGISTER_RBP) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
target_addr_t
|
||||||
|
CpuStateX8664::StackPointer() const
|
||||||
|
{
|
||||||
|
return IsRegisterSet(X86_64_REGISTER_RSP)
|
||||||
|
? IntRegisterValue(X86_64_REGISTER_RSP) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
CpuStateX8664::GetRegisterValue(const Register* reg, BVariant& _value) const
|
||||||
|
{
|
||||||
|
int32 index = reg->Index();
|
||||||
|
if (!IsRegisterSet(index))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (index >= X86_64_INT_REGISTER_END)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (reg->BitSize() == 16)
|
||||||
|
_value.SetTo((uint16)fIntRegisters[index]);
|
||||||
|
else
|
||||||
|
_value.SetTo(fIntRegisters[index]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
CpuStateX8664::SetRegisterValue(const Register* reg, const BVariant& value)
|
||||||
|
{
|
||||||
|
int32 index = reg->Index();
|
||||||
|
if (index >= X86_64_INT_REGISTER_END)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fIntRegisters[index] = value.ToUInt64();
|
||||||
|
fSetRegisters[index] = 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
CpuStateX8664::IsRegisterSet(int32 index) const
|
||||||
|
{
|
||||||
|
return index >= 0 && index < X86_64_REGISTER_COUNT && fSetRegisters[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint64
|
||||||
|
CpuStateX8664::IntRegisterValue(int32 index) const
|
||||||
|
{
|
||||||
|
if (!IsRegisterSet(index) || index >= X86_64_INT_REGISTER_END)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return fIntRegisters[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CpuStateX8664::SetIntRegister(int32 index, uint64 value)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= X86_64_INT_REGISTER_END)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fIntRegisters[index] = value;
|
||||||
|
fSetRegisters[index] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CpuStateX8664::UnsetRegister(int32 index)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= X86_64_REGISTER_COUNT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fSetRegisters[index] = 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
|
||||||
|
* Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Copyright 2011, Rene Gollent, rene@gollent.com.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef CPU_STATE_X86_64_H
|
||||||
|
#define CPU_STATE_X86_64_H
|
||||||
|
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
|
#include <debugger.h>
|
||||||
|
|
||||||
|
#include "CpuState.h"
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
X86_64_REGISTER_RIP = 0,
|
||||||
|
X86_64_REGISTER_RSP,
|
||||||
|
X86_64_REGISTER_RBP,
|
||||||
|
|
||||||
|
X86_64_REGISTER_RAX,
|
||||||
|
X86_64_REGISTER_RBX,
|
||||||
|
X86_64_REGISTER_RCX,
|
||||||
|
X86_64_REGISTER_RDX,
|
||||||
|
|
||||||
|
X86_64_REGISTER_RSI,
|
||||||
|
X86_64_REGISTER_RDI,
|
||||||
|
|
||||||
|
X86_64_REGISTER_R8,
|
||||||
|
X86_64_REGISTER_R9,
|
||||||
|
X86_64_REGISTER_R10,
|
||||||
|
X86_64_REGISTER_R11,
|
||||||
|
X86_64_REGISTER_R12,
|
||||||
|
X86_64_REGISTER_R13,
|
||||||
|
X86_64_REGISTER_R14,
|
||||||
|
X86_64_REGISTER_R15,
|
||||||
|
|
||||||
|
X86_64_REGISTER_CS,
|
||||||
|
X86_64_REGISTER_DS,
|
||||||
|
X86_64_REGISTER_ES,
|
||||||
|
X86_64_REGISTER_FS,
|
||||||
|
X86_64_REGISTER_GS,
|
||||||
|
X86_64_REGISTER_SS,
|
||||||
|
|
||||||
|
X86_64_INT_REGISTER_END,
|
||||||
|
X86_64_REGISTER_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CpuStateX8664 : public CpuState {
|
||||||
|
public:
|
||||||
|
CpuStateX8664();
|
||||||
|
CpuStateX8664(const x86_64_debug_cpu_state& state);
|
||||||
|
virtual ~CpuStateX8664();
|
||||||
|
|
||||||
|
virtual target_addr_t InstructionPointer() const;
|
||||||
|
virtual target_addr_t StackFramePointer() const;
|
||||||
|
virtual target_addr_t StackPointer() const;
|
||||||
|
virtual bool GetRegisterValue(const Register* reg,
|
||||||
|
BVariant& _value) const;
|
||||||
|
virtual bool SetRegisterValue(const Register* reg,
|
||||||
|
const BVariant& value);
|
||||||
|
|
||||||
|
bool IsRegisterSet(int32 index) const;
|
||||||
|
uint64 IntRegisterValue(int32 index) const;
|
||||||
|
void SetIntRegister(int32 index, uint64 value);
|
||||||
|
void UnsetRegister(int32 index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::bitset<X86_64_REGISTER_COUNT> RegisterBitSet;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64 fIntRegisters[X86_64_REGISTER_COUNT];
|
||||||
|
RegisterBitSet fSetRegisters;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CPU_STATE_X86_64_H
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
|
||||||
|
* Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Copyright 2008, François Revol, revol@free.fr
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "DisassemblerX8664.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include "udis86.h"
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct DisassemblerX8664::UdisData : ud_t {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
DisassemblerX8664::DisassemblerX8664()
|
||||||
|
:
|
||||||
|
fAddress(0),
|
||||||
|
fCode(NULL),
|
||||||
|
fCodeSize(0),
|
||||||
|
fUdisData(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DisassemblerX8664::~DisassemblerX8664()
|
||||||
|
{
|
||||||
|
delete fUdisData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DisassemblerX8664::Init(target_addr_t address, const void* code, size_t codeSize)
|
||||||
|
{
|
||||||
|
// unset old data
|
||||||
|
delete fUdisData;
|
||||||
|
fUdisData = NULL;
|
||||||
|
|
||||||
|
// set new data
|
||||||
|
fUdisData = new(std::nothrow) UdisData;
|
||||||
|
if (fUdisData == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
fAddress = address;
|
||||||
|
fCode = (const uint8*)code;
|
||||||
|
fCodeSize = codeSize;
|
||||||
|
|
||||||
|
// init udis
|
||||||
|
ud_init(fUdisData);
|
||||||
|
ud_set_input_buffer(fUdisData, (unsigned char*)fCode, fCodeSize);
|
||||||
|
ud_set_mode(fUdisData, 64);
|
||||||
|
ud_set_pc(fUdisData, (uint64_t)fAddress);
|
||||||
|
ud_set_syntax(fUdisData, UD_SYN_ATT);
|
||||||
|
ud_set_vendor(fUdisData, UD_VENDOR_INTEL);
|
||||||
|
// TODO: Set the correct vendor!
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DisassemblerX8664::GetNextInstruction(BString& line, target_addr_t& _address,
|
||||||
|
target_size_t& _size, bool& _breakpointAllowed)
|
||||||
|
{
|
||||||
|
unsigned int size = ud_disassemble(fUdisData);
|
||||||
|
if (size < 1)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
uint64 address = ud_insn_off(fUdisData);
|
||||||
|
|
||||||
|
char buffer[256];
|
||||||
|
snprintf(buffer, sizeof(buffer), "0x%08" B_PRIx64 ": %16.16s %s", address,
|
||||||
|
ud_insn_hex(fUdisData), ud_insn_asm(fUdisData));
|
||||||
|
// TODO: Resolve symbols!
|
||||||
|
|
||||||
|
line = buffer;
|
||||||
|
_address = address;
|
||||||
|
_size = size;
|
||||||
|
_breakpointAllowed = true;
|
||||||
|
// TODO: Implement (rep!)!
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DisassemblerX8664::GetPreviousInstruction(target_addr_t nextAddress,
|
||||||
|
target_addr_t& _address, target_size_t& _size)
|
||||||
|
{
|
||||||
|
if (nextAddress < fAddress || nextAddress > fAddress + fCodeSize)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// loop until hitting the last instruction
|
||||||
|
while (true) {
|
||||||
|
target_size_t size = ud_disassemble(fUdisData);
|
||||||
|
if (size < 1)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
target_addr_t address = ud_insn_off(fUdisData);
|
||||||
|
if (address + size == nextAddress) {
|
||||||
|
_address = address;
|
||||||
|
_size = size;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef DISASSEMBLER_X86_64_H
|
||||||
|
#define DISASSEMBLER_X86_64_H
|
||||||
|
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
|
|
||||||
|
class DisassemblerX8664 {
|
||||||
|
public:
|
||||||
|
DisassemblerX8664();
|
||||||
|
virtual ~DisassemblerX8664();
|
||||||
|
|
||||||
|
virtual status_t Init(target_addr_t address, const void* code,
|
||||||
|
size_t codeSize);
|
||||||
|
|
||||||
|
virtual status_t GetNextInstruction(BString& line,
|
||||||
|
target_addr_t& _address,
|
||||||
|
target_size_t& _size,
|
||||||
|
bool& _breakpointAllowed);
|
||||||
|
virtual status_t GetPreviousInstruction(
|
||||||
|
target_addr_t nextAddress,
|
||||||
|
target_addr_t& _address,
|
||||||
|
target_size_t& _size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct UdisData;
|
||||||
|
|
||||||
|
private:
|
||||||
|
target_addr_t fAddress;
|
||||||
|
const uint8* fCode;
|
||||||
|
size_t fCodeSize;
|
||||||
|
UdisData* fUdisData;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // DISASSEMBLER_X86_64_H
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
SubDir HAIKU_TOP src apps debugger arch x86_64 disasm ;
|
||||||
|
|
||||||
|
CCFLAGS += -Werror ;
|
||||||
|
C++FLAGS += -Werror ;
|
||||||
|
|
||||||
|
UseHeaders [ LibraryHeaders udis86 ] ;
|
||||||
|
UseHeaders [ LibraryHeaders [ FDirName udis86 libudis86 ] ] ;
|
||||||
|
|
||||||
|
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ;
|
||||||
|
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) $(DOTDOT) types ] ;
|
||||||
|
|
||||||
|
|
||||||
|
MergeObject Debugger_disasm_x86_64.o
|
||||||
|
:
|
||||||
|
DisassemblerX8664.cpp
|
||||||
|
;
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "debug_utils.h"
|
#include "debug_utils.h"
|
||||||
|
|
||||||
#include "ArchitectureX86.h"
|
#include "ArchitectureX86.h"
|
||||||
|
#include "ArchitectureX8664.h"
|
||||||
#include "CpuState.h"
|
#include "CpuState.h"
|
||||||
#include "DebugEvent.h"
|
#include "DebugEvent.h"
|
||||||
#include "ImageInfo.h"
|
#include "ImageInfo.h"
|
||||||
@@ -255,8 +256,10 @@ DebuggerInterface::Init()
|
|||||||
// TODO: this probably needs to be rethought a bit,
|
// TODO: this probably needs to be rethought a bit,
|
||||||
// since especially when we eventually support remote debugging,
|
// since especially when we eventually support remote debugging,
|
||||||
// the architecture will depend on the target machine, not the host
|
// the architecture will depend on the target machine, not the host
|
||||||
#ifdef ARCH_x86
|
#if defined(ARCH_x86)
|
||||||
fArchitecture = new(std::nothrow) ArchitectureX86(this);
|
fArchitecture = new(std::nothrow) ArchitectureX86(this);
|
||||||
|
#elif defined(ARCH_x86_64)
|
||||||
|
fArchitecture = new(std::nothrow) ArchitectureX8664(this);
|
||||||
#else
|
#else
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+164
-136
@@ -107,8 +107,7 @@ ElfSegment::~ElfSegment()
|
|||||||
ElfFile::ElfFile()
|
ElfFile::ElfFile()
|
||||||
:
|
:
|
||||||
fFileSize(0),
|
fFileSize(0),
|
||||||
fFD(-1),
|
fFD(-1)
|
||||||
fElfHeader(NULL)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,8 +120,6 @@ ElfFile::~ElfFile()
|
|||||||
while (ElfSection* section = fSections.RemoveHead())
|
while (ElfSection* section = fSections.RemoveHead())
|
||||||
delete section;
|
delete section;
|
||||||
|
|
||||||
free(fElfHeader);
|
|
||||||
|
|
||||||
if (fFD >= 0)
|
if (fFD >= 0)
|
||||||
close(fFD);
|
close(fFD);
|
||||||
}
|
}
|
||||||
@@ -146,129 +143,16 @@ ElfFile::Init(const char* fileName)
|
|||||||
}
|
}
|
||||||
fFileSize = st.st_size;
|
fFileSize = st.st_size;
|
||||||
|
|
||||||
// read the elf header
|
// Read the identification information to determine the class.
|
||||||
fElfHeader = (Elf32_Ehdr*)malloc(sizeof(Elf32_Ehdr));
|
uint8 elfIdent[EI_NIDENT];
|
||||||
if (fElfHeader == NULL)
|
ssize_t bytesRead = pread(fFD, elfIdent, sizeof(elfIdent), 0);
|
||||||
return B_NO_MEMORY;
|
if (bytesRead != (ssize_t)sizeof(elfIdent))
|
||||||
|
|
||||||
ssize_t bytesRead = pread(fFD, fElfHeader, sizeof(Elf32_Ehdr), 0);
|
|
||||||
if (bytesRead != (ssize_t)sizeof(Elf32_Ehdr))
|
|
||||||
return bytesRead < 0 ? errno : B_ERROR;
|
return bytesRead < 0 ? errno : B_ERROR;
|
||||||
|
|
||||||
// check the ELF header
|
if(elfIdent[EI_CLASS] == ELFCLASS64)
|
||||||
if (!_CheckRange(0, sizeof(Elf32_Ehdr)) || !_CheckElfHeader()) {
|
return _LoadFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(fileName);
|
||||||
WARNING("\"%s\": Not an ELF file\n", fileName);
|
else
|
||||||
return B_BAD_DATA;
|
return _LoadFile<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(fileName);
|
||||||
}
|
|
||||||
|
|
||||||
// check section header table values
|
|
||||||
off_t sectionHeadersOffset = fElfHeader->e_shoff;
|
|
||||||
size_t sectionHeaderSize = fElfHeader->e_shentsize;
|
|
||||||
int sectionCount = fElfHeader->e_shnum;
|
|
||||||
size_t sectionHeaderTableSize = sectionHeaderSize * sectionCount;
|
|
||||||
if (!_CheckRange(sectionHeadersOffset, sectionHeaderTableSize)) {
|
|
||||||
WARNING("\"%s\": Invalid ELF header\n", fileName);
|
|
||||||
return B_BAD_DATA;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read the section header table
|
|
||||||
uint8* sectionHeaderTable = (uint8*)malloc(sectionHeaderTableSize);
|
|
||||||
if (sectionHeaderTable == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
MemoryDeleter sectionHeaderTableDeleter(sectionHeaderTable);
|
|
||||||
|
|
||||||
bytesRead = pread(fFD, sectionHeaderTable, sectionHeaderTableSize,
|
|
||||||
sectionHeadersOffset);
|
|
||||||
if (bytesRead != (ssize_t)sectionHeaderTableSize)
|
|
||||||
return bytesRead < 0 ? errno : B_ERROR;
|
|
||||||
|
|
||||||
// check and get the section header string section
|
|
||||||
Elf32_Shdr* stringSectionHeader = (Elf32_Shdr*)(sectionHeaderTable
|
|
||||||
+ fElfHeader->e_shstrndx * sectionHeaderSize);
|
|
||||||
if (!_CheckRange(stringSectionHeader->sh_offset,
|
|
||||||
stringSectionHeader->sh_size)) {
|
|
||||||
WARNING("\"%s\": Invalid string section header\n", fileName);
|
|
||||||
return B_BAD_DATA;
|
|
||||||
}
|
|
||||||
size_t sectionStringSize = stringSectionHeader->sh_size;
|
|
||||||
|
|
||||||
ElfSection* sectionStringSection = new(std::nothrow) ElfSection(".shstrtab",
|
|
||||||
fFD, stringSectionHeader->sh_offset, sectionStringSize,
|
|
||||||
stringSectionHeader->sh_addr, stringSectionHeader->sh_flags);
|
|
||||||
if (sectionStringSection == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
fSections.Add(sectionStringSection);
|
|
||||||
|
|
||||||
status_t error = sectionStringSection->Load();
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
const char* sectionStrings = (const char*)sectionStringSection->Data();
|
|
||||||
|
|
||||||
// read the other sections
|
|
||||||
for (int i = 0; i < sectionCount; i++) {
|
|
||||||
Elf32_Shdr* sectionHeader = (Elf32_Shdr*)(sectionHeaderTable
|
|
||||||
+ i * sectionHeaderSize);
|
|
||||||
// skip invalid sections and the section header string section
|
|
||||||
const char* name = sectionStrings + sectionHeader->sh_name;
|
|
||||||
if (sectionHeader->sh_name >= sectionStringSize
|
|
||||||
|| !_CheckRange(sectionHeader->sh_offset, sectionHeader->sh_size)
|
|
||||||
|| i == fElfHeader->e_shstrndx) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create an ElfSection
|
|
||||||
ElfSection* section = new(std::nothrow) ElfSection(name, fFD,
|
|
||||||
sectionHeader->sh_offset, sectionHeader->sh_size,
|
|
||||||
sectionHeader->sh_addr, sectionHeader->sh_flags);
|
|
||||||
if (section == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
fSections.Add(section);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check program header table values
|
|
||||||
off_t programHeadersOffset = fElfHeader->e_phoff;
|
|
||||||
size_t programHeaderSize = fElfHeader->e_phentsize;
|
|
||||||
int segmentCount = fElfHeader->e_phnum;
|
|
||||||
size_t programHeaderTableSize = programHeaderSize * segmentCount;
|
|
||||||
if (!_CheckRange(programHeadersOffset, programHeaderTableSize)) {
|
|
||||||
WARNING("\"%s\": Invalid ELF header\n", fileName);
|
|
||||||
return B_BAD_DATA;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read the program header table
|
|
||||||
uint8* programHeaderTable = (uint8*)malloc(programHeaderTableSize);
|
|
||||||
if (programHeaderTable == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
MemoryDeleter programHeaderTableDeleter(programHeaderTable);
|
|
||||||
|
|
||||||
bytesRead = pread(fFD, programHeaderTable, programHeaderTableSize,
|
|
||||||
programHeadersOffset);
|
|
||||||
if (bytesRead != (ssize_t)programHeaderTableSize)
|
|
||||||
return bytesRead < 0 ? errno : B_ERROR;
|
|
||||||
|
|
||||||
// read the program headers and create ElfSegment objects
|
|
||||||
for (int i = 0; i < segmentCount; i++) {
|
|
||||||
Elf32_Phdr* programHeader = (Elf32_Phdr*)(programHeaderTable
|
|
||||||
+ i * programHeaderSize);
|
|
||||||
// skip program headers we aren't interested in or that are invalid
|
|
||||||
if (programHeader->p_type != PT_LOAD || programHeader->p_filesz == 0
|
|
||||||
|| programHeader->p_memsz == 0
|
|
||||||
|| !_CheckRange(programHeader->p_offset, programHeader->p_filesz)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create an ElfSegment
|
|
||||||
ElfSegment* segment = new(std::nothrow) ElfSegment(
|
|
||||||
programHeader->p_offset, programHeader->p_filesz,
|
|
||||||
programHeader->p_vaddr, programHeader->p_memsz,
|
|
||||||
(programHeader->p_flags & PF_WRITE) != 0);
|
|
||||||
if (segment == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
fSegments.Add(segment);
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -330,6 +214,134 @@ ElfFile::DataSegment() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Ehdr, typename Phdr, typename Shdr>
|
||||||
|
status_t
|
||||||
|
ElfFile::_LoadFile(const char* fileName)
|
||||||
|
{
|
||||||
|
Ehdr elfHeader;
|
||||||
|
|
||||||
|
// read the elf header
|
||||||
|
ssize_t bytesRead = pread(fFD, &elfHeader, sizeof(Ehdr), 0);
|
||||||
|
if (bytesRead != (ssize_t)sizeof(Ehdr))
|
||||||
|
return bytesRead < 0 ? errno : B_ERROR;
|
||||||
|
|
||||||
|
// check the ELF header
|
||||||
|
if (!_CheckRange(0, sizeof(Ehdr)) || !_CheckElfHeader(elfHeader)) {
|
||||||
|
WARNING("\"%s\": Not an ELF file\n", fileName);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check section header table values
|
||||||
|
off_t sectionHeadersOffset = elfHeader.e_shoff;
|
||||||
|
size_t sectionHeaderSize = elfHeader.e_shentsize;
|
||||||
|
int sectionCount = elfHeader.e_shnum;
|
||||||
|
size_t sectionHeaderTableSize = sectionHeaderSize * sectionCount;
|
||||||
|
if (!_CheckRange(sectionHeadersOffset, sectionHeaderTableSize)) {
|
||||||
|
WARNING("\"%s\": Invalid ELF header\n", fileName);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the section header table
|
||||||
|
uint8* sectionHeaderTable = (uint8*)malloc(sectionHeaderTableSize);
|
||||||
|
if (sectionHeaderTable == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
MemoryDeleter sectionHeaderTableDeleter(sectionHeaderTable);
|
||||||
|
|
||||||
|
bytesRead = pread(fFD, sectionHeaderTable, sectionHeaderTableSize,
|
||||||
|
sectionHeadersOffset);
|
||||||
|
if (bytesRead != (ssize_t)sectionHeaderTableSize)
|
||||||
|
return bytesRead < 0 ? errno : B_ERROR;
|
||||||
|
|
||||||
|
// check and get the section header string section
|
||||||
|
Shdr* stringSectionHeader = (Shdr*)(sectionHeaderTable
|
||||||
|
+ elfHeader.e_shstrndx * sectionHeaderSize);
|
||||||
|
if (!_CheckRange(stringSectionHeader->sh_offset,
|
||||||
|
stringSectionHeader->sh_size)) {
|
||||||
|
WARNING("\"%s\": Invalid string section header\n", fileName);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
size_t sectionStringSize = stringSectionHeader->sh_size;
|
||||||
|
|
||||||
|
ElfSection* sectionStringSection = new(std::nothrow) ElfSection(".shstrtab",
|
||||||
|
fFD, stringSectionHeader->sh_offset, sectionStringSize,
|
||||||
|
stringSectionHeader->sh_addr, stringSectionHeader->sh_flags);
|
||||||
|
if (sectionStringSection == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
fSections.Add(sectionStringSection);
|
||||||
|
|
||||||
|
status_t error = sectionStringSection->Load();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
const char* sectionStrings = (const char*)sectionStringSection->Data();
|
||||||
|
|
||||||
|
// read the other sections
|
||||||
|
for (int i = 0; i < sectionCount; i++) {
|
||||||
|
Shdr* sectionHeader = (Shdr*)(sectionHeaderTable + i
|
||||||
|
* sectionHeaderSize);
|
||||||
|
// skip invalid sections and the section header string section
|
||||||
|
const char* name = sectionStrings + sectionHeader->sh_name;
|
||||||
|
if (sectionHeader->sh_name >= sectionStringSize
|
||||||
|
|| !_CheckRange(sectionHeader->sh_offset, sectionHeader->sh_size)
|
||||||
|
|| i == elfHeader.e_shstrndx) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create an ElfSection
|
||||||
|
ElfSection* section = new(std::nothrow) ElfSection(name, fFD,
|
||||||
|
sectionHeader->sh_offset, sectionHeader->sh_size,
|
||||||
|
sectionHeader->sh_addr, sectionHeader->sh_flags);
|
||||||
|
if (section == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
fSections.Add(section);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check program header table values
|
||||||
|
off_t programHeadersOffset = elfHeader.e_phoff;
|
||||||
|
size_t programHeaderSize = elfHeader.e_phentsize;
|
||||||
|
int segmentCount = elfHeader.e_phnum;
|
||||||
|
size_t programHeaderTableSize = programHeaderSize * segmentCount;
|
||||||
|
if (!_CheckRange(programHeadersOffset, programHeaderTableSize)) {
|
||||||
|
WARNING("\"%s\": Invalid ELF header\n", fileName);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the program header table
|
||||||
|
uint8* programHeaderTable = (uint8*)malloc(programHeaderTableSize);
|
||||||
|
if (programHeaderTable == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
MemoryDeleter programHeaderTableDeleter(programHeaderTable);
|
||||||
|
|
||||||
|
bytesRead = pread(fFD, programHeaderTable, programHeaderTableSize,
|
||||||
|
programHeadersOffset);
|
||||||
|
if (bytesRead != (ssize_t)programHeaderTableSize)
|
||||||
|
return bytesRead < 0 ? errno : B_ERROR;
|
||||||
|
|
||||||
|
// read the program headers and create ElfSegment objects
|
||||||
|
for (int i = 0; i < segmentCount; i++) {
|
||||||
|
Phdr* programHeader = (Phdr*)(programHeaderTable + i
|
||||||
|
* programHeaderSize);
|
||||||
|
// skip program headers we aren't interested in or that are invalid
|
||||||
|
if (programHeader->p_type != PT_LOAD || programHeader->p_filesz == 0
|
||||||
|
|| programHeader->p_memsz == 0
|
||||||
|
|| !_CheckRange(programHeader->p_offset, programHeader->p_filesz)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create an ElfSegment
|
||||||
|
ElfSegment* segment = new(std::nothrow) ElfSegment(
|
||||||
|
programHeader->p_offset, programHeader->p_filesz,
|
||||||
|
programHeader->p_vaddr, programHeader->p_memsz,
|
||||||
|
(programHeader->p_flags & PF_WRITE) != 0);
|
||||||
|
if (segment == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
fSegments.Add(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ElfFile::_CheckRange(off_t offset, off_t size) const
|
ElfFile::_CheckRange(off_t offset, off_t size) const
|
||||||
{
|
{
|
||||||
@@ -338,16 +350,32 @@ ElfFile::_CheckRange(off_t offset, off_t size) const
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ElfFile::_CheckElfHeader() const
|
ElfFile::_CheckElfHeader(Elf32_Ehdr& elfHeader)
|
||||||
{
|
{
|
||||||
return memcmp(fElfHeader->e_ident, ELF_MAGIC, 4) == 0
|
return memcmp(elfHeader.e_ident, ELF_MAGIC, 4) == 0
|
||||||
&& fElfHeader->e_ident[4] == ELFCLASS32
|
&& elfHeader.e_ident[4] == ELFCLASS32
|
||||||
&& fElfHeader->e_shoff > 0
|
&& elfHeader.e_shoff > 0
|
||||||
&& fElfHeader->e_shnum > 0
|
&& elfHeader.e_shnum > 0
|
||||||
&& fElfHeader->e_shentsize >= sizeof(struct Elf32_Shdr)
|
&& elfHeader.e_shentsize >= sizeof(struct Elf32_Shdr)
|
||||||
&& fElfHeader->e_shstrndx != SHN_UNDEF
|
&& elfHeader.e_shstrndx != SHN_UNDEF
|
||||||
&& fElfHeader->e_shstrndx < fElfHeader->e_shnum
|
&& elfHeader.e_shstrndx < elfHeader.e_shnum
|
||||||
&& fElfHeader->e_phoff > 0
|
&& elfHeader.e_phoff > 0
|
||||||
&& fElfHeader->e_phnum > 0
|
&& elfHeader.e_phnum > 0
|
||||||
&& fElfHeader->e_phentsize >= sizeof(struct Elf32_Phdr);
|
&& elfHeader.e_phentsize >= sizeof(struct Elf32_Phdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
ElfFile::_CheckElfHeader(Elf64_Ehdr& elfHeader)
|
||||||
|
{
|
||||||
|
return memcmp(elfHeader.e_ident, ELF_MAGIC, 4) == 0
|
||||||
|
&& elfHeader.e_ident[4] == ELFCLASS64
|
||||||
|
&& elfHeader.e_shoff > 0
|
||||||
|
&& elfHeader.e_shnum > 0
|
||||||
|
&& elfHeader.e_shentsize >= sizeof(struct Elf64_Shdr)
|
||||||
|
&& elfHeader.e_shstrndx != SHN_UNDEF
|
||||||
|
&& elfHeader.e_shstrndx < elfHeader.e_shnum
|
||||||
|
&& elfHeader.e_phoff > 0
|
||||||
|
&& elfHeader.e_phnum > 0
|
||||||
|
&& elfHeader.e_phentsize >= sizeof(struct Elf64_Phdr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
#include <elf32.h>
|
#include <elf32.h>
|
||||||
|
#include <elf64.h>
|
||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
@@ -90,13 +91,16 @@ private:
|
|||||||
typedef DoublyLinkedList<ElfSegment> SegmentList;
|
typedef DoublyLinkedList<ElfSegment> SegmentList;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
template<typename Ehdr, typename Phdr, typename Shdr>
|
||||||
|
status_t _LoadFile(const char* fileName);
|
||||||
|
|
||||||
bool _CheckRange(off_t offset, off_t size) const;
|
bool _CheckRange(off_t offset, off_t size) const;
|
||||||
bool _CheckElfHeader() const;
|
static bool _CheckElfHeader(Elf32_Ehdr& elfHeader);
|
||||||
|
static bool _CheckElfHeader(Elf64_Ehdr& elfHeader);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
off_t fFileSize;
|
off_t fFileSize;
|
||||||
int fFD;
|
int fFD;
|
||||||
Elf32_Ehdr* fElfHeader;
|
|
||||||
SectionList fSections;
|
SectionList fSections;
|
||||||
SegmentList fSegments;
|
SegmentList fSegments;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user