I've written before about a simple user-space approach to intercepting and modifying system calls, by turning system calls into SIGILL and then executing the perhaps-modified system call in the signal handler. I also mentioned that handling clone(), Linux's system call for creating a new thread, is challenging in this context. Let's imagine we want our handler firstly to print out a message, then to do the original clone(), and then return to the original caller (twice, naturally!). Since the...| Rambles around computer science
Python's os.path.abspath or Path.absolute are great: you give them a path, which might not exist, and you get a path you can use regardless of the current directory. os.path.abspath will also normalize it, while Path will not by default because with Paths a normal form is less needed. This is great to normalize input, regardless of if it's an existing file you're needing to open, or a new file you're needing to create. In C++17, there is a filesystem library with methods with enticingly simil...| Enrico's blog
str.endswith() can take a tuple of possible endings instead of a single string About JACK and Debian There are 3 JACK implementations: jackd1, jackd2, pipewire-jack. jackd1 is mostly superseded in favour of jackd2, and as far as I understand, can be ignored pipewire-jack integrates well with pipewire and the rest of the Linux audio world jackd2 is the native JACK server. When started it handles the sound card directly, and will steal it from pipewire. Non-JACK audio applications will likely c...| Enrico's blog
[Obligatory banner-esque note: between now and August-ish I'm prospecting for crowdfunding that might support my research and writing in the future, as I move to being only a part-time academic. Read more in my earlier post, or you can directly drop me a no-commitment HTML form submission if you think you might be able to contribute, or e-mail me. Thanks so much to everyone who has done so already! Also, moral support is support too, and is appreciated. :-)] I recently(-ish) spent a while on ...| Rambles around computer science
In my last post I floated the idea of writing a slow, edit-prone shell script instead as a self-rebuilding C program. Just for fun, here is the briefest way I've found to make a one-file C program self-rebuilding. Note that it only works given an env that implements the -S option. That includes the env in GNU Coreutils 8.30 or above, and (so I'm told) FreeBSD's. So regard it as a total hack not for serious use! Of course for a more portable version you can use #!/bin/sh and the self-extractin...| Rambles around computer science
* really Suppose we want to interfere with how a vaguely Unix-style C compiler does its job, and that we want to try compiling existing software with this modified compiler. Assuming the build system will let us do something like: CC=/path/to/my/wrapper make or CC=/path/to/my/wrapper ./configure && make ... then we'd like something that is a drop-in replacement at the command-line level. Let's also assume that our modifications are black-box: we want to do “what the stock compiler was doing...| Rambles around computer science
This post is about the following strange program I wrote recently. dummy=; define () { true; } define dummy echo "Hello from shell; PATH is ${PATH}" return 0 2>/dev/null || exit 0 endef .PHONY: say-hello say-hello: @echo "Hello from make; makevar PATH is $(PATH), envvar PATH is $${PATH}" One of my guilty secrets is that ‘make’ is one of my favourite programming languages. It has persistence and goal-driven incremental execution... so high-level! Although it is string-based, it has much l...| Rambles around computer science
On Linux, what is a process's name? I've found this to be more complicated than I thought it would be. Clearly it's non-trivial because it seems top and ps can disagree about a process's name. As usual I have Firefox and some of its worker processes cheerfully burning some CPU for no apparent reason, so let's use one of those. top - 14:53:48 up 5 days, 3:20, 28 users, load average: 0.47, 0.82, 0.74 Tasks: 629 total, 1 running, 543 sleeping, 0 stopped, 4 zombie %Cpu(s): 1.9 us, 0.8 sy, 0.0 ni,...| Rambles around computer science
Is there good interoperability with C from C++? I could have named any two languages, and for most pairs the answer would be a clear “no”. But in the case of working with C code from C++, the situation is a lot better than normal. In this post I'll observe why it's still not good, via the lens of a particular programming task I carried out recently. I'll end with some notes on what I think good interoperability ought to mean. My task was writing some code to target a C-style plugin interf...| Rambles around computer science
For a long time I struggled to remember the rules for using inline in C. I think I've cracked it now, though. As often with C, the trick is to think about how it's implemented. It doesn't help that in C++, the programmer-facing semantics of inline are much more straightforward. If you want to hint that a function should be inlined, put inline (or, for a member function, define it within its class). inline int foo() { return 42; } // this is C++, not C! The toolchain takes care of the rest. Th...| Rambles around computer science
I wrote recently about the problems with link-time symbol wrapping using the --wrap option to GNU linkers and similar. In short, references don't get wrapped in some cases when they arguably should, if definition and use are in the same file. But there is another way, using symbol replacement, that can do such wrapping if we're careful about self-references and the like. I've now created a plugin for the GNU BFD or gold linkers that implements, in effect, a command-line option for wrapping th...| Rambles around computer science
It's sometimes useful to hook functions at link time. On ELF platforms (among others) a GNU-style linker offers the --wrap option which seems to be exactly what we want. --wrap=symbol Use a wrapper function for symbol. Any undefined reference to symbol will be resolved to "__wrap_symbol". Any undefined reference to "__real_symbol" will be resolved to symbol. Unfortunately there are several problems that arise when using this. In this post I'll cover some ways to solve these problems. Some of ...| Rambles around computer science
[I wrote this to help current or future students who might want to do projects involving dynamic linking. But it may be of interest more widely. There may well be an equivalent or better article out there; if anyone knows one, please let me know.] In old-fashioned static linking, the executable file captures a complete starting “memory image” of the program being loaded. The kernel simply maps the binary into memory, creates an initial thread stack, dumps some useful information onto it (...| Rambles around computer science
Some months back I wrote about a possible better alternative to LD_PRELOAD using chain loading. And I promised a follow-up with more details... so here it is. We'll walk through a little system call tracer built using this technique. Unlike strace and similar, it will do its tracing in-process, without using ptrace() or equivalents. I should add that it's a proof-of-concept only so isn't nearly as good as strace in practice; in particular it can't yet accurately print the arguments to most s...| Rambles around computer science
Suppose you want to run a pre-existing binary program but in some kind of instrumented or modified form. On ELF-based systems, people often do this with LD_PRELOAD: you preload a library that interferes with some C library calls or somehow tweaks the process state at startup (say to install a signal handler). The program itself is (hopefully) oblivious to what you've done, but its behaviour is modified accordingly. Some years back I saw a nice survey of applications in a presentation by Kevin...| Rambles around computer science
I recently ran into a nasty problem, arguably a bug, in GCC. I decided to write a little tool to help me detect when I'm triggering this bug. This post is about how I did that, using some simple but handy helper scripts I've been growing for a while. The bug is to do with “constructor” functions in GNU C (not to be confused with C++ constructors!). I'll quote from my bug report, slightly edited. I was surprised to find that my __attribute__((constructor(101))) on a function was not giving...| Rambles around computer science
A couple of times recently I've found myself wanting to create ELF files with custom program headers. This post explains what that means, why you might want it, why there's a practical difficulty in doing so using a standard linker, and my slightly hacky way of solving it. Program headers are metadata within ELF files. They describe a contiguous chunk of the file's address space. There are several different kinds of program header, of which the most critical is LOAD, signifying that the relev...| Rambles around computer science
ARM Macs might be good for Apple, but developers should be concerned about interoperability.| Chris Warrick