diff options
Diffstat (limited to 'debian/patches/introspection0008-utils-rpctrace-support-attaching-to-servers.patch')
-rw-r--r-- | debian/patches/introspection0008-utils-rpctrace-support-attaching-to-servers.patch | 372 |
1 files changed, 0 insertions, 372 deletions
diff --git a/debian/patches/introspection0008-utils-rpctrace-support-attaching-to-servers.patch b/debian/patches/introspection0008-utils-rpctrace-support-attaching-to-servers.patch deleted file mode 100644 index 97a96ebd..00000000 --- a/debian/patches/introspection0008-utils-rpctrace-support-attaching-to-servers.patch +++ /dev/null @@ -1,372 +0,0 @@ -From 3e02ff327e6ec3961bfbb68850e30ba62c817e5b Mon Sep 17 00:00:00 2001 -From: Justus Winter <4winter@informatik.uni-hamburg.de> -Date: Fri, 23 May 2014 08:42:45 +0200 -Subject: [PATCH hurd 8/9] utils/rpctrace: support attaching to servers - -* utils/rpctrace.c (options): Add `--pid' and `--reference-port'. -(print_contents): Prevent the translation of rights if `req' is NULL. -We will use this to print messages in `trace_server'. -(parse_task): New function. -(trace_server): Mach server function that displays relayed messages. -(trace_class_rpcs): New function that attaches to a server and starts -tracing. -(parse_opt): Handle `--pid' and `--reference-port'. -(main): Handle new arguments, call trace_class_rpcs if desired. ---- - utils/Makefile | 5 +- - utils/rpctrace.c | 245 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 247 insertions(+), 3 deletions(-) - -diff --git a/utils/Makefile b/utils/Makefile -index 603b722..94a389b 100644 ---- a/utils/Makefile -+++ b/utils/Makefile -@@ -34,7 +34,7 @@ SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \ - nullauth.c match-options.c msgids.c rpcscan.c - - OBJS = $(filter-out %.sh,$(SRCS:.c=.o)) --HURDLIBS = ps ihash store fshelp ports ftpconn shouldbeinlibc -+HURDLIBS = ps ihash store fshelp ports ftpconn shouldbeinlibc introspection - LDLIBS += -lpthread - login-LDLIBS = -lutil -lcrypt - addauth-LDLIBS = -lcrypt -@@ -68,7 +68,8 @@ ps w ids settrans syncfs showtrans fsysopts storeinfo login vmstat portinfo \ - - $(filter-out $(special-targets), $(targets)): %: %.o - --rpctrace: ../libports/libports.a -+rpctrace: ../libports/libports.a \ -+ ../libintrospection/libintrospection.a hurd_portUser.o - rpctrace rpcscan: msgids.o \ - ../libihash/libihash.a - msgids-CPPFLAGS = -DDATADIR=\"${datadir}\" -diff --git a/utils/rpctrace.c b/utils/rpctrace.c -index b2f7b2b..98a8c7a 100644 ---- a/utils/rpctrace.c -+++ b/utils/rpctrace.c -@@ -23,6 +23,7 @@ - #include <hurd.h> - #include <hurd/ports.h> - #include <hurd/ihash.h> -+#include <hurd/introspection.h> - #include <mach/message.h> - #include <assert.h> - #include <fcntl.h> -@@ -40,14 +41,22 @@ - #include <envz.h> - - #include "msgids.h" -+#include "hurd_port_U.h" - - const char *argp_program_version = STANDARD_HURD_VERSION (rpctrace); - - static unsigned strsize = 80; -+static int trace_class; - - static const struct argp_option options[] = - { - {"output", 'o', "FILE", 0, "Send trace output to FILE instead of stderr."}, -+ {"pid", 'p', "PID", 0, "Attach to PID and trace all requests to objects " -+ "of the same class as the given reference port. This will only work " -+ "for Hurd servers implementing the introspection protocol."}, -+ {"port", 'P', "PORT", 0, "Trace all requests PORT. " -+ "PORT must denote a receive right in PID."}, -+ {"class", 'c', NULL, 0, "Trace all requests to the same class as PORT."}, - {0, 's', "SIZE", 0, "Specify the maximum string size to print (the default is 80)."}, - {0, 'E', "var[=value]", 0, - "Set/change (var=value) or remove (var) an environment variable among the " -@@ -852,7 +861,7 @@ print_contents (mach_msg_header_t *inp, - what task that port name is meaningful in. If it's meaningful in - a traced task, then it refers to our intercepting port rather than - the original port anyway. */ -- if (MACH_MSG_TYPE_PORT_ANY_RIGHT (name)) -+ if (MACH_MSG_TYPE_PORT_ANY_RIGHT (name) && req != NULL) - { - /* These are port rights. Translate them into wrappers. */ - mach_port_t *const portnames = data; -@@ -1674,10 +1683,217 @@ traced_spawn (char **argv, char **envp) - - return pid; - } -+ -+/* Return the task corresponding to the user argument ARG, exiting with an -+ appriate error message if we can't. */ -+static task_t -+parse_task (char *arg) -+{ -+ error_t err; -+ task_t task; -+ char *arg_end; -+ pid_t pid = strtoul (arg, &arg_end, 10); -+ static process_t proc = MACH_PORT_NULL; -+ -+ if (*arg == '\0' || *arg_end != '\0') -+ error (10, 0, "%s: Invalid process id", arg); -+ -+ if (proc == MACH_PORT_NULL) -+ proc = getproc (); -+ -+ err = proc_pid2task (proc, pid, &task); -+ if (err) -+ error (11, err, "%s", arg); -+ else if (task == MACH_PORT_NULL) -+ error (11, 0, "%s: Process %d is dead and has no task", arg, (int) pid); -+ -+ return task; -+} -+ -+static mach_port_t trace_notification_port; -+static mach_port_t reference_port; -+ -+boolean_t -+trace_server (mach_msg_header_t *inp, -+ mach_msg_header_t *outp) -+{ -+ error_t err; -+ static struct hurd_ihash ongoing_requests = -+ HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP); -+ struct msgid_info *info; -+ mach_port_t trace_id; -+ int is_reply; -+ -+ if (inp->msgh_local_port == trace_notification_port -+ && inp->msgh_id == MACH_NOTIFY_NO_SENDERS) -+ { -+ error (0, 0, "The tracee vanished."); -+ exit (EXIT_SUCCESS); -+ } -+ -+ err = introspection_extract_message (inp, &trace_id); -+ if (err) -+ { -+ error (0, err, "introspection_extract_message"); -+ goto out; -+ } -+ info = msgid_info (inp->msgh_id); -+ -+ /* XXX This hardcodes an assumption about reply message ids. */ -+ is_reply = (inp->msgh_id / 100) % 2 == 1; -+ if (is_reply) -+ { -+ /* This looks like a traced reply or a pseudo-reply. A -+ pseudo-reply is a message containing the result of a simple -+ procedure that is only sent to us. */ -+ mig_reply_header_t *reply = (mig_reply_header_t *) inp; -+ -+ mach_port_t request_port; -+ request_port = hurd_ihash_find (&ongoing_requests, trace_id); -+ if (! MACH_PORT_VALID (request_port)) -+ { -+ fprintf (stderr, "unsolicited reply packet with id: %d\n", -+ trace_id); -+ goto out; -+ } -+ hurd_ihash_remove (&ongoing_requests, trace_id); -+ -+ if (! (trace_class || request_port == reference_port)) -+ goto out; -+ -+ if (last_reply_port != trace_id) -+ { -+ print_ellipsis (); -+ fprintf (ostream, "%u...", (unsigned int) trace_id); -+ } -+ last_reply_port = MACH_PORT_NULL; -+ -+ fprintf (ostream, " = "); -+ -+ if (reply->RetCode == 0) -+ fprintf (ostream, "0"); -+ else -+ { -+ const char *str = strerror (reply->RetCode); -+ if (str == 0) -+ fprintf (ostream, "%#x", reply->RetCode); -+ else -+ fprintf (ostream, "%#x (%s)", reply->RetCode, str); -+ } -+ -+ if (inp->msgh_size > sizeof *reply) -+ { -+ fprintf (ostream, " "); -+ print_contents (inp, (void *) inp + sizeof *reply, NULL); -+ } -+ fprintf (ostream, "\n"); -+ } -+ else -+ { -+ /* Remember the request port. */ -+ hurd_ihash_add (&ongoing_requests, trace_id, inp->msgh_local_port); -+ -+ if (! (trace_class || inp->msgh_local_port == reference_port)) -+ goto out; -+ -+ /* This looks like a traced request. */ -+ print_ellipsis (); -+ last_reply_port = trace_id; -+ -+ if (info) -+ fprintf (ostream, "% 4d->%s (", inp->msgh_local_port, info->name); -+ else -+ fprintf (ostream, "% 4d->%d (", inp->msgh_local_port, inp->msgh_id); -+ -+ print_contents (inp, (void *) inp + sizeof *inp, NULL); -+ fprintf (ostream, ")"); -+ } -+ -+ out: -+ /* vm_deallocate any out-of-band memory. */ -+ mach_msg_destroy (inp); -+ -+ /* Prevent mach_msg_server from sending messages. */ -+ ((mig_reply_header_t *) outp)->RetCode = MIG_NO_REPLY; -+ return TRUE; -+} -+ -+int -+trace_class_rpcs (mach_port_t task, -+ mach_port_t name) -+{ -+ error_t err; -+ mach_port_t trace_port; -+ mach_port_t introspection_port; -+ mach_port_t previous; -+ mach_port_t port_set; -+ -+ err = introspection_get_port (task, &introspection_port); -+ if (err) -+ error (13, err, "Failed to get introspection port"); -+ -+ if (! MACH_PORT_VALID (introspection_port)) -+ error (13, 0, "The server does not implement the introspection protocol"); -+ -+ err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, -+ &trace_port); -+ if (err) -+ error (13, err, "mach_port_allocate"); -+ -+ err = hurd_port_trace_class_rpcs (introspection_port, name, -+ trace_port, MACH_MSG_TYPE_MAKE_SEND); -+ if (err) -+ { -+ if (err == EINVAL) -+ error (13, 0, -+ "%d does not denote a receive right managed by libports", name); -+ else -+ error (13, err, "hurd_port_trace_class_rpcs"); -+ } -+ -+ err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, -+ &trace_notification_port); -+ if (err) -+ error (13, err, "mach_port_allocate"); -+ -+ err = mach_port_request_notification (mach_task_self (), -+ trace_port, -+ MACH_NOTIFY_NO_SENDERS, -+ 0, -+ trace_notification_port, -+ MACH_MSG_TYPE_MAKE_SEND_ONCE, -+ &previous); -+ if (err) -+ error (13, err, "mach_port_request_notification"); -+ assert (! MACH_PORT_VALID (previous)); -+ -+ -+ err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_PORT_SET, -+ &port_set); -+ if (err) -+ error (13, err, "mach_port_allocate"); -+ -+ err = mach_port_move_member (mach_task_self (), trace_port, port_set); -+ if (err) -+ error (13, err, "mach_port_move_member"); - -+ err = mach_port_move_member (mach_task_self (), trace_notification_port, -+ port_set); -+ if (err) -+ error (13, err, "mach_port_move_member"); -+ -+ error (0, 0, "entering service loop"); -+ while (1) -+ mach_msg_server (trace_server, 0, port_set); -+ -+ /* Not reached. */ -+ return 0; -+} -+ - int - main (int argc, char **argv, char **envp) - { -+ mach_port_t target_task = MACH_PORT_NULL; - const char *outfile = 0; - char **cmd_argv = 0; - pthread_t thread; -@@ -1689,12 +1905,27 @@ main (int argc, char **argv, char **envp) - /* Parse our options... */ - error_t parse_opt (int key, char *arg, struct argp_state *state) - { -+ char *arg_end; - switch (key) - { - case 'o': - outfile = arg; - break; - -+ case 'p': -+ target_task = parse_task (arg); -+ break; -+ -+ case 'P': -+ reference_port = strtoul (arg, &arg_end, 10); -+ if (*arg == '\0' || *arg_end != '\0') -+ argp_error (state, "Invalid port name: %s", arg); -+ break; -+ -+ case 'c': -+ trace_class = 1; -+ break; -+ - case 's': - strsize = atoi (arg); - break; -@@ -1728,10 +1959,16 @@ main (int argc, char **argv, char **envp) - break; - - case ARGP_KEY_NO_ARGS: -+ if (MACH_PORT_VALID (target_task)) -+ break; -+ - argp_usage (state); - return EINVAL; - - case ARGP_KEY_ARG: -+ if (MACH_PORT_VALID (target_task)) -+ argp_error (state, "Superfluous argument: %s", arg); -+ - cmd_argv = &state->argv[state->next - 1]; - state->next = state->argc; - break; -@@ -1751,6 +1988,9 @@ main (int argc, char **argv, char **envp) - /* Parse our arguments. */ - argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0); - -+ if (MACH_PORT_VALID (target_task) != MACH_PORT_VALID (reference_port)) -+ error (10, 0, "Please specify either both -p and -P, or neither."); -+ - err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_DEAD_NAME, - &unknown_task); - assert_perror (err); -@@ -1765,6 +2005,9 @@ main (int argc, char **argv, char **envp) - ostream = stderr; - setlinebuf (ostream); - -+ if (MACH_PORT_VALID (target_task)) -+ return trace_class_rpcs (target_task, reference_port); -+ - traced_bucket = ports_create_bucket (); - traced_class = ports_create_class (&traced_clean, NULL); - other_class = ports_create_class (0, 0); --- -2.1.4 - |