GDB (API)
|
00001 /* Target-dependent code for GNU/Linux AArch64. 00002 00003 Copyright (C) 2009-2013 Free Software Foundation, Inc. 00004 Contributed by ARM Ltd. 00005 00006 This file is part of GDB. 00007 00008 This program is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 This program is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00020 00021 #include "defs.h" 00022 00023 #include "gdbarch.h" 00024 #include "glibc-tdep.h" 00025 #include "linux-tdep.h" 00026 #include "aarch64-tdep.h" 00027 #include "aarch64-linux-tdep.h" 00028 #include "osabi.h" 00029 #include "solib-svr4.h" 00030 #include "symtab.h" 00031 #include "tramp-frame.h" 00032 #include "trad-frame.h" 00033 00034 #include "inferior.h" 00035 #include "regcache.h" 00036 #include "regset.h" 00037 00038 /* The general-purpose regset consists of 31 X registers, plus SP, PC, 00039 and PSTATE registers, as defined in the AArch64 port of the Linux 00040 kernel. */ 00041 #define AARCH64_LINUX_SIZEOF_GREGSET (34 * X_REGISTER_SIZE) 00042 00043 /* The fp regset consists of 32 V registers, plus FPCR and FPSR which 00044 are 4 bytes wide each, and the whole structure is padded to 128 bit 00045 alignment. */ 00046 #define AARCH64_LINUX_SIZEOF_FPREGSET (33 * V_REGISTER_SIZE) 00047 00048 /* Signal frame handling. 00049 00050 +----------+ ^ 00051 | saved lr | | 00052 +->| saved fp |--+ 00053 | | | 00054 | | | 00055 | +----------+ 00056 | | saved lr | 00057 +--| saved fp | 00058 ^ | | 00059 | | | 00060 | +----------+ 00061 ^ | | 00062 | | signal | 00063 | | | 00064 | | saved lr |-->interrupted_function_pc 00065 +--| saved fp | 00066 | +----------+ 00067 | | saved lr |--> default_restorer (movz x8, NR_sys_rt_sigreturn; svc 0) 00068 +--| saved fp |<- FP 00069 | | 00070 | |<- SP 00071 +----------+ 00072 00073 On signal delivery, the kernel will create a signal handler stack 00074 frame and setup the return address in LR to point at restorer stub. 00075 The signal stack frame is defined by: 00076 00077 struct rt_sigframe 00078 { 00079 siginfo_t info; 00080 struct ucontext uc; 00081 }; 00082 00083 typedef struct 00084 { 00085 ... 128 bytes 00086 } siginfo_t; 00087 00088 The ucontext has the following form: 00089 struct ucontext 00090 { 00091 unsigned long uc_flags; 00092 struct ucontext *uc_link; 00093 stack_t uc_stack; 00094 sigset_t uc_sigmask; 00095 struct sigcontext uc_mcontext; 00096 }; 00097 00098 typedef struct sigaltstack 00099 { 00100 void *ss_sp; 00101 int ss_flags; 00102 size_t ss_size; 00103 } stack_t; 00104 00105 struct sigcontext 00106 { 00107 unsigned long fault_address; 00108 unsigned long regs[31]; 00109 unsigned long sp; / * 31 * / 00110 unsigned long pc; / * 32 * / 00111 unsigned long pstate; / * 33 * / 00112 __u8 __reserved[4096] 00113 }; 00114 00115 The restorer stub will always have the form: 00116 00117 d28015a8 movz x8, #0xad 00118 d4000001 svc #0x0 00119 00120 We detect signal frames by snooping the return code for the restorer 00121 instruction sequence. 00122 00123 The handler then needs to recover the saved register set from 00124 ucontext.uc_mcontext. */ 00125 00126 /* These magic numbers need to reflect the layout of the kernel 00127 defined struct rt_sigframe and ucontext. */ 00128 #define AARCH64_SIGCONTEXT_REG_SIZE 8 00129 #define AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET 128 00130 #define AARCH64_UCONTEXT_SIGCONTEXT_OFFSET 176 00131 #define AARCH64_SIGCONTEXT_XO_OFFSET 8 00132 00133 /* Implement the "init" method of struct tramp_frame. */ 00134 00135 static void 00136 aarch64_linux_sigframe_init (const struct tramp_frame *self, 00137 struct frame_info *this_frame, 00138 struct trad_frame_cache *this_cache, 00139 CORE_ADDR func) 00140 { 00141 struct gdbarch *gdbarch = get_frame_arch (this_frame); 00142 CORE_ADDR sp = get_frame_register_unsigned (this_frame, AARCH64_SP_REGNUM); 00143 CORE_ADDR fp = get_frame_register_unsigned (this_frame, AARCH64_FP_REGNUM); 00144 CORE_ADDR sigcontext_addr = 00145 sp 00146 + AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET 00147 + AARCH64_UCONTEXT_SIGCONTEXT_OFFSET; 00148 int i; 00149 00150 for (i = 0; i < 31; i++) 00151 { 00152 trad_frame_set_reg_addr (this_cache, 00153 AARCH64_X0_REGNUM + i, 00154 sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET 00155 + i * AARCH64_SIGCONTEXT_REG_SIZE); 00156 } 00157 00158 trad_frame_set_reg_addr (this_cache, AARCH64_FP_REGNUM, fp); 00159 trad_frame_set_reg_addr (this_cache, AARCH64_LR_REGNUM, fp + 8); 00160 trad_frame_set_reg_addr (this_cache, AARCH64_PC_REGNUM, fp + 8); 00161 00162 trad_frame_set_id (this_cache, frame_id_build (fp, func)); 00163 } 00164 00165 static const struct tramp_frame aarch64_linux_rt_sigframe = 00166 { 00167 SIGTRAMP_FRAME, 00168 4, 00169 { 00170 /* movz x8, 0x8b (S=1,o=10,h=0,i=0x8b,r=8) 00171 Soo1 0010 1hhi iiii iiii iiii iiir rrrr */ 00172 {0xd2801168, -1}, 00173 00174 /* svc 0x0 (o=0, l=1) 00175 1101 0100 oooi iiii iiii iiii iii0 00ll */ 00176 {0xd4000001, -1}, 00177 {TRAMP_SENTINEL_INSN, -1} 00178 }, 00179 aarch64_linux_sigframe_init 00180 }; 00181 00182 /* Fill GDB's register array with the general-purpose register values 00183 in the buffer pointed by GREGS_BUF. */ 00184 00185 void 00186 aarch64_linux_supply_gregset (struct regcache *regcache, 00187 const gdb_byte *gregs_buf) 00188 { 00189 int regno; 00190 00191 for (regno = AARCH64_X0_REGNUM; regno <= AARCH64_CPSR_REGNUM; regno++) 00192 regcache_raw_supply (regcache, regno, 00193 gregs_buf + X_REGISTER_SIZE 00194 * (regno - AARCH64_X0_REGNUM)); 00195 } 00196 00197 /* The "supply_regset" function for the general-purpose register set. */ 00198 00199 static void 00200 supply_gregset_from_core (const struct regset *regset, 00201 struct regcache *regcache, 00202 int regnum, const void *regbuf, size_t len) 00203 { 00204 aarch64_linux_supply_gregset (regcache, (const gdb_byte *) regbuf); 00205 } 00206 00207 /* Fill GDB's register array with the floating-point register values 00208 in the buffer pointed by FPREGS_BUF. */ 00209 00210 void 00211 aarch64_linux_supply_fpregset (struct regcache *regcache, 00212 const gdb_byte *fpregs_buf) 00213 { 00214 int regno; 00215 00216 for (regno = AARCH64_V0_REGNUM; regno <= AARCH64_V31_REGNUM; regno++) 00217 regcache_raw_supply (regcache, regno, 00218 fpregs_buf + V_REGISTER_SIZE 00219 * (regno - AARCH64_V0_REGNUM)); 00220 00221 regcache_raw_supply (regcache, AARCH64_FPSR_REGNUM, 00222 fpregs_buf + V_REGISTER_SIZE * 32); 00223 regcache_raw_supply (regcache, AARCH64_FPCR_REGNUM, 00224 fpregs_buf + V_REGISTER_SIZE * 32 + 4); 00225 } 00226 00227 /* The "supply_regset" function for the floating-point register set. */ 00228 00229 static void 00230 supply_fpregset_from_core (const struct regset *regset, 00231 struct regcache *regcache, 00232 int regnum, const void *regbuf, size_t len) 00233 { 00234 aarch64_linux_supply_fpregset (regcache, (const gdb_byte *) regbuf); 00235 } 00236 00237 /* Implement the "regset_from_core_section" gdbarch method. */ 00238 00239 static const struct regset * 00240 aarch64_linux_regset_from_core_section (struct gdbarch *gdbarch, 00241 const char *sect_name, 00242 size_t sect_size) 00243 { 00244 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00245 00246 if (strcmp (sect_name, ".reg") == 0 00247 && sect_size == AARCH64_LINUX_SIZEOF_GREGSET) 00248 { 00249 if (tdep->gregset == NULL) 00250 tdep->gregset = regset_alloc (gdbarch, supply_gregset_from_core, 00251 NULL); 00252 return tdep->gregset; 00253 } 00254 00255 if (strcmp (sect_name, ".reg2") == 0 00256 && sect_size == AARCH64_LINUX_SIZEOF_FPREGSET) 00257 { 00258 if (tdep->fpregset == NULL) 00259 tdep->fpregset = regset_alloc (gdbarch, supply_fpregset_from_core, 00260 NULL); 00261 return tdep->fpregset; 00262 } 00263 return NULL; 00264 } 00265 00266 static void 00267 aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 00268 { 00269 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00270 00271 tdep->lowest_pc = 0x8000; 00272 00273 linux_init_abi (info, gdbarch); 00274 00275 set_solib_svr4_fetch_link_map_offsets (gdbarch, 00276 svr4_lp64_fetch_link_map_offsets); 00277 00278 /* Enable TLS support. */ 00279 set_gdbarch_fetch_tls_load_module_address (gdbarch, 00280 svr4_fetch_objfile_link_map); 00281 00282 /* Shared library handling. */ 00283 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); 00284 00285 set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type); 00286 tramp_frame_prepend_unwinder (gdbarch, &aarch64_linux_rt_sigframe); 00287 00288 /* Enable longjmp. */ 00289 tdep->jb_pc = 11; 00290 00291 set_gdbarch_regset_from_core_section (gdbarch, 00292 aarch64_linux_regset_from_core_section); 00293 } 00294 00295 /* Provide a prototype to silence -Wmissing-prototypes. */ 00296 extern initialize_file_ftype _initialize_aarch64_linux_tdep; 00297 00298 void 00299 _initialize_aarch64_linux_tdep (void) 00300 { 00301 gdbarch_register_osabi (bfd_arch_aarch64, 0, GDB_OSABI_LINUX, 00302 aarch64_linux_init_abi); 00303 }