summaryrefslogtreecommitdiffhomepage
path: root/src/os-unix.h
diff options
context:
space:
mode:
authorMichael Smith <mikesmiffy128@gmail.com>2023-08-20 16:20:03 +0100
committerMichael Smith <mikesmiffy128@gmail.com>2023-08-27 00:46:09 +0100
commita1998f2f7ce4153d670e2e5cb5018366517cc1ca (patch)
tree4d899fbad24c728c0b51f183c61ed6a7fb213c04 /src/os-unix.h
parent38fa6c52a8a26ac178a3e1f80a8317740b8e82b3 (diff)
Get things at least compiling under Linux
Nothing really works yet, but at least test.h and fastspin are fixed and some of the issues with RTTI and libdl and stuff are maybe kind of sorted, subject to more testing later. The main issue now seems to be the cvar interface not quite lining up and crashing pretty much immediately. That'll probably take a lot more debugging to figure out, which likely still won't be a priority for quite a while.
Diffstat (limited to 'src/os-unix.h')
-rw-r--r--src/os-unix.h53
1 files changed, 40 insertions, 13 deletions
diff --git a/src/os-unix.h b/src/os-unix.h
index a25d8ed..097d300 100644
--- a/src/os-unix.h
+++ b/src/os-unix.h
@@ -47,31 +47,58 @@ typedef char os_char;
static inline void *os_dlopen(const char *name) {
return dlopen(name, RTLD_NOW);
}
-static inline void *os_dlhandle(const char *name) {
- void *ret = dlopen(name, RTLD_NOW | RTLD_NOLOAD);
- if (ret) dlclose(ret);
- return ret;
-}
#define os_dlsym dlsym
#ifdef __linux__
// note: this is glibc-specific. it shouldn't be used in build-time code, just
// the plugin itself (that really shouldn't be a problem).
+
+// private struct hidden behind _GNU_SOURCE. see dlinfo(3) or <link.h>
+struct gnu_link_map {
+ unsigned long l_addr;
+ const char *l_name;
+ void *l_ld;
+ struct gnu_link_map *l_next, *l_prev;
+ // [more private stuff below]
+};
+
+static inline void *os_dlhandle(const char *name) {
+ extern struct gnu_link_map *_os_lmbase; // note: defined in sst.c for now
+ if (!_os_lmbase) { // IMPORTANT: not thread safe. don't forget later!
+ _os_lmbase = (struct gnu_link_map *)dlopen("libc.so.6",
+ RTLD_LAZY | RTLD_NOLOAD);
+ dlclose(_os_lmbase); // assume success
+ while (_os_lmbase->l_prev) _os_lmbase = _os_lmbase->l_prev;
+ }
+ // this is a tiny bit crude, but basically okay. we just want to find
+ // something that roughly matches the basename, rather than needing an exact
+ // path, in a manner vaguely similar to Windows' GetModuleHandle(). that way
+ // we can just look up client.so or something without having to figure out
+ // where exactly that is.
+ for (struct gnu_link_map *lm = _os_lmbase; lm; lm = lm->l_next) {
+ if (name[0] == '/') {
+ if (!strcmp(name, lm->l_name)) return lm;
+ continue;
+ }
+ int namelen = strlen(lm->l_name);
+ int sublen = strlen(name);
+ if (sublen >= namelen) continue;
+ if (lm->l_name[namelen - sublen - 1] == '/' && !memcmp(
+ lm->l_name + namelen - sublen, name, sublen)) {
+ return lm;
+ }
+ }
+ return 0;
+}
+
static inline int os_dlfile(void *m, char *buf, int sz) {
- // private struct hidden behind _GNU_SOURCE. see dlinfo(3) or <link.h>
- struct gnu_link_map {
- unsigned long l_addr;
- const char *l_name;
- void *l_ld;
- struct gnu_link_map *l_next, *l_prev;
- // [more private stuff below]
- };
struct gnu_link_map *lm = m;
int ssz = strlen(lm->l_name) + 1;
if (ssz > sz) { errno = ENAMETOOLONG; return -1; }
memcpy(buf, lm->l_name, ssz);
return ssz;
}
+
#endif
// unix mprot flags are much nicer but cannot be defined in terms of the windows