Fix potential buffer overflows with sprintf and very large integer values.
[deliverable/binutils-gdb.git] / gdb / i386bsd-nat.c
CommitLineData
e6031aeb 1/* Native-dependent code for modern i386 BSD's.
3f63813d 2
618f726f 3 Copyright (C) 2000-2016 Free Software Foundation, Inc.
e6031aeb
MK
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
e6031aeb
MK
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
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
e6031aeb
MK
19
20#include "defs.h"
21#include "inferior.h"
4e052eda 22#include "regcache.h"
e6031aeb 23
b7247919 24#include <signal.h>
e6031aeb
MK
25#include <sys/types.h>
26#include <sys/ptrace.h>
27#include <machine/reg.h>
28#include <machine/frame.h>
29
57976e88 30#include "i386-tdep.h"
1fc7d519 31#include "i387-tdep.h"
9692934b
MK
32#include "i386bsd-nat.h"
33#include "inf-ptrace.h"
b051bfa4
MK
34\f
35
e6031aeb
MK
36/* In older BSD versions we cannot get at some of the segment
37 registers. FreeBSD for example didn't support the %fs and %gs
38 registers until the 3.0 release. We have autoconf checks for their
39 presence, and deal gracefully with their absence. */
40
6cfb2041
MK
41/* Offset in `struct reg' where MEMBER is stored. */
42#define REG_OFFSET(member) offsetof (struct reg, member)
e6031aeb 43
6cfb2041
MK
44/* At i386bsd_reg_offset[REGNUM] you'll find the offset in `struct
45 reg' where the GDB register REGNUM is stored. Unsupported
e6031aeb 46 registers are marked with `-1'. */
6cfb2041 47static int i386bsd_r_reg_offset[] =
e6031aeb
MK
48{
49 REG_OFFSET (r_eax),
50 REG_OFFSET (r_ecx),
51 REG_OFFSET (r_edx),
2c48bda3 52 REG_OFFSET (r_ebx),
e6031aeb
MK
53 REG_OFFSET (r_esp),
54 REG_OFFSET (r_ebp),
55 REG_OFFSET (r_esi),
56 REG_OFFSET (r_edi),
57 REG_OFFSET (r_eip),
58 REG_OFFSET (r_eflags),
59 REG_OFFSET (r_cs),
60 REG_OFFSET (r_ss),
61 REG_OFFSET (r_ds),
62 REG_OFFSET (r_es),
422ea4b8 63#ifdef HAVE_STRUCT_REG_R_FS
e6031aeb
MK
64 REG_OFFSET (r_fs),
65#else
66 -1,
67#endif
422ea4b8 68#ifdef HAVE_STRUCT_REG_R_GS
e6031aeb
MK
69 REG_OFFSET (r_gs)
70#else
71 -1
72#endif
73};
74
7e89e357 75/* Macro to determine if a register is fetched with PT_GETREGS. */
283accbc
MK
76#define GETREGS_SUPPLIES(regnum) \
77 ((0 <= (regnum) && (regnum) <= 15))
7e89e357
JT
78
79#ifdef HAVE_PT_GETXMMREGS
80/* Set to 1 if the kernel supports PT_GETXMMREGS. Initialized to -1
81 so that we try PT_GETXMMREGS the first time around. */
82static int have_ptrace_xmmregs = -1;
83#endif
97de3545
JB
84
85#ifdef PT_GETXSTATE_INFO
86size_t i386bsd_xsave_len;
87#endif
e6031aeb
MK
88\f
89
6cfb2041 90/* Supply the general-purpose registers in GREGS, to REGCACHE. */
e6031aeb 91
1fc7d519 92static void
6cfb2041 93i386bsd_supply_gregset (struct regcache *regcache, const void *gregs)
e6031aeb 94{
21002a63 95 const char *regs = (const char *) gregs;
feae6502 96 int regnum;
e6031aeb 97
6cfb2041 98 for (regnum = 0; regnum < ARRAY_SIZE (i386bsd_r_reg_offset); regnum++)
e6031aeb 99 {
6cfb2041
MK
100 int offset = i386bsd_r_reg_offset[regnum];
101
102 if (offset != -1)
103 regcache_raw_supply (regcache, regnum, regs + offset);
e6031aeb
MK
104 }
105}
106
6cfb2041
MK
107/* Collect register REGNUM from REGCACHE and store its contents in
108 GREGS. If REGNUM is -1, collect and store all appropriate
109 registers. */
e6031aeb 110
1fc7d519 111static void
6cfb2041
MK
112i386bsd_collect_gregset (const struct regcache *regcache,
113 void *gregs, int regnum)
e6031aeb 114{
21002a63 115 char *regs = (char *) gregs;
e6031aeb
MK
116 int i;
117
6cfb2041
MK
118 for (i = 0; i < ARRAY_SIZE (i386bsd_r_reg_offset); i++)
119 {
120 if (regnum == -1 || regnum == i)
121 {
122 int offset = i386bsd_r_reg_offset[i];
e6031aeb 123
6cfb2041
MK
124 if (offset != -1)
125 regcache_raw_collect (regcache, i, regs + offset);
126 }
127 }
128}
e6031aeb 129
283accbc 130/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
e6031aeb
MK
131 for all registers (including the floating point registers). */
132
9692934b 133static void
28439f5e
PA
134i386bsd_fetch_inferior_registers (struct target_ops *ops,
135 struct regcache *regcache, int regnum)
e6031aeb 136{
283accbc 137 if (regnum == -1 || GETREGS_SUPPLIES (regnum))
7e89e357 138 {
6cfb2041 139 struct reg regs;
7e89e357 140
94309df7 141 if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid),
9f8e0089 142 (PTRACE_TYPE_ARG3) &regs, 0) == -1)
e2e0b3e5 143 perror_with_name (_("Couldn't get registers"));
e6031aeb 144
56be3814 145 i386bsd_supply_gregset (regcache, &regs);
283accbc 146 if (regnum != -1)
7e89e357
JT
147 return;
148 }
e6031aeb 149
283accbc 150 if (regnum == -1 || regnum >= I386_ST0_REGNUM)
e6031aeb 151 {
6cfb2041 152 struct fpreg fpregs;
7e89e357
JT
153#ifdef HAVE_PT_GETXMMREGS
154 char xmmregs[512];
97de3545
JB
155#endif
156
157#ifdef PT_GETXSTATE_INFO
158 if (i386bsd_xsave_len != 0)
159 {
21002a63 160 void *xstateregs;
97de3545
JB
161
162 xstateregs = alloca (i386bsd_xsave_len);
94309df7 163 if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid),
97de3545
JB
164 (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
165 perror_with_name (_("Couldn't get extended state status"));
7e89e357 166
97de3545
JB
167 i387_supply_xsave (regcache, -1, xstateregs);
168 return;
169 }
170#endif
171
172#ifdef HAVE_PT_GETXMMREGS
a144416f 173 if (have_ptrace_xmmregs != 0
94309df7 174 && ptrace(PT_GETXMMREGS, get_ptrace_pid (inferior_ptid),
9f8e0089 175 (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
7e89e357
JT
176 {
177 have_ptrace_xmmregs = 1;
56be3814 178 i387_supply_fxsave (regcache, -1, xmmregs);
7e89e357
JT
179 }
180 else
181 {
97de3545
JB
182 have_ptrace_xmmregs = 0;
183#endif
94309df7 184 if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid),
9f8e0089 185 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
e2e0b3e5 186 perror_with_name (_("Couldn't get floating point status"));
e6031aeb 187
56be3814 188 i387_supply_fsave (regcache, -1, &fpregs);
97de3545 189#ifdef HAVE_PT_GETXMMREGS
7e89e357 190 }
7e89e357 191#endif
e6031aeb 192 }
b051bfa4 193}
e6031aeb 194
283accbc 195/* Store register REGNUM back into the inferior. If REGNUM is -1, do
e6031aeb
MK
196 this for all registers (including the floating point registers). */
197
9692934b 198static void
28439f5e
PA
199i386bsd_store_inferior_registers (struct target_ops *ops,
200 struct regcache *regcache, int regnum)
e6031aeb 201{
283accbc 202 if (regnum == -1 || GETREGS_SUPPLIES (regnum))
7e89e357 203 {
6cfb2041 204 struct reg regs;
7e89e357 205
94309df7 206 if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid),
9f8e0089 207 (PTRACE_TYPE_ARG3) &regs, 0) == -1)
e2e0b3e5 208 perror_with_name (_("Couldn't get registers"));
e6031aeb 209
56be3814 210 i386bsd_collect_gregset (regcache, &regs, regnum);
e6031aeb 211
94309df7 212 if (ptrace (PT_SETREGS, get_ptrace_pid (inferior_ptid),
9f8e0089 213 (PTRACE_TYPE_ARG3) &regs, 0) == -1)
e2e0b3e5 214 perror_with_name (_("Couldn't write registers"));
7e89e357 215
283accbc 216 if (regnum != -1)
7e89e357
JT
217 return;
218 }
e6031aeb 219
283accbc 220 if (regnum == -1 || regnum >= I386_ST0_REGNUM)
e6031aeb 221 {
6cfb2041 222 struct fpreg fpregs;
7e89e357
JT
223#ifdef HAVE_PT_GETXMMREGS
224 char xmmregs[512];
97de3545
JB
225#endif
226
227#ifdef PT_GETXSTATE_INFO
228 if (i386bsd_xsave_len != 0)
229 {
21002a63 230 void *xstateregs;
97de3545
JB
231
232 xstateregs = alloca (i386bsd_xsave_len);
94309df7 233 if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid),
97de3545
JB
234 (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
235 perror_with_name (_("Couldn't get extended state status"));
e6031aeb 236
97de3545
JB
237 i387_collect_xsave (regcache, -1, xstateregs, 0);
238
94309df7 239 if (ptrace (PT_SETXSTATE, get_ptrace_pid (inferior_ptid),
97de3545
JB
240 (PTRACE_TYPE_ARG3) xstateregs, i386bsd_xsave_len) == -1)
241 perror_with_name (_("Couldn't write extended state status"));
242 return;
243 }
244#endif
245
246#ifdef HAVE_PT_GETXMMREGS
a144416f 247 if (have_ptrace_xmmregs != 0
94309df7 248 && ptrace(PT_GETXMMREGS, get_ptrace_pid (inferior_ptid),
9f8e0089 249 (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
7e89e357
JT
250 {
251 have_ptrace_xmmregs = 1;
252
56be3814 253 i387_collect_fxsave (regcache, regnum, xmmregs);
e6031aeb 254
94309df7 255 if (ptrace (PT_SETXMMREGS, get_ptrace_pid (inferior_ptid),
9f8e0089 256 (PTRACE_TYPE_ARG3) xmmregs, 0) == -1)
e2e0b3e5 257 perror_with_name (_("Couldn't write XMM registers"));
7e89e357
JT
258 }
259 else
260 {
261 have_ptrace_xmmregs = 0;
262#endif
94309df7 263 if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid),
9f8e0089 264 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
e2e0b3e5 265 perror_with_name (_("Couldn't get floating point status"));
7e89e357 266
56be3814 267 i387_collect_fsave (regcache, regnum, &fpregs);
f5b1afdf 268
94309df7 269 if (ptrace (PT_SETFPREGS, get_ptrace_pid (inferior_ptid),
9f8e0089 270 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
e2e0b3e5 271 perror_with_name (_("Couldn't write floating point status"));
7e89e357
JT
272#ifdef HAVE_PT_GETXMMREGS
273 }
274#endif
e6031aeb
MK
275 }
276}
9692934b
MK
277
278/* Create a prototype *BSD/i386 target. The client can override it
279 with local methods. */
280
281struct target_ops *
282i386bsd_target (void)
283{
284 struct target_ops *t;
285
286 t = inf_ptrace_target ();
287 t->to_fetch_registers = i386bsd_fetch_inferior_registers;
288 t->to_store_registers = i386bsd_store_inferior_registers;
289 return t;
290}
e6031aeb
MK
291\f
292
0afdd437
MK
293/* Support for debug registers. */
294
295#ifdef HAVE_PT_GETDBREGS
296
297/* Not all versions of FreeBSD/i386 that support the debug registers
298 have this macro. */
299#ifndef DBREG_DRX
300#define DBREG_DRX(d, x) ((&d->dr0)[x])
301#endif
302
7b50312a
PA
303static unsigned long
304i386bsd_dr_get (ptid_t ptid, int regnum)
305{
306 struct dbreg dbregs;
307
94309df7 308 if (ptrace (PT_GETDBREGS, get_ptrace_pid (inferior_ptid),
7b50312a
PA
309 (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
310 perror_with_name (_("Couldn't read debug registers"));
311
312 return DBREG_DRX ((&dbregs), regnum);
313}
314
0afdd437
MK
315static void
316i386bsd_dr_set (int regnum, unsigned int value)
317{
318 struct dbreg dbregs;
319
94309df7 320 if (ptrace (PT_GETDBREGS, get_ptrace_pid (inferior_ptid),
9f8e0089 321 (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
e2e0b3e5 322 perror_with_name (_("Couldn't get debug registers"));
0afdd437
MK
323
324 /* For some mysterious reason, some of the reserved bits in the
325 debug control register get set. Mask these off, otherwise the
326 ptrace call below will fail. */
afdb036a 327 DBREG_DRX ((&dbregs), 7) &= ~(0x0000fc00);
0afdd437
MK
328
329 DBREG_DRX ((&dbregs), regnum) = value;
330
94309df7 331 if (ptrace (PT_SETDBREGS, get_ptrace_pid (inferior_ptid),
9f8e0089 332 (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
e2e0b3e5 333 perror_with_name (_("Couldn't write debug registers"));
0afdd437
MK
334}
335
336void
337i386bsd_dr_set_control (unsigned long control)
338{
339 i386bsd_dr_set (7, control);
340}
341
342void
343i386bsd_dr_set_addr (int regnum, CORE_ADDR addr)
344{
345 gdb_assert (regnum >= 0 && regnum <= 4);
346
347 i386bsd_dr_set (regnum, addr);
348}
349
7b50312a
PA
350CORE_ADDR
351i386bsd_dr_get_addr (int regnum)
0afdd437 352{
7b50312a 353 return i386bsd_dr_get (inferior_ptid, regnum);
0afdd437
MK
354}
355
356unsigned long
357i386bsd_dr_get_status (void)
358{
7b50312a
PA
359 return i386bsd_dr_get (inferior_ptid, 6);
360}
0afdd437 361
7b50312a
PA
362unsigned long
363i386bsd_dr_get_control (void)
364{
365 return i386bsd_dr_get (inferior_ptid, 7);
0afdd437
MK
366}
367
368#endif /* PT_GETDBREGS */
369\f
370
15add3f5
MK
371/* Provide a prototype to silence -Wmissing-prototypes. */
372void _initialize_i386bsd_nat (void);
373
b7247919
MK
374void
375_initialize_i386bsd_nat (void)
376{
a3386186 377 int offset;
8201327c 378
b7247919
MK
379 /* To support the recognition of signal handlers, i386bsd-tdep.c
380 hardcodes some constants. Inclusion of this file means that we
381 are compiling a native debugger, which means that we can use the
382 system header files and sysctl(3) to get at the relevant
383 information. */
384
8201327c 385#if defined (__FreeBSD_version) && __FreeBSD_version >= 400011
a3386186
MK
386#define SC_REG_OFFSET i386fbsd4_sc_reg_offset
387#elif defined (__FreeBSD_version) && __FreeBSD_version >= 300005
a3386186 388#define SC_REG_OFFSET i386fbsd_sc_reg_offset
005328e3 389#elif defined (NetBSD) || defined (__NetBSD_Version__)
a3386186 390#define SC_REG_OFFSET i386nbsd_sc_reg_offset
005328e3 391#elif defined (OpenBSD)
a3386186 392#define SC_REG_OFFSET i386obsd_sc_reg_offset
8201327c
MK
393#endif
394
bbe06c74
MK
395#ifdef SC_REG_OFFSET
396
a3386186
MK
397 /* We only check the program counter, stack pointer and frame
398 pointer since these members of `struct sigcontext' are essential
399 for providing backtraces. More checks could be added, but would
400 involve adding configure checks for the appropriate structure
401 members, since older BSD's don't provide all of them. */
402
403#define SC_PC_OFFSET SC_REG_OFFSET[I386_EIP_REGNUM]
404#define SC_SP_OFFSET SC_REG_OFFSET[I386_ESP_REGNUM]
405#define SC_FP_OFFSET SC_REG_OFFSET[I386_EBP_REGNUM]
406
b7247919
MK
407 /* Override the default value for the offset of the program counter
408 in the sigcontext structure. */
a3386186 409 offset = offsetof (struct sigcontext, sc_pc);
8201327c 410
a3386186 411 if (SC_PC_OFFSET != offset)
8201327c 412 {
8a3fe4f8 413 warning (_("\
8201327c 414offsetof (struct sigcontext, sc_pc) yields %d instead of %d.\n\
8a3fe4f8 415Please report this to <bug-gdb@gnu.org>."),
a3386186 416 offset, SC_PC_OFFSET);
8201327c
MK
417 }
418
a3386186 419 SC_PC_OFFSET = offset;
6bff26de
MK
420
421 /* Likewise for the stack pointer. */
a3386186 422 offset = offsetof (struct sigcontext, sc_sp);
6bff26de 423
a3386186 424 if (SC_SP_OFFSET != offset)
6bff26de 425 {
8a3fe4f8 426 warning (_("\
6bff26de 427offsetof (struct sigcontext, sc_sp) yields %d instead of %d.\n\
8a3fe4f8 428Please report this to <bug-gdb@gnu.org>."),
a3386186
MK
429 offset, SC_SP_OFFSET);
430 }
431
432 SC_SP_OFFSET = offset;
433
434 /* And the frame pointer. */
435 offset = offsetof (struct sigcontext, sc_fp);
436
437 if (SC_FP_OFFSET != offset)
438 {
8a3fe4f8 439 warning (_("\
a3386186 440offsetof (struct sigcontext, sc_fp) yields %d instead of %d.\n\
8a3fe4f8 441Please report this to <bug-gdb@gnu.org>."),
a3386186 442 offset, SC_FP_OFFSET);
6bff26de
MK
443 }
444
a3386186 445 SC_FP_OFFSET = offset;
bbe06c74
MK
446
447#endif /* SC_REG_OFFSET */
b7247919 448}
This page took 1.311769 seconds and 4 git commands to generate.