Comment by Y_Y
2 days ago
(What's the language lawyer equivalent of an ambulance chaser?)
Fair point, I hadn't thought it all the way through. It's also all too easy to assume you can use C++ features or GNU extensions if you're not in the habit of enforcing the standard. For your trouble here are two partial solutions:
---
1. CPP abuse
If I was doing this myself I'd probably just use the preprocessor to make the last function my entry point like
SOURCE=file.c gcc -DLATEST_MAIN=$(grep -E "^[a-zA-Z_].*\(.*\)\s*\{" ${SOURCE} | tail -1 | grep -Po "[a-zA-Z_]\w*(?=\()") ${SOURCE}
and then you can start with
int main(void){LATEST_MAIN();};
and append
void foo(){...}
...
void bar(){...}
and execution will start from the last defined function (that matches the regex).
---
2. Pre-defining non-static functions
If that's cheating then you can redefine "external" functions before the linker has a chance to provide them. For example:
#include <stdlib.h>
int (*foo)(void);
int main(void){exit(0); *foo();}
is a valid program, and you can append
void f1(){puts("oh");}
int exit(){foo=&f1;}
and foo will indeed be called. It does require some forward planning if you want to append multiple times, but it shouldn't be so difficult to generate a library full of dummy functions to use.
This isn't a language-lawyer kind of thing, and, as I said, I don't think C++ features or GNU extensions will help. The pre-defining extern functions approach will get you a finite number of tries, but I suppose it could be a fairly large finite number.
If for some reason I had to solve this problem in real life I would do it with a postprocesing step like your #1 suggestion. But once you're putting code into your Makefile anything goes.
You can just append a function with __attribute__((constructor)) if GNU extensions are allowed and that will run before main and let you mess with the function pointers.
In an undefined order?
2 replies →