Exetools  

Go Back   Exetools > General > Source Code

Notices

 
 
Thread Tools Display Modes
Prev Previous Post   Next Post Next
  #23  
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(int, MessageBoxA, HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT 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(RET, NAME, NAME, __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(TYPE, NAME, NAME)

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

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

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

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

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

#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(DLL, STRUCT) \
    
DYNSYM_DEINIT(DLL, STRUCT)

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

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

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

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

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

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

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

#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 void* dlopen(const char *n, int)
{
    return (
void*)LoadLibraryA(n);
}
inline int dlclose(void *h)
{
    return 
FreeLibrary((HMODULE)h) ? 0 : -1;
}
inline void* dlsym(void *h, const char *n)
{
    return (
void*)GetProcAddress((HMODULE)h, n);
}

#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      = (1 << 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(ap, fmt);
    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(fmt, ap);
    
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 *lib, dynsym_tab_t *symtab)
{
    
int n = 0;
    const 
char *lib_name = dynsym_libname(lib);
    
dynsym_sym_t *syms = symtab->syms;
    for(
uint32_t i = 0; i < symtab->nSyms; i++)
    {
        
uintptr_t flags = (uintptr_t)syms[i].fn;
        
int opt = flags & eDYNSYM_OPTIONAL;
        
void *fn = dlsym(lib->lib, syms[i].name);
        if(!
fn)
        {
            
int l = opt ? eDYNSYM_LOG_WARN : eDYNSYM_LOG_ERROR;
            
DYNSYM_LOG(l,"dlsym lib: '%s' '%s' failed.\n", lib_name, syms[i].name);
            if(!
opt)
                return -
1;
        }
        else
        {
            
DYNSYM_LOG(eDYNSYM_LOG_INFO,"dlsym lib: '%s' '%s' %p.\n", lib_name, syms[i].name, fn);
            
n++;
        }

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

static 
void dynsym_tab_deinit(
        
dynsym_lib_t *lib, dynsym_tab_t *symtab)
{
    
void *_lib = lib->lib;
    if(
_lib)
    {
        
lib->lib = 0;
        
dynsym_sym_t *syms = symtab->syms;
        for(
uint32_t i = 0; i < symtab->nSyms; i++)
            
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 *lib, dynsym_lib_t *dynsymlib, dynsym_tab_t *symtab)
{
    if(!
lib)
        return -
1;
    if(
dynsymlib->lib)
        return -
1;

    
dynsymlib->lib = lib;

#ifndef _WIN32
    
struct link_map *lm = 0;
    
dlinfo(lib, RTLD_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_name, 0);
#else
    
{
        
char tmp[MAX_PATH];
        
memset(tmp, 0, sizeof(tmp));
        if(
GetModuleFileNameA((HMODULE)lib, tmp, ARRAYSIZE(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(dynsymlib, symtab);
    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_pattern, dynsym_lib_t *dynsymlib, const char *const _LIB_PATH, sgo_log_t logger)
{
    if(!
name_pattern)
    {
        
void *lib = dlopen(0, RTLD_LAZY);
        return 
lib;
    }

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

            if(
LD_LIBRARY_PATH && LD_LIBRARY_PATH[0])
                
snprintf(LIB_PATH, sizeof(LIB_PATH) - 1, "%s:", LD_LIBRARY_PATH);
            
strncat(LIB_PATH, _LIB_PATH, sizeof(LIB_PATH) - 1);

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

        
char *strtok_dir = 0;
        const 
char *libdir = strtok_r(LIB_PATH, TOKEN_PATH_SPLIT, &strtok_dir);
        
void *lib = 0;
        do
        {
            
char libpath[PATH_MAX];
            
memset(libpath, 0, sizeof(libpath));
            if(
libdir)
                
snprintf(libpath, sizeof(libpath) - 1, "%s/%s", libdir, name);
            else
                
strncpy(libpath, name, sizeof(libpath) - 1);

            
glob_t blob;
            
int r = glob(libpath, GLOB_BRACE, 0, &blob);
            if(
r)
            {
                
DYNSYM_LOG(eDYNSYM_LOG_DBG, "glob('%s') failed. [%s]\n", libpath, strerror(ENOENT));
            }
            else
            {
                for(
size_t i = 0; i < blob.gl_pathc; i++)
                {
                    const 
char *name = blob.gl_pathv[i];
                    
lib = dlopen(name, RTLD_LAZY);
                    if(
lib)
                        break;
                }
            }

            
globfree(&blob);

            if(
lib)
                return 
lib;

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

        
name = strtok_r(0, TOKEN_PATH_SPLIT, &strtok_name);
    }

    return 
0;
}

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

    return 
dynsym_init_ex(lib, dynsymlib, symtab);
}

#endif // #ifndef __DYNSYM_H__


#ifndef DYNSYM_CALL_DECL
#define DYNSYM_CALL_DECL
#endif

#define DYNSYM_DEF(RET, NAME, ...) \
    
DYNSYM_DEF_EX(RET, NAME, NAME, __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(T, VNAME, SNAME)

#define DYNSYM_VAR_EX(T, VNAME, SNAME)

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

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

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

#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), niculaita (04-14-2018), tonyweb (05-09-2018)
 


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On


Similar Threads
Thread Thread Starter Forum Replies Last Post
Calling any function dynamically without typedef Succubus Source Code 0 10-21-2021 16:34
WinAPI: No WM_COMMAND Message? aldente General Discussion 2 07-05-2006 07:17


All times are GMT +8. The time now is 17:24.


Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX, chessgod101
( Since 1998 )