2008-11-14 Daniel Gutson <dgutson@codesourcery.com>
* configure.tgt (sparc64-*-linux*): Added gdbserver support. * regformats/reg-sparc64.dat: New file. gdbserver/ 2008-11-14 Daniel Gutson <dgutson@codesourcery.com> * Makefile.in (SFILES, clean): Added sparc64 files. (reg-sparc64.o, reg-sparc64.c): New. * configure.srv (sparc*-*-linux*): New configuration. * linux-low.c (regsets_fetch_inferior_registers): Swap ptrace syscall arguments for SPARC. (regsets_store_inferior_registers): Likewise. * linux-sparc-low.c: New file.
This commit is contained in:
parent
28b027518b
commit
dfb64f85d3
8 changed files with 418 additions and 3 deletions
|
@ -1,3 +1,8 @@
|
|||
2008-11-14 Daniel Gutson <dgutson@codesourcery.com>
|
||||
|
||||
* configure.tgt (sparc64-*-linux*): Added gdbserver support.
|
||||
* regformats/reg-sparc64.dat: New file.
|
||||
|
||||
2008-11-14 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
PR mi/2549:
|
||||
|
|
|
@ -411,6 +411,7 @@ sparc64-*-linux*)
|
|||
gdb_target_obs="sparc64-tdep.o sparc64-sol2-tdep.o sol2-tdep.o \
|
||||
sparc64-linux-tdep.o sparc-tdep.o sparc-sol2-tdep.o \
|
||||
sparc-linux-tdep.o solib.o solib-svr4.o"
|
||||
build_gdbserver=yes
|
||||
;;
|
||||
sparc*-*-freebsd* | sparc*-*-kfreebsd*-gnu)
|
||||
# Target: FreeBSD/sparc64
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
2008-11-14 Daniel Gutson <dgutson@codesourcery.com>
|
||||
|
||||
* Makefile.in (SFILES, clean): Added sparc64 files.
|
||||
(reg-sparc64.o, reg-sparc64.c): New.
|
||||
* configure.srv (sparc*-*-linux*): New configuration.
|
||||
* linux-low.c (regsets_fetch_inferior_registers): Swap ptrace
|
||||
syscall arguments for SPARC.
|
||||
(regsets_store_inferior_registers): Likewise.
|
||||
* linux-sparc-low.c: New file.
|
||||
|
||||
2008-10-21 Doug Evans <dje@google.com>
|
||||
|
||||
* Makefile.in (BFD_DIR,BFD,BFD_SRC,BFD_CFLAGS): Delete.
|
||||
|
|
|
@ -117,7 +117,8 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c \
|
|||
$(srcdir)/linux-m68k-low.c $(srcdir)/linux-mips-low.c \
|
||||
$(srcdir)/linux-ppc-low.c \
|
||||
$(srcdir)/linux-s390-low.c \
|
||||
$(srcdir)/linux-sh-low.c $(srcdir)/linux-x86-64-low.c \
|
||||
$(srcdir)/linux-sh-low.c $(srcdir)/linux-sparc-low.c \
|
||||
$(srcdir)/linux-x86-64-low.c \
|
||||
$(srcdir)/linux-xtensa-low.c \
|
||||
$(srcdir)/win32-arm-low.c $(srcdir)/win32-i386-low.c \
|
||||
$(srcdir)/win32-low.c $(srcdir)/wincecompat.c \
|
||||
|
@ -209,7 +210,7 @@ clean:
|
|||
rm -f version.c
|
||||
rm -f gdbserver$(EXEEXT) gdbreplay$(EXEEXT) core make.log
|
||||
rm -f reg-arm.c reg-i386.c reg-ia64.c reg-m32r.c reg-m68k.c
|
||||
rm -f reg-sh.c reg-spu.c reg-x86-64.c reg-i386-linux.c
|
||||
rm -f reg-sh.c reg-sparc.c reg-spu.c reg-x86-64.c reg-i386-linux.c
|
||||
rm -f reg-cris.c reg-crisv32.c reg-x86-64-linux.c reg-xtensa.c
|
||||
rm -f arm-with-iwmmxt.c mips-linux.c mips64-linux.c
|
||||
rm -f powerpc-32l.c powerpc-64l.c powerpc-e500l.c
|
||||
|
@ -382,6 +383,9 @@ reg-s390x.c : $(srcdir)/../regformats/reg-s390x.dat $(regdat_sh)
|
|||
reg-sh.o : reg-sh.c $(regdef_h)
|
||||
reg-sh.c : $(srcdir)/../regformats/reg-sh.dat $(regdat_sh)
|
||||
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-sh.dat reg-sh.c
|
||||
reg-sparc64.o : reg-sparc64.c $(regdef_h)
|
||||
reg-sparc64.c : $(srcdir)/../regformats/reg-sparc64.dat $(regdat_sh)
|
||||
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-sparc64.dat reg-sparc64.c
|
||||
reg-spu.o : reg-spu.c $(regdef_h)
|
||||
reg-spu.c : $(srcdir)/../regformats/reg-spu.dat $(regdat_sh)
|
||||
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-spu.dat reg-spu.c
|
||||
|
|
|
@ -139,6 +139,11 @@ case "${target}" in
|
|||
srv_linux_regsets=yes
|
||||
srv_linux_thread_db=yes
|
||||
;;
|
||||
sparc*-*-linux*) srv_regobj=reg-sparc64.o
|
||||
srv_tgtobj="linux-low.o linux-sparc-low.o"
|
||||
srv_linux_regsets=yes
|
||||
srv_linux_thread_db=yes
|
||||
;;
|
||||
spu*-*-*) srv_regobj=reg-spu.o
|
||||
srv_tgtobj="spu-low.o"
|
||||
;;
|
||||
|
|
|
@ -1523,7 +1523,11 @@ regsets_fetch_inferior_registers ()
|
|||
}
|
||||
|
||||
buf = malloc (regset->size);
|
||||
#ifndef __sparc__
|
||||
res = ptrace (regset->get_request, inferior_pid, 0, buf);
|
||||
#else
|
||||
res = ptrace (regset->get_request, inferior_pid, buf, 0);
|
||||
#endif
|
||||
if (res < 0)
|
||||
{
|
||||
if (errno == EIO)
|
||||
|
@ -1576,7 +1580,11 @@ regsets_store_inferior_registers ()
|
|||
/* First fill the buffer with the current register set contents,
|
||||
in case there are any items in the kernel's regset that are
|
||||
not in gdbserver's regcache. */
|
||||
#ifndef __sparc__
|
||||
res = ptrace (regset->get_request, inferior_pid, 0, buf);
|
||||
#else
|
||||
res = ptrace (regset->get_request, inferior_pid, buf, 0);
|
||||
#endif
|
||||
|
||||
if (res == 0)
|
||||
{
|
||||
|
@ -1584,7 +1592,11 @@ regsets_store_inferior_registers ()
|
|||
regset->fill_function (buf);
|
||||
|
||||
/* Only now do we write the register set. */
|
||||
res = ptrace (regset->set_request, inferior_pid, 0, buf);
|
||||
#ifndef __sparc__
|
||||
res = ptrace (regset->set_request, inferior_pid, 0, buf);
|
||||
#else
|
||||
res = ptrace (regset->set_request, inferior_pid, buf, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (res < 0)
|
||||
|
|
287
gdb/gdbserver/linux-sparc-low.c
Normal file
287
gdb/gdbserver/linux-sparc-low.c
Normal file
|
@ -0,0 +1,287 @@
|
|||
/* Low level interface to ptrace, for the remote server for GDB.
|
||||
Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
||||
2006, 2007, 2008 Free Software Foundation, 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 "server.h"
|
||||
#include "linux-low.h"
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
|
||||
#include "gdb_proc_service.h"
|
||||
|
||||
/* The stack pointer is offset from the stack frame by a BIAS of 2047
|
||||
(0x7ff) for 64-bit code. BIAS is likely to be defined on SPARC
|
||||
hosts, so undefine it first. */
|
||||
#undef BIAS
|
||||
#define BIAS 2047
|
||||
|
||||
#ifdef HAVE_SYS_REG_H
|
||||
#include <sys/reg.h>
|
||||
#endif
|
||||
|
||||
#define INSN_SIZE 4
|
||||
|
||||
#define SPARC_R_REGS_NUM 32
|
||||
#define SPARC_F_REGS_NUM 48
|
||||
#define SPARC_CONTROL_REGS_NUM 6
|
||||
|
||||
#define sparc_num_regs (SPARC_R_REGS_NUM + SPARC_F_REGS_NUM + SPARC_CONTROL_REGS_NUM)
|
||||
|
||||
/* Each offset is multiplied by 8, because of the register size.
|
||||
These offsets apply to the buffer sent/filled by ptrace.
|
||||
Additionally, the array elements order corresponds to the .dat file, and the
|
||||
gdb's registers enumeration order. */
|
||||
|
||||
static int sparc_regmap[] = {
|
||||
/* These offsets correspond to GET/SETREGSET. */
|
||||
-1, 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, /* g0 .. g7 */
|
||||
7*8, 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, /* o0 .. o5, sp, o7 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, /* l0 .. l7 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, /* i0 .. i5, fp, i7 */
|
||||
|
||||
/* Floating point registers offsets correspond to GET/SETFPREGSET. */
|
||||
0*4, 1*4, 2*4, 3*4, 4*4, 5*4, 6*4, 7*4, /* f0 .. f7 */
|
||||
8*4, 9*4, 10*4, 11*4, 12*4, 13*4, 14*4, 15*4, /* f8 .. f15 */
|
||||
16*4, 17*4, 18*4, 19*4, 20*4, 21*4, 22*4, 23*4, /* f16 .. f23 */
|
||||
24*4, 25*4, 26*4, 27*4, 28*4, 29*4, 30*4, 31*4, /* f24 .. f31 */
|
||||
|
||||
/* F32 offset starts next to f31: 31*4+4 = 16 * 8. */
|
||||
16*8, 17*8, 18*8, 19*8, 20*8, 21*8, 22*8, 23*8, /* f32 .. f46 */
|
||||
24*8, 25*8, 26*8, 27*8, 28*8, 29*8, 30*8, 31*8, /* f48 .. f62 */
|
||||
|
||||
17 *8, /* pc */
|
||||
18 *8, /* npc */
|
||||
16 *8, /* state */
|
||||
/* FSR offset also corresponds to GET/SETFPREGSET, ans is placed next to f62. */
|
||||
32 *8, /* fsr */
|
||||
-1, /* fprs */
|
||||
/* Y register is 32-bits length, but gdb takes care of that. */
|
||||
19 *8, /* y */
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct regs_range_t
|
||||
{
|
||||
int regno_start;
|
||||
int regno_end;
|
||||
};
|
||||
|
||||
static const struct regs_range_t gregs_ranges[] = {
|
||||
{ 0, 31 }, /* g0 .. i7 */
|
||||
{ 80, 82 }, /* pc .. state */
|
||||
{ 84, 85 } /* fprs .. y */
|
||||
};
|
||||
|
||||
#define N_GREGS_RANGES (sizeof (gregs_ranges) / sizeof (struct regs_range_t))
|
||||
|
||||
static const struct regs_range_t fpregs_ranges[] = {
|
||||
{ 32, 79 }, /* f0 .. f62 */
|
||||
{ 83, 83 } /* fsr */
|
||||
};
|
||||
|
||||
#define N_FPREGS_RANGES (sizeof (fpregs_ranges) / sizeof (struct regs_range_t))
|
||||
|
||||
/* Defined in auto-generated file reg-sparc64.c. */
|
||||
void init_registers_sparc64 (void);
|
||||
|
||||
static int
|
||||
sparc_cannot_store_register (int regno)
|
||||
{
|
||||
return (regno >= sparc_num_regs || sparc_regmap[regno] == -1);
|
||||
}
|
||||
|
||||
static int
|
||||
sparc_cannot_fetch_register (int regno)
|
||||
{
|
||||
return (regno >= sparc_num_regs || sparc_regmap[regno] == -1);
|
||||
}
|
||||
|
||||
static void
|
||||
sparc_fill_gregset_to_stack (const void *buf)
|
||||
{
|
||||
int i;
|
||||
CORE_ADDR addr = 0;
|
||||
unsigned char tmp_reg_buf[8];
|
||||
const int l0_regno = find_regno("l0");
|
||||
const int i7_regno = l0_regno + 15;
|
||||
|
||||
/* These registers have to be stored in the stack. */
|
||||
memcpy(&addr, ((char *) buf) + sparc_regmap[find_regno("sp")], sizeof(addr));
|
||||
|
||||
addr += BIAS;
|
||||
|
||||
for (i = l0_regno; i <= i7_regno; i++)
|
||||
{
|
||||
collect_register (i, tmp_reg_buf);
|
||||
(*the_target->write_memory) (addr, tmp_reg_buf, sizeof(tmp_reg_buf));
|
||||
addr += sizeof(tmp_reg_buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sparc_fill_gregset (void *buf)
|
||||
{
|
||||
int i;
|
||||
int range;
|
||||
|
||||
for (range = 0; range < N_GREGS_RANGES; range++)
|
||||
for (i = gregs_ranges[range].regno_start; i <= gregs_ranges[range].regno_end; i++)
|
||||
if (sparc_regmap[i] != -1)
|
||||
collect_register (i, ((char *) buf) + sparc_regmap[i]);
|
||||
|
||||
sparc_fill_gregset_to_stack (buf);
|
||||
}
|
||||
|
||||
static void
|
||||
sparc_fill_fpregset (void *buf)
|
||||
{
|
||||
int i;
|
||||
int range;
|
||||
|
||||
for (range = 0; range < N_FPREGS_RANGES; range++)
|
||||
for (i = fpregs_ranges[range].regno_start; i <= fpregs_ranges[range].regno_end; i++)
|
||||
collect_register (i, ((char *) buf) + sparc_regmap[i]);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
sparc_store_gregset_from_stack (const void *buf)
|
||||
{
|
||||
int i;
|
||||
CORE_ADDR addr = 0;
|
||||
unsigned char tmp_reg_buf[8];
|
||||
const int l0_regno = find_regno("l0");
|
||||
const int i7_regno = l0_regno + 15;
|
||||
|
||||
/* These registers have to be obtained from the stack. */
|
||||
memcpy(&addr, ((char *) buf) + sparc_regmap[find_regno("sp")], sizeof(addr));
|
||||
|
||||
addr += BIAS;
|
||||
|
||||
for (i = l0_regno; i <= i7_regno; i++)
|
||||
{
|
||||
(*the_target->read_memory) (addr, tmp_reg_buf, sizeof(tmp_reg_buf));
|
||||
supply_register (i, tmp_reg_buf);
|
||||
addr += sizeof(tmp_reg_buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sparc_store_gregset (const void *buf)
|
||||
{
|
||||
int i;
|
||||
char zerobuf[8];
|
||||
int range;
|
||||
|
||||
memset (zerobuf, 0, sizeof(zerobuf));
|
||||
|
||||
for (range = 0; range < N_GREGS_RANGES; range++)
|
||||
for (i = gregs_ranges[range].regno_start; i <= gregs_ranges[range].regno_end; i++)
|
||||
if (sparc_regmap[i] != -1)
|
||||
supply_register (i, ((char *) buf) + sparc_regmap[i]);
|
||||
else
|
||||
supply_register (i, zerobuf);
|
||||
|
||||
sparc_store_gregset_from_stack (buf);
|
||||
}
|
||||
|
||||
static void
|
||||
sparc_store_fpregset (const void *buf)
|
||||
{
|
||||
int i;
|
||||
int range;
|
||||
|
||||
for (range = 0; range < N_FPREGS_RANGES; range++)
|
||||
for (i = fpregs_ranges[range].regno_start; i <= fpregs_ranges[range].regno_end; i++)
|
||||
supply_register (i, ((char *) buf) + sparc_regmap[i]);
|
||||
}
|
||||
|
||||
extern int debug_threads;
|
||||
|
||||
static CORE_ADDR
|
||||
sparc_get_pc ()
|
||||
{
|
||||
CORE_ADDR pc;
|
||||
collect_register_by_name ("pc", &pc);
|
||||
if (debug_threads)
|
||||
fprintf (stderr, "stop pc is %08lx\n", pc);
|
||||
return pc;
|
||||
}
|
||||
|
||||
static const unsigned char sparc_breakpoint[INSN_SIZE] = { 0x91, 0xd0, 0x20, 0x01 };
|
||||
#define sparc_breakpoint_len INSN_SIZE
|
||||
|
||||
|
||||
static int
|
||||
sparc_breakpoint_at (CORE_ADDR where)
|
||||
{
|
||||
unsigned char insn[INSN_SIZE];
|
||||
|
||||
(*the_target->read_memory) (where, (unsigned char *) insn, sizeof(insn));
|
||||
|
||||
if (memcmp(sparc_breakpoint, insn, sizeof(insn)) == 0)
|
||||
return 1;
|
||||
|
||||
/* If necessary, recognize more trap instructions here. GDB only uses TRAP Always. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We only place breakpoints in empty marker functions, and thread locking
|
||||
is outside of the function. So rather than importing software single-step,
|
||||
we can just run until exit. */
|
||||
static CORE_ADDR
|
||||
sparc_reinsert_addr ()
|
||||
{
|
||||
CORE_ADDR lr;
|
||||
/* O7 is the equivalent to the 'lr' of other archs. */
|
||||
collect_register_by_name ("o7", &lr);
|
||||
return lr;
|
||||
}
|
||||
|
||||
|
||||
struct regset_info target_regsets[] = {
|
||||
{ PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
|
||||
GENERAL_REGS,
|
||||
sparc_fill_gregset, sparc_store_gregset },
|
||||
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof (fpregset_t),
|
||||
FP_REGS,
|
||||
sparc_fill_fpregset, sparc_store_fpregset },
|
||||
{ 0, 0, -1, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
struct linux_target_ops the_low_target = {
|
||||
init_registers_sparc64,
|
||||
sparc_num_regs,
|
||||
/* No regmap needs to be provided since this impl. doesn't use USRREGS. */
|
||||
NULL,
|
||||
sparc_cannot_fetch_register,
|
||||
sparc_cannot_store_register,
|
||||
sparc_get_pc,
|
||||
/* No sparc_set_pc is needed. */
|
||||
NULL,
|
||||
(const unsigned char *) sparc_breakpoint,
|
||||
sparc_breakpoint_len,
|
||||
sparc_reinsert_addr,
|
||||
0,
|
||||
sparc_breakpoint_at,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL
|
||||
};
|
||||
|
91
gdb/regformats/reg-sparc64.dat
Normal file
91
gdb/regformats/reg-sparc64.dat
Normal file
|
@ -0,0 +1,91 @@
|
|||
name:sparc64
|
||||
expedite:sp,fp,pc,npc,o7
|
||||
64:g0
|
||||
64:g1
|
||||
64:g2
|
||||
64:g3
|
||||
64:g4
|
||||
64:g5
|
||||
64:g6
|
||||
64:g7
|
||||
64:o0
|
||||
64:o1
|
||||
64:o2
|
||||
64:o3
|
||||
64:o4
|
||||
64:o5
|
||||
64:sp
|
||||
64:o7
|
||||
64:l0
|
||||
64:l1
|
||||
64:l2
|
||||
64:l3
|
||||
64:l4
|
||||
64:l5
|
||||
64:l6
|
||||
64:l7
|
||||
64:i0
|
||||
64:i1
|
||||
64:i2
|
||||
64:i3
|
||||
64:i4
|
||||
64:i5
|
||||
64:fp
|
||||
64:i7
|
||||
|
||||
32:f0
|
||||
32:f1
|
||||
32:f2
|
||||
32:f3
|
||||
32:f4
|
||||
32:f5
|
||||
32:f6
|
||||
32:f7
|
||||
32:f8
|
||||
32:f9
|
||||
32:f10
|
||||
32:f11
|
||||
32:f12
|
||||
32:f13
|
||||
32:f14
|
||||
32:f15
|
||||
32:f16
|
||||
32:f17
|
||||
32:f18
|
||||
32:f19
|
||||
32:f20
|
||||
32:f21
|
||||
32:f22
|
||||
32:f23
|
||||
32:f24
|
||||
32:f25
|
||||
32:f26
|
||||
32:f27
|
||||
32:f28
|
||||
32:f29
|
||||
32:f30
|
||||
32:f31
|
||||
|
||||
64:f32
|
||||
64:f34
|
||||
64:f36
|
||||
64:f38
|
||||
64:f40
|
||||
64:f42
|
||||
64:f44
|
||||
64:f46
|
||||
64:f48
|
||||
64:f50
|
||||
64:f52
|
||||
64:f54
|
||||
64:f56
|
||||
64:f58
|
||||
64:f60
|
||||
64:f62
|
||||
|
||||
64:pc
|
||||
64:npc
|
||||
64:state
|
||||
64:fsr
|
||||
64:fprs
|
||||
64:y
|
Loading…
Add table
Add a link
Reference in a new issue