Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Change how arch/ works in preparation for 32-on-64 support.

  • Loading branch information...
commit 14f87543822c83003956391be46e8bfa8b46bd2b 1 parent 568c654
@nelhage authored
View
30 arch/amd64.h
@@ -19,16 +19,24 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#define orig_ax orig_rax
-#define reg_ax rax
-#define reg_ip rip
+#include "x86_common.h"
-#define syscall_rv rax
-#define syscall_arg0 rdi
-#define syscall_arg1 rsi
-#define syscall_arg2 rdx
-#define syscall_arg3 r10
-#define syscall_arg4 r8
-#define syscall_arg5 r9
+static struct ptrace_personality arch_personality[1] = {
+ {
+ offsetof(struct user, regs.rax),
+ offsetof(struct user, regs.rdi),
+ offsetof(struct user, regs.rsi),
+ offsetof(struct user, regs.rdx),
+ offsetof(struct user, regs.r10),
+ offsetof(struct user, regs.r8),
+ offsetof(struct user, regs.r9),
+ offsetof(struct user, regs.rip),
+ },
+};
-#include "x86_common.h"
+struct x86_personality x86_personality[1] = {
+ {
+ offsetof(struct user, regs.orig_rax),
+ offsetof(struct user, regs.rax),
+ },
+};
View
27 arch/arm.h
@@ -19,18 +19,21 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#define reg_ip ARM_pc
+static struct ptrace_personality arch_personality[1] = {
+ {
+ offsetof(struct user, regs.uregs[0]),
+ offsetof(struct user, regs.uregs[0]),
+ offsetof(struct user, regs.uregs[1]),
+ offsetof(struct user, regs.uregs[2]),
+ offsetof(struct user, regs.uregs[3]),
+ offsetof(struct user, regs.uregs[4]),
+ offsetof(struct user, regs.uregs[5]),
+ offsetof(struct user, regs.ARM_pc),
+ }
+};
-#define syscall_rv uregs[0]
-#define syscall_arg0 uregs[0]
-#define syscall_arg1 uregs[1]
-#define syscall_arg2 uregs[2]
-#define syscall_arg3 uregs[3]
-#define syscall_arg4 uregs[4]
-#define syscall_arg5 uregs[5]
-
-static inline void arch_fixup_regs(struct user *user) {
- user->regs.reg_ip -= 4;
+static inline void arch_fixup_regs(struct ptrace_child *child) {
+ child->user.regs.ARM_pc -= 4;
}
static inline int arch_set_syscall(struct ptrace_child *child,
@@ -40,7 +43,7 @@ static inline int arch_set_syscall(struct ptrace_child *child,
static inline int arch_save_syscall(struct ptrace_child *child) {
unsigned long swi;
- swi = ptrace_command(child, PTRACE_PEEKTEXT, child->user.regs.reg_ip);
+ swi = ptrace_command(child, PTRACE_PEEKTEXT, child->user.regs.ARM_pc);
if (child->error)
return -1;
if (swi == 0xef000000)
View
30 arch/i386.h
@@ -19,16 +19,24 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#define orig_ax orig_eax
-#define reg_ax eax
-#define reg_ip eip
+#include "x86_common.h"
-#define syscall_rv eax
-#define syscall_arg0 ebx
-#define syscall_arg1 ecx
-#define syscall_arg2 edx
-#define syscall_arg3 esi
-#define syscall_arg4 edi
-#define syscall_arg5 ebp
+static struct ptrace_personality arch_personality[1] = {
+ {
+ offsetof(struct user, regs.eax),
+ offsetof(struct user, regs.ebx),
+ offsetof(struct user, regs.ecx),
+ offsetof(struct user, regs.edx),
+ offsetof(struct user, regs.esi),
+ offsetof(struct user, regs.edi),
+ offsetof(struct user, regs.ebp),
+ offsetof(struct user, regs.eip),
+ }
+};
-#include "x86_common.h"
+struct x86_personality x86_personality[1] = {
+ {
+ offsetof(struct user, regs.orig_eax),
+ offsetof(struct user, regs.eax),
+ }
+};
View
28 arch/x86_common.h
@@ -19,23 +19,41 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-static inline void arch_fixup_regs(struct user *user) {
- user->regs.reg_ip -= 2;
- user->regs.reg_ax = user->regs.orig_ax;
+
+struct x86_personality {
+ size_t orig_ax;
+ size_t ax;
+};
+
+struct x86_personality x86_personality[];
+
+static inline struct x86_personality *x86_pers(struct ptrace_child *child) {
+ return &x86_personality[child->personality];
+}
+
+static inline void arch_fixup_regs(struct ptrace_child *child) {
+ struct x86_personality *x86pers = x86_pers(child);
+ struct ptrace_personality *pers = personality(child);
+ struct user *user = &child->user;
+#define ptr(user, off) ((unsigned long*)((void*)(user)+(off)))
+ *ptr(user, pers->reg_ip) -= 2;
+ *ptr(user, x86pers->ax) = *ptr(user, x86pers->orig_ax);
}
static inline int arch_set_syscall(struct ptrace_child *child,
unsigned long sysno) {
return ptrace_command(child, PTRACE_POKEUSER,
- offsetof(struct user, regs.orig_ax),
+ x86_pers(child)->orig_ax,
sysno);
}
static inline int arch_save_syscall(struct ptrace_child *child) {
- child->saved_syscall = child->user.regs.orig_ax;
+ child->saved_syscall = *ptr(&child->user, x86_pers(child)->orig_ax);
return 0;
}
static inline int arch_restore_syscall(struct ptrace_child *child) {
return 0;
}
+
+#undef ptr
View
31 ptrace.c
@@ -64,6 +64,20 @@ static long __ptrace_command(struct ptrace_child *child, enum __ptrace_request r
#define ptrace_command(cld, req, ...) _ptrace_command(cld, req, ## __VA_ARGS__, NULL, NULL)
#define _ptrace_command(cld, req, addr, data, ...) __ptrace_command((cld), (req), (void*)(addr), (void*)(data))
+
+struct ptrace_personality {
+ size_t syscall_rv;
+ size_t syscall_arg0;
+ size_t syscall_arg1;
+ size_t syscall_arg2;
+ size_t syscall_arg3;
+ size_t syscall_arg4;
+ size_t syscall_arg5;
+ size_t reg_ip;
+};
+
+struct ptrace_personality *personality(struct ptrace_child *child);
+
#if defined(__amd64__)
#include "arch/amd64.h"
#elif defined(__i386__)
@@ -74,6 +88,10 @@ static long __ptrace_command(struct ptrace_child *child, enum __ptrace_request r
#error Unsupported architecture.
#endif
+struct ptrace_personality *personality(struct ptrace_child *child) {
+ return &arch_personality[child->personality];
+}
+
int ptrace_attach_child(struct ptrace_child *child, pid_t pid) {
memset(child, 0, sizeof *child);
child->pid = pid;
@@ -168,16 +186,12 @@ int ptrace_advance_to_state(struct ptrace_child *child,
}
-static void reset_user_struct(struct user *user) {
- arch_fixup_regs(user);
-}
-
int ptrace_save_regs(struct ptrace_child *child) {
if (ptrace_advance_to_state(child, ptrace_at_syscall) < 0)
return -1;
if (ptrace_command(child, PTRACE_GETREGS, 0, &child->user) < 0)
return -1;
- reset_user_struct(&child->user);
+ arch_fixup_regs(child);
if (arch_save_syscall(child) < 0)
return -1;
return 0;
@@ -202,7 +216,7 @@ unsigned long ptrace_remote_syscall(struct ptrace_child *child,
#define setreg(r, v) do { \
if (ptrace_command(child, PTRACE_POKEUSER, \
- offsetof(struct user, regs.r), \
+ personality(child)->r, \
(v)) < 0) \
return -1; \
} while (0)
@@ -220,11 +234,12 @@ unsigned long ptrace_remote_syscall(struct ptrace_child *child,
return -1;
rv = ptrace_command(child, PTRACE_PEEKUSER,
- offsetof(struct user, regs.syscall_rv));
+ personality(child)->syscall_rv);
if (child->error)
return -1;
- setreg(reg_ip, child->user.regs.reg_ip);
+ setreg(reg_ip, *(unsigned long*)((void*)&child->user +
+ personality(child)->reg_ip));
#undef setreg
View
1  ptrace.h
@@ -35,6 +35,7 @@ enum child_state {
struct ptrace_child {
pid_t pid;
enum child_state state;
+ int personality;
int status;
int error;
unsigned long forked_pid;
Please sign in to comment.
Something went wrong with that request. Please try again.