* added breakpoints and stepping * add link register to allow single-stepping a ret instruction, fix stacktraces * refactor to avoid passing the IO layer structs to the breakpoint function * add tests, refine the stacktrace to not include non-function * add register information for core file parsing * core file generation for RISC-V * make tests run under riscv-64 * make tests run under riscv-32
193 lines
5 KiB
C
193 lines
5 KiB
C
// SPDX-FileCopyrightText: 2015 Álvaro Felipe Melchor <alvaro.felipe91@gmail.com>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
/* __
|
|
-=(o '.
|
|
\.-.\
|
|
/| \\
|
|
'| ||
|
|
_\_):,_
|
|
*/
|
|
|
|
#ifndef LINUX_DEBUG_H
|
|
#define LINUX_DEBUG_H
|
|
|
|
#include <rz_debug.h>
|
|
#include <limits.h>
|
|
|
|
struct user_regs_struct_x86_64 {
|
|
ut64 r15;
|
|
ut64 r14;
|
|
ut64 r13;
|
|
ut64 r12;
|
|
ut64 rbp;
|
|
ut64 rbx;
|
|
ut64 r11;
|
|
ut64 r10;
|
|
ut64 r9;
|
|
ut64 r8;
|
|
ut64 rax;
|
|
ut64 rcx;
|
|
ut64 rdx;
|
|
ut64 rsi;
|
|
ut64 rdi;
|
|
ut64 orig_rax;
|
|
ut64 rip;
|
|
ut64 cs;
|
|
ut64 eflags;
|
|
ut64 rsp;
|
|
ut64 ss;
|
|
ut64 fs_base;
|
|
ut64 gs_base;
|
|
ut64 ds;
|
|
ut64 es;
|
|
ut64 fs;
|
|
ut64 gs;
|
|
};
|
|
|
|
struct user_regs_struct_x86_32 {
|
|
ut32 ebx;
|
|
ut32 ecx;
|
|
ut32 edx;
|
|
ut32 esi;
|
|
ut32 edi;
|
|
ut32 ebp;
|
|
ut32 eax;
|
|
ut32 xds;
|
|
ut32 xes;
|
|
ut32 xfs;
|
|
ut32 xgs;
|
|
ut32 orig_eax;
|
|
ut32 eip;
|
|
ut32 xcs;
|
|
ut32 eflags;
|
|
ut32 esp;
|
|
ut32 xss;
|
|
};
|
|
|
|
#if __ANDROID__
|
|
|
|
#if __arm64__ || __aarch64__
|
|
#define RZ_DEBUG_REG_T struct user_pt_regs
|
|
|
|
#ifndef NT_PRSTATUS
|
|
#define NT_PRSTATUS 1
|
|
#endif
|
|
|
|
#else
|
|
#define RZ_DEBUG_REG_T struct pt_regs
|
|
#endif
|
|
|
|
#else
|
|
|
|
#include <sys/user.h>
|
|
#if __i386__ || __x86_64__
|
|
#define RZ_DEBUG_REG_T struct user_regs_struct
|
|
#elif __s390x__ || __s390__
|
|
#define RZ_DEBUG_REG_T struct _user_regs_struct
|
|
#if 0
|
|
// https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/s390/sys/user.h;hb=HEAD#l50
|
|
50 struct _user_regs_struct
|
|
51 {
|
|
52 struct _user_psw_struct psw; /* Program status word. */
|
|
53 unsigned long gprs[16]; /* General purpose registers. */
|
|
54 unsigned int acrs[16]; /* Access registers. */
|
|
55 unsigned long orig_gpr2; /* Original gpr2. */
|
|
56 struct _user_fpregs_struct fp_regs; /* Floating point registers. */
|
|
57 struct _user_per_struct per_info; /* Hardware tracing registers. */
|
|
58 unsigned long ieee_instruction_pointer; /* Always 0. */
|
|
59 };
|
|
#endif
|
|
#elif __arm64__ || __aarch64__
|
|
#include <asm/ptrace.h>
|
|
#ifndef NT_PRSTATUS
|
|
#define NT_PRSTATUS 1
|
|
#endif
|
|
#define RZ_DEBUG_REG_T struct user_pt_regs
|
|
#elif __arm__
|
|
#define RZ_DEBUG_REG_T struct user_regs
|
|
#elif __POWERPC__
|
|
struct powerpc_regs_t {
|
|
unsigned long gpr[32];
|
|
unsigned long nip;
|
|
unsigned long msr;
|
|
unsigned long orig_gpr3; /* Used for restarting system calls */
|
|
unsigned long ctr;
|
|
unsigned long link;
|
|
unsigned long xer;
|
|
unsigned long ccr;
|
|
#ifdef __powerpc64__
|
|
unsigned long softe; /* Soft enabled/disabled */
|
|
#else
|
|
unsigned long mq; /* 601 only (not used at present) */
|
|
/* Used on APUS to hold IPL value. */
|
|
#endif
|
|
unsigned long trap; /* Reason for being here */
|
|
/* N.B. for critical exceptions on 4xx, the dar and dsisr
|
|
fields are overloaded to hold srr0 and srr1. */
|
|
unsigned long dar; /* Fault registers */
|
|
unsigned long dsisr; /* on 4xx/Book-E used for ESR */
|
|
unsigned long result; /* Result of a system call */
|
|
};
|
|
#define RZ_DEBUG_REG_T struct powerpc_regs_t
|
|
#elif __riscv || __riscv__ || __riscv64__
|
|
|
|
#include <sys/ucontext.h>
|
|
#include <asm/ptrace.h>
|
|
|
|
#define RZ_DEBUG_REG_T struct user_regs_struct
|
|
#define RZ_DEBUG_FPREG32_T __riscv_f_ext_state
|
|
#define RZ_DEBUG_FPREG64_T __riscv_d_ext_state
|
|
#define RZ_DEBUG_FPREG128_T __riscv_q_ext_state
|
|
#define RZ_DEBUG_VREG_T __riscv_v_regset_state
|
|
|
|
#elif __loongarch64
|
|
#include <sys/ucontext.h>
|
|
#include <asm/ptrace.h>
|
|
#define RZ_DEBUG_REG_T struct user_regs_struct
|
|
|
|
// #define RZ_DEBUG_REG_T mcontext_t 77 784 in size (coz the fpu regs)
|
|
|
|
#elif __mips__
|
|
|
|
#include <sys/ucontext.h>
|
|
typedef ut64 mips64_regs_t[274];
|
|
#define RZ_DEBUG_REG_T mips64_regs_t
|
|
#endif
|
|
#endif
|
|
|
|
// SIGTRAP si_codes from <asm/siginfo.h>
|
|
#if !defined(TRAP_BRKPT) && !defined(TRAP_TRACE)
|
|
#define TRAP_BRKPT 1
|
|
#define TRAP_TRACE 2
|
|
#define TRAP_BRANCH 3
|
|
#define TRAP_HWBKPT 4
|
|
#define TRAP_UNK 5
|
|
#endif
|
|
|
|
// API
|
|
bool linux_set_options(RzDebug *dbg, int pid);
|
|
int linux_step(RzDebug *dbg);
|
|
RzDebugReasonType linux_ptrace_event(RzDebug *dbg, int pid, int status, bool dowait);
|
|
int linux_attach(RzDebug *dbg, int pid);
|
|
bool linux_attach_new_process(RzDebug *dbg, int pid);
|
|
RzDebugInfo *linux_info(RzDebug *dbg, const char *arg);
|
|
RzList /*<RzDebugPid *>*/ *linux_pid_list(int pid, RzList /*<RzDebugPid *>*/ *list);
|
|
RzList /*<RzDebugPid *>*/ *linux_thread_list(RzDebug *dbg, int pid, RzList /*<RzDebugPid *>*/ *list);
|
|
bool linux_select(RzDebug *dbg, int pid, int tid);
|
|
RZ_API ut64 get_linux_tls_val(RZ_NONNULL RzDebug *dbg, int tid);
|
|
RzDebugPid *fill_pid_info(const char *info, const char *path, int tid);
|
|
int linux_reg_read(RzDebug *dbg, int type, ut8 *buf, int size);
|
|
int linux_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size);
|
|
RzList /*<RzDebugDesc *>*/ *linux_desc_list(int pid);
|
|
bool linux_stop_threads(RzDebug *dbg, int except);
|
|
int linux_handle_signals(RzDebug *dbg, int tid);
|
|
RzDebugReasonType linux_dbg_wait(RzDebug *dbg, int pid);
|
|
char *linux_reg_profile(RzDebug *dbg);
|
|
int match_pid(const void *pid_o, const void *th_o, void *user);
|
|
RzDebugMap *linux_map_alloc(RzDebug *dbg, ut64 addr, int size, bool thp);
|
|
int linux_map_dealloc(RzDebug *dbg, ut64 addr, int size);
|
|
RzList /*<RzDebugMap *>*/ *linux_map_get(RzDebug *dbg);
|
|
int linux_map_protect(RzDebug *dbg, ut64 addr, int size, int perms);
|
|
|
|
#endif
|