diff options
author | Josh Stone <jistone@redhat.com> | 2009-11-10 18:37:02 -0800 |
---|---|---|
committer | Josh Stone <jistone@redhat.com> | 2009-11-10 18:48:34 -0800 |
commit | af234c407dbab3e62994863272a63b612b0c8c63 (patch) | |
tree | 7b2fb7929bbc776a3eae96ef311f890e319a0bf2 /tapset | |
parent | b513cd75dac185ac258dc8260a01891c30be6251 (diff) | |
download | systemtap-steved-af234c407dbab3e62994863272a63b612b0c8c63.tar.gz systemtap-steved-af234c407dbab3e62994863272a63b612b0c8c63.tar.xz systemtap-steved-af234c407dbab3e62994863272a63b612b0c8c63.zip |
PR5916: Exploit kretprobe data storage area
Since 2.6.25, kretprobes can carry a data packet to be filled in an
entry_handler. This patch lets us store our implicitly-saved $target
variables in .return probes in that data area.
* tapset/kretprobe.stp: New get/set functions for kretprobe data.
* translate.cxx (c_unparser::emit_common_header): Add context->pi_longs.
* tapsets.cxx
(dwarf_var_expanding_visitor::visit_target_symbol_saved_return): Switch
between the old and new methods of saving $vars in .return probes.
(dwarf_var_expanding_visitor::gen_mapped_saved_return): The old way.
(dwarf_var_expanding_visitor::gen_kretprobe_saved_return): The new way.
(dwarf_derived_probe::join_group): Don't register paired entry-handlers.
(dwarf_derived_probe::dwarf_derived_probe): Remember saved-var details.
(dwarf_derived_probe_group::emit_module_decls): Output saved-var details.
Also split the kretprobe handler whether we're on entry or return.
(dwarf_derived_probe_group::emit_module_init): Prepare the entry handler.
* testsuite/systemtap.base/kretprobe-vars.stp: Test implicit $var saving.
Diffstat (limited to 'tapset')
-rw-r--r-- | tapset/kretprobe.stp | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/tapset/kretprobe.stp b/tapset/kretprobe.stp new file mode 100644 index 00000000..3742708f --- /dev/null +++ b/tapset/kretprobe.stp @@ -0,0 +1,56 @@ +// kretprobe data tapset +// Copyright (C) 2009 Red Hat Inc. +// +// This file is part of systemtap, and is free software. You can +// redistribute it and/or modify it under the terms of the GNU General +// Public License (GPL); either version 2, or (at your option) any +// later version. + + +// This is an internally-used tapset for sharing data between kretprobe +// entry / return handlers. See the function +// dwarf_var_expanding_visitor::gen_kretprobe_saved_return +// for details. +// +// Note, invalid calls are silently ignored... + +%{ +static void * +_kretprobe_data(struct kretprobe_instance *pi, size_t offset, size_t length) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) + size_t end = offset + length; + if (end > offset && pi && end <= pi->rp->data_size) + return &pi->data[offset]; +#endif + return NULL; +} +%} + +function _get_kretprobe_long:long(i:long) %{ /* pure */ + size_t offset = THIS->i * sizeof(int64_t); + const int64_t *data = _kretprobe_data(CONTEXT->pi, offset, sizeof(int64_t)); + THIS->__retvalue = data ? *data : 0; +%} + +function _set_kretprobe_long(i:long, value:long) %{ /* impure */ + size_t offset = THIS->i * sizeof(int64_t); + int64_t *data = _kretprobe_data(CONTEXT->pi, offset, sizeof(int64_t)); + if (data) + *data = THIS->value; +%} + +function _get_kretprobe_string:string(i:long) %{ /* pure */ + size_t offset = CONTEXT->pi_longs * sizeof(int64_t) + + THIS->i * MAXSTRINGLEN; + const char *data = _kretprobe_data(CONTEXT->pi, offset, MAXSTRINGLEN); + strlcpy(THIS->__retvalue, data ?: "", MAXSTRINGLEN); +%} + +function _set_kretprobe_string(i:long, value:string) %{ /* impure */ + size_t offset = CONTEXT->pi_longs * sizeof(int64_t) + + THIS->i * MAXSTRINGLEN; + char *data = _kretprobe_data(CONTEXT->pi, offset, MAXSTRINGLEN); + if (data) + strlcpy(data, THIS->value, MAXSTRINGLEN); +%} |