2003-07-13 18:15:59 +02:00
|
|
|
|
/* Native-dependent code for FreeBSD/amd64.
|
2003-08-29 15:58:26 +02:00
|
|
|
|
|
2014-01-01 04:54:24 +01:00
|
|
|
|
Copyright (C) 2003-2014 Free Software Foundation, Inc.
|
2003-07-13 18:15:59 +02:00
|
|
|
|
|
|
|
|
|
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
|
2007-08-23 20:08:50 +02:00
|
|
|
|
the Free Software Foundation; either version 3 of the License, or
|
2003-07-13 18:15:59 +02:00
|
|
|
|
(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
|
2007-08-23 20:08:50 +02:00
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
2003-07-13 18:15:59 +02:00
|
|
|
|
|
|
|
|
|
#include "defs.h"
|
|
|
|
|
#include "inferior.h"
|
|
|
|
|
#include "regcache.h"
|
2004-09-26 20:42:30 +02:00
|
|
|
|
#include "target.h"
|
2003-07-13 18:15:59 +02:00
|
|
|
|
|
|
|
|
|
#include "gdb_assert.h"
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/ptrace.h>
|
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
|
#include <machine/reg.h>
|
|
|
|
|
|
2004-09-26 20:42:30 +02:00
|
|
|
|
#include "fbsd-nat.h"
|
2004-02-25 21:59:12 +01:00
|
|
|
|
#include "amd64-tdep.h"
|
2003-08-29 15:58:26 +02:00
|
|
|
|
#include "amd64-nat.h"
|
2012-02-09 17:06:44 +01:00
|
|
|
|
#include "amd64bsd-nat.h"
|
|
|
|
|
#include "i386-nat.h"
|
2003-07-13 18:15:59 +02:00
|
|
|
|
|
|
|
|
|
|
2004-06-26 13:47:53 +02:00
|
|
|
|
/* Offset in `struct reg' where MEMBER is stored. */
|
|
|
|
|
#define REG_OFFSET(member) offsetof (struct reg, member)
|
2003-07-13 18:15:59 +02:00
|
|
|
|
|
2004-06-26 13:47:53 +02:00
|
|
|
|
/* At amd64fbsd64_r_reg_offset[REGNUM] you'll find the offset in
|
|
|
|
|
`struct reg' location where the GDB register REGNUM is stored.
|
|
|
|
|
Unsupported registers are marked with `-1'. */
|
|
|
|
|
static int amd64fbsd64_r_reg_offset[] =
|
2003-07-13 18:15:59 +02:00
|
|
|
|
{
|
|
|
|
|
REG_OFFSET (r_rax),
|
|
|
|
|
REG_OFFSET (r_rbx),
|
|
|
|
|
REG_OFFSET (r_rcx),
|
|
|
|
|
REG_OFFSET (r_rdx),
|
|
|
|
|
REG_OFFSET (r_rsi),
|
|
|
|
|
REG_OFFSET (r_rdi),
|
|
|
|
|
REG_OFFSET (r_rbp),
|
|
|
|
|
REG_OFFSET (r_rsp),
|
|
|
|
|
REG_OFFSET (r_r8),
|
|
|
|
|
REG_OFFSET (r_r9),
|
|
|
|
|
REG_OFFSET (r_r10),
|
|
|
|
|
REG_OFFSET (r_r11),
|
|
|
|
|
REG_OFFSET (r_r12),
|
|
|
|
|
REG_OFFSET (r_r13),
|
|
|
|
|
REG_OFFSET (r_r14),
|
|
|
|
|
REG_OFFSET (r_r15),
|
|
|
|
|
REG_OFFSET (r_rip),
|
|
|
|
|
REG_OFFSET (r_rflags),
|
2004-01-10 13:52:41 +01:00
|
|
|
|
REG_OFFSET (r_cs),
|
|
|
|
|
REG_OFFSET (r_ss),
|
2003-07-13 18:15:59 +02:00
|
|
|
|
-1,
|
|
|
|
|
-1,
|
|
|
|
|
-1,
|
|
|
|
|
-1
|
|
|
|
|
};
|
2003-08-29 15:58:26 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Mapping between the general-purpose registers in FreeBSD/amd64
|
|
|
|
|
`struct reg' format and GDB's register cache layout for
|
|
|
|
|
FreeBSD/i386.
|
2003-07-13 18:15:59 +02:00
|
|
|
|
|
2003-08-29 15:58:26 +02:00
|
|
|
|
Note that most FreeBSD/amd64 registers are 64-bit, while the
|
|
|
|
|
FreeBSD/i386 registers are all 32-bit, but since we're
|
|
|
|
|
little-endian we get away with that. */
|
2003-07-13 18:15:59 +02:00
|
|
|
|
|
2003-08-29 15:58:26 +02:00
|
|
|
|
/* From <machine/reg.h>. */
|
|
|
|
|
static int amd64fbsd32_r_reg_offset[I386_NUM_GREGS] =
|
|
|
|
|
{
|
|
|
|
|
14 * 8, 13 * 8, /* %eax, %ecx */
|
|
|
|
|
12 * 8, 11 * 8, /* %edx, %ebx */
|
|
|
|
|
20 * 8, 10 * 8, /* %esp, %ebp */
|
|
|
|
|
9 * 8, 8 * 8, /* %esi, %edi */
|
|
|
|
|
17 * 8, 19 * 8, /* %eip, %eflags */
|
|
|
|
|
18 * 8, 21 * 8, /* %cs, %ss */
|
|
|
|
|
-1, -1, -1, -1 /* %ds, %es, %fs, %gs */
|
|
|
|
|
};
|
2003-07-13 18:15:59 +02:00
|
|
|
|
|
|
|
|
|
|
2004-06-27 17:44:22 +02:00
|
|
|
|
/* Support for debugging kernel virtual memory images. */
|
|
|
|
|
|
|
|
|
|
#include <machine/pcb.h>
|
2009-10-17 01:18:27 +02:00
|
|
|
|
#include <osreldate.h>
|
2004-06-27 17:44:22 +02:00
|
|
|
|
|
|
|
|
|
#include "bsd-kvm.h"
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
amd64fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
|
|
|
|
|
{
|
|
|
|
|
/* The following is true for FreeBSD 5.2:
|
|
|
|
|
|
|
|
|
|
The pcb contains %rip, %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15,
|
|
|
|
|
%ds, %es, %fs and %gs. This accounts for all callee-saved
|
|
|
|
|
registers specified by the psABI and then some. Here %esp
|
|
|
|
|
contains the stack pointer at the point just after the call to
|
|
|
|
|
cpu_switch(). From this information we reconstruct the register
|
|
|
|
|
state as it would like when we just returned from cpu_switch(). */
|
|
|
|
|
|
|
|
|
|
/* The stack pointer shouldn't be zero. */
|
|
|
|
|
if (pcb->pcb_rsp == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
pcb->pcb_rsp += 8;
|
|
|
|
|
regcache_raw_supply (regcache, AMD64_RIP_REGNUM, &pcb->pcb_rip);
|
|
|
|
|
regcache_raw_supply (regcache, AMD64_RBX_REGNUM, &pcb->pcb_rbx);
|
|
|
|
|
regcache_raw_supply (regcache, AMD64_RSP_REGNUM, &pcb->pcb_rsp);
|
|
|
|
|
regcache_raw_supply (regcache, AMD64_RBP_REGNUM, &pcb->pcb_rbp);
|
|
|
|
|
regcache_raw_supply (regcache, 12, &pcb->pcb_r12);
|
|
|
|
|
regcache_raw_supply (regcache, 13, &pcb->pcb_r13);
|
|
|
|
|
regcache_raw_supply (regcache, 14, &pcb->pcb_r14);
|
|
|
|
|
regcache_raw_supply (regcache, 15, &pcb->pcb_r15);
|
2010-02-03 16:30:25 +01:00
|
|
|
|
#if (__FreeBSD_version < 800075) && (__FreeBSD_kernel_version < 800075)
|
2009-10-19 21:48:43 +02:00
|
|
|
|
/* struct pcb provides the pcb_ds/pcb_es/pcb_fs/pcb_gs fields only
|
|
|
|
|
up until __FreeBSD_version 800074: The removal of these fields
|
|
|
|
|
occurred on 2009-04-01 while the __FreeBSD_version number was
|
|
|
|
|
bumped to 800075 on 2009-04-06. So 800075 is the closest version
|
|
|
|
|
number where we should not try to access these fields. */
|
2004-06-27 17:44:22 +02:00
|
|
|
|
regcache_raw_supply (regcache, AMD64_DS_REGNUM, &pcb->pcb_ds);
|
|
|
|
|
regcache_raw_supply (regcache, AMD64_ES_REGNUM, &pcb->pcb_es);
|
|
|
|
|
regcache_raw_supply (regcache, AMD64_FS_REGNUM, &pcb->pcb_fs);
|
|
|
|
|
regcache_raw_supply (regcache, AMD64_GS_REGNUM, &pcb->pcb_gs);
|
2009-10-17 01:18:27 +02:00
|
|
|
|
#endif
|
2004-06-27 17:44:22 +02:00
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
[native x86 GNU/Linux] Access debug register mirror from the corresponding process.
While reviewing the native AArch64 patch, I noticed a problem:
On 02/06/2013 08:46 PM, Pedro Alves wrote:
>
>> > +static void
>> > +aarch64_linux_prepare_to_resume (struct lwp_info *lwp)
>> > +{
>> > + struct arch_lwp_info *info = lwp->arch_private;
>> > +
>> > + /* NULL means this is the main thread still going through the shell,
>> > + or, no watchpoint has been set yet. In that case, there's
>> > + nothing to do. */
>> > + if (info == NULL)
>> > + return;
>> > +
>> > + if (DR_HAS_CHANGED (info->dr_changed_bp)
>> > + || DR_HAS_CHANGED (info->dr_changed_wp))
>> > + {
>> > + int tid = GET_LWP (lwp->ptid);
>> > + struct aarch64_debug_reg_state *state = aarch64_get_debug_reg_state ();
> Hmm. This is always fetching the debug_reg_state of
> the current inferior, but may not be the inferior of lwp.
> I see the same bug on x86. Sorry about that. I'll fix it.
A natural fix would be to make xxx_get_debug_reg_state take an
inferior argument, but that doesn't work because of the case where we
detach breakpoints/watchpoints from the child fork, at a time there's
no inferior for the child fork at all. We do a nasty hack in
i386_inferior_data_get, but that relies on all callers pointing the
current inferior to the correct inferior, which isn't actually being
done by all callers, and I don't think we want to enforce that -- deep
in the bowls of linux-nat.c, there are many cases we resume lwps
behind the scenes, and it's be better to not have that code rely on
global state (as it doesn't today).
The fix is to decouple the watchpoints code from inferiors, making it
track target processes instead. This way, we can freely keep track of
the watchpoint mirrors for these processes behind the core's back.
Checkpoints also play dirty tricks with swapping the process behind
the inferior, so they get special treatment too in the patch (which
just amounts to calling a new hook). Instead of the old hack in
i386_inferior_data_get, where we returned a copy of the current
inferior's debug registers mirror, as soon as we detect a fork in the
target, we copy the debug register mirror from the parent to the child
process.
I don't have an old kernel handy to test, but I stepped through gdb doing
the watchpoint removal in the fork child in the watchpoint-fork test
seeing that the debug registers end up cleared in the child.
I didn't find the need for linux_nat_iterate_watchpoint_lwps. If
we use plain iterate_over_lwps instead, what happens is that
when removing watchpoints, that iterate_over_lwps doesn't actually
iterate over anything, since the fork child is not added to the
lwp list until later, at detach time, in linux_child_follow_fork.
And if we don't iterate over that lwp, we don't mark its debug
registers as needing update. But linux_child_follow_fork takes
care of doing that explicitly:
child_lp = add_lwp (inferior_ptid);
child_lp->stopped = 1;
child_lp->last_resume_kind = resume_stop;
make_cleanup (delete_lwp_cleanup, child_lp);
/* CHILD_LP has new PID, therefore linux_nat_new_thread is not called for it.
See i386_inferior_data_get for the Linux kernel specifics.
Ensure linux_nat_prepare_to_resume will reset the hardware debug
registers. It is done by the linux_nat_new_thread call, which is
being skipped in add_lwp above for the first lwp of a pid. */
gdb_assert (num_lwps (GET_PID (child_lp->ptid)) == 1);
if (linux_nat_new_thread != NULL)
linux_nat_new_thread (child_lp);
if (linux_nat_prepare_to_resume != NULL)
linux_nat_prepare_to_resume (child_lp);
ptrace (PTRACE_DETACH, child_pid, 0, 0);
so unless I'm missing something (quite possible) it ends up all
the same. But, the !detach-on-fork, and the "follow-fork child" paths
should also call linux_nat_new_thread, and they don't presently. It
seems to me in those cases we're not clearing debug regs correctly
when that's needed. Instead of copying that bit that works around
add_lwp bypassing the linux_nat_new_thread call, I thought it'd
be better to add an add_initial_lwp call to be used in the case we
really need to bypass linux_nat_new_thread, and make
add_lwp always call linux_nat_new_thread.
i386_cleanup_dregs is rewritten to forget about the current process
debug mirrors, which takes cares of other i386 ports. Only a couple
of extra tweaks here and there were needed, as some targets wheren't
actually calling i386_cleanup_dregs.
Tested on Fedora 17 x86_64 -m64/-m32.
GDBserver already fetches the i386_debug_reg_state from the right
process, and, it doesn't handle forks at all, so no fix is needed over
there.
gdb/
2013-02-13 Pedro Alves <palves@redhat.com>
* amd64-linux-nat.c (update_debug_registers_callback):
Update comment.
(amd64_linux_dr_set_control, amd64_linux_dr_set_addr): Use
iterate_over_lwps.
(amd64_linux_prepare_to_resume): Pass the lwp's pid to
i386_debug_reg_state.
(amd64_linux_new_fork): New function.
(_initialize_amd64_linux_nat): Install amd64_linux_new_fork as
linux_nat_new_fork hook, and i386_forget_process as
linux_nat_forget_process hook.
* i386-linux-nat.c (update_debug_registers_callback):
Update comment.
(amd64_linux_dr_set_control, amd64_linux_dr_set_addr): Use
iterate_over_lwps.
(i386_linux_prepare_to_resume): Pass the lwp's pid to
i386_debug_reg_state.
(i386_linux_new_fork): New function.
(_initialize_i386_linux_nat): Install i386_linux_new_fork as
linux_nat_new_fork hook, and i386_forget_process as
linux_nat_forget_process hook.
* i386-nat.c (i386_init_dregs): Delete.
(i386_inferior_data, struct i386_inferior_data):
Delete.
(struct i386_process_info): New.
(i386_process_list): New global.
(i386_find_process_pid, i386_add_process, i386_process_info_get):
New functions.
(i386_inferior_data_get): Delete.
(i386_process_info_get): New function.
(i386_debug_reg_state): New parameter 'pid'. Reimplement.
(i386_forget_process): New function.
(i386_cleanup_dregs): Rewrite.
(i386_update_inferior_debug_regs, i386_insert_watchpoint)
(i386_remove_watchpoint, i386_region_ok_for_watchpoint)
(i386_stopped_data_address, i386_insert_hw_breakpoint)
(i386_remove_hw_breakpoint): Adjust to pass the current process id
to i386_debug_reg_state.
(i386_use_watchpoints): Don't register inferior data.
* i386-nat.h (i386_debug_reg_state): Add new 'pid' parameter, and
adjust comment.
(i386_forget_process): Declare.
* linux-fork.c (delete_fork): Call linux_nat_forget_process.
* linux-nat.c (linux_nat_new_fork, linux_nat_forget_process_hook):
New static globals.
(linux_child_follow_fork): Don't call linux_nat_new_thread here.
(add_initial_lwp): New, factored out from ...
(add_lwp): ... this. Don't check the number of lwps before
calling linux_nat_new_thread.
(linux_nat_iterate_watchpoint_lwps): Delete.
(linux_nat_attach): Use add_initial_lwp instead of add_lwp.
(linux_handle_extended_wait): Call the linux_nat_new_fork hook on
forks and vforks.
(linux_nat_wait_1): Use add_initial_lwp instead of add_lwp for the
initial lwp.
(linux_nat_kill, linux_nat_mourn_inferior): Call
linux_nat_forget_process.
(linux_nat_set_new_fork, linux_nat_set_forget_process)
(linux_nat_forget_process): New functions.
* linux-nat.h (linux_nat_iterate_watchpoint_lwps_ftype): Delete
type.
(linux_nat_iterate_watchpoint_lwps): Delete declaration.
(linux_nat_new_fork_ftype, linux_nat_forget_process_ftype): New
types.
(linux_nat_set_new_fork, linux_nat_set_forget_process)
(linux_nat_forget_process): New declarations.
* amd64fbsd-nat.c (super_mourn_inferior): New global.
(amd64fbsd_mourn_inferior): New function.
(_initialize_amd64fbsd_nat): Override to_mourn_inferior.
* windows-nat.c (windows_detach): Call i386_cleanup_dregs.
2013-02-13 15:59:49 +01:00
|
|
|
|
static void (*super_mourn_inferior) (struct target_ops *ops);
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
amd64fbsd_mourn_inferior (struct target_ops *ops)
|
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_PT_GETDBREGS
|
|
|
|
|
i386_cleanup_dregs ();
|
|
|
|
|
#endif
|
|
|
|
|
super_mourn_inferior (ops);
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-13 18:15:59 +02:00
|
|
|
|
/* Provide a prototype to silence -Wmissing-prototypes. */
|
|
|
|
|
void _initialize_amd64fbsd_nat (void);
|
|
|
|
|
|
|
|
|
|
void
|
2003-09-15 21:30:50 +02:00
|
|
|
|
_initialize_amd64fbsd_nat (void)
|
2003-07-13 18:15:59 +02:00
|
|
|
|
{
|
2004-09-26 20:42:30 +02:00
|
|
|
|
struct target_ops *t;
|
2003-07-13 18:15:59 +02:00
|
|
|
|
int offset;
|
|
|
|
|
|
2003-08-29 15:58:26 +02:00
|
|
|
|
amd64_native_gregset32_reg_offset = amd64fbsd32_r_reg_offset;
|
2004-06-26 13:47:53 +02:00
|
|
|
|
amd64_native_gregset64_reg_offset = amd64fbsd64_r_reg_offset;
|
2003-08-29 15:58:26 +02:00
|
|
|
|
|
2004-09-26 20:42:30 +02:00
|
|
|
|
/* Add some extra features to the common *BSD/i386 target. */
|
|
|
|
|
t = amd64bsd_target ();
|
2012-02-09 17:06:44 +01:00
|
|
|
|
|
|
|
|
|
#ifdef HAVE_PT_GETDBREGS
|
|
|
|
|
|
|
|
|
|
i386_use_watchpoints (t);
|
|
|
|
|
|
|
|
|
|
i386_dr_low.set_control = amd64bsd_dr_set_control;
|
|
|
|
|
i386_dr_low.set_addr = amd64bsd_dr_set_addr;
|
|
|
|
|
i386_dr_low.get_addr = amd64bsd_dr_get_addr;
|
|
|
|
|
i386_dr_low.get_status = amd64bsd_dr_get_status;
|
|
|
|
|
i386_dr_low.get_control = amd64bsd_dr_get_control;
|
|
|
|
|
i386_set_debug_register_length (8);
|
|
|
|
|
|
|
|
|
|
#endif /* HAVE_PT_GETDBREGS */
|
|
|
|
|
|
[native x86 GNU/Linux] Access debug register mirror from the corresponding process.
While reviewing the native AArch64 patch, I noticed a problem:
On 02/06/2013 08:46 PM, Pedro Alves wrote:
>
>> > +static void
>> > +aarch64_linux_prepare_to_resume (struct lwp_info *lwp)
>> > +{
>> > + struct arch_lwp_info *info = lwp->arch_private;
>> > +
>> > + /* NULL means this is the main thread still going through the shell,
>> > + or, no watchpoint has been set yet. In that case, there's
>> > + nothing to do. */
>> > + if (info == NULL)
>> > + return;
>> > +
>> > + if (DR_HAS_CHANGED (info->dr_changed_bp)
>> > + || DR_HAS_CHANGED (info->dr_changed_wp))
>> > + {
>> > + int tid = GET_LWP (lwp->ptid);
>> > + struct aarch64_debug_reg_state *state = aarch64_get_debug_reg_state ();
> Hmm. This is always fetching the debug_reg_state of
> the current inferior, but may not be the inferior of lwp.
> I see the same bug on x86. Sorry about that. I'll fix it.
A natural fix would be to make xxx_get_debug_reg_state take an
inferior argument, but that doesn't work because of the case where we
detach breakpoints/watchpoints from the child fork, at a time there's
no inferior for the child fork at all. We do a nasty hack in
i386_inferior_data_get, but that relies on all callers pointing the
current inferior to the correct inferior, which isn't actually being
done by all callers, and I don't think we want to enforce that -- deep
in the bowls of linux-nat.c, there are many cases we resume lwps
behind the scenes, and it's be better to not have that code rely on
global state (as it doesn't today).
The fix is to decouple the watchpoints code from inferiors, making it
track target processes instead. This way, we can freely keep track of
the watchpoint mirrors for these processes behind the core's back.
Checkpoints also play dirty tricks with swapping the process behind
the inferior, so they get special treatment too in the patch (which
just amounts to calling a new hook). Instead of the old hack in
i386_inferior_data_get, where we returned a copy of the current
inferior's debug registers mirror, as soon as we detect a fork in the
target, we copy the debug register mirror from the parent to the child
process.
I don't have an old kernel handy to test, but I stepped through gdb doing
the watchpoint removal in the fork child in the watchpoint-fork test
seeing that the debug registers end up cleared in the child.
I didn't find the need for linux_nat_iterate_watchpoint_lwps. If
we use plain iterate_over_lwps instead, what happens is that
when removing watchpoints, that iterate_over_lwps doesn't actually
iterate over anything, since the fork child is not added to the
lwp list until later, at detach time, in linux_child_follow_fork.
And if we don't iterate over that lwp, we don't mark its debug
registers as needing update. But linux_child_follow_fork takes
care of doing that explicitly:
child_lp = add_lwp (inferior_ptid);
child_lp->stopped = 1;
child_lp->last_resume_kind = resume_stop;
make_cleanup (delete_lwp_cleanup, child_lp);
/* CHILD_LP has new PID, therefore linux_nat_new_thread is not called for it.
See i386_inferior_data_get for the Linux kernel specifics.
Ensure linux_nat_prepare_to_resume will reset the hardware debug
registers. It is done by the linux_nat_new_thread call, which is
being skipped in add_lwp above for the first lwp of a pid. */
gdb_assert (num_lwps (GET_PID (child_lp->ptid)) == 1);
if (linux_nat_new_thread != NULL)
linux_nat_new_thread (child_lp);
if (linux_nat_prepare_to_resume != NULL)
linux_nat_prepare_to_resume (child_lp);
ptrace (PTRACE_DETACH, child_pid, 0, 0);
so unless I'm missing something (quite possible) it ends up all
the same. But, the !detach-on-fork, and the "follow-fork child" paths
should also call linux_nat_new_thread, and they don't presently. It
seems to me in those cases we're not clearing debug regs correctly
when that's needed. Instead of copying that bit that works around
add_lwp bypassing the linux_nat_new_thread call, I thought it'd
be better to add an add_initial_lwp call to be used in the case we
really need to bypass linux_nat_new_thread, and make
add_lwp always call linux_nat_new_thread.
i386_cleanup_dregs is rewritten to forget about the current process
debug mirrors, which takes cares of other i386 ports. Only a couple
of extra tweaks here and there were needed, as some targets wheren't
actually calling i386_cleanup_dregs.
Tested on Fedora 17 x86_64 -m64/-m32.
GDBserver already fetches the i386_debug_reg_state from the right
process, and, it doesn't handle forks at all, so no fix is needed over
there.
gdb/
2013-02-13 Pedro Alves <palves@redhat.com>
* amd64-linux-nat.c (update_debug_registers_callback):
Update comment.
(amd64_linux_dr_set_control, amd64_linux_dr_set_addr): Use
iterate_over_lwps.
(amd64_linux_prepare_to_resume): Pass the lwp's pid to
i386_debug_reg_state.
(amd64_linux_new_fork): New function.
(_initialize_amd64_linux_nat): Install amd64_linux_new_fork as
linux_nat_new_fork hook, and i386_forget_process as
linux_nat_forget_process hook.
* i386-linux-nat.c (update_debug_registers_callback):
Update comment.
(amd64_linux_dr_set_control, amd64_linux_dr_set_addr): Use
iterate_over_lwps.
(i386_linux_prepare_to_resume): Pass the lwp's pid to
i386_debug_reg_state.
(i386_linux_new_fork): New function.
(_initialize_i386_linux_nat): Install i386_linux_new_fork as
linux_nat_new_fork hook, and i386_forget_process as
linux_nat_forget_process hook.
* i386-nat.c (i386_init_dregs): Delete.
(i386_inferior_data, struct i386_inferior_data):
Delete.
(struct i386_process_info): New.
(i386_process_list): New global.
(i386_find_process_pid, i386_add_process, i386_process_info_get):
New functions.
(i386_inferior_data_get): Delete.
(i386_process_info_get): New function.
(i386_debug_reg_state): New parameter 'pid'. Reimplement.
(i386_forget_process): New function.
(i386_cleanup_dregs): Rewrite.
(i386_update_inferior_debug_regs, i386_insert_watchpoint)
(i386_remove_watchpoint, i386_region_ok_for_watchpoint)
(i386_stopped_data_address, i386_insert_hw_breakpoint)
(i386_remove_hw_breakpoint): Adjust to pass the current process id
to i386_debug_reg_state.
(i386_use_watchpoints): Don't register inferior data.
* i386-nat.h (i386_debug_reg_state): Add new 'pid' parameter, and
adjust comment.
(i386_forget_process): Declare.
* linux-fork.c (delete_fork): Call linux_nat_forget_process.
* linux-nat.c (linux_nat_new_fork, linux_nat_forget_process_hook):
New static globals.
(linux_child_follow_fork): Don't call linux_nat_new_thread here.
(add_initial_lwp): New, factored out from ...
(add_lwp): ... this. Don't check the number of lwps before
calling linux_nat_new_thread.
(linux_nat_iterate_watchpoint_lwps): Delete.
(linux_nat_attach): Use add_initial_lwp instead of add_lwp.
(linux_handle_extended_wait): Call the linux_nat_new_fork hook on
forks and vforks.
(linux_nat_wait_1): Use add_initial_lwp instead of add_lwp for the
initial lwp.
(linux_nat_kill, linux_nat_mourn_inferior): Call
linux_nat_forget_process.
(linux_nat_set_new_fork, linux_nat_set_forget_process)
(linux_nat_forget_process): New functions.
* linux-nat.h (linux_nat_iterate_watchpoint_lwps_ftype): Delete
type.
(linux_nat_iterate_watchpoint_lwps): Delete declaration.
(linux_nat_new_fork_ftype, linux_nat_forget_process_ftype): New
types.
(linux_nat_set_new_fork, linux_nat_set_forget_process)
(linux_nat_forget_process): New declarations.
* amd64fbsd-nat.c (super_mourn_inferior): New global.
(amd64fbsd_mourn_inferior): New function.
(_initialize_amd64fbsd_nat): Override to_mourn_inferior.
* windows-nat.c (windows_detach): Call i386_cleanup_dregs.
2013-02-13 15:59:49 +01:00
|
|
|
|
super_mourn_inferior = t->to_mourn_inferior;
|
|
|
|
|
t->to_mourn_inferior = amd64fbsd_mourn_inferior;
|
|
|
|
|
|
2004-09-26 20:42:30 +02:00
|
|
|
|
t->to_pid_to_exec_file = fbsd_pid_to_exec_file;
|
|
|
|
|
t->to_find_memory_regions = fbsd_find_memory_regions;
|
|
|
|
|
t->to_make_corefile_notes = fbsd_make_corefile_notes;
|
|
|
|
|
add_target (t);
|
|
|
|
|
|
|
|
|
|
/* Support debugging kernel virtual memory images. */
|
|
|
|
|
bsd_kvm_add_target (amd64fbsd_supply_pcb);
|
|
|
|
|
|
2003-07-13 18:15:59 +02:00
|
|
|
|
/* To support the recognition of signal handlers, i386bsd-tdep.c
|
|
|
|
|
hardcodes some constants. Inclusion of this file means that we
|
|
|
|
|
are compiling a native debugger, which means that we can use the
|
|
|
|
|
system header files and sysctl(3) to get at the relevant
|
|
|
|
|
information. */
|
|
|
|
|
|
|
|
|
|
#define SC_REG_OFFSET amd64fbsd_sc_reg_offset
|
|
|
|
|
|
|
|
|
|
/* We only check the program counter, stack pointer and frame
|
|
|
|
|
pointer since these members of `struct sigcontext' are essential
|
|
|
|
|
for providing backtraces. */
|
|
|
|
|
|
* x86-64-tdep.h: Tewak comment.
(enum amd64_regnum): New.
(X86_64_RAX_REGNUM, X86_64_RDX_REGNUM, X86_64_RDI_REGNUM)
(X86_64_RBP_REGNUM, X86_64_RSP_REGNUM, X86_64_RIP_REGNUM)
(X86_64_EFLAGS_REGNUM, X86_64_ST0_REGNUM, X86_64_XMM0_REGNUM)
(X86_64_XMM1_REGNUM): Removed.
(AMD64_NUM_GREGS): Renamed from X86_64_NUM_GREGS.
(amd64_init_abi, amd64_supply_fxsave, amd64_fill_fxsave): Adjust
prototypes for renamed functions.
* x86-64-tdep.c: Fix typo.
(amd64_dwarf_regmap): Use constants from `enum amd64_regnum' for
register numbers.
(amd64_return_value, amd64_push_arguments, amd64_push_dummy_call):
Use constants from `enum amd64_regnum' for register numbers.
(AMD64_NUM_SAVED_REGS): Adjust for renamed macros.
(amd64_analyze_prologue, amd64_frame_cache,
amd64_sigtramp_frame_cache): Use constants from `enum
amd64_regnum' for register numbers.
(amd64_supply_fpregset): Adjust for renamed functions.
(amd64_init_abi): Rename from x86_64_init_abi. Use constants from
`enum amd64_regnum' for register numbers.
(I387_ST0_REGNUM): Use constant from `enum amd64_regnum'.
(amd64_supply_fxsave): Rename from x86_64_supply_fxsave.
(amd64_fill_fxsave): Rename fro x86_64_fill_fxsave.
* x86-64-linux-tdep.c (amd64_linux_supply_gregset)
(amd64_linux_fill_gregset): Adjust for renamed macros.
(fetch_core_registers): Adjust for renamed functions.
(amd64_linux_init_abi): Adjust for renamed functions.
* x86-64-linux-nat.c (supply_gregset, fill_gregset): Adjust for
renamed functions.
* amd64-nat.c: Adjust for renamed macros.
* amd64bsd-nat.c (fetch_inferior_registers)
(store_inferior_registers): Use constants from `enum amd64_regnum'
for register numbers. Adjust for renamed variables.
* amd64fbsd-nat.c (supply_gregset, fill_gregset): Adjust for
renamed variables.
(_initialize_amd64fbsd_nat): Use constants from `enum
amd64_regnum' for register numbers.
* amd64fbsd-tdep.c (amd64fbsd_sigcontext_addr): Use constants from
`enum amd64_regnum' for register numbers.
(amd64fbsd_init_abi): Adjust for renamed functions.
* amd64nbsd-tdep.c (amd64nbsd_sigcontext_addr): Use constants from
`enum amd64_regnum' for register numbers.
(amd64nbsd_init_abi): Adjust for renamed functions.
(_initialize_amd64nbsd_ndep): Adjust for renamed macros.
* amd64obsd-tdep.c (amd64obsd_sigcontext_addr): Use constants from
`enum amd64_regnum' for register numbers.
(amd64obsd_init_abi): Adjust for renamed functions.
(_initialize_amd64obsd_ndep): Adjust for renamed macros.
2004-02-23 22:37:52 +01:00
|
|
|
|
#define SC_RIP_OFFSET SC_REG_OFFSET[AMD64_RIP_REGNUM]
|
|
|
|
|
#define SC_RSP_OFFSET SC_REG_OFFSET[AMD64_RSP_REGNUM]
|
|
|
|
|
#define SC_RBP_OFFSET SC_REG_OFFSET[AMD64_RBP_REGNUM]
|
2003-07-13 18:15:59 +02:00
|
|
|
|
|
|
|
|
|
/* Override the default value for the offset of the program counter
|
|
|
|
|
in the sigcontext structure. */
|
|
|
|
|
offset = offsetof (struct sigcontext, sc_rip);
|
|
|
|
|
|
|
|
|
|
if (SC_RIP_OFFSET != offset)
|
|
|
|
|
{
|
2005-01-05 Baurjan Ismagulov <ibr@ata.cs.hun.edu.tr>
Committed by Andrew Cagney.
* ada-valprint.c, aix-thread.c, alpha-nat.c: I18n markup.
* alphabsd-nat.c, alphanbsd-tdep.c, amd64-linux-nat.c: I18n markup.
* amd64-tdep.c, amd64bsd-nat.c, amd64fbsd-nat.c: I18n markup.
* arch-utils.c, arm-linux-nat.c, arm-tdep.c: I18n markup.
* armnbsd-nat.c, armnbsd-tdep.c, auxv.c, avr-tdep.c: I18n markup.
* aix-thread.c (_initialize_aix_thread): Get rid of the
deprecated_add_show_from_set call.
* alpha-tdep.c (_initialize_alpha_tdep): Ditto.
* arm-tdep.c (_initialize_arm_tdep): Ditto.
* command.h (add_setshow_enum_cmd): Add arguments for returning
new list elements.
* cli/cli-decode.c (add_setshow_enum_cmd): Ditto.
* mips-tdep.c (_initialize_mips_tdep): Modify calls to
add_setshow_enum_cmd.
2005-01-05 16:43:50 +01:00
|
|
|
|
warning (_("\
|
2003-07-13 18:15:59 +02:00
|
|
|
|
offsetof (struct sigcontext, sc_rip) yields %d instead of %d.\n\
|
2005-01-05 Baurjan Ismagulov <ibr@ata.cs.hun.edu.tr>
Committed by Andrew Cagney.
* ada-valprint.c, aix-thread.c, alpha-nat.c: I18n markup.
* alphabsd-nat.c, alphanbsd-tdep.c, amd64-linux-nat.c: I18n markup.
* amd64-tdep.c, amd64bsd-nat.c, amd64fbsd-nat.c: I18n markup.
* arch-utils.c, arm-linux-nat.c, arm-tdep.c: I18n markup.
* armnbsd-nat.c, armnbsd-tdep.c, auxv.c, avr-tdep.c: I18n markup.
* aix-thread.c (_initialize_aix_thread): Get rid of the
deprecated_add_show_from_set call.
* alpha-tdep.c (_initialize_alpha_tdep): Ditto.
* arm-tdep.c (_initialize_arm_tdep): Ditto.
* command.h (add_setshow_enum_cmd): Add arguments for returning
new list elements.
* cli/cli-decode.c (add_setshow_enum_cmd): Ditto.
* mips-tdep.c (_initialize_mips_tdep): Modify calls to
add_setshow_enum_cmd.
2005-01-05 16:43:50 +01:00
|
|
|
|
Please report this to <bug-gdb@gnu.org>."),
|
2003-07-13 18:15:59 +02:00
|
|
|
|
offset, SC_RIP_OFFSET);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SC_RIP_OFFSET = offset;
|
|
|
|
|
|
|
|
|
|
/* Likewise for the stack pointer. */
|
|
|
|
|
offset = offsetof (struct sigcontext, sc_rsp);
|
|
|
|
|
|
|
|
|
|
if (SC_RSP_OFFSET != offset)
|
|
|
|
|
{
|
2005-01-05 Baurjan Ismagulov <ibr@ata.cs.hun.edu.tr>
Committed by Andrew Cagney.
* ada-valprint.c, aix-thread.c, alpha-nat.c: I18n markup.
* alphabsd-nat.c, alphanbsd-tdep.c, amd64-linux-nat.c: I18n markup.
* amd64-tdep.c, amd64bsd-nat.c, amd64fbsd-nat.c: I18n markup.
* arch-utils.c, arm-linux-nat.c, arm-tdep.c: I18n markup.
* armnbsd-nat.c, armnbsd-tdep.c, auxv.c, avr-tdep.c: I18n markup.
* aix-thread.c (_initialize_aix_thread): Get rid of the
deprecated_add_show_from_set call.
* alpha-tdep.c (_initialize_alpha_tdep): Ditto.
* arm-tdep.c (_initialize_arm_tdep): Ditto.
* command.h (add_setshow_enum_cmd): Add arguments for returning
new list elements.
* cli/cli-decode.c (add_setshow_enum_cmd): Ditto.
* mips-tdep.c (_initialize_mips_tdep): Modify calls to
add_setshow_enum_cmd.
2005-01-05 16:43:50 +01:00
|
|
|
|
warning (_("\
|
2003-07-13 18:15:59 +02:00
|
|
|
|
offsetof (struct sigcontext, sc_rsp) yields %d instead of %d.\n\
|
2005-01-05 Baurjan Ismagulov <ibr@ata.cs.hun.edu.tr>
Committed by Andrew Cagney.
* ada-valprint.c, aix-thread.c, alpha-nat.c: I18n markup.
* alphabsd-nat.c, alphanbsd-tdep.c, amd64-linux-nat.c: I18n markup.
* amd64-tdep.c, amd64bsd-nat.c, amd64fbsd-nat.c: I18n markup.
* arch-utils.c, arm-linux-nat.c, arm-tdep.c: I18n markup.
* armnbsd-nat.c, armnbsd-tdep.c, auxv.c, avr-tdep.c: I18n markup.
* aix-thread.c (_initialize_aix_thread): Get rid of the
deprecated_add_show_from_set call.
* alpha-tdep.c (_initialize_alpha_tdep): Ditto.
* arm-tdep.c (_initialize_arm_tdep): Ditto.
* command.h (add_setshow_enum_cmd): Add arguments for returning
new list elements.
* cli/cli-decode.c (add_setshow_enum_cmd): Ditto.
* mips-tdep.c (_initialize_mips_tdep): Modify calls to
add_setshow_enum_cmd.
2005-01-05 16:43:50 +01:00
|
|
|
|
Please report this to <bug-gdb@gnu.org>."),
|
2003-07-13 18:15:59 +02:00
|
|
|
|
offset, SC_RSP_OFFSET);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SC_RSP_OFFSET = offset;
|
|
|
|
|
|
|
|
|
|
/* And the frame pointer. */
|
|
|
|
|
offset = offsetof (struct sigcontext, sc_rbp);
|
|
|
|
|
|
|
|
|
|
if (SC_RBP_OFFSET != offset)
|
|
|
|
|
{
|
2005-01-05 Baurjan Ismagulov <ibr@ata.cs.hun.edu.tr>
Committed by Andrew Cagney.
* ada-valprint.c, aix-thread.c, alpha-nat.c: I18n markup.
* alphabsd-nat.c, alphanbsd-tdep.c, amd64-linux-nat.c: I18n markup.
* amd64-tdep.c, amd64bsd-nat.c, amd64fbsd-nat.c: I18n markup.
* arch-utils.c, arm-linux-nat.c, arm-tdep.c: I18n markup.
* armnbsd-nat.c, armnbsd-tdep.c, auxv.c, avr-tdep.c: I18n markup.
* aix-thread.c (_initialize_aix_thread): Get rid of the
deprecated_add_show_from_set call.
* alpha-tdep.c (_initialize_alpha_tdep): Ditto.
* arm-tdep.c (_initialize_arm_tdep): Ditto.
* command.h (add_setshow_enum_cmd): Add arguments for returning
new list elements.
* cli/cli-decode.c (add_setshow_enum_cmd): Ditto.
* mips-tdep.c (_initialize_mips_tdep): Modify calls to
add_setshow_enum_cmd.
2005-01-05 16:43:50 +01:00
|
|
|
|
warning (_("\
|
2003-07-13 18:15:59 +02:00
|
|
|
|
offsetof (struct sigcontext, sc_rbp) yields %d instead of %d.\n\
|
2005-01-05 Baurjan Ismagulov <ibr@ata.cs.hun.edu.tr>
Committed by Andrew Cagney.
* ada-valprint.c, aix-thread.c, alpha-nat.c: I18n markup.
* alphabsd-nat.c, alphanbsd-tdep.c, amd64-linux-nat.c: I18n markup.
* amd64-tdep.c, amd64bsd-nat.c, amd64fbsd-nat.c: I18n markup.
* arch-utils.c, arm-linux-nat.c, arm-tdep.c: I18n markup.
* armnbsd-nat.c, armnbsd-tdep.c, auxv.c, avr-tdep.c: I18n markup.
* aix-thread.c (_initialize_aix_thread): Get rid of the
deprecated_add_show_from_set call.
* alpha-tdep.c (_initialize_alpha_tdep): Ditto.
* arm-tdep.c (_initialize_arm_tdep): Ditto.
* command.h (add_setshow_enum_cmd): Add arguments for returning
new list elements.
* cli/cli-decode.c (add_setshow_enum_cmd): Ditto.
* mips-tdep.c (_initialize_mips_tdep): Modify calls to
add_setshow_enum_cmd.
2005-01-05 16:43:50 +01:00
|
|
|
|
Please report this to <bug-gdb@gnu.org>."),
|
2003-07-13 18:15:59 +02:00
|
|
|
|
offset, SC_RBP_OFFSET);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SC_RBP_OFFSET = offset;
|
|
|
|
|
|
|
|
|
|
/* FreeBSD provides a kern.ps_strings sysctl that we can use to
|
|
|
|
|
locate the sigtramp. That way we can still recognize a sigtramp
|
|
|
|
|
if its location is changed in a new kernel. Of course this is
|
|
|
|
|
still based on the assumption that the sigtramp is placed
|
|
|
|
|
directly under the location where the program arguments and
|
|
|
|
|
environment can be found. */
|
|
|
|
|
{
|
|
|
|
|
int mib[2];
|
2003-09-15 22:05:17 +02:00
|
|
|
|
long ps_strings;
|
2003-07-13 18:15:59 +02:00
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
|
|
mib[0] = CTL_KERN;
|
|
|
|
|
mib[1] = KERN_PS_STRINGS;
|
|
|
|
|
len = sizeof (ps_strings);
|
|
|
|
|
if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
|
|
|
|
|
{
|
2004-02-22 20:14:55 +01:00
|
|
|
|
amd64fbsd_sigtramp_start_addr = ps_strings - 32;
|
|
|
|
|
amd64fbsd_sigtramp_end_addr = ps_strings;
|
2003-07-13 18:15:59 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|