2006-12-20 15:16:16 +01:00
|
|
|
/*
|
|
|
|
Copyright (C) 2006 Mandriva Conectiva S.A.
|
|
|
|
Copyright (C) 2006 Arnaldo Carvalho de Melo <acme@mandriva.com>
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
|
|
|
under the terms of version 2 of the GNU General Public License as
|
|
|
|
published by the Free Software Foundation.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <getopt.h>
|
2006-12-27 17:59:17 +01:00
|
|
|
#include <limits.h>
|
2006-12-20 15:16:16 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2006-12-27 17:59:17 +01:00
|
|
|
#include <sys/types.h>
|
2006-12-20 15:16:16 +01:00
|
|
|
|
2007-01-11 19:07:05 +01:00
|
|
|
#include "dwarves.h"
|
2006-12-20 15:16:16 +01:00
|
|
|
|
2006-12-23 22:29:27 +01:00
|
|
|
static struct cus *cus;
|
2006-12-27 17:59:17 +01:00
|
|
|
static struct cus *kprobes_cus;
|
|
|
|
|
|
|
|
static LIST_HEAD(cus__definitions);
|
|
|
|
static LIST_HEAD(cus__fwd_decls);
|
2006-12-23 22:29:27 +01:00
|
|
|
|
2006-12-20 15:16:16 +01:00
|
|
|
static void method__add(struct cu *cu, struct function *function)
|
|
|
|
{
|
|
|
|
list_add(&function->tool_node, &cu->tool_list);
|
|
|
|
}
|
|
|
|
|
2007-01-04 00:29:24 +01:00
|
|
|
static struct tag *function__filter(struct tag *tag, struct cu *cu, void *cookie)
|
2006-12-20 15:16:16 +01:00
|
|
|
{
|
2007-01-04 00:29:24 +01:00
|
|
|
struct function *function;
|
|
|
|
|
|
|
|
if (tag->tag != DW_TAG_subprogram)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
function = tag__function(tag);
|
2006-12-20 16:10:31 +01:00
|
|
|
if (function__inlined(function) ||
|
2007-01-09 17:26:07 +01:00
|
|
|
function->abstract_origin != 0 ||
|
2007-01-04 00:29:24 +01:00
|
|
|
!ftype__has_parm_of_type(&function->proto, cookie, cu))
|
2006-12-20 15:16:16 +01:00
|
|
|
return NULL;
|
|
|
|
|
2007-01-04 00:29:24 +01:00
|
|
|
return tag;
|
2006-12-20 15:16:16 +01:00
|
|
|
}
|
|
|
|
|
2007-01-04 00:29:24 +01:00
|
|
|
static int find_methods_iterator(struct tag *tag, struct cu *cu, void *cookie)
|
2006-12-20 15:16:16 +01:00
|
|
|
{
|
2007-01-04 00:29:24 +01:00
|
|
|
if (tag->tag == DW_TAG_subprogram) {
|
|
|
|
struct function *function = tag__function(tag);
|
|
|
|
method__add(cu, function);
|
|
|
|
}
|
2006-12-20 15:16:16 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cu_find_methods_iterator(struct cu *cu, void *cookie)
|
|
|
|
{
|
2007-01-07 16:11:20 +01:00
|
|
|
struct tag *target = cu__find_struct_by_name(cu, cookie);
|
2006-12-20 15:16:16 +01:00
|
|
|
|
|
|
|
if (target == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2007-01-04 00:29:24 +01:00
|
|
|
return cu__for_each_tag(cu, find_methods_iterator, target, function__filter);
|
2006-12-20 15:16:16 +01:00
|
|
|
}
|
|
|
|
|
2007-01-07 20:13:39 +01:00
|
|
|
static int function__emit_kprobes(struct function *self, const struct cu *cu,
|
2006-12-29 18:28:58 +01:00
|
|
|
const struct tag *target)
|
2006-12-20 15:16:16 +01:00
|
|
|
{
|
2007-01-09 16:34:15 +01:00
|
|
|
char bf[2048];
|
|
|
|
char jprobe_name[256];
|
2006-12-20 23:09:49 +01:00
|
|
|
struct parameter *pos;
|
2007-01-07 20:13:39 +01:00
|
|
|
const char *name = function__name(self, cu);
|
2006-12-20 15:16:16 +01:00
|
|
|
|
2007-01-09 16:34:15 +01:00
|
|
|
snprintf(jprobe_name, sizeof(jprobe_name), "jprobe_entry__%s", name);
|
|
|
|
ftype__snprintf(&self->proto, cu, bf, sizeof(bf), jprobe_name, 0, 0, 0);
|
|
|
|
printf("static %s\n"
|
|
|
|
"{\n", bf);
|
2006-12-20 15:16:16 +01:00
|
|
|
|
2006-12-30 19:34:20 +01:00
|
|
|
list_for_each_entry(pos, &self->proto.parms, tag.node) {
|
2007-01-09 16:34:15 +01:00
|
|
|
struct tag *type = cu__find_tag_by_id(cu, pos->tag.type);
|
2006-12-20 15:16:16 +01:00
|
|
|
|
2006-12-29 18:28:58 +01:00
|
|
|
if (type->tag != DW_TAG_pointer_type)
|
2006-12-20 15:16:16 +01:00
|
|
|
continue;
|
|
|
|
|
2007-01-04 00:57:35 +01:00
|
|
|
type = cu__find_tag_by_id(cu, type->type);
|
2006-12-29 18:28:58 +01:00
|
|
|
if (type == NULL || type->id != target->id)
|
2006-12-20 15:16:16 +01:00
|
|
|
continue;
|
|
|
|
|
2007-01-09 16:34:15 +01:00
|
|
|
printf("\tprintk(\"-> %s: %s=%%p\\n\", %s);\n",
|
|
|
|
name, pos->name, pos->name);
|
2006-12-20 15:16:16 +01:00
|
|
|
}
|
2007-01-09 16:34:15 +01:00
|
|
|
|
|
|
|
printf("\n\tjprobe_return();\n"
|
|
|
|
"\t/* NOTREACHED */%s\n}\n\n",
|
|
|
|
self->proto.tag.type != 0 ? "\n\treturn 0;" : "");
|
|
|
|
|
2006-12-20 15:16:16 +01:00
|
|
|
printf("static struct jprobe jprobe__%s = {\n"
|
|
|
|
"\t.kp = { .symbol_name = \"%s\", },\n"
|
2006-12-23 21:12:41 +01:00
|
|
|
"\t.entry = (kprobe_opcode_t *)jprobe_entry__%s,\n"
|
2007-01-07 20:13:39 +01:00
|
|
|
"};\n\n", name, name, name);
|
2006-12-20 15:16:16 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cu_emit_kprobes_iterator(struct cu *cu, void *cookie)
|
|
|
|
{
|
2007-01-07 16:11:20 +01:00
|
|
|
struct tag *target = cu__find_struct_by_name(cu, cookie);
|
2006-12-20 15:16:16 +01:00
|
|
|
struct function *pos;
|
|
|
|
|
2006-12-20 17:27:28 +01:00
|
|
|
list_for_each_entry(pos, &cu->tool_list, tool_node) {
|
2007-01-04 00:57:35 +01:00
|
|
|
cus__emit_ftype_definitions(cus, cu, &pos->proto);
|
2007-01-07 16:11:20 +01:00
|
|
|
function__emit_kprobes(pos, cu, target);
|
2006-12-20 17:27:28 +01:00
|
|
|
}
|
2006-12-20 16:18:29 +01:00
|
|
|
|
|
|
|
return 0;
|
2006-12-20 15:16:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static int cu_emit_kprobes_table_iterator(struct cu *cu, void *cookie)
|
|
|
|
{
|
|
|
|
struct function *pos;
|
|
|
|
|
|
|
|
list_for_each_entry(pos, &cu->tool_list, tool_node)
|
2007-01-07 20:13:39 +01:00
|
|
|
printf("\t&jprobe__%s,\n", function__name(pos, cu));
|
2006-12-20 16:18:29 +01:00
|
|
|
|
|
|
|
return 0;
|
2006-12-20 15:16:16 +01:00
|
|
|
}
|
|
|
|
|
2007-01-07 20:13:39 +01:00
|
|
|
static int function__emit_kretprobes(struct function *self,
|
|
|
|
const struct cu *cu)
|
2006-12-24 02:42:39 +01:00
|
|
|
{
|
2007-01-07 20:13:39 +01:00
|
|
|
const char *name = function__name(self, cu);
|
|
|
|
|
2006-12-24 02:42:39 +01:00
|
|
|
printf("static int kretprobe_handler__%s(struct kretprobe_instance *ri, "
|
|
|
|
"struct pt_regs *regs)\n"
|
|
|
|
"{\n"
|
|
|
|
"\tprintk(\"<- %s\\n\");\n"
|
|
|
|
"\treturn 0;\n"
|
2007-01-07 20:13:39 +01:00
|
|
|
"}\n\n", name, name);
|
2006-12-24 02:42:39 +01:00
|
|
|
printf("static struct kretprobe kretprobe__%s = {\n"
|
|
|
|
"\t.kp = { .symbol_name = \"%s\", },\n"
|
|
|
|
"\t.handler = (kretprobe_handler_t)kretprobe_handler__%s,\n"
|
|
|
|
"\t.maxactive = -1,\n\n"
|
2007-01-07 20:13:39 +01:00
|
|
|
"};\n\n", name, name, name);
|
2006-12-24 02:42:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static int cu_emit_kretprobes_iterator(struct cu *cu, void *cookie)
|
|
|
|
{
|
|
|
|
struct function *pos;
|
|
|
|
|
|
|
|
list_for_each_entry(pos, &cu->tool_list, tool_node)
|
2007-01-07 20:13:39 +01:00
|
|
|
function__emit_kretprobes(pos, cu);
|
2006-12-24 02:42:39 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cu_emit_kretprobes_table_iterator(struct cu *cu, void *cookie)
|
|
|
|
{
|
|
|
|
struct function *pos;
|
|
|
|
|
|
|
|
list_for_each_entry(pos, &cu->tool_list, tool_node)
|
2007-01-07 20:13:39 +01:00
|
|
|
printf("\t&kretprobe__%s,\n", function__name(pos, cu));
|
2006-12-24 02:42:39 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-12-23 23:37:23 +01:00
|
|
|
static void emit_function_defs(const char *fn)
|
2006-12-20 15:16:16 +01:00
|
|
|
{
|
2007-01-04 00:57:35 +01:00
|
|
|
struct cu *cu;
|
|
|
|
struct function *f = cus__find_function_by_name(kprobes_cus, &cu, fn);
|
2006-12-23 22:29:27 +01:00
|
|
|
|
|
|
|
if (f != NULL) {
|
2007-01-04 00:57:35 +01:00
|
|
|
cus__emit_ftype_definitions(kprobes_cus, cu, &f->proto);
|
|
|
|
function__print(f, cu, 0, 0, 0);
|
2006-12-23 22:29:27 +01:00
|
|
|
putchar('\n');
|
|
|
|
}
|
2006-12-23 23:37:23 +01:00
|
|
|
}
|
|
|
|
|
2006-12-24 16:36:13 +01:00
|
|
|
static void emit_struct_defs(const char *name)
|
2006-12-23 23:37:23 +01:00
|
|
|
{
|
2007-01-04 00:57:35 +01:00
|
|
|
struct cu *cu;
|
2007-01-07 16:11:20 +01:00
|
|
|
struct tag *c = cus__find_struct_by_name(kprobes_cus, &cu, name);
|
2006-12-23 22:29:27 +01:00
|
|
|
if (c != NULL)
|
2007-01-04 04:41:11 +01:00
|
|
|
cus__emit_struct_definitions(kprobes_cus, cu, c, NULL, NULL);
|
2006-12-24 16:36:13 +01:00
|
|
|
}
|
2006-12-23 23:37:23 +01:00
|
|
|
|
2006-12-24 16:36:13 +01:00
|
|
|
static void emit_class_fwd_decl(const char *name)
|
|
|
|
{
|
2007-01-04 00:57:35 +01:00
|
|
|
struct cu *cu;
|
2007-01-07 16:11:20 +01:00
|
|
|
struct tag *c = cus__find_struct_by_name(kprobes_cus, &cu, name);
|
2006-12-24 02:42:39 +01:00
|
|
|
if (c != NULL)
|
2007-01-07 16:11:20 +01:00
|
|
|
cus__emit_fwd_decl(kprobes_cus, tag__type(c));
|
2006-12-24 16:36:13 +01:00
|
|
|
}
|
2006-12-24 02:42:39 +01:00
|
|
|
|
2006-12-24 16:36:13 +01:00
|
|
|
static void emit_module_preamble(void)
|
|
|
|
{
|
|
|
|
emit_struct_defs("jprobe");
|
|
|
|
emit_struct_defs("kretprobe");
|
|
|
|
|
|
|
|
emit_class_fwd_decl("pt_regs");
|
|
|
|
emit_class_fwd_decl("kretprobe_instance");
|
2006-12-24 02:42:39 +01:00
|
|
|
|
2006-12-23 23:37:23 +01:00
|
|
|
emit_function_defs("printk");
|
|
|
|
emit_function_defs("register_jprobe");
|
|
|
|
emit_function_defs("unregister_jprobe");
|
2006-12-24 02:42:39 +01:00
|
|
|
emit_function_defs("register_kretprobe");
|
|
|
|
emit_function_defs("unregister_kretprobe");
|
2006-12-23 23:37:23 +01:00
|
|
|
emit_function_defs("jprobe_return");
|
2006-12-20 15:16:16 +01:00
|
|
|
}
|
|
|
|
|
2006-12-23 22:58:00 +01:00
|
|
|
static void emit_module_initcall(const char *fn)
|
|
|
|
{
|
|
|
|
printf("int init_module(void) __attribute__((alias(\"%s\")));\n\n", fn);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void emit_module_exitcall(const char *fn)
|
|
|
|
{
|
2006-12-23 23:09:02 +01:00
|
|
|
printf("int cleanup_module(void) __attribute__((alias(\"%s\")));\n\n", fn);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void emit_module_license(const char *license)
|
|
|
|
{
|
|
|
|
printf("static const char __mod_license[] "
|
|
|
|
"__attribute__((__used__)) \n"
|
|
|
|
"\t__attribute__((section(\".modinfo\"),unused)) = "
|
|
|
|
"\"license=%s\";\n\n", license);
|
2006-12-23 22:58:00 +01:00
|
|
|
}
|
|
|
|
|
2006-12-20 15:16:16 +01:00
|
|
|
static void emit_module_init(void)
|
|
|
|
{
|
2006-12-23 21:24:25 +01:00
|
|
|
printf("static int __attribute__ "
|
|
|
|
"((__section__ (\".init.text\"))) jprobe_init(void)\n"
|
2006-12-20 15:16:16 +01:00
|
|
|
"{\n"
|
2006-12-24 02:42:39 +01:00
|
|
|
" unsigned int i = 0, nj = 0, nr = 0;\n"
|
2006-12-23 21:14:37 +01:00
|
|
|
" while (jprobes[i] != (void *)0) {\n"
|
2006-12-20 15:16:16 +01:00
|
|
|
" int err = register_jprobe(jprobes[i]);\n"
|
|
|
|
" if (err != 0)\n"
|
|
|
|
" printk(\"register_jprobe(%%s) failed, "
|
|
|
|
"returned %%d\\n\",\n"
|
|
|
|
" jprobes[i]->kp.symbol_name, err);\n"
|
2006-12-23 23:22:40 +01:00
|
|
|
" else\n"
|
2006-12-24 02:42:39 +01:00
|
|
|
" ++nj;\n"
|
|
|
|
" err = register_kretprobe(kretprobes[i]);\n"
|
|
|
|
" if (err != 0)\n"
|
|
|
|
" printk(\"register_kretprobe(%%s) failed, "
|
|
|
|
"returned %%d\\n\",\n"
|
|
|
|
" kretprobes[i]->kp.symbol_name, err);\n"
|
|
|
|
" else\n"
|
|
|
|
" ++nr;\n"
|
2006-12-20 15:16:16 +01:00
|
|
|
" ++i;\n"
|
|
|
|
" }\n\n"
|
2006-12-24 02:42:39 +01:00
|
|
|
" printk(\"ctracer: registered %%u entry probes\\n\", nj);\n"
|
|
|
|
" printk(\"ctracer: registered %%u exit probes\\n\", nr);\n"
|
2006-12-23 23:22:40 +01:00
|
|
|
"\n"
|
2006-12-20 15:16:16 +01:00
|
|
|
" return 0;\n"
|
2006-12-23 22:58:00 +01:00
|
|
|
"}\n\n");
|
|
|
|
emit_module_initcall("jprobe_init");
|
2006-12-20 15:16:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void emit_module_exit(void)
|
|
|
|
{
|
2006-12-23 21:24:25 +01:00
|
|
|
printf("static void __attribute__ "
|
|
|
|
"((__section__ (\".exit.text\"))) jprobe_exit(void)\n"
|
2006-12-20 15:16:16 +01:00
|
|
|
"{\n"
|
|
|
|
" int i = 0;\n"
|
2006-12-23 21:14:37 +01:00
|
|
|
" while (jprobes[i] != (void *)0) {\n"
|
2006-12-20 15:16:16 +01:00
|
|
|
" unregister_jprobe(jprobes[i]);\n"
|
2006-12-24 02:42:39 +01:00
|
|
|
" unregister_kretprobe(kretprobes[i]);\n"
|
2006-12-20 15:16:16 +01:00
|
|
|
" ++i;\n"
|
|
|
|
" }\n\n"
|
2006-12-23 22:58:00 +01:00
|
|
|
"}\n\n");
|
|
|
|
emit_module_exitcall("jprobe_exit");
|
2006-12-20 15:16:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct option long_options[] = {
|
2006-12-27 17:59:17 +01:00
|
|
|
{ "dir", required_argument, NULL, 'D' },
|
|
|
|
{ "glob", required_argument, NULL, 'g' },
|
|
|
|
{ "kprobes", required_argument, NULL, 'k' },
|
|
|
|
{ "recursive", no_argument, NULL, 'r' },
|
2006-12-20 15:16:16 +01:00
|
|
|
{ "help", no_argument, NULL, 'h' },
|
|
|
|
{ NULL, 0, NULL, 0, }
|
|
|
|
};
|
|
|
|
|
|
|
|
static void usage(void)
|
|
|
|
{
|
|
|
|
fprintf(stdout,
|
2006-12-27 17:59:17 +01:00
|
|
|
"usage: ctracer [options] <filename> <class_name>\n"
|
2006-12-20 15:16:16 +01:00
|
|
|
" where: \n"
|
2006-12-27 17:59:17 +01:00
|
|
|
" -D, --dir load files in this directory\n"
|
|
|
|
" -g, --glob file mask to load\n"
|
|
|
|
" -k, --kprobes kprobes object file\n"
|
|
|
|
" -r, --recursive recursively load files\n"
|
|
|
|
" -h, --help show this help message\n");
|
2006-12-20 15:16:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
2006-12-27 17:59:17 +01:00
|
|
|
int option, option_index, recursive = 0;
|
|
|
|
const char *filename = NULL, *dirname = NULL, *glob = NULL,
|
2007-01-05 19:58:58 +01:00
|
|
|
*kprobes_filename = NULL;
|
2006-12-20 15:16:16 +01:00
|
|
|
char *class_name = NULL;
|
|
|
|
|
2006-12-27 17:59:17 +01:00
|
|
|
while ((option = getopt_long(argc, argv, "D:g:k:rh",
|
2006-12-20 15:16:16 +01:00
|
|
|
long_options, &option_index)) >= 0)
|
|
|
|
switch (option) {
|
2006-12-27 17:59:17 +01:00
|
|
|
case 'D': dirname = optarg; break;
|
|
|
|
case 'g': glob = optarg; break;
|
|
|
|
case 'k': kprobes_filename = optarg; break;
|
|
|
|
case 'r': recursive = 1; break;
|
|
|
|
case 'h': usage(); return EXIT_SUCCESS;
|
|
|
|
default: usage(); return EXIT_FAILURE;
|
2006-12-20 15:16:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (optind < argc) {
|
|
|
|
switch (argc - optind) {
|
2006-12-27 17:59:17 +01:00
|
|
|
case 1: if (kprobes_filename == NULL) {
|
|
|
|
usage();
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
class_name = argv[optind++]; break;
|
|
|
|
case 2: filename = argv[optind++];
|
2006-12-20 15:16:16 +01:00
|
|
|
class_name = argv[optind++]; break;
|
|
|
|
default: usage(); return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
usage();
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2007-01-07 15:30:58 +01:00
|
|
|
cus = cus__new(&cus__definitions, &cus__fwd_decls);
|
2006-12-20 15:16:16 +01:00
|
|
|
if (cus == NULL) {
|
2006-12-27 17:59:17 +01:00
|
|
|
out_enomem:
|
2006-12-20 15:16:16 +01:00
|
|
|
fputs("ctracer: insufficient memory\n", stderr);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
2006-12-27 17:59:17 +01:00
|
|
|
|
|
|
|
if (kprobes_filename != NULL) {
|
2007-01-07 15:30:58 +01:00
|
|
|
kprobes_cus = cus__new(&cus__definitions, &cus__fwd_decls);
|
2006-12-27 17:59:17 +01:00
|
|
|
if (kprobes_cus == NULL)
|
|
|
|
goto out_enomem;
|
|
|
|
if (cus__load(kprobes_cus, kprobes_filename) != 0) {
|
|
|
|
filename = kprobes_filename;
|
|
|
|
goto out_dwarf_err;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
kprobes_cus = cus;
|
|
|
|
|
|
|
|
if (dirname != NULL && cus__load_dir(cus, dirname, glob,
|
|
|
|
recursive) != 0) {
|
|
|
|
fprintf(stderr, "ctracer: couldn't load DWARF info "
|
|
|
|
"from %s dir with glob %s\n",
|
|
|
|
dirname, glob);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
2006-12-20 15:16:16 +01:00
|
|
|
|
2006-12-27 17:59:17 +01:00
|
|
|
if (filename != NULL && cus__load(cus, filename) != 0) {
|
|
|
|
out_dwarf_err:
|
2006-12-20 15:16:16 +01:00
|
|
|
fprintf(stderr, "ctracer: couldn't load DWARF info from %s\n",
|
2006-12-27 17:59:17 +01:00
|
|
|
filename);
|
2006-12-20 15:16:16 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
emit_module_preamble();
|
|
|
|
cus__for_each_cu(cus, cu_find_methods_iterator, class_name, NULL);
|
|
|
|
cus__for_each_cu(cus, cu_emit_kprobes_iterator, class_name, NULL);
|
2006-12-24 02:42:39 +01:00
|
|
|
cus__for_each_cu(cus, cu_emit_kretprobes_iterator, NULL, NULL);
|
2006-12-20 16:24:32 +01:00
|
|
|
puts("static struct jprobe *jprobes[] = {");
|
2006-12-20 15:16:16 +01:00
|
|
|
cus__for_each_cu(cus, cu_emit_kprobes_table_iterator, NULL, NULL);
|
2006-12-23 21:14:37 +01:00
|
|
|
puts("\t(void *)0,\n};\n");
|
2006-12-24 02:42:39 +01:00
|
|
|
puts("static struct kretprobe *kretprobes[] = {");
|
|
|
|
cus__for_each_cu(cus, cu_emit_kretprobes_table_iterator, NULL, NULL);
|
|
|
|
puts("\t(void *)0,\n};\n\n");
|
2006-12-20 15:16:16 +01:00
|
|
|
emit_module_init();
|
|
|
|
emit_module_exit();
|
2006-12-23 23:09:02 +01:00
|
|
|
emit_module_license("GPL");
|
2006-12-20 15:16:16 +01:00
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|