Skip to content

Commit

Permalink
Implemented metacall link table.
Browse files Browse the repository at this point in the history
  • Loading branch information
viferga committed Nov 28, 2024
1 parent 1927c62 commit d9604dd
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 14 deletions.
14 changes: 14 additions & 0 deletions source/dynlink/include/dynlink/dynlink_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,20 @@ typedef void (*dynlink_symbol_addr)(void); /**< Function pointer referrin
\
} while (0)

#define dynlink_symbol_uncast(fn, result) \
do \
{ \
union \
{ \
void *ptr; \
dynlink_symbol_addr fn; \
} cast; \
\
cast.fn = (fn); \
(result) = cast.ptr; \
\
} while (0)

#ifdef __cplusplus
}
#endif
Expand Down
33 changes: 32 additions & 1 deletion source/metacall/include/metacall/metacall_link.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,38 @@ extern "C" {
*/
METACALL_API int metacall_link_initialize(void);

// TODO: Implement dlsym hook function table
/**
* @brief
* Register a function pointer in order to allow function
* interposition when loading a library, if you register a
* function @symbol called 'foo', when you try to dlsym (or the equivalent
* on every platform), you will get the pointer to @fn, even if
* the symbol does not exist in the library, it will work.
* Function interposition is required in order to hook into runtimes
* and dynamically interpose our functions.
*
* @param[in] symbol
* Name of the function to be interposed
*
* @param[in] fn
* Function pointer that will be returned by dlsym (or equivalent) when accessing to @symbol
*
* @return
* Zero if success, different from zero otherwise
*/
METACALL_API int metacall_link_register(const char *symbol, void (*fn)(void));

/**
* @brief
* Remove the hook previously registered
*
* @param[in] symbol
* Name of the function to be removed
*
* @return
* Zero if success, different from zero otherwise
*/
METACALL_API int metacall_link_unregister(const char *symbol);

/**
* @brief
Expand Down
14 changes: 13 additions & 1 deletion source/metacall/source/metacall_fork.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
/*
* MetaCall Library by Parra Studios
* A library for providing a foreign function interface calls.
*
* Copyright (C) 2016 - 2024 Vicente Eduardo Ferrer Garcia <vic798@gmail.com>
*
* A library for providing a foreign function interface calls.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

Expand Down
103 changes: 91 additions & 12 deletions source/metacall/source/metacall_link.c
Original file line number Diff line number Diff line change
@@ -1,26 +1,44 @@
// /*
// * MetaCall Library by Parra Studios
// * Copyright (C) 2016 - 2024 Vicente Eduardo Ferrer Garcia <vic798@gmail.com>
// *
// * A library for providing a foreign function interface calls.
// *
// */

// /* -- Headers -- */
/*
* MetaCall Library by Parra Studios
* A library for providing a foreign function interface calls.
*
* Copyright (C) 2016 - 2024 Vicente Eduardo Ferrer Garcia <vic798@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

/* -- Headers -- */

#include <metacall/metacall.h>
#include <metacall/metacall_link.h>

#include <detour/detour.h>

#include <dynlink/dynlink_type.h>

#include <log/log.h>

#include <adt/adt_set.h>

#include <stdlib.h>

/* -- Private Variables -- */

static detour_handle detour_link_handle = NULL;

static set metacall_link_table = NULL;

#if defined(WIN32) || defined(_WIN32) || \
defined(__CYGWIN__) || defined(__CYGWIN32__) || \
defined(__MINGW32__) || defined(__MINGW64__)
Expand All @@ -38,7 +56,17 @@ FARPROC metacall_link_hook(HMODULE handle, LPCSTR symbol)

metacall_link_func_ptr metacall_link_trampoline = (metacall_link_func_ptr)detour_trampoline(detour_link_handle);

// TODO: Intercept if any, iterate hash map elements and invoke them
/* Intercept if any */
void *ptr = set_get(metacall_link_table, (set_key)symbol);

if (ptr != NULL)
{
dynlink_symbol_addr addr;

dynlink_symbol_cast(void *, ptr, addr);

return (FARPROC)addr;
}

return metacall_link_trampoline(handle, symbol);
}
Expand All @@ -61,7 +89,15 @@ void *metacall_link_hook(void *handle, const char *symbol)

metacall_link_func_ptr metacall_link_trampoline = (metacall_link_func_ptr)detour_trampoline(detour_link_handle);

// TODO: Intercept if any, iterate hash map elements and invoke them
/* Intercept function if any */
void *ptr = set_get(metacall_link_table, (set_key)symbol);

log_write("metacall", LOG_LEVEL_DEBUG, "MetaCall detour link interception: %s -> %p", symbol, ptr);

if (ptr != NULL)
{
return ptr;
}

return metacall_link_trampoline(handle, symbol);
}
Expand Down Expand Up @@ -90,9 +126,47 @@ int metacall_link_initialize(void)
}
}

if (metacall_link_table == NULL)
{
metacall_link_table = set_create(&hash_callback_str, &comparable_callback_str);

if (metacall_link_table == NULL)
{
log_write("metacall", LOG_LEVEL_ERROR, "MetaCall failed to create link table");

metacall_link_destroy();

return 1;
}
}

return 0;
}

int metacall_link_register(const char *symbol, void (*fn)(void))
{
void *ptr;

if (metacall_link_table == NULL)
{
return 1;
}

dynlink_symbol_uncast(fn, ptr);

return set_insert(metacall_link_table, (set_key)symbol, ptr);
}

int metacall_link_unregister(const char *symbol)
{
if (metacall_link_table == NULL)
{
return 1;
}

return (set_remove(metacall_link_table, (set_key)symbol) == NULL);
}

int metacall_link_destroy(void)
{
int result = 0;
Expand All @@ -111,7 +185,12 @@ int metacall_link_destroy(void)
detour_link_handle = NULL;
}

// TODO: Destroy hash map
if (metacall_link_table != NULL)
{
set_destroy(metacall_link_table);

metacall_link_table = NULL;
}

return result;
}

0 comments on commit d9604dd

Please sign in to comment.