Skip to content

Commit

Permalink
Merge branch 'develop' into feature/version_macro
Browse files Browse the repository at this point in the history
  • Loading branch information
hariharan-devarajan authored Jun 3, 2024
2 parents 90908f6 + 936a311 commit 840e932
Show file tree
Hide file tree
Showing 12 changed files with 240 additions and 32 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@
build
tags
**/tags
*.core
.cache
.idea
.vscode
2 changes: 1 addition & 1 deletion src/gotcha.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ static void setBindingAddressPointer(struct gotcha_binding_t *in, void *value) {
writeAddress(target, value);
}

static void **getInternalBindingAddressPointer(struct internal_binding_t **in) {
void **getInternalBindingAddressPointer(struct internal_binding_t **in) {
return (void **)&((*in)->wrappee_pointer);
}

Expand Down
13 changes: 11 additions & 2 deletions src/gotcha_dl.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,16 @@ static void *dlsym_wrapper(void *handle, const char *symbol_name) {
debug_printf(1, "User called dlsym(%p, %s)\n", handle, symbol_name);
int result = lookup_hashtable(&function_hash_table, (hash_key_t)symbol_name,
(hash_data_t *)&binding);
if (result != -1) return binding->user_binding->wrapper_pointer;
void *val = orig_dlsym(handle, symbol_name);
void **wrappee_ptr = getInternalBindingAddressPointer(
(struct internal_binding_t **)binding->user_binding->function_handle);
if (result != -1 && (val == NULL || *wrappee_ptr == val)) {
// if the wrapper is found and the wrappee is the function requested.
// This is needed in cases where we wrap a function F1 from library A and
// we dynamically load function F1 from library B. As name is same, we need
// to make sure the wrappee are the same as well
return binding->user_binding->wrapper_pointer;
}
if (handle == RTLD_NEXT) {
struct link_map *lib = gotchas_dlsym_rtld_next_lookup(
symbol_name, __builtin_return_address(0));
Expand All @@ -169,7 +178,7 @@ static void *dlsym_wrapper(void *handle, const char *symbol_name) {
}
return NULL;
} else {
return orig_dlsym(handle, symbol_name);
return val;
}
}

Expand Down
1 change: 1 addition & 0 deletions src/gotcha_dl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ extern void update_all_library_gots(hash_table_t *bindings);
extern long lookup_exported_symbol(const char *name, const struct link_map *lib,
void **symbol);
extern int prepare_symbol(struct internal_binding_t *binding);
extern void **getInternalBindingAddressPointer(struct internal_binding_t **in);

extern gotcha_wrappee_handle_t orig_dlopen_handle;
extern gotcha_wrappee_handle_t orig_dlsym_handle;
Expand Down
3 changes: 2 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ add_subdirectory(filter)
add_subdirectory(wrap_main)
#add_subdirectory(multi_agent_dlopen)
add_subdirectory(symver)
add_subdirectory(function_ptr)
add_subdirectory(function_ptr)
add_subdirectory(dispatcher)
8 changes: 8 additions & 0 deletions test/dispatcher/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
add_library(impl SHARED libimpl.c)
add_library(dispatcher SHARED libdispatcher.c)
target_link_libraries(dispatcher -ldl -lpthread)
add_executable(test_dispatcher main.c)
target_link_libraries(test_dispatcher gotcha dispatcher)
gotcha_add_test(dispatcher_test test_dispatcher)
set_property(TEST dispatcher_test APPEND PROPERTY ENVIRONMENT "GOTCHA_DEBUG=3")
set_property(TEST dispatcher_test APPEND PROPERTY ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_CURRENT_BINARY_DIR}")
67 changes: 67 additions & 0 deletions test/dispatcher/libdispatcher.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
This file is part of GOTCHA. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/gotcha/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#define _GNU_SOURCE
#include <assert.h>
#include <dlfcn.h>
#include <pthread.h>
#include <stdio.h>

int foo(void);
int bar(void);

static void* impl_lib;
static int (*impl_foo)(void);
static int (*impl_bar)(void);

static pthread_once_t init_once = PTHREAD_ONCE_INIT;
void dispatch_init(void) {
fprintf(stderr, "Ed dispatch_init()\n");

impl_lib = dlopen("libimpl.so", RTLD_NOW);
assert(impl_lib);
impl_foo = dlsym(impl_lib, "foo");
assert(impl_foo);
impl_bar = dlsym(impl_lib, "bar");
assert(impl_bar);

int ret = impl_bar();

fprintf(stderr, "Ld dispatch_init() = %d\n", ret);
}

int foo(void) {
fprintf(stderr, "Ed foo()\n");

pthread_once(&init_once, dispatch_init);

int ret = impl_bar() + impl_foo();

fprintf(stderr, "Ld foo()\n");

return ret;
}

int bar(void) {
fprintf(stderr, "Ed bar()\n");

pthread_once(&init_once, dispatch_init);

int ret = impl_bar();

fprintf(stderr, "Ld bar()\n");

return ret;
}
31 changes: 31 additions & 0 deletions test/dispatcher/libimpl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
This file is part of GOTCHA. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/gotcha/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#define _GNU_SOURCE
#include <stdio.h>

int foo(void) {
fprintf(stderr, "Ei foo()\n");
fprintf(stderr, "Li foo()\n");

return 42;
}

int bar(void) {
fprintf(stderr, "Ei bar()\n");
fprintf(stderr, "Li bar()\n");

return 23;
}
58 changes: 58 additions & 0 deletions test/dispatcher/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
This file is part of GOTCHA. For copyright information see the COPYRIGHT
file in the top level directory, or at
https://github.com/LLNL/gotcha/blob/master/COPYRIGHT
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (as published by the Free
Software Foundation) version 2.1 dated February 1999. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the terms and conditions of the GNU Lesser General Public License
for more details. You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#define _GNU_SOURCE
#include <gotcha/gotcha.h>
#include <stdio.h>

int foo(void);
int bar(void);

static gotcha_wrappee_handle_t handle_foo;
static gotcha_wrappee_handle_t handle_bar;

static int do_foo(void) {
fprintf(stderr, "Ew foo()\n");

typeof(&do_foo) orig_foo = gotcha_get_wrappee(handle_foo);
int ret = orig_foo();

fprintf(stderr, "Lw foo() = %d\n", ret);

return ret;
}

static int do_bar(void) {
fprintf(stderr, "Ew bar()\n");

typeof(&do_bar) orig_bar = gotcha_get_wrappee(handle_bar);
int ret = orig_bar();

fprintf(stderr, "Lw bar() = %d\n", ret);

return ret;
}

static struct gotcha_binding_t bindings[] = {
{"foo", do_foo, &handle_foo},
{"bar", do_bar, &handle_bar},
};

int main(int ac, char *av[]) {
gotcha_wrap(bindings, 2, "test");
printf("%d\n", foo());

return 0;
}
1 change: 0 additions & 1 deletion test/dlopen/num.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ Public License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

extern void mark_had_error();
extern int return_five();

int return_four() {
Expand Down
10 changes: 5 additions & 5 deletions test/dlopen/num2.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ Public License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

extern void mark_had_error();
extern int return_five();
int return_four() { return 6; }

int return_four() { return 4; }

int test_return_five() { return return_five(); }
int return_six() {
/* Intentional bug, gotcha wrapping will correct this to return 6 */
return 7;
}
74 changes: 52 additions & 22 deletions test/dlopen/test_dlopen.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,51 +32,52 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#define LIB_NAME QUOTE(LIB_NAME_RAW)
#define LIB2_NAME QUOTE(LIB2_NAME_RAW)
int correct_return_four() { return 4; }
int correct_return_five() { return 5; }
int correct_return_six() { return 6; }

int return_five() {
/* Intentional bug, gotcha will correct this to return 5*/
return 3;
}

int correct_return_five() { return 5; }

static gotcha_wrappee_handle_t buggy_return_four;
static gotcha_wrappee_handle_t buggy_return_five;
static gotcha_wrappee_handle_t buggy_return_six;

struct gotcha_binding_t funcs[] = {
{"return_four", correct_return_four, &buggy_return_four},
{"return_five", correct_return_five, &buggy_return_five}};
{"return_five", correct_return_five, &buggy_return_five},
{"return_six", correct_return_six, &buggy_return_six}};

int main() {
void *libnum;
void *libnum2;
int (*retfour)(void);
int (*retsix)(void);
int (*test_retfive)(void);
int (*retdummy)(void);
int had_error = 0;
int result;

result = gotcha_wrap(funcs, 2, "dlopen_test");
/* We wrap the functions before they are loaded */
result = gotcha_wrap(funcs, 3, "dlopen_test");
if (result != GOTCHA_FUNCTION_NOT_FOUND) {
fprintf(stderr,
"GOTCHA should have failed to find a function, but found it\n");
return -1;
}

/* Load the first libnum.so */
libnum = dlopen(LIB_NAME, RTLD_NOW);
if (!libnum) {
fprintf(stderr, "ERROR: Test failed to dlopen libnum.so\n");
return -1;
}
libnum = dlopen(LIB2_NAME, RTLD_NOW);
if (!libnum) {
fprintf(stderr, "ERROR: Test failed to dlopen libnum2.so\n");
return -1;
}

/* Test 1: Check if a dlsym generated indirect call gets re-routed by gotcha
*/
/* Check if return_four is wrapped from libnum.so */
retfour = (int (*)(void))dlsym(libnum, "return_four");
if (retfour() != 4) {
fprintf(stderr, "ERROR: dlsym returned original function, not wrapped\n");
if (retfour == NULL || retfour() != 4) {
fprintf(stderr,
"ERROR: dlsym returned original function, not wrapped from "
"libnum.so\n");
had_error = -1;
}

Expand All @@ -88,16 +89,25 @@ int main() {
"by correct_return_five\n");
had_error = -1;
}
/* Test 3: Does the dlsym implementation find the second occurrence of the
* symbol */
test_retfive = (int (*)(void))dlsym(RTLD_NEXT, "test_return_five");
if (test_retfive == NULL || test_retfive() != 5) {

/* Load libnum2.so */
libnum2 = dlopen(LIB2_NAME, RTLD_NOW);
if (!libnum) {
fprintf(stderr, "ERROR: Test failed to dlopen libnum2.so\n");
return -1;
}

/* Check if return_six is wrapped from libnum2.so */
retsix = (int (*)(void))dlsym(libnum2, "return_six");
if (retsix == NULL || retsix() != 6) {
fprintf(stderr,
"ERROR: call to return_four should not be found in "
"RTLD_NEXT from libnum2.so and return 4\n");
"ERROR: dlsym returned original function, not wrapped from "
"libnum2.so\n");
had_error = -1;
}
/* Test 4: Does the dlsym implementation find the first occurrence of the

/* Check RTLD_DEFAULT */
/* Does the dlsym implementation find the first occurrence of the
* symbol */
retfour = (int (*)(void))dlsym(RTLD_DEFAULT, "return_four");
if (retfour == NULL || retfour() != 4) {
Expand All @@ -113,13 +123,33 @@ int main() {
"by correct_return_five\n");
had_error = -1;
}

retsix = (int (*)(void))dlsym(RTLD_DEFAULT, "return_six");
if (retsix == NULL || retsix() != 6) {
fprintf(stderr,
"ERROR: call to return_five in libnum2.so was not wrapped "
"by correct_return_five\n");
had_error = -1;
}

retdummy = (int (*)(void))dlsym(RTLD_DEFAULT, "return_dummy");
if (retdummy != NULL) {
fprintf(
stderr,
"ERROR: call to return_dummy should not be found in RTLD_DEFAULT\n");
had_error = -1;
}

/* Test RTLD_NEXT */
/* Does the dlsym implementation find the second occurrence of the
* symbol */
test_retfive = (int (*)(void))dlsym(RTLD_NEXT, "test_return_five");
if (test_retfive == NULL || test_retfive() != 5) {
fprintf(stderr,
"ERROR: call to return_four should not be found in "
"RTLD_NEXT from libnum2.so and return 4\n");
had_error = -1;
}
retdummy = (int (*)(void))dlsym(RTLD_NEXT, "return_dummy");
if (retdummy != NULL) {
fprintf(stderr,
Expand Down

0 comments on commit 840e932

Please sign in to comment.