Copyright (C) 2022-2025 phantom (phantom@syslbnth.com) (See end of file for copying information.) Within this directory is a file, "domme.asm", that contains a short routine, $domme, that attaches itself to a user-provided SIGSEGV signal handler. When a segfault (short for "segmentation fault", an illegal memory access) occurs, the routine will print a randomly-selected message and then jump directly to the start of the handler; conceptually, it is like a preamble prepended to the start of the handler. On arrival at the handler, any arguments passed by the kernel will appear unmodified in their expected registers; if the default behavior for SIGSEGV on UNIX-like systems--crash and core dump--is registered via $domme, $domme will not appear on the call stack in a subsequent backtrace. In both these ways $domme attempts to appear as though it had never executed, and so avoid getting in the way of error correction and debugging, respectively. Furthermore, for this reason, $domme must assure the preservation, while executing, of certain registers set by the kernel on entering userspace, which are inaccessible from the glibc ABI but may, in principle, be accessed by the handler, as the handler could have been written in any language-- for instance, Assembly. On top of that, a handler originally written to be run without interception, may have been written to expect the address of the signal trampoline to be at the top of the stack, and for kernel-provided data to be at a known offset from the top of the stack. To accomplish this, $domme has to be able jump directly to the start of the handler, rather than making a subroutine call and consequently pushing a new return address onto the stack. The result of all of this is that $domme is itself written in Assembly. Like most assembly programs, it is highly playform-specific; it was written for an x86-64 CPU interfacing with the Linux kernel. Before $domme is run, it may be initialized by calling $DOMME_init and passing it the address of a sigaction, the primary signal-handling data structure on UNIX-like systems; if this address is 0, $DOMME_init allocates its own sigaction with default settings and passes it directly to the kernel, removing the need to declare your own. If no such initialization is detected when a segfault occurs, $domme will register the default behavior for the signal and return. The program will then re-attempt the illegal access and properly fall to pieces (and this is why $domme will not appear in the resulting backtrace). You can also call $domme during normal execution; it will print a randomly selected message and return. $DOMME_init accepts two more arguments: the address of a buffer to store a program's previous SIGSEGV sigaction in, if any (this is optional; null pointers are ignored,) and a non-optional $sigsetsize, the size of the sigset_t datatype used by your standard library or programming environment, as opposed to the sigset_t datatype used internally by the kernel (which $domme converts your sigset_t into). In C, you would typically write DOMME_init(NULL, NULL, sizeof(sigset_t)); at or near the beginning of $main (ideally before you have a chance to segfault!) and that would be the end of it. This returns 0 if successful, or -$EFAULT if either of the addresses passed is neither zero nor mapped to anything. Alternatively you could write: DOMME_init_easy(); which requires no arguments or setup, allows the resulting SIGSEGV handler to catch stack overflow on an alternate signal stack, and is as much a one-liner in assembly as in a high-level language (which can't be said for the general-purpose $DOMME_init). This file, "domme.asm", is position-independent. You can assemble it, turn it into a shared library with "ld" (with the name "libdomme.so", for example,) then link it into any program you like (with an "-ldomme" option from GCC, for example). It even implements its own signal trampoline, so you don't need libc--or even C--to use it. You do need to explicitly set the program's interpreter to "ld.so" when linking with an assembly program, since the library is dynamic. Invoking "ld" like this: ld bin.o -L. -I/lib64/ld-linux-x86-64.so.2 -ldomme -o bin should do the trick, provided you replace "/lib64/ld-linux-x86-64.so.2" with whatever the dynamic linker is named on your computer. (I am now obligated to say: This is the work of an amateur tinkerer going way out of their league. Run at your own risk.) To install: 1. Run "make" to compile the library. 2. Run "make check" to run a short test program. You can run this if you feel nervous about building a recent commit. You should _definitely_ run this if you make changes to either "domme.asm" or "domme.h". Essentially, the test program makes sure the variables defined in "domme.h" point to valid memory, then jumps to address 0 to force a segfault and see if "domme" reacts as expected. 3. Optionally, run "make utils" to compile and test a utility program for editing part of the library. 4. Run "make install" to place the library and header where your compiler can find them (typically "/usr/lib64/" and "/usr/include/", repectively). 5. Run "make clean" to remove files left over after compilation. Note that, in case you haven't noticed already, program symbols are prefixed with a '$' in comments and documentation. ------------------------------------------------------------------------ ...and now that all of this has been established, let's talk about what we're really looking at here. segfaults are probably the most common error in C code ($domme was originally drafted in C, before the technical requirements detailed above forced me to switch to assembly) and can be painful to pick apart. often you'll patch one bad access only to run into another as a result of the patch. chains of function pointers, webs of multilinked data structures, layers of address arithmetic--all of it can be very complex, precise, demanding. the worst bugs can take a long time to trace. but i like it. and not in the stuffy way someone brags about walking to school in the snow, uphill both ways, like some escherian sisyphus. i mean i'm into it. i mean, i'm _really_ into it. i thrill at the cyborg trance i fall into as i debug these errors, the cycle of edit, recompile, crash, tweak, recompile, burn, edit again. i drop out of the world, flow from action to action; it is painful, and suspenseful, and excruciating, and the pain is what makes it work. the pain, transfixed, electrifies it. i am fascinated by the eroticism latent in, inherent to, human-machine interaction, the unreal appeal of getting totally fucking wired. it's a subtext that has run like an undercurrent through humanity's interactions with machines, particularly industrial machines, and especially computers, almost from first contact. on rare and fortunate occasions, it becomes the text. this cute little program is an exploration of this concept, one among many. it was also, if we're being completely honest, written to spice up those long debugging sessions. i am maybe some kind of Actual Masochist. we'll see. the "randomly selected messages" i kept nudging at above are alternately absurd, suggestive and explicit, and, i hope, slip between the three frequently enough to catch you off guard, like any good flirt. it's not safe for work in the literal sense that you probably don't want this in the source code of a public-facing repository. but otherwise, you may do as you please. ----------------------------------------------------------------------- This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see .