1 /* GNU/FreeBSD/amd64 specific low level interface, for the remote server for GDB.
2    Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002
3    Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21 
22 #include <sys/cdefs.h>
23 __FBSDID("$FreeBSD: stable/12/gnu/usr.bin/gdb/gdbserver/fbsd-amd64-low.c 204335 2010-02-25 21:29:00Z jkim $");
24 
25 #include "server.h"
26 #include "fbsd-low.h"
27 #include "i387-fp.h"
28 
29 #include <sys/stddef.h>
30 #include <sys/types.h>
31 #include <sys/ptrace.h>
32 #include <machine/reg.h>
33 
34 /* Mapping between the general-purpose registers in `struct user'
35    format and GDB's register array layout.  */
36 static int amd64_regmap[] = {
37 	offsetof(struct reg, r_rax),
38 	offsetof(struct reg, r_rbx),
39 	offsetof(struct reg, r_rcx),
40 	offsetof(struct reg, r_rdx),
41 	offsetof(struct reg, r_rsi),
42 	offsetof(struct reg, r_rdi),
43 	offsetof(struct reg, r_rbp),
44 	offsetof(struct reg, r_rsp),
45 	offsetof(struct reg, r_r8),
46 	offsetof(struct reg, r_r9),
47 	offsetof(struct reg, r_r10),
48 	offsetof(struct reg, r_r11),
49 	offsetof(struct reg, r_r12),
50 	offsetof(struct reg, r_r13),
51 	offsetof(struct reg, r_r14),
52 	offsetof(struct reg, r_r15),
53 	offsetof(struct reg, r_rip),
54 	offsetof(struct reg, r_rflags),	/* XXX 64-bit */
55 	offsetof(struct reg, r_cs),
56 	offsetof(struct reg, r_ss),
57 	offsetof(struct reg, r_ds),
58 	offsetof(struct reg, r_es),
59 	offsetof(struct reg, r_fs),
60 	offsetof(struct reg, r_gs),
61 };
62 #define	AMD64_NUM_REGS	(sizeof(amd64_regmap) / sizeof(amd64_regmap[0]))
63 
64 static const char amd64_breakpoint[] = { 0xCC };
65 #define	AMD64_BP_LEN	1
66 
67 extern int debug_threads;
68 
69 static int
amd64_cannot_store_register(int regno)70 amd64_cannot_store_register(int regno)
71 {
72 
73 	return (regno >= AMD64_NUM_REGS);
74 }
75 
76 static int
amd64_cannot_fetch_register(int regno)77 amd64_cannot_fetch_register(int regno)
78 {
79 
80 	return (regno >= AMD64_NUM_REGS);
81 }
82 
83 static void
amd64_fill_gregset(void * buf)84 amd64_fill_gregset(void *buf)
85 {
86 	int i;
87 
88 	for (i = 0; i < AMD64_NUM_REGS; i++)
89 		collect_register(i, ((char *)buf) + amd64_regmap[i]);
90 }
91 
92 static void
amd64_store_gregset(const void * buf)93 amd64_store_gregset(const void *buf)
94 {
95 	int i;
96 
97 	for (i = 0; i < AMD64_NUM_REGS; i++)
98 		supply_register(i, ((char *)buf) + amd64_regmap[i]);
99 }
100 
101 static void
amd64_fill_fpregset(void * buf)102 amd64_fill_fpregset(void *buf)
103 {
104 
105 	i387_cache_to_fsave(buf);
106 }
107 
108 static void
amd64_store_fpregset(const void * buf)109 amd64_store_fpregset(const void *buf)
110 {
111 
112 	i387_fsave_to_cache(buf);
113 }
114 
115 static void
amd64_fill_fpxregset(void * buf)116 amd64_fill_fpxregset(void *buf)
117 {
118 
119 	i387_cache_to_fxsave(buf);
120 }
121 
122 static void
amd64_store_fpxregset(const void * buf)123 amd64_store_fpxregset(const void *buf)
124 {
125 
126 	i387_fxsave_to_cache(buf);
127 }
128 
129 
130 struct regset_info target_regsets[] = {
131 	{
132 		PT_GETREGS,
133 		PT_SETREGS,
134 		sizeof(struct reg),
135 		GENERAL_REGS,
136 		amd64_fill_gregset,
137 		amd64_store_gregset,
138 	},
139 #ifdef HAVE_PTRACE_GETFPXREGS
140 	{
141 		PTRACE_GETFPXREGS,
142 		PTRACE_SETFPXREGS,
143 		sizeof(elf_fpxregset_t),
144 		EXTENDED_REGS,
145 		amd64_fill_fpxregset,
146 		amd64_store_fpxregset,
147 	},
148 #endif
149 	{
150 		PT_GETFPREGS,
151 		PT_SETFPREGS,
152 		sizeof(struct fpreg),
153 		FP_REGS,
154 		amd64_fill_fpregset,
155 		amd64_store_fpregset,
156 	},
157 	{
158 		0,
159 		0,
160 		-1,
161 		-1,
162 		NULL,
163 		NULL,
164 	}
165 };
166 
167 static CORE_ADDR
amd64_get_pc(void)168 amd64_get_pc(void)
169 {
170 	unsigned long pc;
171 
172 	collect_register_by_name("rip", &pc);
173 
174 	if (debug_threads)
175 		fprintf(stderr, "stop pc (before any decrement) is %016lx\n", pc);
176 
177 	return (pc);
178 }
179 
180 static void
amd64_set_pc(CORE_ADDR newpc)181 amd64_set_pc(CORE_ADDR newpc)
182 {
183 
184 	if (debug_threads)
185 		fprintf(stderr, "set pc to %016lx\n", (long)newpc);
186 	supply_register_by_name("rip", &newpc);
187 }
188 
189 static int
amd64_breakpoint_at(CORE_ADDR pc)190 amd64_breakpoint_at(CORE_ADDR pc)
191 {
192 	unsigned char c;
193 
194 	read_inferior_memory(pc, &c, 1);
195 	if (c == 0xCC)
196 		return (1);
197 
198 	return (0);
199 }
200 
201 struct fbsd_target_ops the_low_target = {
202 	AMD64_NUM_REGS,
203 	amd64_regmap,
204 	amd64_cannot_fetch_register,
205 	amd64_cannot_store_register,
206 	amd64_get_pc,
207 	amd64_set_pc,
208 	amd64_breakpoint,
209 	AMD64_BP_LEN,
210 	NULL,
211 	1,
212 	amd64_breakpoint_at,
213 };
214