Here is a signiture for a function that I would like to write a tapset for: asmlinkage long sys_stime(time_t __user *tptr) I would like to extract and export the value of tptr. This does not work: function get_uint(ptr)%{ unsigned long g = (unsigned long)THIS->ptr; unsigned long val; get_user(val, (time_t *) g); THIS->__retvalue = (long long) val; %} Produces error: incompatible types in assignment. Much like user_string, it would be great to have a user_int. This may also depend on the fix to bug #1295. Thanks.
Here is another example: asmlinkage long sys_settimeofday(struct timeval __user *tv ..., ) where timeval is defined as: struct timeval { time_t tv_sec; /* seconds */ suseconds_t tv_usec; /* microseconds */ }; probe kernel.syscall.settimeofday = kernel.function("sys_settimeofday"){ tv_sec = $tv->tv_sec tv_usec = $tv->tv_usec } Access to the 2 exported fields from struct timeval produce bogus results.
For the first example, please specify what program produces that error. Note that you're not declaring the get_uint type explicitly, so perhaps the translator was led to believe that get_uint returns a string. A generic user_int() function wouldn't exactly help here, since you are not dereferencing plain user int*, but a user struct foo*. One may need hand-made wrapper functions like your get_uint for such user-side structures. For the settimeofday example, please describe a test that invokes settimeofday().
Here is some more analysis: Consider this C code: __________________________________________ #include <time.h> int main (void) { time_t t = 44; stime(&t); } __________________________________________ ...& this probe script: __________________________________________ %{ #include <asm/uaccess.h> %} function get_uint:long(ptr:long) %{ unsigned long g = (unsigned long) THIS->ptr; unsigned long val = 0; get_user(val, (time_t *) g); THIS->__retvalue = val; %} probe kernel.function("sys_stime") { print("Addr of $tptr: ".string($tptr)."\n"); print("Converted: ".string(get_uint($tptr))."\n"); } __________________________________________ ...and this (condensed) jprobes module: __________________________________________ /* extract the val from the pointer */ int get_uint(time_t __user *ptr) { unsigned long g = (unsigned long) ptr; unsigned long val = 0; get_user(val, (time_t *) g); return val; } /* this is my jprobe handler */ asmlinkage long jdo_stime(time_t __user *tptr) { printk("Addr of $tptr: %d\n",tptr); printk("Converted: %d\n",get_uint(tptr)); jprobe_return(); return 0; } __________________________________________ Here is the output of the script when I run the C program: Addr of $tptr: 25 Converted: 0 And here is the output of the kprobes module: Addr of $tptr: -1075403996 Converted: 44 _________________________________________________ sys_stime and sys_settimeofday are essentially the same function with different args. The module places a single jprobe (basically a kprobe that gives access to args) on "sys_stime". The module behaves as expected. The probe script is (what I think should be) the functional equiv- alent of the kprobes module. However the args are not matching up with what I see from the jprobes handler. Thus, I think this may be a bug in the translator. Please let me know your thoughts on this. Thanks.
This now seems to be another instance of bug# 1295. FWIW, using the .statement() syntax to refer to a place a few lines down the function makes the $tptr value resolve properly. (I used the "tv.tv_nsec = 0" line.) You may need to make similar approximations in your syscall tapset until we get the general debuginfo situation corrected. *** This bug has been marked as a duplicate of 1295 ***