summaryrefslogtreecommitdiffstats
path: root/tapset-procfs.cxx
diff options
context:
space:
mode:
authorDavid Smith <dsmith@redhat.com>2009-07-02 15:39:57 -0500
committerDavid Smith <dsmith@redhat.com>2009-07-02 15:39:57 -0500
commit8e0049e8b601e9377875d2229104d78668f3f7ce (patch)
tree1b17e5701e858c0654b7733e1eccabb3620045a3 /tapset-procfs.cxx
parent1c6b77e564d4d849f1994d56d662ceb018a112d4 (diff)
downloadsystemtap-steved-8e0049e8b601e9377875d2229104d78668f3f7ce.tar.gz
systemtap-steved-8e0049e8b601e9377875d2229104d78668f3f7ce.tar.xz
systemtap-steved-8e0049e8b601e9377875d2229104d78668f3f7ce.zip
Fixed PR 10258.
* tapset-procfs.cxx (procfs_derived_probe::join_group): Outputs structure definition. (procfs_derived_probe_group::emit_module_decls): The generated '_stp_procfs_read' and '_stp_procfs_write' functions no longer put a string_t on the stack. (procfs_var_expanding_visitor::visit_target_symbol): The generated '_procfs_value_set' and '_procfs_value_get' functions copy directly into or out of the os buffer.
Diffstat (limited to 'tapset-procfs.cxx')
-rw-r--r--tapset-procfs.cxx71
1 files changed, 45 insertions, 26 deletions
diff --git a/tapset-procfs.cxx b/tapset-procfs.cxx
index 63a59afb..0c33857b 100644
--- a/tapset-procfs.cxx
+++ b/tapset-procfs.cxx
@@ -103,7 +103,19 @@ void
procfs_derived_probe::join_group (systemtap_session& s)
{
if (! s.procfs_derived_probes)
- s.procfs_derived_probes = new procfs_derived_probe_group ();
+ {
+ s.procfs_derived_probes = new procfs_derived_probe_group ();
+
+ // Make sure 'struct _stp_procfs_data' is defined early.
+ embeddedcode *ec = new embeddedcode;
+ ec->tok = NULL;
+ ec->code = string("struct _stp_procfs_data {\n")
+ + string(" const char *buffer;\n")
+ + string(" off_t off;\n")
+ + string(" unsigned long count;\n")
+ + string("};\n");
+ s.embeds.push_back(ec);
+ }
s.procfs_derived_probes->enroll (this);
}
@@ -208,13 +220,15 @@ procfs_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "static int _stp_procfs_read(char *page, char **start, off_t off, int count, int *eof, void *data) {";
s.op->newline(1) << "struct stap_procfs_probe *spp = (struct stap_procfs_probe *)data;";
- s.op->newline() << "int bytes = 0;";
- s.op->newline() << "string_t strdata = {'\\0'};";
+ s.op->newline() << "struct _stp_procfs_data pdata;";
common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "spp->read_pp");
+ s.op->newline() << "pdata.buffer = page;";
+ s.op->newline() << "pdata.off = off;";
+ s.op->newline() << "pdata.count = count;";
s.op->newline() << "if (c->data == NULL)";
- s.op->newline(1) << "c->data = &strdata;";
+ s.op->newline(1) << "c->data = &pdata;";
s.op->newline(-1) << "else {";
s.op->newline(1) << "if (unlikely (atomic_inc_return (& skipped_count) > MAXSKIPPED)) {";
@@ -225,24 +239,16 @@ procfs_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "goto probe_epilogue;";
s.op->newline(-1) << "}";
- // call probe function (which copies data into strdata)
+ // call probe function
s.op->newline() << "(*spp->read_ph) (c);";
- // copy string data into 'page'
+ // Note that _procfs_value_set copied string data into 'page'
s.op->newline() << "c->data = NULL;";
- s.op->newline() << "bytes = strnlen(strdata, MAXSTRINGLEN - 1);";
- s.op->newline() << "if (off >= bytes)";
- s.op->newline(1) << "*eof = 1;";
- s.op->newline(-1) << "else {";
- s.op->newline(1) << "bytes -= off;";
- s.op->newline() << "if (bytes > count)";
- s.op->newline(1) << "bytes = count;";
- s.op->newline(-1) << "memcpy(page, strdata + off, bytes);";
- s.op->newline() << "*start = page;";
- s.op->newline(-1) << "}";
-
common_probe_entryfn_epilogue (s.op);
- s.op->newline() << "return bytes;";
+ s.op->newline() << "if (pdata.count == 0)";
+ s.op->newline(1) << "*eof = 1;";
+ s.op->indent(-1);
+ s.op->newline() << "return pdata.count;";
s.op->newline(-1) << "}";
}
@@ -251,16 +257,18 @@ procfs_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "static int _stp_procfs_write(struct file *file, const char *buffer, unsigned long count, void *data) {";
s.op->newline(1) << "struct stap_procfs_probe *spp = (struct stap_procfs_probe *)data;";
- s.op->newline() << "string_t strdata = {'\\0'};";
+ s.op->newline() << "struct _stp_procfs_data pdata;";
common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "spp->write_pp");
s.op->newline() << "if (count > (MAXSTRINGLEN - 1))";
s.op->newline(1) << "count = MAXSTRINGLEN - 1;";
- s.op->newline(-1) << "_stp_copy_from_user(strdata, buffer, count);";
+ s.op->indent(-1);
+ s.op->newline() << "pdata.buffer = buffer;";
+ s.op->newline() << "pdata.count = count;";
s.op->newline() << "if (c->data == NULL)";
- s.op->newline(1) << "c->data = &strdata;";
+ s.op->newline(1) << "c->data = &pdata;";
s.op->newline(-1) << "else {";
s.op->newline(1) << "if (unlikely (atomic_inc_return (& skipped_count) > MAXSKIPPED)) {";
@@ -271,7 +279,7 @@ procfs_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "goto probe_epilogue;";
s.op->newline(-1) << "}";
- // call probe function (which copies data out of strdata)
+ // call probe function
s.op->newline() << "(*spp->write_ph) (c);";
s.op->newline() << "c->data = NULL;";
@@ -389,11 +397,22 @@ procfs_var_expanding_visitor::visit_target_symbol (target_symbol* e)
string locvalue = "CONTEXT->data";
if (! lvalue)
- ec->code = string("strlcpy (THIS->__retvalue, ") + locvalue
- + string(", MAXSTRINGLEN); /* pure */");
+ ec->code = string("_stp_copy_from_user(THIS->__retvalue, ((struct _stp_procfs_data *)(")
+ + locvalue + string("))->buffer, ((struct _stp_procfs_data *)(") + locvalue
+ + string("))->count); /* pure */");
else
- ec->code = string("strlcpy (") + locvalue
- + string(", THIS->value, MAXSTRINGLEN);");
+ ec->code = string("int bytes = 0;\n")
+ + string(" struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue + string(");\n")
+ + string(" bytes = strnlen(THIS->value, MAXSTRINGLEN - 1);\n")
+ + string(" if (data->off >= bytes)\n")
+ + string(" bytes = 0;\n")
+ + string(" else {\n")
+ + string(" bytes -= data->off;\n")
+ + string(" if (bytes > data->count)\n")
+ + string(" bytes = data->count;\n")
+ + string(" memcpy((void *)data->buffer, THIS->value + data->off, bytes);\n")
+ + string(" }\n")
+ + string(" data->count = bytes;\n");
fdecl->name = fname;
fdecl->body = ec;