fbsd-i386-low.c revision 157574
155714Skris/* GNU/Linux/i386 specific low level interface, for the remote server for GDB.
255714Skris   Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002
355714Skris   Free Software Foundation, Inc.
455714Skris
555714Skris   This file is part of GDB.
655714Skris
755714Skris   This program is free software; you can redistribute it and/or modify
855714Skris   it under the terms of the GNU General Public License as published by
955714Skris   the Free Software Foundation; either version 2 of the License, or
1055714Skris   (at your option) any later version.
1155714Skris
1255714Skris   This program is distributed in the hope that it will be useful,
1368651Skris   but WITHOUT ANY WARRANTY; without even the implied warranty of
1455714Skris   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1555714Skris   GNU General Public License for more details.
1655714Skris
1755714Skris   You should have received a copy of the GNU General Public License
18238405Sjkim   along with this program; if not, write to the Free Software
1955714Skris   Foundation, Inc., 59 Temple Place - Suite 330,
2055714Skris   Boston, MA 02111-1307, USA.  */
2155714Skris
2255714Skris#include <sys/cdefs.h>
2355714Skris__FBSDID("$FreeBSD: head/gnu/usr.bin/gdb/gdbserver/fbsd-i386-low.c 157574 2006-04-06 22:24:01Z jmg $");
2455714Skris
2555714Skris#include "server.h"
2655714Skris#include "fbsd-low.h"
27109998Smarkm#include "i387-fp.h"
28162911Ssimon
29194206Ssimon#ifdef HAVE_SYS_REG_H
30238405Sjkim#include <sys/reg.h>
3155714Skris#else
3255714Skris#include <machine/reg.h>
3355714Skris#endif
3468651Skris
3555714Skris/* This module only supports access to the general purpose registers.  */
36109998Smarkm
37160814Ssimon#define i386_num_regs 16
38160814Ssimon
3955714Skris/* This stuff comes from i386-fbsd-nat.c.  */
4055714Skris
4155714Skris/* Mapping between the general-purpose registers in `struct user'
4255714Skris   format and GDB's register array layout.  */
4355714Skrisstatic int i386_regmap[] =
4455714Skris{
4555714Skris  tEAX * 4, tECX * 4, tEDX * 4, tEBX * 4,
4655714Skris  tESP * 4, tEBP * 4, tESI * 4, tEDI * 4,
4755714Skris  tEIP * 4, tEFLAGS * 4, tCS * 4, tSS * 4,
4855714Skris  tDS * 4, tES * 4, tFS * 4, tGS * 4
4955714Skris};
5055714Skris
51238405Sjkimstatic int
5255714Skrisi386_cannot_store_register (int regno)
53194206Ssimon{
5455714Skris  return (regno >= i386_num_regs);
5555714Skris}
5655714Skris
5755714Skrisstatic int
58109998Smarkmi386_cannot_fetch_register (int regno)
59109998Smarkm{
60109998Smarkm  return (regno >= i386_num_regs);
61109998Smarkm}
62238405Sjkim
63160814Ssimon
64238405Sjkim#include <sys/procfs.h>
65238405Sjkim#include <sys/ptrace.h>
66238405Sjkim
6755714Skrisstatic void
6855714Skrisi386_fill_gregset (void *buf)
69160814Ssimon{
70238405Sjkim  int i;
7155714Skris
7255714Skris  for (i = 0; i < i386_num_regs; i++)
7355714Skris    collect_register (i, ((char *) buf) + i386_regmap[i]);
7455714Skris
75238405Sjkim}
76238405Sjkim
7755714Skrisstatic void
78142425Snectari386_store_gregset (const void *buf)
7955714Skris{
8055714Skris  int i;
8155714Skris
8255714Skris  for (i = 0; i < i386_num_regs; i++)
8355714Skris    supply_register (i, ((char *) buf) + i386_regmap[i]);
8455714Skris
8555714Skris}
8655714Skris
8755714Skrisstatic void
8855714Skrisi386_fill_fpregset (void *buf)
8955714Skris{
9055714Skris  i387_cache_to_fsave (buf);
9155714Skris}
9255714Skris
9355714Skrisstatic void
9455714Skrisi386_store_fpregset (const void *buf)
9555714Skris{
9655714Skris  i387_fsave_to_cache (buf);
9755714Skris}
9855714Skris
9955714Skrisstatic void
10055714Skrisi386_fill_fpxregset (void *buf)
10155714Skris{
10255714Skris  i387_cache_to_fxsave (buf);
10355714Skris}
10455714Skris
10555714Skrisstatic void
10655714Skrisi386_store_fpxregset (const void *buf)
10755714Skris{
10855714Skris  i387_fxsave_to_cache (buf);
10955714Skris}
11055714Skris
11155714Skris
11255714Skrisstruct regset_info target_regsets[] = {
11355714Skris  { PT_GETREGS, PT_SETREGS, sizeof (struct reg),
11455714Skris    GENERAL_REGS,
11555714Skris    i386_fill_gregset, i386_store_gregset },
11655714Skris#ifdef HAVE_PTRACE_GETFPXREGS
11755714Skris  { PTRACE_GETFPXREGS, PTRACE_SETFPXREGS, sizeof (elf_fpxregset_t),
11855714Skris    EXTENDED_REGS,
11955714Skris    i386_fill_fpxregset, i386_store_fpxregset },
120238405Sjkim#endif
121238405Sjkim  { PT_GETFPREGS, PT_SETFPREGS, sizeof (struct fpreg),
12255714Skris    FP_REGS,
12355714Skris    i386_fill_fpregset, i386_store_fpregset },
12455714Skris  { 0, 0, -1, -1, NULL, NULL }
12555714Skris};
12655714Skris
12755714Skrisstatic const char i386_breakpoint[] = { 0xCC };
12855714Skris#define i386_breakpoint_len 1
12955714Skris
13055714Skrisextern int debug_threads;
131238405Sjkim
132238405Sjkimstatic CORE_ADDR
133238405Sjkimi386_get_pc ()
134238405Sjkim{
135238405Sjkim  unsigned long pc;
136238405Sjkim
137238405Sjkim  collect_register_by_name ("eip", &pc);
138238405Sjkim
139238405Sjkim  if (debug_threads)
14055714Skris    fprintf (stderr, "stop pc (before any decrement) is %08lx\n", pc);
14155714Skris  return pc;
14255714Skris}
14355714Skris
144static void
145i386_set_pc (CORE_ADDR newpc)
146{
147  if (debug_threads)
148    fprintf (stderr, "set pc to %08lx\n", (long) newpc);
149  supply_register_by_name ("eip", &newpc);
150}
151
152static int
153i386_breakpoint_at (CORE_ADDR pc)
154{
155  unsigned char c;
156
157  read_inferior_memory (pc, &c, 1);
158  if (c == 0xCC)
159    return 1;
160
161  return 0;
162}
163
164struct fbsd_target_ops the_low_target = {
165  i386_num_regs,
166  i386_regmap,
167  i386_cannot_fetch_register,
168  i386_cannot_store_register,
169  i386_get_pc,
170  i386_set_pc,
171  i386_breakpoint,
172  i386_breakpoint_len,
173  NULL,
174  1,
175  i386_breakpoint_at,
176};
177