2009-07-03 14:06:36 +02:00
|
|
|
/* Darwin support for GDB, the GNU debugger.
|
2017-01-01 07:50:51 +01:00
|
|
|
Copyright (C) 1997-2017 Free Software Foundation, Inc.
|
2009-07-03 14:06:36 +02:00
|
|
|
|
|
|
|
Contributed by Apple Computer, 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 "frame.h"
|
|
|
|
#include "inferior.h"
|
|
|
|
#include "gdbcore.h"
|
|
|
|
#include "target.h"
|
|
|
|
#include "floatformat.h"
|
|
|
|
#include "symtab.h"
|
|
|
|
#include "regcache.h"
|
|
|
|
#include "objfiles.h"
|
|
|
|
|
|
|
|
#include "i387-tdep.h"
|
|
|
|
#include "amd64-tdep.h"
|
|
|
|
#include "osabi.h"
|
|
|
|
#include "ui-out.h"
|
|
|
|
#include "amd64-darwin-tdep.h"
|
|
|
|
#include "i386-darwin-tdep.h"
|
|
|
|
#include "solib.h"
|
|
|
|
#include "solib-darwin.h"
|
|
|
|
#include "dwarf2-frame.h"
|
|
|
|
|
|
|
|
/* Offsets into the struct x86_thread_state64 where we'll find the saved regs.
|
|
|
|
From <mach/i386/thread_status.h> and amd64-tdep.h. */
|
|
|
|
int amd64_darwin_thread_state_reg_offset[] =
|
|
|
|
{
|
|
|
|
0 * 8, /* %rax */
|
|
|
|
1 * 8, /* %rbx */
|
|
|
|
2 * 8, /* %rcx */
|
|
|
|
3 * 8, /* %rdx */
|
|
|
|
5 * 8, /* %rsi */
|
|
|
|
4 * 8, /* %rdi */
|
|
|
|
6 * 8, /* %rbp */
|
|
|
|
7 * 8, /* %rsp */
|
2011-01-07 20:36:19 +01:00
|
|
|
8 * 8, /* %r8 ... */
|
2009-07-03 14:06:36 +02:00
|
|
|
9 * 8,
|
|
|
|
10 * 8,
|
|
|
|
11 * 8,
|
|
|
|
12 * 8,
|
|
|
|
13 * 8,
|
|
|
|
14 * 8,
|
|
|
|
15 * 8, /* ... %r15 */
|
|
|
|
16 * 8, /* %rip */
|
|
|
|
17 * 8, /* %rflags */
|
|
|
|
18 * 8, /* %cs */
|
|
|
|
-1, /* %ss */
|
|
|
|
-1, /* %ds */
|
|
|
|
-1, /* %es */
|
|
|
|
19 * 8, /* %fs */
|
|
|
|
20 * 8 /* %gs */
|
|
|
|
};
|
|
|
|
|
|
|
|
const int amd64_darwin_thread_state_num_regs =
|
|
|
|
ARRAY_SIZE (amd64_darwin_thread_state_reg_offset);
|
|
|
|
|
|
|
|
/* Assuming THIS_FRAME is a Darwin sigtramp routine, return the
|
|
|
|
address of the associated sigcontext structure. */
|
|
|
|
|
|
|
|
static CORE_ADDR
|
|
|
|
amd64_darwin_sigcontext_addr (struct frame_info *this_frame)
|
|
|
|
{
|
|
|
|
struct gdbarch *gdbarch = get_frame_arch (this_frame);
|
|
|
|
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
|
|
|
CORE_ADDR rbx;
|
|
|
|
gdb_byte buf[8];
|
|
|
|
|
|
|
|
/* A pointer to the ucontext is passed as the fourth argument
|
|
|
|
to the signal handler, which is saved in rbx. */
|
|
|
|
get_frame_register (this_frame, AMD64_RBX_REGNUM, buf);
|
|
|
|
rbx = extract_unsigned_integer (buf, 8, byte_order);
|
|
|
|
|
|
|
|
/* The pointer to mcontext is at offset 48. */
|
|
|
|
read_memory (rbx + 48, buf, 8);
|
|
|
|
|
|
|
|
/* First register (rax) is at offset 16. */
|
|
|
|
return extract_unsigned_integer (buf, 8, byte_order) + 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
x86_darwin_init_abi_64 (struct gdbarch_info info, struct gdbarch *gdbarch)
|
|
|
|
{
|
|
|
|
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
|
|
|
Fix x86-64 GNU/Linux crashes
Ref: https://sourceware.org/ml/gdb-patches/2017-07/msg00162.html
Debugging x86-64 GNU/Linux programs currently crashes GDB in
tdesc_use_registers during gdbarch initialization:
Program received signal SIGSEGV, Segmentation fault.
0x0000000001093eaf in htab_remove_elt_with_hash (htab=0x2ef9fa0, element=0x26af960, hash=557151073) at src/libiberty/hashtab.c:728
728 if (*slot == HTAB_EMPTY_ENTRY)
(top-gdb) p slot
$1 = (void **) 0x0
(top-gdb) bt
#0 0x0000000001093eaf in htab_remove_elt_with_hash (htab=0x2ef9fa0, element=0x26af960, hash=557151073) at src/libiberty/hashtab.c:728
#1 0x0000000001093e79 in htab_remove_elt (htab=0x2ef9fa0, element=0x26af960) at src/libiberty/hashtab.c:714
#2 0x00000000009121b0 in tdesc_use_registers (gdbarch=0x3001240, target_desc=0x2659cb0, early_data=0x2881cb0)
at src/gdb/target-descriptions.c:1328
#3 0x000000000047c93e in i386_gdbarch_init (info=..., arches=0x0) at src/gdb/i386-tdep.c:8634
#4 0x0000000000818d5f in gdbarch_find_by_info (info=...) at src/gdb/gdbarch.c:5394
#5 0x00000000007198a8 in set_gdbarch_from_file (abfd=0x2f48250) at src/gdb/arch-utils.c:618
#6 0x00000000007f21cb in exec_file_attach (filename=0x7fffffffddb0 "/home/pedro/gdb/tests/threads", from_tty=1) at src/gdb/exec.c:380
#7 0x0000000000865c18 in catch_command_errors_const (command=0x7f1d83 <exec_file_attach(char const*, int)>, arg=0x7fffffffddb0 "/home/pedro/gdb/tests/threads",
from_tty=1) at src/gdb/main.c:403
#8 0x00000000008669cf in captured_main_1 (context=0x7fffffffd860) at src/gdb/main.c:1035
#9 0x0000000000866de2 in captured_main (data=0x7fffffffd860) at src/gdb/main.c:1142
#10 0x0000000000866e24 in gdb_main (args=0x7fffffffd860) at src/gdb/main.c:1160
#11 0x000000000041312d in main (argc=3, argv=0x7fffffffd968) at src/gdb/gdb.c:32
The direct cause of the crash is that we tried to remove an element
from the hash which supposedly exists, but does not. (htab_remove_elt
shouldn't really crash in this case, but that's secondary.)
The real problem is that early_data passed to tdesc_use_registers
includes regs from a target description that is not the target_desc,
which violates its assumptions. The registers in question are the
fs_base/gs_base registers, added by amd64_init_abi:
tdesc_numbered_register (feature, tdesc_data_segments,
AMD64_FSBASE_REGNUM, "fs_base");
tdesc_numbered_register (feature, tdesc_data_segments,
AMD64_GSBASE_REGNUM, "gs_base");
and that happens because amd64_linux_init_abi uses amd64_init_abi as
helper, but they don't coordinate on which fallback tdesc to use.
amd64_init_abi does:
if (! tdesc_has_registers (tdesc))
tdesc = tdesc_amd64;
and then adds the fs_base/gs_base registers of the "tdesc_amd64" tdesc
to the tdesc_arch_data.
After amd64_init_abi returns, amd64_linux_init_abi does:
if (! tdesc_has_registers (tdesc))
tdesc = tdesc_amd64_linux;
tdep->tdesc = tdesc;
and we end up tdesc_amd64_linux installed in tdep->tdesc.
The fix is to make sure that amd64_linux_init_abi and amd64_init_abi
agree on default tdesc, by adding a "default tdesc" parameter to
amd64_init_abi, instead of having amd64_init_abi hardcode a default.
With this, amd64_init_abi creates the fs_base/gs_base registers using
the tdesc_amd64_linux tdesc.
Tested on x86-64 GNU/Linux, -m64. I don't have an x32 setup handy.
Thanks to John Baldwin, Yao Qi and Simon Marchi for the investigation.
gdb/ChangeLog:
2017-07-13 Pedro Alves <palves@redhat.com>
* amd64-darwin-tdep.c (x86_darwin_init_abi_64): Pass tdesc_amd64
as default tdesc.
* amd64-dicos-tdep.c (amd64_dicos_init_abi):
* amd64-fbsd-tdep.c (amd64fbsd_init_abi):
* amd64-linux-tdep.c (amd64_linux_init_abi): Pass
tdesc_amd64_linux as default tdesc. Get final tdesc from the
tdep.
(amd64_x32_linux_init_abi): Pass tdesc_x32_linux as default tdesc.
Get final tdesc from the tdep.
* amd64-nbsd-tdep.c (amd64nbsd_init_abi): Pass tdesc_amd64 as
default tdesc.
* amd64-obsd-tdep.c (amd64obsd_init_abi): Likewise.
* amd64-sol2-tdep.c (amd64_sol2_init_abi): Likewise.
* amd64-tdep.c (amd64_init_abi): Add 'default_tdesc' parameter.
Use it as default tdesc.
(amd64_x32_init_abi): Add 'default_tdesc' parameter, and pass it
down to amd_init_abi. No longer handle fallback tdesc here.
* amd64-tdep.h (tdesc_x32): Declare.
(amd64_init_abi, amd64_x32_init_abi): Add 'default_tdesc'
parameter.
* amd64-windows-tdep.c (amd64_windows_init_abi): Pass tdesc_amd64
as default tdesc.
2017-07-13 21:56:42 +02:00
|
|
|
amd64_init_abi (info, gdbarch, tdesc_amd64);
|
2009-07-03 14:06:36 +02:00
|
|
|
|
|
|
|
tdep->struct_return = reg_struct_return;
|
|
|
|
|
|
|
|
dwarf2_frame_set_signal_frame_p (gdbarch, darwin_dwarf_signal_frame_p);
|
|
|
|
|
|
|
|
tdep->sigtramp_p = i386_sigtramp_p;
|
|
|
|
tdep->sigcontext_addr = amd64_darwin_sigcontext_addr;
|
|
|
|
tdep->sc_reg_offset = amd64_darwin_thread_state_reg_offset;
|
|
|
|
tdep->sc_num_regs = amd64_darwin_thread_state_num_regs;
|
|
|
|
|
2012-02-20 10:40:57 +01:00
|
|
|
tdep->jb_pc_offset = 56;
|
2009-07-03 14:06:36 +02:00
|
|
|
|
|
|
|
set_solib_ops (gdbarch, &darwin_so_ops);
|
|
|
|
}
|
|
|
|
|
2012-03-02 01:06:13 +01:00
|
|
|
/* -Wmissing-prototypes */
|
|
|
|
extern initialize_file_ftype _initialize_amd64_darwin_tdep;
|
|
|
|
|
2009-07-03 14:06:36 +02:00
|
|
|
void
|
|
|
|
_initialize_amd64_darwin_tdep (void)
|
|
|
|
{
|
|
|
|
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
|
|
|
|
GDB_OSABI_DARWIN, x86_darwin_init_abi_64);
|
|
|
|
}
|