#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#define HAS_DLOPEN_CALLBACK 0
#define HAS_DLSYM_CALLBACK 0
#define NO_DLOPEN 0
#define LAZY_LOAD 1
#define THREAD_SAFE 1
#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#if THREAD_SAFE
#include <pthread.h>
#endif
#ifdef __arm__
# if defined __thumb__ && ! defined __THUMB_INTERWORK__
# error "ARM trampolines need -mthumb-interwork to work in Thumb mode"
# endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define CHECK(cond, fmt, ...) do { \
if(!(cond)) { \
fprintf(stderr, "implib-gen: libXext.so.6: " fmt "\n", ##__VA_ARGS__); \
assert(0 && "Assertion in generated code"); \
abort(); \
} \
} while(0)
static void *lib_handle;
static int dlopened;
#if ! NO_DLOPEN
#if THREAD_SAFE
static pthread_mutex_t mtx;
static int rec_count;
static void init_lock(void) {
pthread_mutexattr_t attr;
CHECK(0 == pthread_mutexattr_init(&attr), "failed to init mutex");
CHECK(0 == pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE), "failed to init mutex");
CHECK(0 == pthread_mutex_init(&mtx, &attr), "failed to init mutex");
}
static int lock(void) {
static pthread_once_t once = PTHREAD_ONCE_INIT;
CHECK(0 == pthread_once(&once, init_lock), "failed to init lock");
CHECK(0 == pthread_mutex_lock(&mtx), "failed to lock mutex");
return 0 == __sync_fetch_and_add(&rec_count, 1);
}
static void unlock(void) {
__sync_fetch_and_add(&rec_count, -1);
CHECK(0 == pthread_mutex_unlock(&mtx), "failed to unlock mutex");
}
#else
static int lock(void) {
return 1;
}
static void unlock(void) {}
#endif
static int load_library(void) {
int publish = lock();
if (lib_handle) {
unlock();
return publish;
}
#if HAS_DLOPEN_CALLBACK
extern void *(const char *lib_name);
lib_handle = ("libXext.so.6");
CHECK(lib_handle, "failed to load library 'libXext.so.6' via callback ''");
#else
lib_handle = dlopen("libXext.so.6", RTLD_LAZY | RTLD_GLOBAL);
CHECK(lib_handle, "failed to load library 'libXext.so.6' via dlopen: %s", dlerror());
#endif
if (__sync_val_compare_and_swap(&dlopened, 0, 1)) {
dlclose(lib_handle);
}
unlock();
return publish;
}
static void __attribute__((destructor(101))) unload_lib(void) {
if (dlopened) {
dlclose(lib_handle);
lib_handle = 0;
dlopened = 0;
}
}
#endif
#if ! NO_DLOPEN && ! LAZY_LOAD
static void __attribute__((constructor(101))) load_lib(void) {
load_library();
}
#endif
static const char *const sym_names[] = {
"DPMSCapable",
"DPMSDisable",
"DPMSEnable",
"DPMSForceLevel",
"DPMSGetTimeouts",
"DPMSGetVersion",
"DPMSInfo",
"DPMSQueryExtension",
"DPMSSetTimeouts",
"XGEQueryExtension",
"XGEQueryVersion",
"XLbxGetEventBase",
"XLbxQueryExtension",
"XLbxQueryVersion",
"XMITMiscGetBugMode",
"XMITMiscQueryExtension",
"XMITMiscSetBugMode",
"XMissingExtension",
"XSecurityAllocXauth",
"XSecurityFreeXauth",
"XSecurityGenerateAuthorization",
"XSecurityQueryExtension",
"XSecurityRevokeAuthorization",
"XSetExtensionErrorHandler",
"XShapeCombineMask",
"XShapeCombineRectangles",
"XShapeCombineRegion",
"XShapeCombineShape",
"XShapeGetRectangles",
"XShapeInputSelected",
"XShapeOffsetShape",
"XShapeQueryExtension",
"XShapeQueryExtents",
"XShapeQueryVersion",
"XShapeSelectInput",
"XShmAttach",
"XShmCreateImage",
"XShmCreatePixmap",
"XShmDetach",
"XShmGetEventBase",
"XShmGetImage",
"XShmPixmapFormat",
"XShmPutImage",
"XShmQueryExtension",
"XShmQueryVersion",
"XSyncAwait",
"XSyncAwaitFence",
"XSyncChangeAlarm",
"XSyncChangeCounter",
"XSyncCreateAlarm",
"XSyncCreateCounter",
"XSyncCreateFence",
"XSyncDestroyAlarm",
"XSyncDestroyCounter",
"XSyncDestroyFence",
"XSyncFreeSystemCounterList",
"XSyncGetPriority",
"XSyncInitialize",
"XSyncIntToValue",
"XSyncIntsToValue",
"XSyncListSystemCounters",
"XSyncMaxValue",
"XSyncMinValue",
"XSyncQueryAlarm",
"XSyncQueryCounter",
"XSyncQueryExtension",
"XSyncQueryFence",
"XSyncResetFence",
"XSyncSetCounter",
"XSyncSetPriority",
"XSyncTriggerFence",
"XSyncValueAdd",
"XSyncValueEqual",
"XSyncValueGreaterOrEqual",
"XSyncValueGreaterThan",
"XSyncValueHigh32",
"XSyncValueIsNegative",
"XSyncValueIsPositive",
"XSyncValueIsZero",
"XSyncValueLessOrEqual",
"XSyncValueLessThan",
"XSyncValueLow32",
"XSyncValueSubtract",
"XTestFakeInput",
"XTestFlush",
"XTestGetInput",
"XTestMovePointer",
"XTestPressButton",
"XTestPressKey",
"XTestQueryInputSize",
"XTestReset",
"XTestStopInput",
"XagCreateAssociation",
"XagCreateEmbeddedApplicationGroup",
"XagCreateNonembeddedApplicationGroup",
"XagDestroyApplicationGroup",
"XagDestroyAssociation",
"XagGetApplicationGroupAttributes",
"XagQueryApplicationGroup",
"XagQueryVersion",
"XcupGetReservedColormapEntries",
"XcupQueryVersion",
"XcupStoreColors",
"XdbeAllocateBackBufferName",
"XdbeBeginIdiom",
"XdbeDeallocateBackBufferName",
"XdbeEndIdiom",
"XdbeFreeVisualInfo",
"XdbeGetBackBufferAttributes",
"XdbeGetVisualInfo",
"XdbeQueryExtension",
"XdbeSwapBuffers",
"XeviGetVisualInfo",
"XeviQueryExtension",
"XeviQueryVersion",
"XextAddDisplay",
"XextCreateExtension",
"XextDestroyExtension",
"XextFindDisplay",
"XextRemoveDisplay",
"XmbufChangeBufferAttributes",
"XmbufChangeWindowAttributes",
"XmbufClearBufferArea",
"XmbufCreateBuffers",
"XmbufCreateStereoWindow",
"XmbufDestroyBuffers",
"XmbufDisplayBuffers",
"XmbufGetBufferAttributes",
"XmbufGetScreenInfo",
"XmbufGetVersion",
"XmbufGetWindowAttributes",
"XmbufQueryExtension",
0
};
#define SYM_COUNT (sizeof(sym_names)/sizeof(sym_names[0]) - 1)
extern void *_libXext_so_tramp_table[];
void *_libXext_so_tramp_resolve(size_t i) {
assert(i < SYM_COUNT);
int publish = 1;
void *h = 0;
#if NO_DLOPEN
if (lib_handle) {
h = lib_handle;
} else {
# ifndef IMPLIB_EXPORT_SHIMS
h = RTLD_DEFAULT;
# else
h = RTLD_NEXT;
# endif
}
#else
publish = load_library();
h = lib_handle;
CHECK(h, "failed to resolve symbol '%s', library failed to load", sym_names[i]);
#endif
void *addr;
#if HAS_DLSYM_CALLBACK
extern void *(void *handle, const char *sym_name);
addr = (h, sym_names[i]);
CHECK(addr, "failed to resolve symbol '%s' via callback ", sym_names[i]);
#else
addr = dlsym(h, sym_names[i]);
CHECK(addr, "failed to resolve symbol '%s' via dlsym: %s", sym_names[i], dlerror());
#endif
if (publish) {
(void)__sync_val_compare_and_swap(&_libXext_so_tramp_table[i], 0, addr);
}
return addr;
}
void _libXext_so_tramp_resolve_all(void) {
size_t i;
for(i = 0; i < SYM_COUNT; ++i)
_libXext_so_tramp_resolve(i);
}
void _libXext_so_tramp_set_handle(void *handle) {
lib_handle = handle;
dlopened = 0;
}
void _libXext_so_tramp_reset(void) {
memset(_libXext_so_tramp_table, 0, SYM_COUNT * sizeof(_libXext_so_tramp_table[0]));
lib_handle = 0;
dlopened = 0;
}
#ifdef __cplusplus
} #endif