Introduce class target_stack

Currently, the target stack is represented by a singly linked list,
with target_ops having a pointer to the target beneath.  This poses a
problem for multi-process / multi-target debugging.  In that case, we
will naturally want multiple instances of target stacks.  E.g., one
stack for inferior 1 which is debugging a core file, and another
target stack for inferior 2 which is debugging a remote process.  The
problem then is in finding a target's "beneath" target, if we consider
that for some target_ops types, we'll be sharing a single target_ops
instance between several inferiors.  For example, so far, I found no
need to have multiple instances of the spu_multiarch_target /
exec_target / dummy_target targets.

Thus this patch, which changes the target stack representation to an
array of pointers.  For now, there's still a single global instance of
this new target_stack class, though further down in the multi-target
work, each inferior will have its own instance.

gdb/ChangeLog:
2018-06-07  Pedro Alves  <palves@redhat.com>

	* target.h (target_ops) <beneath>: Now a method.  All references
	updated.
	(class target_stack): New.
	* target.c (g_target_stack): New.
	(g_current_top_target): Delete.
	(current_top_target): Get the top target out of g_target_stack.
	(target_stack::push, target_stack::unpush): New.
	(push_target, unpush_target): Reimplement.
	(target_is_pushed): Reimplement in terms of g_target_stack.
	(target_ops::beneath, target_stack::find_beneath): New.
This commit is contained in:
Pedro Alves
2018-06-07 17:27:48 +01:00
parent d6ca69cddc
commit a1740ee157
3 changed files with 122 additions and 65 deletions

View File

@@ -61,7 +61,11 @@ struct inferior;
of variables any more (the file target is handling them and they
never get to the process target). So when you push a file target,
it goes into the file stratum, which is always below the process
stratum. */
stratum.
Note that rather than allow an empty stack, we always have the
dummy target at the bottom stratum, so we can call the target
methods without checking them. */
#include "target/target.h"
#include "target/resume.h"
@@ -425,7 +429,6 @@ struct target_info
struct target_ops
{
/* To the target under this one. */
target_ops *m_beneath;
target_ops *beneath () const;
/* Free resources associated with the target. Note that singleton
@@ -1268,6 +1271,46 @@ extern void set_native_target (target_ops *target);
NULL. */
extern target_ops *get_native_target ();
/* Type that manages a target stack. See description of target stacks
and strata at the top of the file. */
class target_stack
{
public:
target_stack () = default;
DISABLE_COPY_AND_ASSIGN (target_stack);
/* Push a new target into the stack of the existing target
accessors, possibly superseding some existing accessor. */
void push (target_ops *t);
/* Remove a target from the stack, wherever it may be. Return true
if it was removed, false otherwise. */
bool unpush (target_ops *t);
/* Returns true if T is pushed on the target stack. */
bool is_pushed (target_ops *t) const
{ return at (t->to_stratum) == t; }
/* Return the target at STRATUM. */
target_ops *at (strata stratum) const { return m_stack[stratum]; }
/* Return the target at the top of the stack. */
target_ops *top () const { return at (m_top); }
/* Find the next target down the stack from the specified target. */
target_ops *find_beneath (const target_ops *t) const;
private:
/* The stratum of the top target. */
enum strata m_top {};
/* The stack, represented as an array, with one slot per stratum.
If no target is pushed at some stratum, the corresponding slot is
null. */
target_ops *m_stack[(int) debug_stratum + 1] {};
};
/* The ops structure for our "current" target process. This should
never be NULL. If there is no target, it points to the dummy_target. */