GDB (API)
/home/stan/gdb/src/gdb/aarch64-linux-tdep.c
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines