#define _must_check_ __attribute__((warn_unused_result))
#define _printf_format_(a, b) __attribute__((format(printf, a, b)))
#define _always_inline_ __inline__ __attribute__((always_inline))
+#define _sentinel_ __attribute__((sentinel))
#if defined(__clang_analyzer__)
#define _clang_suppress_ __attribute__((suppress))
#include <assert.h>
#include <ctype.h>
+#include <dlfcn.h>
#include <errno.h>
#include <stdarg.h>
#include <stddef.h>
return (unsigned long long)st->st_mtime;
#endif
}
+
+static int dlsym_manyv(void *dl, va_list ap)
+{
+ void (**fn)(void);
+
+ while ((fn = va_arg(ap, typeof(fn)))) {
+ const char *symbol;
+
+ symbol = va_arg(ap, typeof(symbol));
+ *fn = dlsym(dl, symbol);
+ if (!*fn)
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+int dlsym_many(void **dlp, const char *filename, ...)
+{
+ va_list ap;
+ void *dl;
+ int r;
+
+ if (*dlp)
+ return 0;
+
+ dl = dlopen(filename, RTLD_LAZY);
+ if (!dl)
+ return -ENOENT;
+
+ va_start(ap, filename);
+ r = dlsym_manyv(dl, ap);
+ va_end(ap);
+
+ if (r < 0) {
+ dlclose(dl);
+ return r;
+ }
+
+ *dlp = dl;
+
+ return 1;
+}
#include <inttypes.h>
#include <limits.h>
+#include <stdarg.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
(x) = NULL; \
x__; \
})
+
+/* dlfcn helpers */
+/* ************************************************************************ */
+
+/*
+ * Load many various symbols from @filename.
+ * @dlp: pointer to the previous results of this call: it's set when it succeeds
+ * @filename: the library to dlopen() and look for symbols
+ * @...: or 1 more tuples created by DLSYM_ARG() with ( &var, "symbol name" ).
+ */
+_sentinel_ int dlsym_many(void **dlp, const char *filename, ...);
+
+/*
+ * Helper to create tuples passed as arguments to dlsym_many().
+ * @symbol__: symbol to create arguments for. Example: DLSYM_ARG(foo) expands to
+ * `&sym_foo, "foo"`
+ */
+#define DLSYM_ARG(symbol__) &sym_##symbol__, STRINGIFY(symbol__),
+
+/* For symbols being dynamically loaded */
+#define DECLARE_DLSYM(symbol) typeof(symbol) *sym_##symbol = NULL
+
+/* Pointer indirection to support linking directly */
+#define DECLARE_PTRSYM(symbol) typeof(symbol) *sym_##symbol = symbol
+
+/*
+ * Helper defines, to be done locally before including this header to switch between
+ * implementations
+ */
+#if defined(DLSYM_LOCALLY_ENABLED) && DLSYM_LOCALLY_ENABLED
+#define DECLARE_SYM(sym__) DECLARE_DLSYM(sym__);
+#else
+#define DECLARE_SYM(sym__) DECLARE_PTRSYM(sym__);
+#endif