Created
March 7, 2019 19:13
-
-
Save aprell/0e26c731e6a0c41e5539d88a3ddbda5f to your computer and use it in GitHub Desktop.
Wrapping library functions using -Wl,--wrap=symbol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CC := gcc | |
CFLAGS += -Wall -Wextra -std=c99 | |
LDLIBS += -lpthread | |
all: test_wrap | |
test_wrap: LDFLAGS += -Wl,--wrap=pthread_create -Wl,--wrap=pthread_join | |
test_wrap: test_wrap.c wrap.c | |
clean: | |
rm -rf test_wrap | |
.PHONY: all clean |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <pthread.h> | |
#include <stdlib.h> | |
unsigned int num_threads; | |
static void *thread_entry_fn(void *arg) | |
{ | |
(void)arg; | |
return NULL; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
unsigned int n = argc > 1 && atoi(argv[1]) >= 0 ? atoi(argv[1]) : 4; | |
pthread_t *threads = malloc(n * sizeof(pthread_t)); | |
if (!threads) return EXIT_FAILURE; | |
for (unsigned int i = 0; i < n; i++) { | |
pthread_create(&threads[i], NULL, thread_entry_fn, NULL); | |
} | |
assert(num_threads == n); | |
for (unsigned int i = 0; i < n; i++) { | |
pthread_join(threads[i], NULL); | |
} | |
assert(num_threads == 0); | |
free(threads); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <pthread.h> | |
extern unsigned int num_threads; | |
// From the docs: | |
// Any undefined reference to `symbol` will be resolved to `__wrap_symbol`. Any | |
// undefined reference to `__real_symbol` will be resolved to `symbol`. This | |
// can be used to provide a wrapper for a system function. The wrapper function | |
// should be called `__wrap_symbol`. If it wishes to call the system function, | |
// it should call `__real_symbol`. | |
extern int __real_pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *); | |
extern int __real_pthread_join(pthread_t, void **); | |
int __wrap_pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) | |
{ | |
num_threads++; | |
return __real_pthread_create(thread, attr, start_routine, arg); | |
} | |
int __wrap_pthread_join(pthread_t thread, void **retval) | |
{ | |
num_threads--; | |
return __real_pthread_join(thread, retval); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment