1 /* Target-dependent code for GNU/Linux AArch64. 2 3 Copyright (C) 2009-2015 Free Software Foundation, Inc. 4 Contributed by ARM Ltd. 5 6 This file is part of GDB. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21 #include "defs.h" 22 23 #include "gdbarch.h" 24 #include "glibc-tdep.h" 25 #include "linux-tdep.h" 26 #include "aarch64-tdep.h" 27 #include "aarch64-linux-tdep.h" 28 #include "osabi.h" 29 #include "solib-svr4.h" 30 #include "symtab.h" 31 #include "tramp-frame.h" 32 #include "trad-frame.h" 33 34 #include "inferior.h" 35 #include "regcache.h" 36 #include "regset.h" 37 38 #include "cli/cli-utils.h" 39 #include "stap-probe.h" 40 #include "parser-defs.h" 41 #include "user-regs.h" 42 #include <ctype.h> 43 44 /* Signal frame handling. 45 46 +------------+ ^ 47 | saved lr | | 48 +->| saved fp |--+ 49 | | | 50 | | | 51 | +------------+ 52 | | saved lr | 53 +--| saved fp | 54 ^ | | 55 | | | 56 | +------------+ 57 ^ | | 58 | | signal | 59 | | | SIGTRAMP_FRAME (struct rt_sigframe) 60 | | saved regs | 61 +--| saved sp |--> interrupted_sp 62 | | saved pc |--> interrupted_pc 63 | | | 64 | +------------+ 65 | | saved lr |--> default_restorer (movz x8, NR_sys_rt_sigreturn; svc 0) 66 +--| saved fp |<- FP 67 | | NORMAL_FRAME 68 | |<- SP 69 +------------+ 70 71 On signal delivery, the kernel will create a signal handler stack 72 frame and setup the return address in LR to point at restorer stub. 73 The signal stack frame is defined by: 74 75 struct rt_sigframe 76 { 77 siginfo_t info; 78 struct ucontext uc; 79 }; 80 81 typedef struct 82 { 83 ... 128 bytes 84 } siginfo_t; 85 86 The ucontext has the following form: 87 struct ucontext 88 { 89 unsigned long uc_flags; 90 struct ucontext *uc_link; 91 stack_t uc_stack; 92 sigset_t uc_sigmask; 93 struct sigcontext uc_mcontext; 94 }; 95 96 typedef struct sigaltstack 97 { 98 void *ss_sp; 99 int ss_flags; 100 size_t ss_size; 101 } stack_t; 102 103 struct sigcontext 104 { 105 unsigned long fault_address; 106 unsigned long regs[31]; 107 unsigned long sp; / * 31 * / 108 unsigned long pc; / * 32 * / 109 unsigned long pstate; / * 33 * / 110 __u8 __reserved[4096] 111 }; 112 113 The restorer stub will always have the form: 114 115 d28015a8 movz x8, #0xad 116 d4000001 svc #0x0 117 118 This is a system call sys_rt_sigreturn. 119 120 We detect signal frames by snooping the return code for the restorer 121 instruction sequence. 122 123 The handler then needs to recover the saved register set from 124 ucontext.uc_mcontext. */ 125 126 /* These magic numbers need to reflect the layout of the kernel 127 defined struct rt_sigframe and ucontext. */ 128 #define AARCH64_SIGCONTEXT_REG_SIZE 8 129 #define AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET 128 130 #define AARCH64_UCONTEXT_SIGCONTEXT_OFFSET 176 131 #define AARCH64_SIGCONTEXT_XO_OFFSET 8 132 133 /* Implement the "init" method of struct tramp_frame. */ 134 135 static void 136 aarch64_linux_sigframe_init (const struct tramp_frame *self, 137 struct frame_info *this_frame, 138 struct trad_frame_cache *this_cache, 139 CORE_ADDR func) 140 { 141 struct gdbarch *gdbarch = get_frame_arch (this_frame); 142 CORE_ADDR sp = get_frame_register_unsigned (this_frame, AARCH64_SP_REGNUM); 143 CORE_ADDR sigcontext_addr = 144 sp 145 + AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET 146 + AARCH64_UCONTEXT_SIGCONTEXT_OFFSET; 147 int i; 148 149 for (i = 0; i < 31; i++) 150 { 151 trad_frame_set_reg_addr (this_cache, 152 AARCH64_X0_REGNUM + i, 153 sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET 154 + i * AARCH64_SIGCONTEXT_REG_SIZE); 155 } 156 trad_frame_set_reg_addr (this_cache, AARCH64_SP_REGNUM, 157 sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET 158 + 31 * AARCH64_SIGCONTEXT_REG_SIZE); 159 trad_frame_set_reg_addr (this_cache, AARCH64_PC_REGNUM, 160 sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET 161 + 32 * AARCH64_SIGCONTEXT_REG_SIZE); 162 163 trad_frame_set_id (this_cache, frame_id_build (sp, func)); 164 } 165 166 static const struct tramp_frame aarch64_linux_rt_sigframe = 167 { 168 SIGTRAMP_FRAME, 169 4, 170 { 171 /* movz x8, 0x8b (S=1,o=10,h=0,i=0x8b,r=8) 172 Soo1 0010 1hhi iiii iiii iiii iiir rrrr */ 173 {0xd2801168, -1}, 174 175 /* svc 0x0 (o=0, l=1) 176 1101 0100 oooi iiii iiii iiii iii0 00ll */ 177 {0xd4000001, -1}, 178 {TRAMP_SENTINEL_INSN, -1} 179 }, 180 aarch64_linux_sigframe_init 181 }; 182 183 /* Register maps. */ 184 185 static const struct regcache_map_entry aarch64_linux_gregmap[] = 186 { 187 { 31, AARCH64_X0_REGNUM, 8 }, /* x0 ... x30 */ 188 { 1, AARCH64_SP_REGNUM, 8 }, 189 { 1, AARCH64_PC_REGNUM, 8 }, 190 { 1, AARCH64_CPSR_REGNUM, 8 }, 191 { 0 } 192 }; 193 194 static const struct regcache_map_entry aarch64_linux_fpregmap[] = 195 { 196 { 32, AARCH64_V0_REGNUM, 16 }, /* v0 ... v31 */ 197 { 1, AARCH64_FPSR_REGNUM, 4 }, 198 { 1, AARCH64_FPCR_REGNUM, 4 }, 199 { 0 } 200 }; 201 202 /* Register set definitions. */ 203 204 const struct regset aarch64_linux_gregset = 205 { 206 aarch64_linux_gregmap, 207 regcache_supply_regset, regcache_collect_regset 208 }; 209 210 const struct regset aarch64_linux_fpregset = 211 { 212 aarch64_linux_fpregmap, 213 regcache_supply_regset, regcache_collect_regset 214 }; 215 216 /* Implement the "regset_from_core_section" gdbarch method. */ 217 218 static void 219 aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, 220 iterate_over_regset_sections_cb *cb, 221 void *cb_data, 222 const struct regcache *regcache) 223 { 224 cb (".reg", AARCH64_LINUX_SIZEOF_GREGSET, &aarch64_linux_gregset, 225 NULL, cb_data); 226 cb (".reg2", AARCH64_LINUX_SIZEOF_FPREGSET, &aarch64_linux_fpregset, 227 NULL, cb_data); 228 } 229 230 /* Implementation of `gdbarch_stap_is_single_operand', as defined in 231 gdbarch.h. */ 232 233 static int 234 aarch64_stap_is_single_operand (struct gdbarch *gdbarch, const char *s) 235 { 236 return (*s == '#' || isdigit (*s) /* Literal number. */ 237 || *s == '[' /* Register indirection. */ 238 || isalpha (*s)); /* Register value. */ 239 } 240 241 /* This routine is used to parse a special token in AArch64's assembly. 242 243 The special tokens parsed by it are: 244 245 - Register displacement (e.g, [fp, #-8]) 246 247 It returns one if the special token has been parsed successfully, 248 or zero if the current token is not considered special. */ 249 250 static int 251 aarch64_stap_parse_special_token (struct gdbarch *gdbarch, 252 struct stap_parse_info *p) 253 { 254 if (*p->arg == '[') 255 { 256 /* Temporary holder for lookahead. */ 257 const char *tmp = p->arg; 258 char *endp; 259 /* Used to save the register name. */ 260 const char *start; 261 char *regname; 262 int len; 263 int got_minus = 0; 264 long displacement; 265 struct stoken str; 266 267 ++tmp; 268 start = tmp; 269 270 /* Register name. */ 271 while (isalnum (*tmp)) 272 ++tmp; 273 274 if (*tmp != ',') 275 return 0; 276 277 len = tmp - start; 278 regname = alloca (len + 2); 279 280 strncpy (regname, start, len); 281 regname[len] = '\0'; 282 283 if (user_reg_map_name_to_regnum (gdbarch, regname, len) == -1) 284 error (_("Invalid register name `%s' on expression `%s'."), 285 regname, p->saved_arg); 286 287 ++tmp; 288 tmp = skip_spaces_const (tmp); 289 /* Now we expect a number. It can begin with '#' or simply 290 a digit. */ 291 if (*tmp == '#') 292 ++tmp; 293 294 if (*tmp == '-') 295 { 296 ++tmp; 297 got_minus = 1; 298 } 299 else if (*tmp == '+') 300 ++tmp; 301 302 if (!isdigit (*tmp)) 303 return 0; 304 305 displacement = strtol (tmp, &endp, 10); 306 tmp = endp; 307 308 /* Skipping last `]'. */ 309 if (*tmp++ != ']') 310 return 0; 311 312 /* The displacement. */ 313 write_exp_elt_opcode (&p->pstate, OP_LONG); 314 write_exp_elt_type (&p->pstate, builtin_type (gdbarch)->builtin_long); 315 write_exp_elt_longcst (&p->pstate, displacement); 316 write_exp_elt_opcode (&p->pstate, OP_LONG); 317 if (got_minus) 318 write_exp_elt_opcode (&p->pstate, UNOP_NEG); 319 320 /* The register name. */ 321 write_exp_elt_opcode (&p->pstate, OP_REGISTER); 322 str.ptr = regname; 323 str.length = len; 324 write_exp_string (&p->pstate, str); 325 write_exp_elt_opcode (&p->pstate, OP_REGISTER); 326 327 write_exp_elt_opcode (&p->pstate, BINOP_ADD); 328 329 /* Casting to the expected type. */ 330 write_exp_elt_opcode (&p->pstate, UNOP_CAST); 331 write_exp_elt_type (&p->pstate, lookup_pointer_type (p->arg_type)); 332 write_exp_elt_opcode (&p->pstate, UNOP_CAST); 333 334 write_exp_elt_opcode (&p->pstate, UNOP_IND); 335 336 p->arg = tmp; 337 } 338 else 339 return 0; 340 341 return 1; 342 } 343 344 static void 345 aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 346 { 347 static const char *const stap_integer_prefixes[] = { "#", "", NULL }; 348 static const char *const stap_register_prefixes[] = { "", NULL }; 349 static const char *const stap_register_indirection_prefixes[] = { "[", 350 NULL }; 351 static const char *const stap_register_indirection_suffixes[] = { "]", 352 NULL }; 353 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 354 355 tdep->lowest_pc = 0x8000; 356 357 linux_init_abi (info, gdbarch); 358 359 set_solib_svr4_fetch_link_map_offsets (gdbarch, 360 svr4_lp64_fetch_link_map_offsets); 361 362 /* Enable TLS support. */ 363 set_gdbarch_fetch_tls_load_module_address (gdbarch, 364 svr4_fetch_objfile_link_map); 365 366 /* Shared library handling. */ 367 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); 368 369 set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type); 370 tramp_frame_prepend_unwinder (gdbarch, &aarch64_linux_rt_sigframe); 371 372 /* Enable longjmp. */ 373 tdep->jb_pc = 11; 374 375 set_gdbarch_iterate_over_regset_sections 376 (gdbarch, aarch64_linux_iterate_over_regset_sections); 377 378 /* SystemTap related. */ 379 set_gdbarch_stap_integer_prefixes (gdbarch, stap_integer_prefixes); 380 set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes); 381 set_gdbarch_stap_register_indirection_prefixes (gdbarch, 382 stap_register_indirection_prefixes); 383 set_gdbarch_stap_register_indirection_suffixes (gdbarch, 384 stap_register_indirection_suffixes); 385 set_gdbarch_stap_is_single_operand (gdbarch, aarch64_stap_is_single_operand); 386 set_gdbarch_stap_parse_special_token (gdbarch, 387 aarch64_stap_parse_special_token); 388 } 389 390 /* Provide a prototype to silence -Wmissing-prototypes. */ 391 extern initialize_file_ftype _initialize_aarch64_linux_tdep; 392 393 void 394 _initialize_aarch64_linux_tdep (void) 395 { 396 gdbarch_register_osabi (bfd_arch_aarch64, 0, GDB_OSABI_LINUX, 397 aarch64_linux_init_abi); 398 } 399