From 59aa0dcb991177ccdc0d7887d7af0779fde4ebf3 Mon Sep 17 00:00:00 2001 From: Piotr Kubaj Date: Sun, 18 Oct 2026 23:33:41 +0200 Subject: [PATCH] Add FreeBSD/powerpc64 support FreeBSD runs on 64-bit PowerPC (powerpc64 and powerpc64le), but reptyr did not build there: ptrace.h includes for any PowerPC compiler, and the FreeBSD ptrace backend has no arch header for it. Include only on Linux, where the PowerPC and RISC-V register structs come from, and add platform/freebsd/arch/powerpc64.h. The FreeBSD powerpc64 system call ABI (both ELFv1 and ELFv2, either endianness) puts the system call number in r0, the arguments in r3-r10 and the result in r3, so all six arguments reptyr passes fit in registers. SRR0 points past the 4-byte sc instruction when a system call stops, so arch_fixup_regs() rewinds the PC by 4 like the AArch64 code. Tested on FreeBSD 15.1 powerpc64le (POWER9). --- platform/freebsd/arch/powerpc64.h | 63 +++++++++++++++++++++++++++++++ platform/freebsd/freebsd_ptrace.c | 2 + ptrace.h | 5 +-- 3 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 platform/freebsd/arch/powerpc64.h diff --git a/platform/freebsd/arch/powerpc64.h b/platform/freebsd/arch/powerpc64.h new file mode 100644 index 0000000..a05c2e0 --- /dev/null +++ b/platform/freebsd/arch/powerpc64.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2026, Piotr Kubaj. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* + * FreeBSD/powerpc64 (ELFv1 and ELFv2, either endianness): the system call + * number goes in r0, the arguments in r3-r10 and the result comes back in + * r3, so all six arguments reptyr passes fit in registers. + */ +static struct ptrace_personality arch_personality[1] = { + { + offsetof(struct reg, fixreg[3]), + offsetof(struct reg, fixreg[3]), + offsetof(struct reg, fixreg[4]), + offsetof(struct reg, fixreg[5]), + offsetof(struct reg, fixreg[6]), + offsetof(struct reg, fixreg[7]), + offsetof(struct reg, fixreg[8]), + offsetof(struct reg, pc), + offsetof(struct reg, fixreg[1]), + } +}; + +#define ptr(regs, off) ((unsigned long*)((void*)(regs)+(off))) + +static inline void arch_fixup_regs(struct ptrace_child *child, struct reg *regs) { + /* SRR0 already points past the 4-byte sc instruction. */ + regs->pc -= 4; +} + +static inline void arch_set_register(struct ptrace_child *child, unsigned long oft, unsigned long val) +{ + struct reg regs; + + (void)ptrace_command(child, PT_GETREGS, ®s); + *ptr(®s, oft) = val; + (void)ptrace_command(child, PT_SETREGS, ®s); +} + +static inline void arch_set_syscall(struct ptrace_child *child, + unsigned long sysno) { + arch_set_register(child, offsetof(struct reg, fixreg[0]), sysno); +} + +#undef ptr diff --git a/platform/freebsd/freebsd_ptrace.c b/platform/freebsd/freebsd_ptrace.c index 5c27f7e..e5b9ea6 100644 --- a/platform/freebsd/freebsd_ptrace.c +++ b/platform/freebsd/freebsd_ptrace.c @@ -75,6 +75,8 @@ static struct ptrace_personality *personality(struct ptrace_child *child); #include "arch/arm.h" #elif defined(__aarch64__) #include "arch/aarch64.h" +#elif defined(__powerpc64__) +#include "arch/powerpc64.h" #else #error Unsupported architecture. #endif diff --git a/ptrace.h b/ptrace.h index dbb62bb..a17c20e 100644 --- a/ptrace.h +++ b/ptrace.h @@ -22,10 +22,7 @@ #ifndef PTRACE_H #define PTRACE_H -#ifdef __powerpc__ -#include -#endif -#ifdef __riscv +#if defined(__linux__) && (defined(__powerpc__) || defined(__riscv)) #include #endif #include