forked from Imagelibrary/binutils-gdb
gdb/
* infrun.c (displaced_step_fixup): Move some code ... (displaced_step_restore): ... here. New function. (handle_inferior_event): Cleanup displaced stepping state for both child and parent when get forked or vforked event. * regcache.c (get_thread_arch_aspace_regcache): New function. get_thread_arch_regcache (): Call it.
This commit is contained in:
@@ -1,3 +1,12 @@
|
|||||||
|
2011-09-17 Yao Qi <yao@codesourcery.com>
|
||||||
|
|
||||||
|
* infrun.c (displaced_step_fixup): Move some code ...
|
||||||
|
(displaced_step_restore): ... here. New function.
|
||||||
|
(handle_inferior_event): Cleanup displaced stepping state for both
|
||||||
|
child and parent when get forked or vforked event.
|
||||||
|
* regcache.c (get_thread_arch_aspace_regcache): New function.
|
||||||
|
get_thread_arch_regcache (): Call it.
|
||||||
|
|
||||||
2011-09-16 Joel Brobecker <brobecker@adacore.com>
|
2011-09-16 Joel Brobecker <brobecker@adacore.com>
|
||||||
|
|
||||||
* ada-tasks.c (print_ada_task_info): New function, merging
|
* ada-tasks.c (print_ada_task_info): New function, merging
|
||||||
|
|||||||
83
gdb/infrun.c
83
gdb/infrun.c
@@ -1364,6 +1364,23 @@ write_memory_ptid (ptid_t ptid, CORE_ADDR memaddr,
|
|||||||
do_cleanups (ptid_cleanup);
|
do_cleanups (ptid_cleanup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Restore the contents of the copy area for thread PTID. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
displaced_step_restore (struct displaced_step_inferior_state *displaced,
|
||||||
|
ptid_t ptid)
|
||||||
|
{
|
||||||
|
ULONGEST len = gdbarch_max_insn_length (displaced->step_gdbarch);
|
||||||
|
|
||||||
|
write_memory_ptid (ptid, displaced->step_copy,
|
||||||
|
displaced->step_saved_copy, len);
|
||||||
|
if (debug_displaced)
|
||||||
|
fprintf_unfiltered (gdb_stdlog, "displaced: restored %s %s\n",
|
||||||
|
target_pid_to_str (ptid),
|
||||||
|
paddress (displaced->step_gdbarch,
|
||||||
|
displaced->step_copy));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
|
displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
|
||||||
{
|
{
|
||||||
@@ -1382,17 +1399,7 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal)
|
|||||||
|
|
||||||
old_cleanups = make_cleanup (displaced_step_clear_cleanup, displaced);
|
old_cleanups = make_cleanup (displaced_step_clear_cleanup, displaced);
|
||||||
|
|
||||||
/* Restore the contents of the copy area. */
|
displaced_step_restore (displaced, displaced->step_ptid);
|
||||||
{
|
|
||||||
ULONGEST len = gdbarch_max_insn_length (displaced->step_gdbarch);
|
|
||||||
|
|
||||||
write_memory_ptid (displaced->step_ptid, displaced->step_copy,
|
|
||||||
displaced->step_saved_copy, len);
|
|
||||||
if (debug_displaced)
|
|
||||||
fprintf_unfiltered (gdb_stdlog, "displaced: restored %s\n",
|
|
||||||
paddress (displaced->step_gdbarch,
|
|
||||||
displaced->step_copy));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Did the instruction complete successfully? */
|
/* Did the instruction complete successfully? */
|
||||||
if (signal == TARGET_SIGNAL_TRAP)
|
if (signal == TARGET_SIGNAL_TRAP)
|
||||||
@@ -3373,6 +3380,60 @@ handle_inferior_event (struct execution_control_state *ecs)
|
|||||||
if (debug_infrun)
|
if (debug_infrun)
|
||||||
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_FORKED\n");
|
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_FORKED\n");
|
||||||
|
|
||||||
|
/* Check whether the inferior is displaced stepping. */
|
||||||
|
{
|
||||||
|
struct regcache *regcache = get_thread_regcache (ecs->ptid);
|
||||||
|
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||||
|
struct displaced_step_inferior_state *displaced
|
||||||
|
= get_displaced_stepping_state (ptid_get_pid (ecs->ptid));
|
||||||
|
|
||||||
|
/* If checking displaced stepping is supported, and thread
|
||||||
|
ecs->ptid is displaced stepping. */
|
||||||
|
if (displaced && ptid_equal (displaced->step_ptid, ecs->ptid))
|
||||||
|
{
|
||||||
|
struct inferior *parent_inf
|
||||||
|
= find_inferior_pid (ptid_get_pid (ecs->ptid));
|
||||||
|
struct regcache *child_regcache;
|
||||||
|
CORE_ADDR parent_pc;
|
||||||
|
|
||||||
|
/* GDB has got TARGET_WAITKIND_FORKED or TARGET_WAITKIND_VFORKED,
|
||||||
|
indicating that the displaced stepping of syscall instruction
|
||||||
|
has been done. Perform cleanup for parent process here. Note
|
||||||
|
that this operation also cleans up the child process for vfork,
|
||||||
|
because their pages are shared. */
|
||||||
|
displaced_step_fixup (ecs->ptid, TARGET_SIGNAL_TRAP);
|
||||||
|
|
||||||
|
if (ecs->ws.kind == TARGET_WAITKIND_FORKED)
|
||||||
|
{
|
||||||
|
/* Restore scratch pad for child process. */
|
||||||
|
displaced_step_restore (displaced, ecs->ws.value.related_pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Since the vfork/fork syscall instruction was executed in the scratchpad,
|
||||||
|
the child's PC is also within the scratchpad. Set the child's PC
|
||||||
|
to the parent's PC value, which has already been fixed up.
|
||||||
|
FIXME: we use the parent's aspace here, although we're touching
|
||||||
|
the child, because the child hasn't been added to the inferior
|
||||||
|
list yet at this point. */
|
||||||
|
|
||||||
|
child_regcache
|
||||||
|
= get_thread_arch_aspace_regcache (ecs->ws.value.related_pid,
|
||||||
|
gdbarch,
|
||||||
|
parent_inf->aspace);
|
||||||
|
/* Read PC value of parent process. */
|
||||||
|
parent_pc = regcache_read_pc (regcache);
|
||||||
|
|
||||||
|
if (debug_displaced)
|
||||||
|
fprintf_unfiltered (gdb_stdlog,
|
||||||
|
"displaced: write child pc from %s to %s\n",
|
||||||
|
paddress (gdbarch,
|
||||||
|
regcache_read_pc (child_regcache)),
|
||||||
|
paddress (gdbarch, parent_pc));
|
||||||
|
|
||||||
|
regcache_write_pc (child_regcache, parent_pc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!ptid_equal (ecs->ptid, inferior_ptid))
|
if (!ptid_equal (ecs->ptid, inferior_ptid))
|
||||||
{
|
{
|
||||||
context_switch (ecs->ptid);
|
context_switch (ecs->ptid);
|
||||||
|
|||||||
@@ -450,17 +450,33 @@ struct regcache_list
|
|||||||
static struct regcache_list *current_regcache;
|
static struct regcache_list *current_regcache;
|
||||||
|
|
||||||
struct regcache *
|
struct regcache *
|
||||||
get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
|
get_thread_arch_aspace_regcache (ptid_t ptid, struct gdbarch *gdbarch,
|
||||||
|
struct address_space *aspace)
|
||||||
{
|
{
|
||||||
struct regcache_list *list;
|
struct regcache_list *list;
|
||||||
struct regcache *new_regcache;
|
struct regcache *new_regcache;
|
||||||
struct address_space *aspace;
|
|
||||||
|
|
||||||
for (list = current_regcache; list; list = list->next)
|
for (list = current_regcache; list; list = list->next)
|
||||||
if (ptid_equal (list->regcache->ptid, ptid)
|
if (ptid_equal (list->regcache->ptid, ptid)
|
||||||
&& get_regcache_arch (list->regcache) == gdbarch)
|
&& get_regcache_arch (list->regcache) == gdbarch)
|
||||||
return list->regcache;
|
return list->regcache;
|
||||||
|
|
||||||
|
new_regcache = regcache_xmalloc_1 (gdbarch, aspace, 0);
|
||||||
|
new_regcache->ptid = ptid;
|
||||||
|
|
||||||
|
list = xmalloc (sizeof (struct regcache_list));
|
||||||
|
list->regcache = new_regcache;
|
||||||
|
list->next = current_regcache;
|
||||||
|
current_regcache = list;
|
||||||
|
|
||||||
|
return new_regcache;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct regcache *
|
||||||
|
get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
|
||||||
|
{
|
||||||
|
struct address_space *aspace;
|
||||||
|
|
||||||
/* For the benefit of "maint print registers" & co when debugging an
|
/* For the benefit of "maint print registers" & co when debugging an
|
||||||
executable, allow dumping the regcache even when there is no
|
executable, allow dumping the regcache even when there is no
|
||||||
thread selected (target_thread_address_space internal-errors if
|
thread selected (target_thread_address_space internal-errors if
|
||||||
@@ -471,15 +487,7 @@ get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
|
|||||||
? NULL
|
? NULL
|
||||||
: target_thread_address_space (ptid));
|
: target_thread_address_space (ptid));
|
||||||
|
|
||||||
new_regcache = regcache_xmalloc_1 (gdbarch, aspace, 0);
|
return get_thread_arch_aspace_regcache (ptid, gdbarch, aspace);
|
||||||
new_regcache->ptid = ptid;
|
|
||||||
|
|
||||||
list = xmalloc (sizeof (struct regcache_list));
|
|
||||||
list->regcache = new_regcache;
|
|
||||||
list->next = current_regcache;
|
|
||||||
current_regcache = list;
|
|
||||||
|
|
||||||
return new_regcache;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ptid_t current_thread_ptid;
|
static ptid_t current_thread_ptid;
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ struct address_space;
|
|||||||
extern struct regcache *get_current_regcache (void);
|
extern struct regcache *get_current_regcache (void);
|
||||||
extern struct regcache *get_thread_regcache (ptid_t ptid);
|
extern struct regcache *get_thread_regcache (ptid_t ptid);
|
||||||
extern struct regcache *get_thread_arch_regcache (ptid_t, struct gdbarch *);
|
extern struct regcache *get_thread_arch_regcache (ptid_t, struct gdbarch *);
|
||||||
|
extern struct regcache *get_thread_arch_aspace_regcache (ptid_t,
|
||||||
|
struct gdbarch *,
|
||||||
|
struct address_space *);
|
||||||
|
|
||||||
void regcache_xfree (struct regcache *regcache);
|
void regcache_xfree (struct regcache *regcache);
|
||||||
struct cleanup *make_cleanup_regcache_xfree (struct regcache *regcache);
|
struct cleanup *make_cleanup_regcache_xfree (struct regcache *regcache);
|
||||||
|
|||||||
Reference in New Issue
Block a user