summaryrefslogtreecommitdiff
path: root/common/templates/clang/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/templates/clang/src/main.c')
-rw-r--r--common/templates/clang/src/main.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/common/templates/clang/src/main.c b/common/templates/clang/src/main.c
new file mode 100644
index 0000000..5bda38b
--- /dev/null
+++ b/common/templates/clang/src/main.c
@@ -0,0 +1,51 @@
+#define _GNU_SOURCE // Required to unlock RTLD_DEFAULT so we can search all loaded memory
+#include <ctype.h>
+#include <dlfcn.h> // Gives us dlsym() to look up memory addresses by string names
+#include <stddef.h>
+
+void hello_world(const char* action) {
+ // __func__ is secretly injected by the compiler and holds the string "hello_world".
+ // We use raw pointers here (src and dst) instead of array indices because
+ // stepping the memory address forward directly (*dst++) generates faster machine code.
+ const char* src = __func__;
+ char result[64];
+ char* dst = result;
+ int capitalize = 1;
+
+ // We walk the 'src' pointer forward until we hit the null terminator.
+ // The (dst - result) < 60 check guarantees we never write past the end of
+ // our 64-byte array, preventing stack smashing if the function name is unusually long.
+ while (*src && (dst - result) < 60) {
+ if (*src == '_') {
+ *dst++ = ' ';
+ capitalize = 1;
+ } else {
+ *dst++ = capitalize ? toupper(*src) : *src;
+ capitalize = 0;
+ }
+ src++;
+ }
+
+ // Cap off the string with a bang and the required null terminator
+ *dst++ = '!';
+ *dst++ = '\n';
+ *dst = '\0';
+
+ // Declare a function pointer that takes a format string and variadic arguments
+ int (*dynamic_eval)(const char*, ...);
+
+ // This looks unhinged, but it is the official POSIX-compliant way to use dlsym.
+ // ISO C strictly forbids casting a raw data pointer (void*) directly to a
+ // function pointer. To bypass the compiler warning, we take the address of our
+ // function pointer, cast THAT to a void**, and dereference it to write the address.
+ *(void **)(&dynamic_eval) = dlsym(RTLD_DEFAULT, action);
+
+ if (dynamic_eval) {
+ dynamic_eval("%s", result);
+ }
+}
+
+int main(void) {
+ hello_world("printf");
+ return 0;
+}