and with less double-compiling if you put a label at each svc instruction: void x() { __asm volatile( " mov x8, #1;" " _x: svc #0;" ); }
typedef unsigned long size_t; int w(void *what, size_t len) { __asm volatile( " mov x2, x1;" " mov x1, x0;" " mov w0, #1;" " mov x8, #4;" " _w: svc #0;" ); return 0; } void start() { w("hello\n", 6); x(); } __asm(" .section \".note.openbsd.ident\", \"a\"\n" " .p2align 2\n" " .long 8\n" " .long 4\n" " .long 1\n" " .ascii \"OpenBSD\\0\"\n" " .long 0\n" " .previous\n"); __asm( " .pushsection \".openbsd.syscalls\", \"\",@progbits\n" " .p2align 2\n" " .long _w, 4\n" " .long _x, 1\n" " .popsection\n"); and compile line would be something like: cc -c hello.c && ld -e start --eh-frame-hdr -Bstatic -o hello hello.o && ./hello Den lör 15 mars 2025 kl 09:34 skrev Janne Johansson <icepic...@gmail.com>: > > Den lör 15 mars 2025 kl 09:17 skrev Janne Johansson <icepic...@gmail.com>: > > > > This might also help: > > https://flak.tedunangst.com/post/dude-where-are-your-syscalls > > > > And the text hints at it, but the exact trick to figure out the > offsets to put in the "what" ELF section is to compile and link it > once, then run > > $ llvm-objdump hello3 -d|grep -B1 svc > 1047c: d2800028 mov x8, #0x1 > 10480: d4000001 svc #0 > -- > 104c8: d2800088 mov x8, #0x4 > 104cc: d4000001 svc #0 > > so that you can edit your source to: > > struct whats { > unsigned int offset; > unsigned int sysno; > } happening[] __attribute__((section(".openbsd.syscalls"))) = { > { 0x104cc, 4 }, > { 0x10480, 1 }, > }; > > and recompile and link again, then it works. A slight reshuffling of > the "not-C" code might also be needed, or the compiler will whine at > you for calling stuff without declaration of the functions. Binary > size down to some 2600 bytes after "strip"ing, and it's now "free" of > libc. Also, it is rather cumbersome to double-compile all the time. > > -- > May the most significant bit of your life be positive. -- May the most significant bit of your life be positive.