Skip to content

Commit

Permalink
Prep some breakpoint work
Browse files Browse the repository at this point in the history
  • Loading branch information
dd86k committed Sep 29, 2024
1 parent f12ec89 commit d921e66
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 44 deletions.
8 changes: 5 additions & 3 deletions src/adbg/include/linux/ptrace.d
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,16 @@ enum { // __ptrace_setoptions
PT_O_SUSPEND_SECCOMP = 0x00200000, /// syspend on seccomp
PT_O_MASK = 0x003000ff /// mask
}
enum { // __ptrace_eventcodes
enum { // __ptrace_eventcodes (used with PTRACE_GETEVENTMSG)
PT_EVENT_FORK = 1, /// fork event
PT_EVENT_VFORK = 2, /// vfork event
PT_EVENT_CLONE = 3, /// clone event
PT_EVENT_EXEC = 4, /// exec event
PT_EVENT_VFORK_DONE = 5, /// vfork done event
PT_EVENT_VFORK_DONE = 5, /// vfork done event
PT_EVENT_EXIT = 6, /// exit event
PT_EVENT_SECCOMP = 7 /// seccomp event
PT_EVENT_SECCOMP = 7, /// seccomp event
/// Extended result codes which enabled by means other than options.
PT_EVENT_STOP = 128,
}

/// The ptrace() system call provides a means by which one process (the
Expand Down
15 changes: 9 additions & 6 deletions src/adbg/process/base.d
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,16 @@ version (Windows) { // Original identifiers; Otherwise informal
// This is done on a per-function basis for permissions
// and memory management (opening and closing handles)
// purposes.
int pid; /// Process identificiation number
int tid; /// Thread identification number
int pid; /// Event Process ID
int tid; /// Event Thread ID
char *args; /// Saved arguments when process was launched
// TODO: Deprecate hpid and htid
HANDLE htid; /// Thread handle
HANDLE hpid; /// Process handle
}
version (Posix) {
pid_t pid; /// Process ID
pid_t tid; /// HACK: Thread ID
pid_t pid; /// Event Process ID
pid_t tid; /// HACK: Event Thread ID
// On Linux, the starting thread ID is the same as the process ID
char **argv; /// Saved arguments when process was launched
}
Expand All @@ -95,8 +95,10 @@ version (linux) {
AdbgProcStatus status;
/// Process' creation source.
AdbgCreation creation;
/// List of threads
/// List of threads.
list_t *thread_list;
/// List of breakpoints.
list_t *breakpoint_list;

// HACK: Some client debuggers, like the shell, will save the stopped
// process pointer in global memory. Because stack memory references
Expand Down Expand Up @@ -272,7 +274,8 @@ version (LinuxPersonality) {
path[8] = 0;
char *end = void;
uint personality = cast(uint)strtol(path.ptr, &end, 16);
if (personality & ADDR_LIMIT_32BIT) return PERSO32;
enum LINUX32 = PER_LINUX_32BIT | PER_LINUX32 | PER_LINUX32_3GB;
if (personality & LINUX32) return PERSO32;
}
return adbg_machine_current();
}
Expand Down
107 changes: 72 additions & 35 deletions src/adbg/process/breakpoint.d
Original file line number Diff line number Diff line change
Expand Up @@ -6,62 +6,99 @@
module adbg.process.breakpoint;

import adbg.process.base;
import adbg.process.memory;
import adbg.error;
import adbg.utils.list;
import adbg.utils.bit;

extern (C):

// NOTE: When a breakpoint is hit by the debugger, the address should
// be checked against the process' breakpoint list.

// TODO: Test Thumb BKPT
// TODO: Test AArch32 BKPT
// TODO: Test AArch64 BRK

// TODO: Move opcode bits to dedicated module
version (X86) {
private alias ubyte opcode_t;
private enum opcode_t BREAKPOINT = 0xCC; // INT3
private immutable ubyte[] bpdata = [ 0xcc ]; // int3
} else version (X86_64) {
private alias ubyte opcode_t;
private enum opcode_t BREAKPOINT = 0xCC; // INT3
private immutable ubyte[] bpdata = [ 0xcc ]; // int3
} else version (ARM_Thumb) {
// Thumb BKPT
// 1 index
// 5432 1098 7654 3210
// 1011 1110 | |
// +-imm8--+
private template T16BKPT(ubyte n) {
enum T16BKPT = ARRAY16!(0xbe << 8 | n);
/*
version (BigEndian)
enum ubyte[2] T16BKPT = [ 0xbe, n ];
else
enum ubyte[2] T16BKPT = [ n, 0xbe ];
*/
}
private alias ushort opcode_t;
version (LittleEndian)
private enum opcode_t BREAKPOINT = 0xDDBE; // BKPT #221 (0xdd)
else
private enum opcode_t BREAKPOINT = 0xBEDD; // BKPT #221 (0xdd)
private immutable ubyte[] bpdata = T16BKPT!(0xdd);
//private immutable ubyte[] bpdata = [ 0xbe, 0xdd ]; // BRK #221
} else version (ARM) {
// AArch32 BKPT
// 3 2 1 index
// 1098 7654 3210 9876 5432 1098 7654 3210
// | | 0001 0010 | | 0111 | |
// cond(!=1110) +---imm12----+ imm4 - imm12:imm4
private template A32BKPT(ushort n) {
enum A32BKPT = ARRAY32!(0xe12 << 20 | (n >> 4) << 8 | 7 << 4 | n & 15);
/*
version (BigEndian)
enum ubyte[4] A32BKPT = [ 0xe1, 0x20 | (n >> 12), (n >> 4) & 255, 0x70 | (n & 15) ];
else
enum ubyte[4] A32BKPT = [ 0x70 | (n & 15), (n >> 4) & 255, 0x20 | (n >> 12), 0xe1 ];
*/
}
private alias uint opcode_t;
version (LittleEndian)
private enum opcode_t BREAKPOINT = 0x7D0D20E1; // BKPT #221 (0xdd)
else
private enum opcode_t BREAKPOINT = 0xE1200D7D; // BKPT #221 (0xdd)
private immutable ubyte[] bpdata = A32BKPT!(0xdd);
//private immutable ubyte[] bpdata = [ 0xe1, 0x20, 0x0d, 0x7d ]; // BRK #221
} else version (AArch64) {
// AArch64 BRK
// 3 2 1 index
// 1098 7654 3210 9876 5432 1098 7654 3210
// 1101 0100 001| |0 0000
// +-------imm16------+
private template A64BRK(ushort n) {
enum A64BRK = ARRAY32!(0xd42 << 21 | n << 5);
/*
version (BigEndian)
enum ubyte[4] A64BRK = [ 0xd4, n >> 11, (n >> 3) & 255, (n & 7) << 5 ];
else
enum ubyte[4] A64BRK = [ (n & 7) << 5, (n >> 3) & 255, n >> 11, 0xd4 ];
*/
}
private alias uint opcode_t;
// NOTE: Checked under ODA, endianness seems to be moot
version (LittleEndian)
private enum opcode_t BREAKPOINT = 0xA01B20D4; // BKPT #221 (0xdd)
else
private enum opcode_t BREAKPOINT = 0xA01B20D4; // BKPT #221 (0xdd)
private immutable ubyte[] bpdata = A64BRK!(0xdd);
//private immutable ubyte[] bpdata = [ 0xa0, 0x1b, 0x20, 0xd4 ]; // BRK #221
} else
static assert(0, "Missing BREAKPOINT value for target platform");

struct adbg_breakpoints_t {
adbg_breakpoint_t *list;
size_t count;
private enum bplength = bpdata.length;

// Breakpoint layout in memory
struct adbg_breakpoint_t { align(1):
union {
opcode_t opcode;
ubyte[bplength] opdata;
}
int magic;
int id;
}
struct adbg_breakpoint_t {

struct adbg_breakpoint_entry_t {
size_t address;
opcode_t opcode;
}

int adbg_breakpoint_set(adbg_process_t *tracee, size_t addr) {
return adbg_oops(AdbgError.unimplemented);
}
int adbg_breakpoint_get(adbg_process_t *tracee, size_t addr) {
return adbg_oops(AdbgError.unimplemented);
}
int adbg_breakpoint_list(adbg_process_t *tracee, adbg_breakpoints_t *list) {
return adbg_oops(AdbgError.unimplemented);
}
int adbg_breakpoint_unset(adbg_process_t *tracee, size_t address) {
return adbg_oops(AdbgError.unimplemented);
}
int adbg_breakpoint_unset_all(adbg_process_t *tracee) {
return adbg_oops(AdbgError.unimplemented);
}
// TODO: Breakpoint API
// Add, remove, get list, etc. + initiate function

0 comments on commit d921e66

Please sign in to comment.