diff options
Diffstat (limited to 'tapset')
-rw-r--r-- | tapset/i686/registers.stp | 75 | ||||
-rw-r--r-- | tapset/x86_64/registers.stp | 86 |
2 files changed, 161 insertions, 0 deletions
diff --git a/tapset/i686/registers.stp b/tapset/i686/registers.stp new file mode 100644 index 00000000..2afbbb9b --- /dev/null +++ b/tapset/i686/registers.stp @@ -0,0 +1,75 @@ +/* Return the named register value as a signed value. */ +function register:long (name:string) %{ /* pure */ + if (CONTEXT->regs) + THIS->__retvalue = (int64_t) + _stp_get_reg32_by_name(THIS->name, CONTEXT->regs); + else + THIS->__retvalue = 0; +%} + +/* + * Return the named register value as an unsigned value. Specifically, + * don't sign-extend the register value when promoting it to 64 bits. + */ +function u_register:long (name:string) { + return register(name) & 0xffffffff; +} + +/* Return the value of function arg #argnum (1=first arg) as a signed value. */ +function arg:long (argnum:long) %{ + long val; + int n; + int result; + + THIS->__retvalue = 0; + if (!CONTEXT->regs) { + snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), + "cannot access function args in this context"); + CONTEXT->last_error = CONTEXT->error_buffer; + return; + } + if (THIS->argnum < 1) + goto bad_argnum; + n = (int) THIS->argnum; + // TODO: Get nr_regargs from .linkage clause. + result = _stp_get_arg32_by_number(n, 0, CONTEXT->regs, &val); + switch (result) { + case 0: + THIS->__retvalue = (int64_t) val; + break; + case 1: + THIS->__retvalue = kread((long *) val); + break; + case 2: + /* + * Is copy_from_user satisfactory, since uprobe + * handlers can block? + */ + snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), + "arg() not yet implemented for user functions"); + CONTEXT->last_error = CONTEXT->error_buffer; + break; + default: + goto bad_argnum; + } + return; + +bad_argnum: + snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), + "cannot access arg(%lld)", THIS->argnum); + CONTEXT->last_error = CONTEXT->error_buffer; + return; + + if (0) { +deref_fault: /* branched to from deref() */ + snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), + "kernel fault at %#lx accessing arg(%lld)", val, + THIS->argnum); + CONTEXT->last_error = CONTEXT->error_buffer; + } +%} + +/* Return the value of function arg #argnum as an unsigned value. */ +function u_arg:long (argnum:long) { + return arg(argnum) & 0xffffffff; +} diff --git a/tapset/x86_64/registers.stp b/tapset/x86_64/registers.stp new file mode 100644 index 00000000..375be396 --- /dev/null +++ b/tapset/x86_64/registers.stp @@ -0,0 +1,86 @@ +/* Return the named register value as a signed value. */ +function register:long (name:string) %{ /* pure */ + if (CONTEXT->regs) + THIS->__retvalue = (int64_t) + _stp_get_reg64_by_name(THIS->name, CONTEXT->regs); + else + THIS->__retvalue = 0; +%} + +/* Return the named register value as an unsigned value. */ +function u_register:long (name:string) { + return register(name) +} + +/* Return the value of function arg #argnum (1=first arg) as a signed value. */ +function arg:long (argnum:long) %{ + long val; + int result; + int n; + size_t argsz = sizeof(long); + + THIS->__retvalue = 0; + if (!CONTEXT->regs) { + snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), + "cannot access function args in this context"); + CONTEXT->last_error = CONTEXT->error_buffer; + return; + } + if (THIS->argnum < 1) + goto bad_argnum; + n = (int) THIS->argnum; + if (_stp_probing_32bit_app(CONTEXT->regs)) { + // TODO: Get nr_regargs from .linkage clause. + argsz = sizeof(int); + result = _stp_get_arg32_by_number(n, 0, CONTEXT->regs, &val); + } else { + // TODO: Get nr_regargs from .linkage clause. + result = _stp_get_arg64_by_number(n, 6, CONTEXT->regs, &val); + } + switch (result) { + case 0: + THIS->__retvalue = (int64_t) val; + break; + case 1: + THIS->__retvalue = kread((long *) val); + break; + case 2: + /* + * Is copy_from_user satisfactory, since uprobe + * handlers can block? + */ + snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), + "arg() not yet implemented for user functions"); + CONTEXT->last_error = CONTEXT->error_buffer; + break; + default: + goto bad_argnum; + } + return; + +bad_argnum: + snprintf(CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), + "cannot access arg(%lld)", THIS->argnum); + CONTEXT->last_error = CONTEXT->error_buffer; + return; + + if (0) { +deref_fault: /* branched to from deref() */ + snprintf (CONTEXT->error_buffer, sizeof(CONTEXT->error_buffer), + "kernel fault at %#lx accessing arg(%lld)", val, + THIS->argnum); + CONTEXT->last_error = CONTEXT->error_buffer; + } +%} + +function probing_32bit_app() %{ + THIS->__retvalue = _stp_probing_32bit_app(CONTEXT->regs); +%} + +/* Return the value of function arg #argnum as an unsigned value. */ +function u_arg:long (argnum:long) { + if (probing_32bit_app()) + return arg(argnum) & 0xffffffff + else + return arg(argnum) +} |