View Single Post
  #25  
Old 04-09-2018, 08:30
bugficks bugficks is offline
Friend
 
Join Date: Apr 2018
Posts: 8
Rept. Given: 0
Rept. Rcvd 0 Times in 0 Posts
Thanks Given: 3
Thanks Rcvd at 14 Times in 8 Posts
bugficks Reputation: 0
i have to deal a lot w/ dyn sym libs/calls for my stuff @samygo and came up w/ some self-including .h file.
its basically for *nix but i ve hacked some windows support though not all features are available there

- should compile as C and C++
- type safe
- easy to use (imho)
- supports logging

here some example usage:
PHP Code:
// msvc doesn't support weak linking
#define DYNSYM_LOG __dynsym_log

#define DYNSYM_CALL_DECL WINAPI
#define DYNSYM_H "u32.h"
#include "dynsym.h"

#define DYNSYM_CALL_DECL WINAPI
#define DYNSYM_H "k32.h"
#include "dynsym.h"

void main()
{
    if(
user32_init() > 0)
    {
        
user32.MessageBoxA(0"test""test"0);
        
user32_deinit();
    }
    
    if(
k32_init() > 0)
    {
        
k32.Sleep(0);
        
k32_deinit();
    }

u32.h:
PHP Code:
#ifdef DYNSYM_BEGIN

DYNSYM_BEGIN("user32"user32)
DYNSYM_DEF(intMessageBoxAHWND hWndLPCSTR lpTextLPCSTR lpCaptionUINT uType)
DYNSYM_END(user32)

#endif // #ifdef DYNSYM_BEGIN 
dynsym.h macro hell
PHP Code:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// bugficks@samygo
// (c) 2016 - 2018
//
// License: GPLv3
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//lib_blub.h:
// DYNSYM_BEGIN("lib_blub.so.0", lib_blub)
// supports patterns (glob w/ braces) and colon-separated list of libs
// //DYNSYM_BEGIN("{/usr/lib/{lib_blub.so,lib_bla.so*}}", lib_blub)
// //DYNSYM_BEGIN("lib_blub.so*:lib_bla.so*", lib_blub)
// //DYNSYM_BEGIN("lib_blub.so:lib_blub.so.0:lib_blub.so.1", lib_blub)
// // required symbols
// DYNSYM_DEF(int, func_bla, int)
// DYNSYM_DEF_EX(int, short_bla, func_loooooooong_bla, int)
// //optional symbols
// DYNSYM_OPT(int, func_blub, int)
// DYNSYM_OPT_EX(int, short_blub, func_loooooooong_blub, int)
// DYNSYM_END(lib_blub)
//
// // add additional data to lib_blub structure
//#ifndef DYNSYM_DATA
//#define DYNSYM_DATA \
//    int bla; \
//    void *blub;
//#endif
//
//code:
// #define DYNSYM_H    "lib_blub.h"
// optionally supply a colon-separated list of directories as library search path
// #define DYNSYM_LIB_PATH "/usr/lib:/some/lib/dir"
// #include <samygo/dynsym.h>
//
// lib_blub_init();
// lib_blub.func_bla(0);
// if(lib_blub.func_blub)
//    lib_blub.func_blub(0);
// lib_blub_deinit();

// < 0 : error
// else: num resolved symbols
// int xxx_init();
// int xxx_init_ex(void *lib);
//
// void xxx_deinit();

#ifndef __DYNSYM_DONE_H__

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef DYNSYM_H
#error DYNSYM_H is not defined.
#endif

#ifdef DYNSYM_BEGIN
#undef DYNSYM_BEGIN
#endif

#ifdef DYNSYM_END
#undef DYNSYM_END
#endif

#ifdef DYNSYM_DEF
#undef DYNSYM_DEF
#endif

#ifdef DYNSYM_DEF_EX
#undef DYNSYM_DEF_EX
#endif

#ifdef DYNSYM_VAR
#undef DYNSYM_VAR
#endif

#ifdef DYNSYM_VAR_EX
#undef DYNSYM_VAR_EX
#endif

#ifdef DYNSYM_OPT
#undef DYNSYM_OPT
#endif

#ifdef DYNSYM_OPT_EX
#undef DYNSYM_OPT_EX
#endif

#ifdef DYNSYM_VAR_OPT
#undef DYNSYM_VAR_OPT
#endif

#ifdef DYNSYM_VAR_OPT_EX
#undef DYNSYM_VAR_OPT_EX
#endif

#ifdef DYNSYM_INIT
#undef DYNSYM_INIT
#endif

#ifdef DYNSYM_DEINIT
#undef DYNSYM_DEINIT
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if __DYNSYM_INC_LEVEL == 1
#undef __DYNSYM_INC_LEVEL
#define __DYNSYM_INC_LEVEL 2
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef DYNSYM_DATA
#define DYNSYM_DATA void *_dummy_;
#endif

#define DYNSYM_BEGIN(DLL, STRUCT) \
    
typedef union \
    { \
        
struct \
        { \
            const 
uint32_t nSyms;

#define DYNSYM_END(STRUCT) \
            
DYNSYM_DATA \
        }; \
        
dynsym_tab_t symtab; \
    } 
STRUCT##_t; \
    
DYNSYM_STRUCT_DATA(STRUCT);

#define DYNSYM_DEF(RET, NAME, ...) \
    
DYNSYM_DEF_EX(RETNAMENAME__VA_ARGS__)

#define DYNSYM_DEF_EX(RET, FUNC, NAME, ...) \
    
struct FUNC##_t FUNC; const char *name_##FUNC; };

#define DYNSYM_VAR(TYPE, NAME) \
    
DYNSYM_VAR_EX(TYPENAMENAME)

#define DYNSYM_VAR_EX(TYPE, VNAME, SNAME) \
    
struct TYPE *VNAME; const char *name_##VNAME; };

#define DYNSYM_OPT(RET, NAME, ...) \
    
DYNSYM_DEF_EX(RETNAMENAME__VA_ARGS__)

#define DYNSYM_OPT_EX(RET, FUNC, NAME, ...) \
    
DYNSYM_DEF_EX(RETFUNCNAME__VA_ARGS__)

#define DYNSYM_VAR_OPT(TYPE, NAME) \
    
DYNSYM_VAR_EX(TYPENAMENAME)

#define DYNSYM_VAR_OPT_EX(TYPE, VNAME, SNAME) \
    
DYNSYM_VAR_EX(TYPEVNAMESNAME)

#define DYNSYM_STRUCT_DATA(STRUCT) \
    
typedef struct \
    { \
        
DYNSYM_DATA \
    } 
STRUCT##_data_t;


#include DYNSYM_H

#undef DYNSYM_DATA
#undef DYNSYM_STRUCT_DATA

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#elif __DYNSYM_INC_LEVEL == 2
#undef __DYNSYM_INC_LEVEL
#define __DYNSYM_INC_LEVEL 3
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define DYNSYM_BEGIN(DLL, STRUCT) \
    
static STRUCT##_t STRUCT = \
    
{ {\
        (((
sizeof(STRUCT##_t) - sizeof(STRUCT##_data_t)) - sizeof(STRUCT.symtab)) / sizeof(dynsym_sym_t)),

#define DYNSYM_END(STRUCT) \
    
} }; \
    
DYNSYM_INIT(DLLSTRUCT) \
    
DYNSYM_DEINIT(DLLSTRUCT)

#define DYNSYM_DEF(RET, NAME, ...) \
    
DYNSYM_DEF_EX(RETNAMENAME__VA_ARGS__)

#define DYNSYM_DEF_EX(RET, FUNC, NAME, ...) \
    
0#NAME },

#define DYNSYM_VAR(TYPE, NAME) \
    
DYNSYM_VAR_EX(TYPENAMENAME)

#define DYNSYM_VAR_EX(TYPE, VNAME, SNAME) \
    
0#SNAME },

#define DYNSYM_OPT(RET, NAME, ...) \
    
DYNSYM_OPT_EX(RETNAMENAME__VA_ARGS__)

#define DYNSYM_OPT_EX(RET, FUNC, NAME, ...) \
    
{ (FUNC##_t)eDYNSYM_OPTIONAL, #NAME },

#define DYNSYM_VAR_OPT(TYPE, NAME) \
    
DYNSYM_VAR_OPT_EX(TYPENAMENAME)

#define DYNSYM_VAR_OPT_EX(TYPE, VNAME, SNAME) \
    
{ (TYPE*)eDYNSYM_OPTIONAL#SNAME },


#ifndef DYNSYM_LIB_PATH
#define DYNSYM_LIB_PATH "/lib:/usr/lib"
#endif

#define DYNSYM_INIT(DLL, STRUCT) \
    
static int STRUCT##_init_ex(void *lib) \
    
{ \
        return 
dynsym_init_ex(lib, &STRUCT##_lib, &STRUCT.symtab); \
    
} \
    \
    static 
int STRUCT##_init() \
    
{ \
        return 
dynsym_init(&STRUCT##_lib, &STRUCT.symtab, DYNSYM_LIB_PATH); \
    
}

#define DYNSYM_DEINIT(DLL, STRUCT) \
    
static void STRUCT##_deinit() \
    
{ \
        
dynsym_tab_deinit(&STRUCT##_lib, &STRUCT.symtab); \
        
STRUCT##_lib.lib = 0; \
    
}


#include DYNSYM_H

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#elif __DYNSYM_INC_LEVEL == 3
#define __DYNSYM_DONE_H__

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#else
#define __DYNSYM_INC_LEVEL 1
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __DYNSYM_H__
#define __DYNSYM_H__

#include <stdint.h>
#include <errno.h>

#ifdef _WIN32

#include <windows.h>
#include <tchar.h>
#define  __attribute__(...)
#define PATH_MAX MAX_PATH

enum {
    
RTLD_LAZY 0x0001
};
inline voiddlopen(const char *nint)
{
    return (
void*)LoadLibraryA(n);
}
inline int dlclose(void *h)
{
    return 
FreeLibrary((HMODULE)h) ? : -1;
}
inline voiddlsym(void *h, const char *n)
{
    return (
void*)GetProcAddress((HMODULE)hn);
}

#define LIBRARY_PATH        "PATH"
#define TOKEN_PATH_SPLIT    ";"
#define strtok_r(A, B, C) strtok(A, B)

#else

#include <dlfcn.h>
#include <link.h>
#include <glob.h>

#define LIBRARY_PATH        "LD_LIBRARY_PATH"
#define TOKEN_PATH_SPLIT    ":"

#endif

typedef struct
{
    const 
char *name;//[PATH_MAX];
    
void *lib;
dynsym_lib_t;

typedef struct
{
    
void *fn;
    const 
char *name;
dynsym_sym_t;

typedef struct
{
    
uint32_t nSyms;
    
dynsym_sym_t syms[];
dynsym_tab_t;

typedef enum
{
    
eDYNSYM_DEFAULT       0,
    
eDYNSYM_OPTIONAL      = (<< 0),
    
eDYNSYM_MASK          3,
dynsym_flags_t;

typedef enum
{
    
eDYNSYM_LOG_NONE,
    
eDYNSYM_LOG_ERROR,
    
eDYNSYM_LOG_WARN,
    
eDYNSYM_LOG_INFO,
    
eDYNSYM_LOG_DBG
dynsym_log_level_t;


void dynsym_log(
        
int l, const char *fmt, ...) __attribute__ ((weak));

#ifndef DYNSYM_LOG
#define DYNSYM_LOG(L, ...) \
    
{ \
        if(
dynsym_log) \
            
dynsym_log(L__VA_ARGS__); \
        else \
            
__dynsym_log(L__VA_ARGS__); \
    }
#endif

static void __dynsym_log(
        
int l, const char *fmt, ...)
{
    
va_list ap;
    
va_start(apfmt);
    switch(
l)
    {
        case 
eDYNSYM_LOG_ERROR:
            
printf("[E]");
            break;
        case 
eDYNSYM_LOG_WARN:
            
printf("[W]");
            break;
        case 
eDYNSYM_LOG_INFO:
            
printf("[I]");
            break;
        case 
eDYNSYM_LOG_DBG:
            
printf("[D]");
            break;
        default:
            break;
    }
    
printf("[DYNSYM] ");
    
vprintf(fmtap);
    
va_end(ap);
    
fflush(stdout);
}

static 
inline const char *dynsym_libname(
        const 
dynsym_lib_t *lib)
{
    const 
char *lib_name "(nil)";
    if(!
lib)
        return 
lib_name;
    if(!
lib->name)
        return 
lib_name;
    if(!
lib->name[0])
        return 
lib_name;
    return 
lib->name;
}

static 
int dynsym_tab_init(
        
dynsym_lib_t *libdynsym_tab_t *symtab)
{
    
int n 0;
    const 
char *lib_name dynsym_libname(lib);
    
dynsym_sym_t *syms symtab->syms;
    for(
uint32_t i 0symtab->nSymsi++)
    {
        
uintptr_t flags = (uintptr_t)syms[i].fn;
        
int opt flags eDYNSYM_OPTIONAL;
        
void *fn dlsym(lib->libsyms[i].name);
        if(!
fn)
        {
            
int l opt eDYNSYM_LOG_WARN eDYNSYM_LOG_ERROR;
            
DYNSYM_LOG(l,"dlsym lib: '%s' '%s' failed.\n"lib_namesyms[i].name);
            if(!
opt)
                return -
1;
        }
        else
        {
            
DYNSYM_LOG(eDYNSYM_LOG_INFO,"dlsym lib: '%s' '%s' %p.\n"lib_namesyms[i].namefn);
            
n++;
        }

        
syms[i].fn fn;
    }
    return 
n;
}

static 
void dynsym_tab_deinit(
        
dynsym_lib_t *libdynsym_tab_t *symtab)
{
    
void *_lib lib->lib;
    if(
_lib)
    {
        
lib->lib 0;
        
dynsym_sym_t *syms symtab->syms;
        for(
uint32_t i 0symtab->nSymsi++)
            
syms[i].fn 0;

        
dlclose(_lib);
    }
    const 
char *name lib->name;
    if(
name)
    {
        
lib->name 0;
        
free((void*)name);
    }
}

static 
int dynsym_init_ex(
        
void *libdynsym_lib_t *dynsymlibdynsym_tab_t *symtab)
{
    if(!
lib)
        return -
1;
    if(
dynsymlib->lib)
        return -
1;

    
dynsymlib->lib lib;

#ifndef _WIN32
    
struct link_map *lm 0;
    
dlinfo(libRTLD_DI_LINKMAP, &lm);
    if(
lm && lm->l_name && lm->l_name[0])
        
dynsymlib->name strdup(lm->l_name);
    else if(!
dynsymlib->name || !dynsymlib->name[0])
        
dynsymlib->name realpath(program_invocation_name0);
#else
    
{
        
char tmp[MAX_PATH];
        
memset(tmp0sizeof(tmp));
        if(
GetModuleFileNameA((HMODULE)libtmpARRAYSIZE(tmp)))
            
dynsymlib->name _strdup(tmp);
    }
#endif

    
DYNSYM_LOG(eDYNSYM_LOG_DBG,"lib: '%s' %p.\n"dynsym_libname(dynsymlib), dynsymlib->lib);

    
int n dynsym_tab_init(dynsymlibsymtab);
    return 
n;
}

typedef int (*sgo_log_t)(
        
int l, const char *tag, const char *comp, const char *fmt, ...);

static 
void *dynsym_dlopen(
        const 
char *name_patterndynsym_lib_t *dynsymlib, const char *const _LIB_PATHsgo_log_t logger)
{
    if(!
name_pattern)
    {
        
void *lib dlopen(0RTLD_LAZY);
        return 
lib;
    }

    
char *strtok_name 0;
    
char name_wrk[PATH_MAX];
    
memset(name_wrk0sizeof(name_wrk));
    
strncpy(name_wrkname_patternsizeof(name_wrk));
    const 
char *name strtok_r(name_wrkTOKEN_PATH_SPLIT, &strtok_name);
    while(
name)
    {
        
// no pattern, just use dlopen
        
if(!strpbrk(name"?*[]{}"))
        {
            
void *lib dlopen(nameRTLD_LAZY);
            if(
lib)
                return 
lib;
        }
#ifdef HAVE_GLOB
        // pattern, we need absolute path for dlopen, fill lib search dirs
        
char LIB_PATH[PATH_MAX] = { };
        if(!
strchr(name'/'))
        {
            const 
char *const LD_LIBRARY_PATH getenv(LIBRARY_PATH);

            if(
LD_LIBRARY_PATH && LD_LIBRARY_PATH[0])
                
snprintf(LIB_PATHsizeof(LIB_PATH) - 1"%s:"LD_LIBRARY_PATH);
            
strncat(LIB_PATH_LIB_PATHsizeof(LIB_PATH) - 1);

            
DYNSYM_LOG(eDYNSYM_LOG_DBG"LIB_PATH: '%s'\n"LIB_PATH);
        }

        
char *strtok_dir 0;
        const 
char *libdir strtok_r(LIB_PATHTOKEN_PATH_SPLIT, &strtok_dir);
        
void *lib 0;
        do
        {
            
char libpath[PATH_MAX];
            
memset(libpath0sizeof(libpath));
            if(
libdir)
                
snprintf(libpathsizeof(libpath) - 1"%s/%s"libdirname);
            else
                
strncpy(libpathnamesizeof(libpath) - 1);

            
glob_t blob;
            
int r glob(libpathGLOB_BRACE0, &blob);
            if(
r)
            {
                
DYNSYM_LOG(eDYNSYM_LOG_DBG"glob('%s') failed. [%s]\n"libpathstrerror(ENOENT));
            }
            else
            {
                for(
size_t i 0blob.gl_pathci++)
                {
                    const 
char *name blob.gl_pathv[i];
                    
lib dlopen(nameRTLD_LAZY);
                    if(
lib)
                        break;
                }
            }

            
globfree(&blob);

            if(
lib)
                return 
lib;

            
libdir strtok_r(0TOKEN_PATH_SPLIT, &strtok_dir);
        }
        while(
libdir);
#endif

        
name strtok_r(0TOKEN_PATH_SPLIT, &strtok_name);
    }

    return 
0;
}

static 
int dynsym_init(
        
dynsym_lib_t *dynsymlibdynsym_tab_t *symtab, const char *const LIB_PATH)
{
    
void *lib dynsym_dlopen(dynsymlib->namedynsymlibLIB_PATH0);
    if(!
lib)
    {
        
DYNSYM_LOG(eDYNSYM_LOG_ERROR,"dlopen lib: '%s' failed.\n"dynsym_libname(dynsymlib));
    }

    return 
dynsym_init_ex(libdynsymlibsymtab);
}

#endif // #ifndef __DYNSYM_H__


#ifndef DYNSYM_CALL_DECL
#define DYNSYM_CALL_DECL
#endif

#define DYNSYM_DEF(RET, NAME, ...) \
    
DYNSYM_DEF_EX(RETNAMENAME__VA_ARGS__)

#define DYNSYM_DEF_EX(RET, FUNC, NAME, ...) \
    
typedef RET (DYNSYM_CALL_DECL FUNC##_t)(__VA_ARGS__);

#define DYNSYM_VAR(T, NAME) \
    
DYNSYM_VAR_EX(TVNAMESNAME)

#define DYNSYM_VAR_EX(T, VNAME, SNAME)

#define DYNSYM_OPT(RET, NAME, ...) \
    
DYNSYM_DEF_EX(RETNAMENAME__VA_ARGS__)

#define DYNSYM_OPT_EX(RET, FUNC, NAME, ...) \
    
DYNSYM_DEF_EX(RETFUNCNAME__VA_ARGS__)

#define DYNSYM_VAR_OPT(T, NAME) \
    
DYNSYM_VAR_OPT_EX(TNAMENAME)

#define DYNSYM_VAR_OPT_EX(T, VNAME, SNAME)

#define DYNSYM_BEGIN(DLL, STRUCT) \
    
static dynsym_lib_t STRUCT##_lib = { DLL, 0 };

#define DYNSYM_END(STRUCT)

#include DYNSYM_H

#undef DYNSYM_CALL_DECL

#endif

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#if __DYNSYM_INC_LEVEL < 4
#include "dynsym.h"
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#else // #ifndef __DYNSYM_DONE_H__

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#undef __DYNSYM_DONE_H__

#ifdef DYNSYM_LIB_PATH
#undef DYNSYM_LIB_PATH
#endif

#undef DYNSYM_H
#undef __DYNSYM_INC_LEVEL

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#endif  // #ifndef __DYNSYM_DONE_H__

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
Attached Files
File Type: zip dynsym.zip (4.1 KB, 3 views)
Reply With Quote
The Following 5 Users Say Thank You to bugficks For This Useful Post:
0xall0c (04-10-2018), emo (04-12-2018), Indigo (07-19-2019), niculaita (04-14-2018), tonyweb (05-09-2018)