GDBserver
|
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 ®s_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 }