From 576fb31e560dc13319e2a6379431b6d8a2721c65 Mon Sep 17 00:00:00 2001
From: Justus Winter <4winter@informatik.uni-hamburg.de>
Date: Fri, 23 May 2014 17:01:48 +0200
Subject: [PATCH hurd 2/8] libintrospection: a library for Hurd server
introspection
* Makefile (lib-subdirs): Add libintrospection.
* libintrospection/Makefile: New file.
* libintrospection/introspection.c: Likewise.
* libintrospection/introspection.h: Likewise.
* libintrospection/trace.c: Likewise.
---
Makefile | 2 +
libintrospection/Makefile | 27 ++++++++
libintrospection/introspection.c | 86 ++++++++++++++++++++++++
libintrospection/introspection.h | 43 ++++++++++++
libintrospection/trace.c | 139 +++++++++++++++++++++++++++++++++++++++
5 files changed, 297 insertions(+)
create mode 100644 libintrospection/Makefile
create mode 100644 libintrospection/introspection.c
create mode 100644 libintrospection/introspection.h
create mode 100644 libintrospection/trace.c
diff --git a/Makefile b/Makefile
index 3178740..76eec21 100644
--- a/Makefile
+++ b/Makefile
@@ -50,6 +50,8 @@ endif
# Other directories
other-subdirs = hurd doc config release include
+lib-subdirs += libintrospection
+
# All the subdirectories together
subdirs = $(lib-subdirs) $(prog-subdirs) $(other-subdirs)
diff --git a/libintrospection/Makefile b/libintrospection/Makefile
new file mode 100644
index 0000000..75adef2
--- /dev/null
+++ b/libintrospection/Makefile
@@ -0,0 +1,27 @@
+# Copyright (C) 2014 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Hurd.
+#
+# The GNU Hurd is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2, or (at
+# your option) any later version.
+#
+# The GNU Hurd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with the GNU Hurd. If not, see .
+
+dir := libintrospection
+makemode := library
+
+libname := libintrospection
+SRCS = introspection.c trace.c hurd_portUser.c
+installhdrs = introspection.h
+
+OBJS = $(SRCS:.c=.o)
+
+include ../Makeconf
diff --git a/libintrospection/introspection.c b/libintrospection/introspection.c
new file mode 100644
index 0000000..65c0727
--- /dev/null
+++ b/libintrospection/introspection.c
@@ -0,0 +1,86 @@
+/* Hurd server introspection.
+
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+ Written by Justus Winter <4winter@informatik.uni-hamburg.de>
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd. If not, see . */
+
+#include
+
+#include "introspection.h"
+#include "hurd_port_U.h"
+
+error_t
+introspection_set_port (mach_port_t task,
+ mach_port_t introspection_port)
+{
+ error_t err;
+ mach_port_t *ports;
+ size_t ports_len;
+
+ err = mach_ports_lookup (task, &ports, &ports_len);
+ if (err)
+ return err;
+
+ if (MACH_PORT_VALID (ports[HURD_PORT_REGISTER_INTROSPECTION]))
+ mach_port_deallocate (mach_task_self (),
+ ports[HURD_PORT_REGISTER_INTROSPECTION]);
+
+ ports[HURD_PORT_REGISTER_INTROSPECTION] = introspection_port;
+
+ err = mach_ports_register (task, ports, ports_len);
+ if (err)
+ {
+ size_t i;
+ for (i = 0; i < ports_len; i++)
+ if (MACH_PORT_VALID (ports[i]))
+ mach_port_deallocate (mach_task_self (), ports[i]);
+
+ return err;
+ }
+
+ return 0;
+}
+
+error_t
+introspection_get_port (mach_port_t task, mach_port_t *introspection_port)
+{
+ error_t err;
+ mach_port_t *ports;
+ size_t ports_len;
+
+ err = mach_ports_lookup (task, &ports, &ports_len);
+ if (! err)
+ {
+ size_t i;
+ if (MACH_PORT_VALID (*introspection_port))
+ mach_port_deallocate (mach_task_self (), *introspection_port);
+
+ for (i = 0; i < ports_len; i++)
+ if (i == HURD_PORT_REGISTER_INTROSPECTION)
+ *introspection_port = ports[i];
+ else
+ {
+ if (MACH_PORT_VALID (ports[i]))
+ mach_port_deallocate (mach_task_self (), ports[i]);
+ }
+ }
+ else
+ *introspection_port = MACH_PORT_DEAD;
+
+ return err;
+}
diff --git a/libintrospection/introspection.h b/libintrospection/introspection.h
new file mode 100644
index 0000000..e2273ac
--- /dev/null
+++ b/libintrospection/introspection.h
@@ -0,0 +1,43 @@
+/* Hurd server introspection.
+
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+ Written by Justus Winter <4winter@informatik.uni-hamburg.de>
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd. If not, see . */
+
+#ifndef _HURD_INTROSPECTION_H_
+#define _HURD_INTROSPECTION_H_
+
+#include
+#include
+
+error_t
+introspection_set_port (mach_port_t task,
+ mach_port_t introspection_port);
+
+error_t
+introspection_get_port (mach_port_t task,
+ mach_port_t *introspection_port);
+
+error_t
+introspection_trace_message (mach_port_t trace_port,
+ const mach_msg_header_t *msgp);
+
+error_t
+introspection_extract_message (mach_msg_header_t *msgp);
+
+#endif /* _HURD_INTROSPECTION_H_ */
diff --git a/libintrospection/trace.c b/libintrospection/trace.c
new file mode 100644
index 0000000..89b7136
--- /dev/null
+++ b/libintrospection/trace.c
@@ -0,0 +1,139 @@
+/* Hurd server introspection.
+
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+ Written by Justus Winter <4winter@informatik.uni-hamburg.de>
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd. If not, see . */
+
+#include
+#include
+#include
+#include
+
+#include "introspection.h"
+
+static const mach_msg_type_t ports_type = {
+ /* msgt_name = */ MACH_MSG_TYPE_PORT_NAME,
+ /* msgt_size = */ sizeof (mach_port_t) << 3,
+ /* msgt_number = */ 2,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+};
+
+struct trace_footer
+{
+ mach_msg_type_t ports_type;
+ mach_port_t remote_port;
+ mach_port_t local_port;
+};
+
+error_t
+introspection_trace_message (mach_port_t trace_port,
+ const mach_msg_header_t *msgp)
+{
+ error_t err;
+ mach_msg_header_t *copyp;
+ void *msg_buf_ptr;
+ struct trace_footer *footer;
+ size_t size = msgp->msgh_size + sizeof *footer;
+
+ copyp = malloc (size);
+ if (copyp == NULL)
+ return ENOMEM;
+
+ memcpy (copyp, msgp, msgp->msgh_size);
+ footer = (void *) copyp + msgp->msgh_size;
+
+ /* Process the message data, clear msgt_deallocate and turn rights
+ into mere port names. */
+ msg_buf_ptr = (void *) copyp + sizeof *copyp;
+ while (msg_buf_ptr < (void *) copyp + msgp->msgh_size)
+ {
+ mach_msg_type_long_t *type_long = msg_buf_ptr;
+ mach_msg_type_t *type = &type_long->msgtl_header;
+ mach_msg_type_number_t nelt; /* Number of data items. */
+ mach_msg_type_size_t eltsize; /* Bytes per item. */
+
+ type->msgt_deallocate = 0;
+
+ if (! type->msgt_longform)
+ {
+ nelt = type->msgt_number;
+ eltsize = type->msgt_size / 8;
+ if (MACH_MSG_TYPE_PORT_ANY (type->msgt_name))
+ type->msgt_name = MACH_MSG_TYPE_PORT_NAME;
+ msg_buf_ptr += sizeof *type;
+ }
+ else
+ {
+ nelt = type_long->msgtl_number;
+ eltsize = type_long->msgtl_size / 8;
+ if (MACH_MSG_TYPE_PORT_ANY (type_long->msgtl_name))
+ type_long->msgtl_name = MACH_MSG_TYPE_PORT_NAME;
+ msg_buf_ptr += sizeof *type_long;
+ }
+
+ if (! type->msgt_inline)
+ /* This datum is out-of-line, meaning the message actually
+ contains a pointer to a vm_allocate'd region of data. */
+ msg_buf_ptr += sizeof (void *);
+ else
+ msg_buf_ptr += ((nelt * eltsize + sizeof(natural_t) - 1)
+ & ~(sizeof(natural_t) - 1));
+ }
+
+ copyp->msgh_bits =
+ MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0)
+ | (msgp->msgh_bits & MACH_MSGH_BITS_COMPLEX);
+ copyp->msgh_remote_port = trace_port;
+ copyp->msgh_local_port = MACH_PORT_NULL;
+
+ *footer = (struct trace_footer)
+ {
+ ports_type,
+ msgp->msgh_remote_port,
+ msgp->msgh_local_port,
+ };
+
+ err = mach_msg (copyp, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, size,
+ 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+ free (copyp);
+ return err;
+}
+
+error_t
+introspection_extract_message (mach_msg_header_t *msgp)
+{
+ size_t size = msgp->msgh_size - sizeof (struct trace_footer);
+ struct trace_footer *footer = (void *) msgp + size;
+
+ if (memcmp (&footer->ports_type, &ports_type, sizeof ports_type) != 0)
+ return MIG_BAD_ARGUMENTS;
+
+ if (footer->local_port == MACH_PORT_NULL)
+ msgp->msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0);
+ else
+ msgp->msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0); // XXX
+
+ msgp->msgh_remote_port = footer->remote_port;
+ msgp->msgh_local_port = footer->local_port;
+ msgp->msgh_size = size;
+ return 0;
+}
--
2.1.4