aboutsummaryrefslogtreecommitdiffstats
path: root/linux
diff options
context:
space:
mode:
Diffstat (limited to 'linux')
-rw-r--r--linux/os.h32
-rw-r--r--linux/x86-64.h86
2 files changed, 118 insertions, 0 deletions
diff --git a/linux/os.h b/linux/os.h
new file mode 100644
index 0000000..db22f10
--- /dev/null
+++ b/linux/os.h
@@ -0,0 +1,32 @@
+/* See LICENSE file for copyright and license details. */
+#include <linux/elf.h>
+#include <sys/ptrace.h>
+#include <linux/ptrace.h> /* after <sys/ptrace.h> */
+#include <sys/syscall.h>
+#include <sys/user.h>
+
+#ifndef ERESTARTSYS
+# define ERESTARTSYS 512
+# define ALSO_ERESTARTSYS
+#endif
+#ifndef ERESTARTNOINTR
+# define ERESTARTNOINTR 513
+# define ALSO_ERESTARTNOINTR
+#endif
+#ifndef ERESTARTNOHAND
+# define ERESTARTNOHAND 514
+# define ALSO_ERESTARTNOHAND
+#endif
+#ifndef ERESTART_RESTARTBLOCK
+# define ERESTART_RESTARTBLOCK 516
+# define ALSO_ERESTART_RESTARTBLOCK
+#endif
+
+#define RETURN_IS_ERROR(RET)\
+ ((RET) > -(unsigned long long int)PAGE_SIZE) /* Don't know the actual limit, but this seems safe */
+
+#if defined(__x86_64__) && !defined(__IPL32__)
+# include "x86-64.h"
+#else
+# error "This program is only implemented for x86-64 on Linux"
+#endif
diff --git a/linux/x86-64.h b/linux/x86-64.h
new file mode 100644
index 0000000..16ff32f
--- /dev/null
+++ b/linux/x86-64.h
@@ -0,0 +1,86 @@
+/* See LICENSE file for copyright and license details. */
+struct i386_user_regs_struct
+{
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+ uint32_t esi;
+ uint32_t edi;
+ uint32_t ebp;
+ uint32_t eax;
+ uint32_t xds;
+ uint32_t xes;
+ uint32_t xfs;
+ uint32_t xgs;
+ uint32_t orig_eax;
+ uint32_t eip;
+ uint32_t xcs;
+ uint32_t eflags;
+ uint32_t esp;
+ uint32_t xss;
+};
+
+#define SYSCALL_NUM_REG orig_rax
+#define SYSCALL_RET_REG rax
+
+enum {
+ x86_64 = 0,
+ x32,
+ i386
+};
+
+#define CHECK_ARCHITECTURE(proc, regsp)\
+ do {\
+ struct iovec iov = {\
+ .iov_base = (regsp),\
+ .iov_len = sizeof(*(regsp)),\
+ };\
+ if (ptrace(PTRACE_GETREGSET, (proc)->pid, NT_PRSTATUS, &iov)) {\
+ eprintf("ptrace PTRACE_GETREGSET %ju NT_PRSTATUS {.iov_base=<buffer>, .iov_len=%zu}:",\
+ (uintmax_t)(proc)->pid, sizeof(*(regsp)));\
+ } else if (iov.iov_len != sizeof(*(regsp))) {\
+ if ((proc)->mode != i386) {\
+ (proc)->mode = i386;\
+ (proc)->long_is_int = 1;\
+ (proc)->ptr_is_int = 1;\
+ (proc)->scall_xor = 0;\
+ tprintf(proc, "Process is running in i386 mode, this is not yet supported\n"); /* TODO */\
+ exit(1);\
+ }\
+ } else if ((proc)->scall & __X32_SYSCALL_BIT) {\
+ if ((proc)->mode != x32) {\
+ (proc)->mode = x32;\
+ (proc)->long_is_int = 0;\
+ (proc)->ptr_is_int = 1;\
+ (proc)->scall_xor = __X32_SYSCALL_BIT;\
+ tprintf(proc, "Process is running in x32 mode (support is untested)\n");\
+ }\
+ } else {\
+ if ((proc)->mode != x86_64) {\
+ (proc)->mode = x86_64;\
+ (proc)->long_is_int = 0;\
+ (proc)->ptr_is_int = 0;\
+ (proc)->scall_xor = 0;\
+ tprintf(proc, "Process is running in x86-64 mode\n");\
+ }\
+ }\
+ } while (0)
+
+#define GET_SYSCALL_ARGUMENTS(proc, regsp)\
+ do {\
+ if ((proc)->mode != i386) {\
+ (proc)->args[0] = (regsp)->rdi;\
+ (proc)->args[1] = (regsp)->rsi;\
+ (proc)->args[2] = (regsp)->rdx;\
+ (proc)->args[3] = (regsp)->r10;\
+ (proc)->args[4] = (regsp)->r8;\
+ (proc)->args[5] = (regsp)->r9;\
+ } else {\
+ (proc)->args[0] = ((const struct i386_user_regs_struct *)(regsp))->ebx;\
+ (proc)->args[1] = ((const struct i386_user_regs_struct *)(regsp))->ecx;\
+ (proc)->args[2] = ((const struct i386_user_regs_struct *)(regsp))->edx;\
+ (proc)->args[3] = ((const struct i386_user_regs_struct *)(regsp))->esi;\
+ (proc)->args[4] = ((const struct i386_user_regs_struct *)(regsp))->edi;\
+ (proc)->args[5] = ((const struct i386_user_regs_struct *)(regsp))->ebp;\
+ }\
+ } while (0)