It is possible using the LD_PRELOAD
trick. I'll not get really deep in the explanation of it, as this could be seen here, as well as in a short search in Google.
I'll show how I implemented it in C, for it to be valid for C users as well:
Let's have another C file and call it trick.c:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <time.h>
typedef struct tm * (*gmtime_r_t)(const time_t *, struct tm *);
static int __fail = 0;
void __fail_gmtime_r() { __fail = 1; }
void __pass_gmtime_r() { __fail = 0; }
struct tm *gmtime_r(const time_t *timep, struct tm *result)
{
if (__fail) { return NULL; }
return ((gmtime_r_t)dlsym(RTLD_NEXT, "gmtime_r"))(timep, result);
}
Here, we implement our version of gmtime_r()
, and we either call the original method, or fail it (returning NULL
), depending on a flag (__fail
).
We also expose two methods to set the value of this flag: __fail_gmtime_r()
, and __pass_gmtime_r()
.
We compile this file into a shared object using the command line gcc trick.c -shared -fPIC -o trick.so -ldl
.
I also implemented a small executable with a main()
similar to yours for testing it, where I use the trick
shared object. main.c:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <time.h>
#include <stdio.h>
typedef void (*__fail_gmtime_r_t)();
typedef void (*__pass_gmtime_r_t)();
int main()
{
__fail_gmtime_r_t __fail_gmtime_r = dlsym(RTLD_DEFAULT, "__fail_gmtime_r");
__pass_gmtime_r_t __pass_gmtime_r = dlsym(RTLD_DEFAULT, "__pass_gmtime_r");
time_t ptr;
time(&ptr);
struct tm dates;
printf(gmtime_r(&ptr, &dates) ? "OK\n" : "FAIL\n");
__fail_gmtime_r();
printf(gmtime_r(&ptr, &dates) ? "OK\n" : "FAIL\n");
__pass_gmtime_r();
printf(gmtime_r(&ptr, &dates) ? "OK\n" : "FAIL\n");
return 0;
}
And I compile it using the command line gcc main.c -o main -ldl
.
Then, I used the following command in order to run the executable with the trick shared object replacing gmtime_r()
: LD_PRELOAD=<FULL PATH TO trick.so> ./main
.
You should call __fail_gmtime_r()
and __pass_gmtime_r()
from your main()
to acheive the same effect.
I didn't go deep into explanations, but if it's something you'd like I have no problem in further explaining everything here.