mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-02-05 00:36:22 +00:00
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:
parent
53dad163f7
commit
e2d966398c
@ -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>
|
||||
|
||||
* 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);
|
||||
}
|
||||
|
||||
/* 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
|
||||
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);
|
||||
|
||||
/* Restore the contents of the copy area. */
|
||||
{
|
||||
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));
|
||||
}
|
||||
displaced_step_restore (displaced, displaced->step_ptid);
|
||||
|
||||
/* Did the instruction complete successfully? */
|
||||
if (signal == TARGET_SIGNAL_TRAP)
|
||||
@ -3373,6 +3380,60 @@ handle_inferior_event (struct execution_control_state *ecs)
|
||||
if (debug_infrun)
|
||||
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))
|
||||
{
|
||||
context_switch (ecs->ptid);
|
||||
|
@ -450,17 +450,33 @@ struct regcache_list
|
||||
static struct regcache_list *current_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 *new_regcache;
|
||||
struct address_space *aspace;
|
||||
|
||||
for (list = current_regcache; list; list = list->next)
|
||||
if (ptid_equal (list->regcache->ptid, ptid)
|
||||
&& get_regcache_arch (list->regcache) == gdbarch)
|
||||
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
|
||||
executable, allow dumping the regcache even when there is no
|
||||
thread selected (target_thread_address_space internal-errors if
|
||||
@ -471,15 +487,7 @@ get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
|
||||
? NULL
|
||||
: target_thread_address_space (ptid));
|
||||
|
||||
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;
|
||||
return get_thread_arch_aspace_regcache (ptid, gdbarch, aspace);
|
||||
}
|
||||
|
||||
static ptid_t current_thread_ptid;
|
||||
|
@ -28,6 +28,9 @@ struct address_space;
|
||||
extern struct regcache *get_current_regcache (void);
|
||||
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_aspace_regcache (ptid_t,
|
||||
struct gdbarch *,
|
||||
struct address_space *);
|
||||
|
||||
void regcache_xfree (struct regcache *regcache);
|
||||
struct cleanup *make_cleanup_regcache_xfree (struct regcache *regcache);
|
||||
|
Loading…
x
Reference in New Issue
Block a user