1/* Target-dependent code for AMD64 Solaris.
2
3   Copyright (C) 2001, 2002, 2003, 2004, 2006, 2007
4   Free Software Foundation, Inc.
5
6   Contributed by Joseph Myers, CodeSourcery, LLC.
7
8   This file is part of GDB.
9
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 3 of the License, or
13   (at your option) any later version.
14
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19
20   You should have received a copy of the GNU General Public License
21   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
23#include "defs.h"
24#include "frame.h"
25#include "gdbcore.h"
26#include "regcache.h"
27#include "osabi.h"
28#include "symtab.h"
29
30#include "gdb_string.h"
31
32#include "sol2-tdep.h"
33#include "amd64-tdep.h"
34#include "solib-svr4.h"
35
36/* Mapping between the general-purpose registers in gregset_t format
37   and GDB's register cache layout.  */
38
39/* From <sys/regset.h>.  */
40static int amd64_sol2_gregset_reg_offset[] = {
41  14 * 8,			/* %rax */
42  11 * 8,			/* %rbx */
43  13 * 8,			/* %rcx */
44  12 * 8,			/* %rdx */
45  9 * 8,			/* %rsi */
46  8 * 8,			/* %rdi */
47  10 * 8,			/* %rbp */
48  20 * 8,			/* %rsp */
49  7 * 8,			/* %r8 ... */
50  6 * 8,
51  5 * 8,
52  4 * 8,
53  3 * 8,
54  2 * 8,
55  1 * 8,
56  0 * 8,			/* ... %r15 */
57  17 * 8,			/* %rip */
58  16 * 8,			/* %eflags */
59  18 * 8,			/* %cs */
60  21 * 8,			/* %ss */
61  25 * 8,			/* %ds */
62  24 * 8,			/* %es */
63  22 * 8,			/* %fs */
64  23 * 8			/* %gs */
65};
66
67
68/* Return whether the frame preceding NEXT_FRAME corresponds to a
69   Solaris sigtramp routine.  */
70
71static int
72amd64_sol2_sigtramp_p (struct frame_info *next_frame)
73{
74  CORE_ADDR pc = frame_pc_unwind (next_frame);
75  char *name;
76
77  find_pc_partial_function (pc, &name, NULL, NULL);
78  return (name && (strcmp ("sigacthandler", name) == 0
79		   || strcmp (name, "ucbsigvechandler") == 0));
80}
81
82/* Solaris doesn't have a 'struct sigcontext', but it does have a
83   'mcontext_t' that contains the saved set of machine registers.  */
84
85static CORE_ADDR
86amd64_sol2_mcontext_addr (struct frame_info *next_frame)
87{
88  CORE_ADDR sp, ucontext_addr;
89
90  sp = frame_unwind_register_unsigned (next_frame, AMD64_RSP_REGNUM);
91  ucontext_addr = get_frame_memory_unsigned (next_frame, sp + 8, 8);
92
93  return ucontext_addr + 72;
94}
95
96static void
97amd64_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
98{
99  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
100
101  tdep->gregset_reg_offset = amd64_sol2_gregset_reg_offset;
102  tdep->gregset_num_regs = ARRAY_SIZE (amd64_sol2_gregset_reg_offset);
103  tdep->sizeof_gregset = 28 * 8;
104
105  amd64_init_abi (info, gdbarch);
106
107  tdep->sigtramp_p = amd64_sol2_sigtramp_p;
108  tdep->sigcontext_addr = amd64_sol2_mcontext_addr;
109  tdep->sc_reg_offset = tdep->gregset_reg_offset;
110  tdep->sc_num_regs = tdep->gregset_num_regs;
111
112  /* Solaris uses SVR4-style shared libraries.  */
113  set_gdbarch_skip_solib_resolver (gdbarch, sol2_skip_solib_resolver);
114  set_solib_svr4_fetch_link_map_offsets
115    (gdbarch, svr4_lp64_fetch_link_map_offsets);
116}
117
118
119/* Provide a prototype to silence -Wmissing-prototypes.  */
120extern void _initialize_amd64_sol2_tdep (void);
121
122void
123_initialize_amd64_sol2_tdep (void)
124{
125  gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
126			  GDB_OSABI_SOLARIS, amd64_sol2_init_abi);
127}
128