GDBserver
/home/stan/gdb/src/gdb/gdbserver/linux-m68k-low.c
Go to the documentation of this file.
00001 /* GNU/Linux/m68k specific low level interface, for the remote server for GDB.
00002    Copyright (C) 1995-2013 Free Software Foundation, Inc.
00003 
00004    This file is part of GDB.
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 3 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00018 
00019 #include "server.h"
00020 #include "linux-low.h"
00021 
00022 /* Defined in auto-generated file reg-m68k.c.  */
00023 void init_registers_m68k (void);
00024 extern const struct target_desc *tdesc_m68k;
00025 
00026 #ifdef HAVE_SYS_REG_H
00027 #include <sys/reg.h>
00028 #endif
00029 
00030 #define m68k_num_regs 29
00031 #define m68k_num_gregs 18
00032 
00033 /* This table must line up with REGISTER_NAMES in tm-m68k.h */
00034 static int m68k_regmap[] =
00035 {
00036 #ifdef PT_D0
00037   PT_D0 * 4, PT_D1 * 4, PT_D2 * 4, PT_D3 * 4,
00038   PT_D4 * 4, PT_D5 * 4, PT_D6 * 4, PT_D7 * 4,
00039   PT_A0 * 4, PT_A1 * 4, PT_A2 * 4, PT_A3 * 4,
00040   PT_A4 * 4, PT_A5 * 4, PT_A6 * 4, PT_USP * 4,
00041   PT_SR * 4, PT_PC * 4,
00042 #else
00043   14 * 4, 0 * 4, 1 * 4, 2 * 4, 3 * 4, 4 * 4, 5 * 4, 6 * 4,
00044   7 * 4, 8 * 4, 9 * 4, 10 * 4, 11 * 4, 12 * 4, 13 * 4, 15 * 4,
00045   17 * 4, 18 * 4,
00046 #endif
00047 #ifdef PT_FP0
00048   PT_FP0 * 4, PT_FP1 * 4, PT_FP2 * 4, PT_FP3 * 4,
00049   PT_FP4 * 4, PT_FP5 * 4, PT_FP6 * 4, PT_FP7 * 4,
00050   PT_FPCR * 4, PT_FPSR * 4, PT_FPIAR * 4
00051 #else
00052   21 * 4, 24 * 4, 27 * 4, 30 * 4, 33 * 4, 36 * 4,
00053   39 * 4, 42 * 4, 45 * 4, 46 * 4, 47 * 4
00054 #endif
00055 };
00056 
00057 static int
00058 m68k_cannot_store_register (int regno)
00059 {
00060   return (regno >= m68k_num_regs);
00061 }
00062 
00063 static int
00064 m68k_cannot_fetch_register (int regno)
00065 {
00066   return (regno >= m68k_num_regs);
00067 }
00068 
00069 #ifdef HAVE_PTRACE_GETREGS
00070 #include <sys/procfs.h>
00071 #include <sys/ptrace.h>
00072 
00073 static void
00074 m68k_fill_gregset (struct regcache *regcache, void *buf)
00075 {
00076   int i;
00077 
00078   for (i = 0; i < m68k_num_gregs; i++)
00079     collect_register (regcache, i, (char *) buf + m68k_regmap[i]);
00080 }
00081 
00082 static void
00083 m68k_store_gregset (struct regcache *regcache, const void *buf)
00084 {
00085   int i;
00086 
00087   for (i = 0; i < m68k_num_gregs; i++)
00088     supply_register (regcache, i, (const char *) buf + m68k_regmap[i]);
00089 }
00090 
00091 static void
00092 m68k_fill_fpregset (struct regcache *regcache, void *buf)
00093 {
00094   int i;
00095 
00096   for (i = m68k_num_gregs; i < m68k_num_regs; i++)
00097     collect_register (regcache, i, ((char *) buf
00098                          + (m68k_regmap[i] - m68k_regmap[m68k_num_gregs])));
00099 }
00100 
00101 static void
00102 m68k_store_fpregset (struct regcache *regcache, const void *buf)
00103 {
00104   int i;
00105 
00106   for (i = m68k_num_gregs; i < m68k_num_regs; i++)
00107     supply_register (regcache, i, ((const char *) buf
00108                          + (m68k_regmap[i] - m68k_regmap[m68k_num_gregs])));
00109 }
00110 
00111 #endif /* HAVE_PTRACE_GETREGS */
00112 
00113 static struct regset_info m68k_regsets[] = {
00114 #ifdef HAVE_PTRACE_GETREGS
00115   { PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
00116     GENERAL_REGS,
00117     m68k_fill_gregset, m68k_store_gregset },
00118   { PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, sizeof (elf_fpregset_t),
00119     FP_REGS,
00120     m68k_fill_fpregset, m68k_store_fpregset },
00121 #endif /* HAVE_PTRACE_GETREGS */
00122   { 0, 0, 0, -1, -1, NULL, NULL }
00123 };
00124 
00125 static const unsigned char m68k_breakpoint[] = { 0x4E, 0x4F };
00126 #define m68k_breakpoint_len 2
00127 
00128 static CORE_ADDR
00129 m68k_get_pc (struct regcache *regcache)
00130 {
00131   unsigned long pc;
00132 
00133   collect_register_by_name (regcache, "pc", &pc);
00134   return pc;
00135 }
00136 
00137 static void
00138 m68k_set_pc (struct regcache *regcache, CORE_ADDR value)
00139 {
00140   unsigned long newpc = value;
00141 
00142   supply_register_by_name (regcache, "pc", &newpc);
00143 }
00144 
00145 static int
00146 m68k_breakpoint_at (CORE_ADDR pc)
00147 {
00148   unsigned char c[2];
00149 
00150   read_inferior_memory (pc, c, 2);
00151   if (c[0] == 0x4E && c[1] == 0x4F)
00152     return 1;
00153 
00154   return 0;
00155 }
00156 
00157 #include <asm/ptrace.h>
00158 
00159 #ifdef PTRACE_GET_THREAD_AREA
00160 /* Fetch the thread-local storage pointer for libthread_db.  */
00161 
00162 ps_err_e
00163 ps_get_thread_area (const struct ps_prochandle *ph,
00164                     lwpid_t lwpid, int idx, void **base)
00165 {
00166   if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
00167     return PS_ERR;
00168 
00169   /* IDX is the bias from the thread pointer to the beginning of the
00170      thread descriptor.  It has to be subtracted due to implementation
00171      quirks in libthread_db.  */
00172   *base = (void *) ((char *)*base - idx);
00173 
00174   return PS_OK;
00175 }
00176 #endif /* PTRACE_GET_THREAD_AREA */
00177 
00178 static struct regsets_info m68k_regsets_info =
00179   {
00180     m68k_regsets, /* regsets */
00181     0, /* num_regsets */
00182     NULL, /* disabled_regsets */
00183   };
00184 
00185 static struct usrregs_info m68k_usrregs_info =
00186   {
00187     m68k_num_regs,
00188     m68k_regmap,
00189   };
00190 
00191 static struct regs_info regs_info =
00192   {
00193     NULL, /* regset_bitmap */
00194     &m68k_usrregs_info,
00195     &m68k_regsets_info
00196   };
00197 
00198 static const struct regs_info *
00199 m68k_regs_info (void)
00200 {
00201   return &regs_info;
00202 }
00203 
00204 static void
00205 m68k_arch_setup (void)
00206 {
00207   current_process ()->tdesc = tdesc_m68k;
00208 }
00209 
00210 struct linux_target_ops the_low_target = {
00211   m68k_arch_setup,
00212   m68k_regs_info,
00213   m68k_cannot_fetch_register,
00214   m68k_cannot_store_register,
00215   NULL, /* fetch_register */
00216   m68k_get_pc,
00217   m68k_set_pc,
00218   m68k_breakpoint,
00219   m68k_breakpoint_len,
00220   NULL,
00221   2,
00222   m68k_breakpoint_at,
00223 };
00224 
00225 void
00226 initialize_low_arch (void)
00227 {
00228   /* Initialize the Linux target descriptions.  */
00229   init_registers_m68k ();
00230 
00231   initialize_regsets_info (&m68k_regsets_info);
00232 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines