From 3b412f479bc34cd4a6e9d0e6617079cec7df1e15 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