1/* Target-dependent code for GNU/Linux on CSKY. 2 3 Copyright (C) 2012-2020 Free Software Foundation, Inc. 4 5 Contributed by C-SKY Microsystems and Mentor Graphics. 6 7 This file is part of GDB. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 21 22#include "defs.h" 23#include "osabi.h" 24#include "glibc-tdep.h" 25#include "linux-tdep.h" 26#include "gdbarch.h" 27#include "solib-svr4.h" 28#include "regset.h" 29#include "trad-frame.h" 30#include "tramp-frame.h" 31#include "csky-tdep.h" 32 33/* Functions, definitions, and data structures for C-Sky core file debug. */ 34 35/* General regset pc, r1, r0, psr, r2-r31 for CK810. */ 36#define SIZEOF_CSKY_GREGSET 34*4 37/* Float regset fesr fsr fr0-fr31 for CK810. */ 38#define SIZEOF_CSKY_FREGSET 34*4 39 40/* Offset mapping table from core_section to regcache of general 41 registers for ck810. */ 42static const int csky_gregset_offset[] = 43{ 44 72, 1, 0, 89, 2, /* pc, r1, r0, psr, r2. */ 45 3, 4, 5, 6, 7, /* r3 ~ r32. */ 46 8, 9, 10, 11, 12, 47 13, 14, 15, 16, 17, 48 18, 19, 20, 21, 22, 49 23, 24, 25, 26, 27, 50 28, 29, 30, 31 51}; 52 53/* Offset mapping table from core_section to regcache of float 54 registers for ck810. */ 55 56static const int csky_fregset_offset[] = 57{ 58 122, 123, 40, 41, 42, /* fcr, fesr, fr0 ~ fr2. */ 59 43, 44, 45, 46, 47, /* fr3 ~ fr15. */ 60 48, 49, 50, 51, 52, 61 53, 54, 55 62}; 63 64/* Implement the supply_regset hook for GP registers in core files. */ 65 66static void 67csky_supply_gregset (const struct regset *regset, 68 struct regcache *regcache, int regnum, 69 const void *regs, size_t len) 70{ 71 int i, gregset_num; 72 const gdb_byte *gregs = (const gdb_byte *) regs ; 73 74 gdb_assert (len >= SIZEOF_CSKY_GREGSET); 75 gregset_num = ARRAY_SIZE (csky_gregset_offset); 76 77 for (i = 0; i < gregset_num; i++) 78 { 79 if ((regnum == csky_gregset_offset[i] || regnum == -1) 80 && csky_gregset_offset[i] != -1) 81 regcache->raw_supply (csky_gregset_offset[i], gregs + 4 * i); 82 } 83} 84 85/* Implement the collect_regset hook for GP registers in core files. */ 86 87static void 88csky_collect_gregset (const struct regset *regset, 89 const struct regcache *regcache, 90 int regnum, void *gregs_buf, size_t len) 91{ 92 int regno, gregset_num; 93 gdb_byte *gregs = (gdb_byte *) gregs_buf ; 94 95 gdb_assert (len >= SIZEOF_CSKY_GREGSET); 96 gregset_num = ARRAY_SIZE (csky_gregset_offset); 97 98 for (regno = 0; regno < gregset_num; regno++) 99 { 100 if ((regnum == csky_gregset_offset[regno] || regnum == -1) 101 && csky_gregset_offset[regno] != -1) 102 regcache->raw_collect (regno, 103 gregs + 4 + csky_gregset_offset[regno]); 104 } 105} 106 107/* Implement the supply_regset hook for FP registers in core files. */ 108 109static void 110csky_supply_fregset (const struct regset *regset, 111 struct regcache *regcache, int regnum, 112 const void *regs, size_t len) 113{ 114 int i; 115 int offset = 0; 116 struct gdbarch *gdbarch = regcache->arch (); 117 const gdb_byte *fregs = (const gdb_byte *) regs; 118 int fregset_num = ARRAY_SIZE (csky_fregset_offset); 119 120 gdb_assert (len >= SIZEOF_CSKY_FREGSET); 121 for (i = 0; i < fregset_num; i++) 122 { 123 if ((regnum == csky_fregset_offset[i] || regnum == -1) 124 && csky_fregset_offset[i] != -1) 125 { 126 int num = csky_fregset_offset[i]; 127 offset += register_size (gdbarch, num); 128 regcache->raw_supply (csky_fregset_offset[i], fregs + offset); 129 } 130 } 131} 132 133/* Implement the collect_regset hook for FP registers in core files. */ 134 135static void 136csky_collect_fregset (const struct regset *regset, 137 const struct regcache *regcache, 138 int regnum, void *fregs_buf, size_t len) 139{ 140 int regno; 141 struct gdbarch *gdbarch = regcache->arch (); 142 gdb_byte *fregs = (gdb_byte *) fregs_buf ; 143 int fregset_num = ARRAY_SIZE (csky_fregset_offset); 144 int offset = 0; 145 146 gdb_assert (len >= SIZEOF_CSKY_FREGSET); 147 for (regno = 0; regno < fregset_num; regno++) 148 { 149 if ((regnum == csky_fregset_offset[regno] || regnum == -1) 150 && csky_fregset_offset[regno] != -1) 151 { 152 offset += register_size (gdbarch, csky_fregset_offset[regno]); 153 regcache->raw_collect (regno, fregs + offset); 154 } 155 } 156} 157 158static const struct regset csky_regset_general = 159{ 160 NULL, 161 csky_supply_gregset, 162 csky_collect_gregset 163}; 164 165static const struct regset csky_regset_float = 166{ 167 NULL, 168 csky_supply_fregset, 169 csky_collect_fregset 170}; 171 172/* Iterate over core file register note sections. */ 173 174static void 175csky_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, 176 iterate_over_regset_sections_cb *cb, 177 void *cb_data, 178 const struct regcache *regcache) 179{ 180 cb (".reg", sizeof (csky_gregset_offset), sizeof (csky_gregset_offset), 181 &csky_regset_general, NULL, cb_data); 182 cb (".reg2", sizeof (csky_fregset_offset), sizeof (csky_fregset_offset), 183 &csky_regset_float, NULL, cb_data); 184} 185 186static void 187csky_linux_rt_sigreturn_init (const struct tramp_frame *self, 188 struct frame_info *this_frame, 189 struct trad_frame_cache *this_cache, 190 CORE_ADDR func) 191{ 192 int i; 193 CORE_ADDR sp = get_frame_register_unsigned (this_frame, 14); 194 195 CORE_ADDR base = sp + CSKY_SIGINFO_OFFSET + CSKY_SIGINFO_SIZE 196 + CSKY_UCONTEXT_SIGCONTEXT 197 + CSKY_SIGCONTEXT_SC_USP 198 + CSKY_SIGCONTEXT_SC_A0; 199 200 /* Set addrs of R0 ~ R13. */ 201 for (i = 0; i < 14; i++) 202 trad_frame_set_reg_addr (this_cache, i, base + i * 4); 203 204 /* Set addrs of SP(R14) and R15. */ 205 trad_frame_set_reg_addr (this_cache, 14, base - 4); 206 trad_frame_set_reg_addr (this_cache, 15, base + 4 * 14); 207 208 /* Set addrs of R16 ~ R31. */ 209 for (i = 15; i < 31; i++) 210 trad_frame_set_reg_addr (this_cache, i, base + i * 4); 211 212 /* Set addrs of PSR and PC. */ 213 trad_frame_set_reg_addr (this_cache, 89, base + 4 * 33); 214 trad_frame_set_reg_addr (this_cache, 72, base + 4 * 34); 215 216 trad_frame_set_id (this_cache, frame_id_build (sp, func)); 217} 218 219static struct tramp_frame 220csky_linux_rt_sigreturn_tramp_frame = { 221 SIGTRAMP_FRAME, 222 4, 223 { 224 { CSKY_MOVI_R7_173, ULONGEST_MAX }, 225 { CSKY_TRAP_0, ULONGEST_MAX }, 226 { TRAMP_SENTINEL_INSN } 227 }, 228 csky_linux_rt_sigreturn_init 229}; 230 231/* Hook function for gdbarch_register_osabi. */ 232 233static void 234csky_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 235{ 236 linux_init_abi (info, gdbarch); 237 238 /* Shared library handling. */ 239 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); 240 set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver); 241 set_solib_svr4_fetch_link_map_offsets (gdbarch, 242 svr4_ilp32_fetch_link_map_offsets); 243 244 /* Enable TLS support. */ 245 set_gdbarch_fetch_tls_load_module_address (gdbarch, 246 svr4_fetch_objfile_link_map); 247 248 /* Core file support. */ 249 set_gdbarch_iterate_over_regset_sections ( 250 gdbarch, csky_linux_iterate_over_regset_sections); 251 252 /* Append tramp frame unwinder for SIGNAL. */ 253 254 tramp_frame_prepend_unwinder (gdbarch, 255 &csky_linux_rt_sigreturn_tramp_frame); 256} 257 258void _initialize_csky_linux_tdep (); 259void 260_initialize_csky_linux_tdep () 261{ 262 gdbarch_register_osabi (bfd_arch_csky, 0, GDB_OSABI_LINUX, 263 csky_linux_init_abi); 264} 265