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:
Alex Smith
2012-12-19 19:54:20 +00:00
parent bbdb605224
commit c8d82cf6db
13 changed files with 1191 additions and 141 deletions
+2 -2
View File
@@ -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
+2
View File
@@ -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
+7
View File
@@ -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, alex@alex-smith.me.uk.
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2011-2012, Rene Gollent, rene@gollent.com.
* 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, 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.
*/
#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
View File
@@ -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);
} }
+6 -2
View File
@@ -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;
}; };