mirror of
https://github.com/yugr/Implib.so
synced 2026-06-08 18:33:41 +00:00
Added user API to specify manually loaded library handle (gh-14).
This commit is contained in:
Vendored
+24
-9
@@ -41,6 +41,7 @@ extern "C" {
|
||||
#define LAZY_LOAD $lazy_load
|
||||
|
||||
static void *lib_handle;
|
||||
static int do_dlclose;
|
||||
static int is_lib_loading;
|
||||
|
||||
#if ! NO_DLOPEN
|
||||
@@ -59,13 +60,14 @@ static void *load_library() {
|
||||
CHECK(lib_handle, "failed to load library via dlopen: %s", dlerror());
|
||||
#endif
|
||||
|
||||
do_dlclose = 1;
|
||||
is_lib_loading = 0;
|
||||
|
||||
return lib_handle;
|
||||
}
|
||||
|
||||
static void __attribute__((destructor)) unload_lib() {
|
||||
if(lib_handle)
|
||||
if(do_dlclose && lib_handle)
|
||||
dlclose(lib_handle);
|
||||
}
|
||||
#endif
|
||||
@@ -94,14 +96,20 @@ void _${lib_suffix}_tramp_resolve(int i) {
|
||||
|
||||
void *h = 0;
|
||||
#if NO_DLOPEN
|
||||
// Library with implementations has already been loaded.
|
||||
// If shim symbols are hidden we should search for first available definition of symbol
|
||||
// in library list, otherwise look for next available definition
|
||||
# ifdef IMPLIB_HIDDEN_SHIMS
|
||||
h = RTLD_DEFAULT;
|
||||
# else
|
||||
h = RTLD_NEXT;
|
||||
# endif
|
||||
// Library with implementations must have already been loaded.
|
||||
if (lib_handle) {
|
||||
// User has specified loaded library
|
||||
h = lib_handle;
|
||||
} else {
|
||||
// User hasn't provided us the loaded library so search the global namespace.
|
||||
// If shim symbols are hidden we should search for first available definition of symbol
|
||||
// in library list, otherwise look for next available definition
|
||||
# ifdef IMPLIB_HIDDEN_SHIMS
|
||||
h = RTLD_DEFAULT;
|
||||
# else
|
||||
h = RTLD_NEXT;
|
||||
# endif
|
||||
}
|
||||
#else
|
||||
h = load_library();
|
||||
CHECK(h, "failed to resolve symbol '%s', library failed to load", sym_names[i]);
|
||||
@@ -119,11 +127,18 @@ void _${lib_suffix}_tramp_resolve_all(void) {
|
||||
_${lib_suffix}_tramp_resolve(i);
|
||||
}
|
||||
|
||||
// Allows user to specify manually loaded implementation library.
|
||||
void _${lib_suffix}_tramp_set_handle(void *handle) {
|
||||
lib_handle = handle;
|
||||
do_dlclose = 0;
|
||||
}
|
||||
|
||||
// Resets all resolved symbols. This is needed in case
|
||||
// client code wants to reload interposed library multiple times.
|
||||
void _${lib_suffix}_tramp_reset(void) {
|
||||
memset(_${lib_suffix}_tramp_table, 0, SYM_COUNT * sizeof(_${lib_suffix}_tramp_table[0]));
|
||||
lib_handle = 0;
|
||||
do_dlclose = 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -36,3 +36,4 @@ tests/verbose/run.sh $ARCH
|
||||
tests/no_dlopen/run.sh $ARCH
|
||||
tests/multiple-dlopens/run.sh $ARCH
|
||||
tests/multiple-dlopens-2/run.sh $ARCH
|
||||
tests/multiple-dlopens-3/run.sh $ARCH
|
||||
|
||||
@@ -33,21 +33,16 @@ void *my_load_library(const char *name) {
|
||||
return handle;
|
||||
}
|
||||
|
||||
void my_unload_library() {
|
||||
dlclose(handle);
|
||||
handle = 0;
|
||||
assert(dlopen("libinterposed.so", RTLD_NOLOAD) == 0);
|
||||
|
||||
extern void _libinterposed_so_tramp_reset(void);
|
||||
_libinterposed_so_tramp_reset();
|
||||
}
|
||||
|
||||
int main() {
|
||||
test();
|
||||
my_unload_library();
|
||||
extern void _libinterposed_so_tramp_reset(void);
|
||||
|
||||
test();
|
||||
my_unload_library();
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
test();
|
||||
dlclose(handle);
|
||||
handle = 0;
|
||||
assert(dlopen("libinterposed.so", RTLD_NOLOAD) == 0);
|
||||
_libinterposed_so_tramp_reset();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2022 Yury Gribov
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Use of this source code is governed by MIT license that can be
|
||||
* found in the LICENSE.txt file.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "interposed.h"
|
||||
|
||||
__attribute__((visibility("default")))
|
||||
int foo(int x, float y) {
|
||||
printf("Calling foo from libtest: %d %g\n", x, y);
|
||||
return 0xf00;
|
||||
}
|
||||
|
||||
__attribute__((visibility("default")))
|
||||
int bar(int x, int y, int z) {
|
||||
printf("Calling bar from libtest: %d %d %d\n", x, y, z);
|
||||
return 0xba7;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2022 Yury Gribov
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Use of this source code is governed by MIT license that can be
|
||||
* found in the LICENSE.txt file.
|
||||
*/
|
||||
|
||||
#ifndef INTERPOSED_H
|
||||
#define INTERPOSED_H
|
||||
|
||||
extern int foo(int x, float y);
|
||||
extern int bar(int x, int y, int z);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2022 Yury Gribov
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Use of this source code is governed by MIT license that can be
|
||||
* found in the LICENSE.txt file.
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "interposed.h"
|
||||
|
||||
void test() {
|
||||
int x, y;
|
||||
// Slow path
|
||||
x = foo(25, 0.5),
|
||||
y = bar(11, 22, 33);
|
||||
printf("Results: %x %x\n", x, y);
|
||||
// Fast path
|
||||
x = foo(35, 0.25);
|
||||
y = bar(44, 55, 66);
|
||||
printf("Results: %x %x\n", x, y);
|
||||
}
|
||||
|
||||
int main() {
|
||||
extern void _libinterposed_so_tramp_set_handle(void *handle);
|
||||
extern void _libinterposed_so_tramp_reset(void);
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
void *h = dlopen("libinterposed.so", RTLD_LOCAL | RTLD_LAZY);
|
||||
_libinterposed_so_tramp_set_handle(h);
|
||||
|
||||
test();
|
||||
|
||||
dlclose(h);
|
||||
assert(dlopen("libinterposed.so", RTLD_NOLOAD) == 0);
|
||||
_libinterposed_so_tramp_reset();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright 2022 Yury Gribov
|
||||
#
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Use of this source code is governed by MIT license that can be
|
||||
# found in the LICENSE.txt file.
|
||||
|
||||
# This is a test for manual loading of destination library (--no-dlopen flag).
|
||||
# Run it like
|
||||
# ./run.sh ARCH
|
||||
# where ARCH stands for any supported arch (arm, x86_64, etc., see `implib-gen -h' for full list).
|
||||
# Note that you may need to install qemu-user for respective platform
|
||||
# (i386 also needs gcc-multilib).
|
||||
|
||||
set -eu
|
||||
|
||||
cd $(dirname $0)
|
||||
|
||||
if test -n "${1:-}"; then
|
||||
ARCH="$1"
|
||||
fi
|
||||
|
||||
. ../common.sh
|
||||
|
||||
CFLAGS="-g -O2 $CFLAGS"
|
||||
LIBS='-ldl'
|
||||
|
||||
# Build shlib to test against
|
||||
$CC $CFLAGS -shared -fPIC interposed.c -o libinterposed.so
|
||||
|
||||
# Prepare implib
|
||||
${PYTHON:-} ../../implib-gen.py -q --target $TARGET --no-dlopen libinterposed.so
|
||||
|
||||
# Build app
|
||||
$CC $CFLAGS -fPIE main.c libinterposed.so.tramp.S libinterposed.so.init.c $LIBS
|
||||
|
||||
LD_LIBRARY_PATH=.:${LD_LIBRARY_PATH:-} $INTERP ./a.out > a.out.log
|
||||
diff test.ref a.out.log
|
||||
|
||||
echo SUCCESS
|
||||
@@ -0,0 +1,12 @@
|
||||
Calling foo from libtest: 25 0.5
|
||||
Calling bar from libtest: 11 22 33
|
||||
Results: f00 ba7
|
||||
Calling foo from libtest: 35 0.25
|
||||
Calling bar from libtest: 44 55 66
|
||||
Results: f00 ba7
|
||||
Calling foo from libtest: 25 0.5
|
||||
Calling bar from libtest: 11 22 33
|
||||
Results: f00 ba7
|
||||
Calling foo from libtest: 35 0.25
|
||||
Calling bar from libtest: 44 55 66
|
||||
Results: f00 ba7
|
||||
@@ -28,17 +28,13 @@ void test() {
|
||||
extern void _libinterposed_so_tramp_reset(void);
|
||||
|
||||
int main() {
|
||||
void *h = dlopen("libinterposed.so", RTLD_GLOBAL | RTLD_LAZY);
|
||||
test();
|
||||
dlclose(h);
|
||||
assert(dlopen("libinterposed.so", RTLD_NOLOAD) == 0);
|
||||
_libinterposed_so_tramp_reset();
|
||||
|
||||
h = dlopen("libinterposed.so", RTLD_GLOBAL | RTLD_LAZY);
|
||||
test();
|
||||
dlclose(h);
|
||||
assert(dlopen("libinterposed.so", RTLD_NOLOAD) == 0);
|
||||
_libinterposed_so_tramp_reset();
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
void *h = dlopen("libinterposed.so", RTLD_GLOBAL | RTLD_LAZY);
|
||||
test();
|
||||
dlclose(h);
|
||||
assert(dlopen("libinterposed.so", RTLD_NOLOAD) == 0);
|
||||
_libinterposed_so_tramp_reset();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user