diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 9 | ||||
-rw-r--r-- | src/Makefile.OSX | 2 | ||||
-rw-r--r-- | src/libfaketime.c | 254 | ||||
-rw-r--r-- | src/libfaketime.map | 10 |
4 files changed, 208 insertions, 67 deletions
diff --git a/src/Makefile b/src/Makefile index d4d5be2..2ae30bd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -50,9 +50,9 @@ INSTALL ?= install PREFIX ?= /usr/local -CFLAGS += -std=gnu99 -Wall -DFAKE_STAT -DFAKE_SLEEP -DFAKE_INTERNAL_CALLS -fPIC -DPREFIX='"'$(PREFIX)'"' +CFLAGS += -std=gnu99 -Wall -DFAKE_STAT -DFAKE_SLEEP -DFAKE_TIMERS -DFAKE_INTERNAL_CALLS -fPIC -DPREFIX='"'$(PREFIX)'"' LIB_LDFLAGS += -shared -LDFLAGS += -lrt +LDFLAGS += -lrt -Wl,--version-script=libfaketime.map LDADD += -ldl -lm -lpthread SRC = libfaketime.c @@ -69,9 +69,12 @@ faketimeMT.o: EXTRA_FLAGS := -DPTHREAD -DPTHREAD_SINGLETHREADED_TIME ${LIBS_OBJ}: libfaketime.c ${CC} -o $@ -c ${CFLAGS} ${EXTRA_FLAGS} $< -%.so.${SONAME}: %.o +%.so.${SONAME}: %.o libfaketime.map ${CC} -o $@ -Wl,-soname,$@ ${LDFLAGS} ${LIB_LDFLAGS} $< ${LDADD} +${BINS}: faketime.c + ${CC} -o $@ -c ${CFLAGS} ${EXTRA_FLAGS} $< + clean: @rm -f ${LIBS_OBJ} ${LIBS} ${BINS} diff --git a/src/Makefile.OSX b/src/Makefile.OSX index f3a0ceb..8b414c4 100644 --- a/src/Makefile.OSX +++ b/src/Makefile.OSX @@ -48,7 +48,7 @@ PREFIX ?= /usr/local # 10.5 #CFLAGS = -dynamiclib -arch i386 -arch ppc # 10.6 -CFLAGS = -dynamiclib -DFAKE_SLEEP -arch i386 -arch x86_64 -DPREFIX='"'$(PREFIX)'"' +CFLAGS = -dynamiclib -DFAKE_SLEEP -DFAKE_TIMERS -arch i386 -arch x86_64 -DPREFIX='"'$(PREFIX)'"' LIB_SRC = libfaketime.c SONAME = 1 diff --git a/src/libfaketime.c b/src/libfaketime.c index 4cadc64..a26e22f 100644 --- a/src/libfaketime.c +++ b/src/libfaketime.c @@ -118,9 +118,15 @@ static int (*real_gettimeofday) (struct timeval *, void *); static int (*real_clock_gettime) (clockid_t clk_id, struct timespec *tp); #ifndef __APPLE__ #ifdef FAKE_TIMERS -static int (*real_timer_settime) (timer_t timerid, int flags, const struct itimerspec *new_value, - struct itimerspec * old_value); -static int (*real_timer_gettime) (timer_t timerid, struct itimerspec *curr_value); +static int (*real_timer_settime_22) (int timerid, int flags, const struct itimerspec *new_value, + struct itimerspec * old_value); +static int (*real_timer_settime_233) (timer_t timerid, int flags, + const struct itimerspec *new_value, + struct itimerspec * old_value); +static int (*real_timer_gettime_22) (int timerid, + struct itimerspec *curr_value); +static int (*real_timer_gettime_233) (timer_t timerid, + struct itimerspec *curr_value); #endif #endif #ifdef FAKE_SLEEP @@ -923,21 +929,31 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout) #ifndef __APPLE__ #ifdef FAKE_TIMERS + +/* timer related functions and structures */ +typedef union { + int int_member; + timer_t timer_t_member; +} timer_t_or_int; + +/* + * Faketime's function implementation's compatibility mode + */ +typedef enum {FT_COMPAT_GLIBC_2_2, FT_COMPAT_GLIBC_2_3_3} ft_lib_compat; + + /* * Faked timer_settime() * Does not affect timer speed when stepping clock with each time() call. */ -int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value, - struct itimerspec *old_value) +static int +timer_settime_common(timer_t_or_int timerid, int flags, + const struct itimerspec *new_value, + struct itimerspec *old_value, ft_lib_compat compat) { int result; - struct itimerspec new_real, old_real; - struct itimerspec *new_real_pt = &new_real, *old_real_pt = &old_real; - - if (real_timer_settime == NULL) - { - return -1; - } + struct itimerspec new_real; + struct itimerspec *new_real_pt = &new_real; if (new_value == NULL) { @@ -950,40 +966,63 @@ int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value } else { - // TODO fake - struct timespec tdiff, timeadj; - timespecsub(&new_value->it_value, &user_faked_time_timespec, &timeadj); - if (user_rate_set) + /* set it_value */ + if ((new_value->it_value.tv_sec != 0) || + (new_value->it_value.tv_nsec != 0)) { - timespecmul(&timeadj, 1.0/user_rate, &tdiff); + if (flags & TIMER_ABSTIME) + { + struct timespec tdiff, timeadj; + timespecsub(&new_value->it_value, &user_faked_time_timespec, &timeadj); + if (user_rate_set) + { + timespecmul(&timeadj, 1.0/user_rate, &tdiff); + } + else + { + tdiff = timeadj; + } + /* only CLOCK_REALTIME is handled */ + timespecadd(&ftpl_starttime.real, &tdiff, &new_real.it_value); + } + else + { + if (user_rate_set) + { + timespecmul(&new_value->it_value, 1.0/user_rate, &new_real.it_value); + } + else + { + new_real.it_value = new_value->it_value; + } + } } else { - tdiff = timeadj; + new_real.it_value = new_value->it_value; } - /* only CLOCK_REALTIME is handled */ - timespecadd(&ftpl_starttime.real, &tdiff, &new_real.it_value); - - new_real.it_value = new_value->it_value; - if (user_rate_set) + /* set it_interval */ + if (user_rate_set && ((new_value->it_interval.tv_sec != 0) || + (new_value->it_interval.tv_nsec != 0))) { timespecmul(&new_value->it_interval, 1.0/user_rate, &new_real.it_interval); } + else + { + new_real.it_interval = new_value->it_interval; + } } - if (old_value == NULL) - { - old_real_pt = NULL; - } - else if (dont_fake) - { - old_real_pt = old_value; - } - else + + switch (compat) { - old_real = *old_value; + case FT_COMPAT_GLIBC_2_2: + DONT_FAKE_TIME(result = (*real_timer_settime_22)(timerid.int_member, flags, + new_real_pt, old_value)); + case FT_COMPAT_GLIBC_2_3_3: + DONT_FAKE_TIME(result = (*real_timer_settime_233)(timerid.timer_t_member, + flags, new_real_pt, old_value)); } - DONT_FAKE_TIME(result = (*real_timer_settime)(timerid, flags, new_real_pt, old_real_pt)); if (result == -1) { return result; @@ -992,30 +1031,79 @@ int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value /* fake returned parts */ if ((old_value != NULL) && !dont_fake) { - result = fake_clock_gettime(CLOCK_REALTIME, &old_real.it_value); - if (user_rate_set) + if ((old_value->it_value.tv_sec != 0) || + (old_value->it_value.tv_nsec != 0)) + { + result = fake_clock_gettime(CLOCK_REALTIME, &old_value->it_value); + } + if (user_rate_set && ((old_value->it_interval.tv_sec != 0) || + (old_value->it_interval.tv_nsec != 0))) { - timespecmul(&old_real.it_interval, user_rate, &old_value->it_interval); + timespecmul(&old_value->it_interval, user_rate, &old_value->it_interval); } } + /* return the result to the caller */ return result; } -/** +/* + * Faked timer_settime() compatible with implementation in GLIBC 2.2 + */ +int timer_settime_22(int timerid, int flags, + const struct itimerspec *new_value, + struct itimerspec *old_value) +{ + if (real_timer_settime_22 == NULL) + { + return -1; + } + else + { + return (timer_settime_common((timer_t_or_int)timerid, flags, new_value, old_value, + FT_COMPAT_GLIBC_2_2)); + } +} + +/* + * Faked timer_settime() compatible with implementation in GLIBC 2.3.3 + */ +int timer_settime_233(timer_t timerid, int flags, + const struct itimerspec *new_value, + struct itimerspec *old_value) +{ + if (real_timer_settime_233 == NULL) + { + return -1; + } + else + { + return (timer_settime_common((timer_t_or_int)timerid, flags, new_value, old_value, + FT_COMPAT_GLIBC_2_3_3)); + } +} + +/* * Faked timer_gettime() * Does not affect timer speed when stepping clock with each time() call. */ -int timer_gettime(timer_t timerid, struct itimerspec *curr_value) +int timer_gettime_common(timer_t_or_int timerid, struct itimerspec *curr_value, ft_lib_compat compat) { int result; - if (real_timer_gettime == NULL) + if (real_timer_gettime_233 == NULL) { return -1; } - DONT_FAKE_TIME(result = (*real_timer_gettime)(timerid, curr_value)); + switch (compat) + { + case FT_COMPAT_GLIBC_2_2: + DONT_FAKE_TIME(result = (*real_timer_gettime_22)(timerid.int_member, curr_value)); + case FT_COMPAT_GLIBC_2_3_3: + DONT_FAKE_TIME(result = (*real_timer_gettime_233)(timerid.timer_t_member, curr_value)); + } + if (result == -1) { return result; @@ -1033,6 +1121,44 @@ int timer_gettime(timer_t timerid, struct itimerspec *curr_value) /* return the result to the caller */ return result; } + +/* + * Faked timer_gettime() compatible with implementation in GLIBC 2.2 + */ +int timer_gettime_22(timer_t timerid, struct itimerspec *curr_value) +{ + if (real_timer_gettime_22 == NULL) + { + return -1; + } + else + { + return (timer_gettime_common((timer_t_or_int)timerid, curr_value, + FT_COMPAT_GLIBC_2_2)); + } +} + +/* + * Faked timer_gettime() compatible with implementation in GLIBC 2.3.3 + */ +int timer_gettime_233(timer_t timerid, struct itimerspec *curr_value) +{ + if (real_timer_gettime_233 == NULL) + { + return -1; + } + else + { + return (timer_gettime_common((timer_t_or_int)timerid, curr_value, + FT_COMPAT_GLIBC_2_3_3)); + } +} + +__asm__(".symver timer_gettime_22, timer_gettime@GLIBC_2.2"); +__asm__(".symver timer_gettime_233, timer_gettime@@GLIBC_2.3.3"); +__asm__(".symver timer_settime_22, timer_settime@GLIBC_2.2"); +__asm__(".symver timer_settime_233, timer_settime@@GLIBC_2.3.3"); + #endif #endif @@ -1247,33 +1373,35 @@ void __attribute__ ((constructor)) ftpl_init(void) char *tmp_env; /* Look up all real_* functions. NULL will mark missing ones. */ - real_stat = dlsym(RTLD_NEXT, "__xstat"); - real_fstat = dlsym(RTLD_NEXT, "__fxstat"); - real_fstatat = dlsym(RTLD_NEXT, "__fxstatat"); - real_lstat = dlsym(RTLD_NEXT, "__lxstat"); - real_stat64 = dlsym(RTLD_NEXT,"__xstat64"); - real_fstat64 = dlsym(RTLD_NEXT, "__fxstat64"); - real_fstatat64 = dlsym(RTLD_NEXT, "__fxstatat64"); - real_lstat64 = dlsym(RTLD_NEXT, "__lxstat64"); - real_time = dlsym(RTLD_NEXT, "time"); - real_ftime = dlsym(RTLD_NEXT, "ftime"); - real_gettimeofday = dlsym(RTLD_NEXT, "gettimeofday"); + real_stat = dlsym(RTLD_NEXT, "__xstat"); + real_fstat = dlsym(RTLD_NEXT, "__fxstat"); + real_fstatat = dlsym(RTLD_NEXT, "__fxstatat"); + real_lstat = dlsym(RTLD_NEXT, "__lxstat"); + real_stat64 = dlsym(RTLD_NEXT,"__xstat64"); + real_fstat64 = dlsym(RTLD_NEXT, "__fxstat64"); + real_fstatat64 = dlsym(RTLD_NEXT, "__fxstatat64"); + real_lstat64 = dlsym(RTLD_NEXT, "__lxstat64"); + real_time = dlsym(RTLD_NEXT, "time"); + real_ftime = dlsym(RTLD_NEXT, "ftime"); + real_gettimeofday = dlsym(RTLD_NEXT, "gettimeofday"); #ifdef FAKE_SLEEP - real_nanosleep = dlsym(RTLD_NEXT, "nanosleep"); - real_usleep = dlsym(RTLD_NEXT, "usleep"); - real_sleep = dlsym(RTLD_NEXT, "sleep"); - real_alarm = dlsym(RTLD_NEXT, "alarm"); - real_poll = dlsym(RTLD_NEXT, "poll"); - real_ppoll = dlsym(RTLD_NEXT, "ppoll"); + real_nanosleep = dlsym(RTLD_NEXT, "nanosleep"); + real_usleep = dlsym(RTLD_NEXT, "usleep"); + real_sleep = dlsym(RTLD_NEXT, "sleep"); + real_alarm = dlsym(RTLD_NEXT, "alarm"); + real_poll = dlsym(RTLD_NEXT, "poll"); + real_ppoll = dlsym(RTLD_NEXT, "ppoll"); #endif #ifdef __APPLE__ - real_clock_get_time = dlsym(RTLD_NEXT, "clock_get_time"); - real_clock_gettime = apple_clock_gettime; + real_clock_get_time = dlsym(RTLD_NEXT, "clock_get_time"); + real_clock_gettime = apple_clock_gettime; #else - real_clock_gettime = dlsym(RTLD_NEXT, "clock_gettime"); + real_clock_gettime = dlsym(RTLD_NEXT, "clock_gettime"); #ifdef FAKE_TIMERS - real_timer_settime = dlsym(RTLD_NEXT, "timer_settime"); - real_timer_gettime = dlsym(RTLD_NEXT, "timer_gettime"); + real_timer_settime_22 = dlvsym(RTLD_NEXT, "timer_settime","GLIBC_2.2"); + real_timer_settime_233 = dlvsym(RTLD_NEXT, "timer_settime","GLIBC_2.3.3"); + real_timer_gettime_22 = dlvsym(RTLD_NEXT, "timer_gettime","GLIBC_2.2"); + real_timer_gettime_233 = dlvsym(RTLD_NEXT, "timer_gettime","GLIBC_2.3.3"); #endif #endif diff --git a/src/libfaketime.map b/src/libfaketime.map new file mode 100644 index 0000000..6e008cf --- /dev/null +++ b/src/libfaketime.map @@ -0,0 +1,10 @@ +GLIBC_2.2 { + global: + + timer_gettime; timer_settime; + local: timer_settime_*; timer_gettime_*; +}; +GLIBC_2.3.3 { + # Changed timer_t. + timer_gettime; timer_settime; +} GLIBC_2.2; |