[PATCH 11/18] Add partition support.

Joel Brobecker
2011-02-24T17:56:22Z

This is the module which is providing partition support. Since our
implementation is not entirely clean (see other message - right now,
we do some nasty swapping of objfiles in and out of the object_files
list), the code that is being provided here has been cleaned up a bit.
All the nasties have been removed, allowing us to keep the interface
and sufficient implementation for partition-less systems (VxWorks 5.x
and 6.x), but leaving out support for VxWorks 653.

I will look at implementing proper partition support independently of
this effort.

gdb/ChangeLog:

* remote-wtx-pd.h, remote-wtx-pd.c: New files.
---
gdb/remote-wtx-pd.c | 348 +++++++++++++++++++++++++++++++++++++++++++++++++++
gdb/remote-wtx-pd.h | 58 +++++++++
2 files changed, 406 insertions(+), 0 deletions(-)
create mode 100644 gdb/remote-wtx-pd.c
create mode 100644 gdb/remote-wtx-pd.h

diff --git a/gdb/remote-wtx-pd.c b/gdb/remote-wtx-pd.c
new file mode 100644
index 0000000..5d58c3c
--- /dev/null
+++ b/gdb/remote-wtx-pd.c
@@ -0,0 +1,348 @@
+/* Support for the WTX protocol.
+
+ Copyright (C) 2007, 2010, 2011 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program 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 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "gdb_assert.h"
+#include "objfiles.h"
+#include "source.h"
+#include "remote-wtx-pd.h"
+#include "remote-wtx-opt.h"
+#include "ada-lang.h"
+#include "language.h"
+#include "observer.h"
+#include "command.h"
+#include "gdbcmd.h"
+
+#include <ctype.h>
+
+/* We need to keep the symbols in each PD separate from the others.
+ One of the reasons is that 2 symbols with the same name are allowed to
+ coexist in 653 provided that these 2 symbols live in 2 separate PDs.
+ Another important reason is that virtual memory regions can overlap
+ between PDs, and one symbol address in a PD is not suitable in the
+ context of another PD.
+
+ GDB maintains a global list of objfiles where the symbols can be found.
+ To achieve this separation, we simply maintain one such list per PD in
+ this module. At each PD change, we simply save the objfile list for
+ the current PD, and restore it for the new PD. The net effect is that
+ GDB will only recognize symbols in the current PD, and will complain if
+ a user tries to do any operation that needs symbols from other PDs.
+
+ In practice, GDB maintains a few other global variables that also
+ need to be saved/restored, but the principle remains valid.
+
+ If would have been slicker to actually maintain one list of objfiles
+ for all PDs and modify GDB to automatically switch to the right PD
+ when performing an operation such as inserting a BP in some code that's
+ in a different partition. This would probably not be such a great
+ improvment in terms of usability, but this would require a major
+ overall rework. So we dropped this idea. */
+
+/* Return nonzero if the target system supports PDs. */
+
+int
+wtx_pd_system_has_pds ()
+{
+#if WTX_PROT_VERSION > 2
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+/* Return the name of the PD which ID is equal to PD_ID. If the given PD
+ could not be found, then return "<none>". */
+
+char *
+wtx_pd_get_pd_name (pd_id_t pd_id)
+{
+ struct wtxapi_pd_desc_q *pds;
+
+ pds = wtxapi_pd_info_q_get ();
+ make_cleanup (cleanup_wtxapi_pd_desc_q, pds);
+
+ for (; pds != NULL; pds = pds->next)
+ if (pds->pd_desc.pd_id == pd_id)
+ return xstrdup (pds->pd_desc.pd_name);
+
+ /* Fallback, if we did not find the PD, or if the system does not support
+ PDs, then return a string saying that the given PD does not have a name
+ associated to it. */
+ return xstrdup ("<none>");
+}
+
+/* Return the PD ID for the Protection Domain which name is NAME.
+ Raise an error if this PD does not exist. */
+
+static pd_id_t
+wtx_pd_pd_id_from_name (const char *name)
+{
+ struct wtxapi_pd_desc_q *pds;
+
+ pds = wtxapi_pd_info_q_get ();
+ make_cleanup (cleanup_wtxapi_pd_desc_q, pds);
+
+ while (pds != NULL)
+ if (strcmp (pds->pd_desc.pd_name, name) == 0)
+ return pds->pd_desc.pd_id;
+ else
+ pds = pds->next;
+
+ error (_("Unable to find partition: %s.\n"), name);
+}
+
+/* Set the curent Protection Domain to the given PD ID. No-op on less
+ recent versions of Tornado (T2) where the notion of PD is not supported. */
+
+static void
+switch_to_pd_internal (pd_id_t pd_id, int from_tty)
+{
+ pd_id_t current_pd;
+
+ if (!wtxapi_tool_connected ())
+ error (_("Not attached to a target. Use \"target wtx\" first."));
+
+ current_pd = wtxapi_pd_current_get ();
+
+ if (pd_id == current_pd)
+ {
+ /* Emit a warning when the PD switch has been requested explicitely
+ by the user, to make sure he knows the operation was meaningless
+ and has been aborted. */
+ if (from_tty)
+ warning (_("Partition unchanged, as already set to 0x%lx."), pd_id);
+ return;
+ }
+
+ if (wtx_pd_system_has_pds ())
+ error (_("Operation not implemented yet."));
+}
+
+/* Equivalent to switch_to_pd_internal (pd_id, 1). Useful either as a
+ shortcut to switch_to_pd_internal, or in conjunction with the
+ make_cleanup mechanism. */
+
+void
+wtx_pd_switch_to_pd (pd_id_t pd_id)
+{
+ switch_to_pd_internal (pd_id, 1);
+}
+
+/* On systems where Protection Domains are supported, return the ID of
+ the PD where the given module is loaded. Return NULL_PD if the system
+ does not support PD. */
+
+pd_id_t
+wtx_pd_get_module_pd (module_id_t module_id)
+{
+ int i;
+ struct wtxapi_module_list *module_list =
+ wtxapi_obj_module_list_get (WTX_MOD_FIND_IN_ALL_PD);
+
+ if (module_list == NULL)
+ error (_("Failed to get target list of modules: %s"), wtxapi_err_msg_get ());
+ else
+ make_cleanup (cleanup_wtxapi_module_list, module_list);
+
+ for (i = 0; i < module_list->num_obj_mod; i++)
+ if (module_list->mod_id_array [i] == module_id)
+ return module_list->pd_id_array [i];
+
+ /* If we reach this point, it means we did not find the given module. */
+ error (_("Failed to find module by ID: 0x%x"), module_id);
+}
+
+/* Given the name of a module that has just been unloaded, returni
+ the PD ID where it was loaded. The modules loaded on the current PD
+ are searched first.
+
+ The search is not performed by querying the target server as
+ the module has probably already been unloaded. Instead, this function
+ searches the current object_files list first, and then the object_files
+ list that we have saved for each PD.
+
+ On systems that do not support PDs, simply always return NULL_PD.
+ If the module is unknown to GDB, an error will be reported later
+ when searching the module in the list of objfiles. */
+
+pd_id_t
+wtx_pd_get_unloaded_module_pd (const char *module_name)
+{
+ /* FIXME: Not properly implemented for VxWorks 653 systems yet. */
+ return NULL_PD;
+}
+
+static void
+switch_to_pd_stub (void *pd_id)
+{
+ wtx_pd_switch_to_pd ((pd_id_t) pd_id);
+}
+
+struct cleanup *
+wtx_pd_make_switch_to_pd_cleanup (pd_id_t pd_id)
+{
+ return make_cleanup (switch_to_pd_stub, (void *) pd_id);
+}
+
+/* Switch to the partition where the given task is running.
+ This function is a no-op if we are already in the right PD. */
+
+void
+wtx_pd_switch_to_task_pd (int task_id)
+{
+ pd_id_t task_pd;
+ int success;
+
+ /* Try to retrieve ID of the PD inside which the module is running.
+ This operation may fail in normal conditions (eg when the event
+ we just received for this task is a CTX_EXIT), so abort silently
+ if the lookup fails. */
+ success = wtxapi_get_task_pd (task_id, &task_pd);
+ if (!success)
+ return;
+
+ if (task_pd != wtxapi_pd_current_get ())
+ wtx_pd_switch_to_pd (task_pd);
+}
+
+/* Display the list of PDs on the target. */
+
+static void
+info_partitions_command (char *arg, int from_tty)
+{
+ struct wtxapi_pd_desc_q *pds, *iter;
+ pd_id_t current_pd;
+
+ if (arg != NULL && arg[0] != '\000')
+ warning (_("Unexpected arguments at end of command, ignored."));
+
+ if (!wtxapi_tool_connected ())
+ error (_("Not attached to a target. "
+ "Use the \"target wtx\" command first."));
+
+ current_pd = wtxapi_pd_current_get ();
+ pds = wtxapi_pd_info_q_get ();
+ iter = pds;
+
+ printf_filtered (" PD-ID \t Name \n");
+ while (iter != NULL)
+ {
+ printf_filtered ("%s ", iter->pd_desc.pd_id == current_pd ? "*" : " ");
+ printf_filtered ("0x%x \t %s \n",
+ (unsigned int) iter->pd_desc.pd_id,
+ iter->pd_desc.pd_name);
+ iter = iter->next;
+ }
+ free_wtxapi_pd_desc_q (pds);
+}
+
+/* Implement the "pd" command. */
+
+static void
+partition_command (char *arg, int from_tty)
+{
+ pd_id_t pd_id;
+ STATUS result;
+
+ if (arg == NULL || arg[0] == '\000')
+ error (_("Please specify a partition ID. Use \"info partition\" to\n"
+ "see the IDs of the existing partitions."));
+
+ if (!isdigit (arg[0]))
+ pd_id = wtx_pd_pd_id_from_name (arg);
+ else
+ pd_id = strtol (arg, NULL, 0);
+
+ wtx_pd_switch_to_pd (pd_id);
+}
+
+/* Print a notification to the user if the current PD is no longer
+ the same as the PD that was current at the time when this function
+ was last called. */
+
+static void
+wtx_pd_check_pd_change (void)
+{
+ static pd_id_t pd_after_last_command = NULL_PD;
+
+ pd_id_t previous_pd = pd_after_last_command;
+ pd_after_last_command = wtxapi_pd_current_get ();
+
+ if (pd_after_last_command != previous_pd)
+ {
+ char *pd_name = wtx_pd_get_pd_name (pd_after_last_command);
+ printf_filtered ("[Switching to Partition %s (0x%lx)]\n",
+ pd_name, pd_after_last_command);
+ free (pd_name);
+ }
+}
+
+/* Observer for the "command_post" notification. */
+
+static void
+wtx_pd_command_post_notification (void)
+{
+ /* If the current PD has changed as a consequence of the previous command,
+ then we notify the user about the new PD. */
+ wtx_pd_check_pd_change ();
+}
+
+/* Print the Link Path of all PDs. */
+
+static void
+maintenance_info_link_path (char *arg, int from_tty)
+{
+ struct wtxapi_pd_desc_q *pds, *iter;
+
+ pds = wtxapi_pd_info_q_get ();
+ iter = pds;
+
+ printf ("Partition \t Name \t [Link Path]\n");
+ while (iter != NULL)
+ {
+ const struct wtxapi_pd_desc desc = iter->pd_desc;
+ printf (" 0x%lx \t %s \t [%s]\n",
+ iter->pd_desc.pd_id, iter->pd_desc.pd_name,
+ desc.pd_link_path_str ? desc.pd_link_path_str
+ : "(no link path)");
+ iter = iter->next;
+ }
+ free_wtxapi_pd_desc_q (pds);
+}
+
+void
+_initialize_remote_wtx_pd (void)
+{
+ if (!wtx_pd_system_has_pds ())
+ return;
+
+ observer_attach_command_post (wtx_pd_command_post_notification);
+
+ add_info ("partitions", info_partitions_command,
+ _("Display the list of existing partitions."));
+
+ add_com ("partition", class_run, partition_command,
+ _("Set the current partition."));
+
+ add_cmd ("link-path", class_maintenance, maintenance_info_link_path,
+ _("Display the link path of each partition."),
+ &maintenanceinfolist);
+}
+
diff --git a/gdb/remote-wtx-pd.h b/gdb/remote-wtx-pd.h
new file mode 100644
index 0000000..27e813c
--- /dev/null
+++ b/gdb/remote-wtx-pd.h
@@ -0,0 +1,58 @@
+/* Support for the WTX protocol.
+
+ Copyright (C) 2007, 2010, 2011 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program 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 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef REMOTE_WTX_PD_H
+#define REMOTE_WTX_PD_H
+
+#include "defs.h"
+#include "remote-wtxapi.h"
+
+/* This unit provides an abstraction layer to Partitions for both
+ Tornado 2.x & Tornado 653. Although only Tornado 653 systems
+ really support the concept of partitions, we can apply the same
+ concept to Tornado 2.x by imagining that these systems are a
+ special case where there is only one (kernel) partition.
+
+ For historical reasons (in the defunct produce Tornado AE), Partitions
+ are also refered as PD, an accronym for Protection Domain, the technical
+ term used to refer to partitions in Tornado AE. This accronym is very
+ short and handy, so we'll use it in place of partition. */
+
+struct cleanup;
+
+/* On Tornado 2.x, we will use the following NULL_PD to emulate the
+ system unique PD ID. On Tornado 653, we will be using the real
+ PD IDs. */
+#define NULL_PD (0)
+
+int wtx_pd_system_has_pds ();
+
+char *wtx_pd_get_pd_name (pd_id_t pd_id);
+
+void wtx_pd_switch_to_pd (pd_id_t pd_id);
+
+pd_id_t wtx_pd_get_module_pd (module_id_t module_id);
+
+pd_id_t wtx_pd_get_unloaded_module_pd (const char *module_name);
+
+struct cleanup *wtx_pd_make_switch_to_pd_cleanup (pd_id_t pd_id);
+
+void wtx_pd_switch_to_task_pd (int task_id);
+
+#endif
--
1.7.0.4