bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH hurd 2/8] libintrospection: a library for Hurd server introspecti


From: Justus Winter
Subject: [PATCH hurd 2/8] libintrospection: a library for Hurd server introspection
Date: Thu, 23 Oct 2014 17:16:40 +0200

* 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 <http://www.gnu.org/licenses/>.
+
+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 <http://www.gnu.org/licenses/>.  */
+
+#include <mach.h>
+
+#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 <http://www.gnu.org/licenses/>.  */
+
+#ifndef _HURD_INTROSPECTION_H_
+#define _HURD_INTROSPECTION_H_
+
+#include <errno.h>
+#include <mach.h>
+
+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 <http://www.gnu.org/licenses/>.  */
+
+#include <error.h>
+#include <mach/mig_errors.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]