GDB (API)
/home/stan/gdb/src/gdb/arm-linux-nat.c
Go to the documentation of this file.
00001 /* GNU/Linux on ARM native support.
00002    Copyright (C) 1999-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 "defs.h"
00020 #include "inferior.h"
00021 #include "gdbcore.h"
00022 #include "gdb_string.h"
00023 #include "regcache.h"
00024 #include "target.h"
00025 #include "linux-nat.h"
00026 #include "target-descriptions.h"
00027 #include "auxv.h"
00028 #include "observer.h"
00029 #include "gdbthread.h"
00030 
00031 #include "arm-tdep.h"
00032 #include "arm-linux-tdep.h"
00033 
00034 #include <elf/common.h>
00035 #include <sys/user.h>
00036 #include <sys/ptrace.h>
00037 #include <sys/utsname.h>
00038 #include <sys/procfs.h>
00039 
00040 /* Prototypes for supply_gregset etc.  */
00041 #include "gregset.h"
00042 
00043 /* Defines ps_err_e, struct ps_prochandle.  */
00044 #include "gdb_proc_service.h"
00045 
00046 #ifndef PTRACE_GET_THREAD_AREA
00047 #define PTRACE_GET_THREAD_AREA 22
00048 #endif
00049 
00050 #ifndef PTRACE_GETWMMXREGS
00051 #define PTRACE_GETWMMXREGS 18
00052 #define PTRACE_SETWMMXREGS 19
00053 #endif
00054 
00055 #ifndef PTRACE_GETVFPREGS
00056 #define PTRACE_GETVFPREGS 27
00057 #define PTRACE_SETVFPREGS 28
00058 #endif
00059 
00060 #ifndef PTRACE_GETHBPREGS
00061 #define PTRACE_GETHBPREGS 29
00062 #define PTRACE_SETHBPREGS 30
00063 #endif
00064 
00065 /* A flag for whether the WMMX registers are available.  */
00066 static int arm_linux_has_wmmx_registers;
00067 
00068 /* The number of 64-bit VFP registers we have (expect this to be 0,
00069    16, or 32).  */
00070 static int arm_linux_vfp_register_count;
00071 
00072 extern int arm_apcs_32;
00073 
00074 /* On GNU/Linux, threads are implemented as pseudo-processes, in which
00075    case we may be tracing more than one process at a time.  In that
00076    case, inferior_ptid will contain the main process ID and the
00077    individual thread (process) ID.  get_thread_id () is used to get
00078    the thread id if it's available, and the process id otherwise.  */
00079 
00080 static int
00081 get_thread_id (ptid_t ptid)
00082 {
00083   int tid = ptid_get_lwp (ptid);
00084   if (0 == tid)
00085     tid = ptid_get_pid (ptid);
00086   return tid;
00087 }
00088 
00089 #define GET_THREAD_ID(PTID)     get_thread_id (PTID)
00090 
00091 /* Get the value of a particular register from the floating point
00092    state of the process and store it into regcache.  */
00093 
00094 static void
00095 fetch_fpregister (struct regcache *regcache, int regno)
00096 {
00097   int ret, tid;
00098   gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
00099   
00100   /* Get the thread id for the ptrace call.  */
00101   tid = GET_THREAD_ID (inferior_ptid);
00102 
00103   /* Read the floating point state.  */
00104   ret = ptrace (PT_GETFPREGS, tid, 0, fp);
00105   if (ret < 0)
00106     {
00107       warning (_("Unable to fetch floating point register."));
00108       return;
00109     }
00110 
00111   /* Fetch fpsr.  */
00112   if (ARM_FPS_REGNUM == regno)
00113     regcache_raw_supply (regcache, ARM_FPS_REGNUM,
00114                          fp + NWFPE_FPSR_OFFSET);
00115 
00116   /* Fetch the floating point register.  */
00117   if (regno >= ARM_F0_REGNUM && regno <= ARM_F7_REGNUM)
00118     supply_nwfpe_register (regcache, regno, fp);
00119 }
00120 
00121 /* Get the whole floating point state of the process and store it
00122    into regcache.  */
00123 
00124 static void
00125 fetch_fpregs (struct regcache *regcache)
00126 {
00127   int ret, regno, tid;
00128   gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
00129 
00130   /* Get the thread id for the ptrace call.  */
00131   tid = GET_THREAD_ID (inferior_ptid);
00132   
00133   /* Read the floating point state.  */
00134   ret = ptrace (PT_GETFPREGS, tid, 0, fp);
00135   if (ret < 0)
00136     {
00137       warning (_("Unable to fetch the floating point registers."));
00138       return;
00139     }
00140 
00141   /* Fetch fpsr.  */
00142   regcache_raw_supply (regcache, ARM_FPS_REGNUM,
00143                        fp + NWFPE_FPSR_OFFSET);
00144 
00145   /* Fetch the floating point registers.  */
00146   for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
00147     supply_nwfpe_register (regcache, regno, fp);
00148 }
00149 
00150 /* Save a particular register into the floating point state of the
00151    process using the contents from regcache.  */
00152 
00153 static void
00154 store_fpregister (const struct regcache *regcache, int regno)
00155 {
00156   int ret, tid;
00157   gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
00158 
00159   /* Get the thread id for the ptrace call.  */
00160   tid = GET_THREAD_ID (inferior_ptid);
00161   
00162   /* Read the floating point state.  */
00163   ret = ptrace (PT_GETFPREGS, tid, 0, fp);
00164   if (ret < 0)
00165     {
00166       warning (_("Unable to fetch the floating point registers."));
00167       return;
00168     }
00169 
00170   /* Store fpsr.  */
00171   if (ARM_FPS_REGNUM == regno
00172       && REG_VALID == regcache_register_status (regcache, ARM_FPS_REGNUM))
00173     regcache_raw_collect (regcache, ARM_FPS_REGNUM, fp + NWFPE_FPSR_OFFSET);
00174 
00175   /* Store the floating point register.  */
00176   if (regno >= ARM_F0_REGNUM && regno <= ARM_F7_REGNUM)
00177     collect_nwfpe_register (regcache, regno, fp);
00178 
00179   ret = ptrace (PTRACE_SETFPREGS, tid, 0, fp);
00180   if (ret < 0)
00181     {
00182       warning (_("Unable to store floating point register."));
00183       return;
00184     }
00185 }
00186 
00187 /* Save the whole floating point state of the process using
00188    the contents from regcache.  */
00189 
00190 static void
00191 store_fpregs (const struct regcache *regcache)
00192 {
00193   int ret, regno, tid;
00194   gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
00195 
00196   /* Get the thread id for the ptrace call.  */
00197   tid = GET_THREAD_ID (inferior_ptid);
00198   
00199   /* Read the floating point state.  */
00200   ret = ptrace (PT_GETFPREGS, tid, 0, fp);
00201   if (ret < 0)
00202     {
00203       warning (_("Unable to fetch the floating point registers."));
00204       return;
00205     }
00206 
00207   /* Store fpsr.  */
00208   if (REG_VALID == regcache_register_status (regcache, ARM_FPS_REGNUM))
00209     regcache_raw_collect (regcache, ARM_FPS_REGNUM, fp + NWFPE_FPSR_OFFSET);
00210 
00211   /* Store the floating point registers.  */
00212   for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
00213     if (REG_VALID == regcache_register_status (regcache, regno))
00214       collect_nwfpe_register (regcache, regno, fp);
00215 
00216   ret = ptrace (PTRACE_SETFPREGS, tid, 0, fp);
00217   if (ret < 0)
00218     {
00219       warning (_("Unable to store floating point registers."));
00220       return;
00221     }
00222 }
00223 
00224 /* Fetch a general register of the process and store into
00225    regcache.  */
00226 
00227 static void
00228 fetch_register (struct regcache *regcache, int regno)
00229 {
00230   int ret, tid;
00231   elf_gregset_t regs;
00232 
00233   /* Get the thread id for the ptrace call.  */
00234   tid = GET_THREAD_ID (inferior_ptid);
00235   
00236   ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
00237   if (ret < 0)
00238     {
00239       warning (_("Unable to fetch general register."));
00240       return;
00241     }
00242 
00243   if (regno >= ARM_A1_REGNUM && regno < ARM_PC_REGNUM)
00244     regcache_raw_supply (regcache, regno, (char *) &regs[regno]);
00245 
00246   if (ARM_PS_REGNUM == regno)
00247     {
00248       if (arm_apcs_32)
00249         regcache_raw_supply (regcache, ARM_PS_REGNUM,
00250                              (char *) &regs[ARM_CPSR_GREGNUM]);
00251       else
00252         regcache_raw_supply (regcache, ARM_PS_REGNUM,
00253                              (char *) &regs[ARM_PC_REGNUM]);
00254     }
00255     
00256   if (ARM_PC_REGNUM == regno)
00257     { 
00258       regs[ARM_PC_REGNUM] = gdbarch_addr_bits_remove
00259                               (get_regcache_arch (regcache),
00260                                regs[ARM_PC_REGNUM]);
00261       regcache_raw_supply (regcache, ARM_PC_REGNUM,
00262                            (char *) &regs[ARM_PC_REGNUM]);
00263     }
00264 }
00265 
00266 /* Fetch all general registers of the process and store into
00267    regcache.  */
00268 
00269 static void
00270 fetch_regs (struct regcache *regcache)
00271 {
00272   int ret, regno, tid;
00273   elf_gregset_t regs;
00274 
00275   /* Get the thread id for the ptrace call.  */
00276   tid = GET_THREAD_ID (inferior_ptid);
00277   
00278   ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
00279   if (ret < 0)
00280     {
00281       warning (_("Unable to fetch general registers."));
00282       return;
00283     }
00284 
00285   for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
00286     regcache_raw_supply (regcache, regno, (char *) &regs[regno]);
00287 
00288   if (arm_apcs_32)
00289     regcache_raw_supply (regcache, ARM_PS_REGNUM,
00290                          (char *) &regs[ARM_CPSR_GREGNUM]);
00291   else
00292     regcache_raw_supply (regcache, ARM_PS_REGNUM,
00293                          (char *) &regs[ARM_PC_REGNUM]);
00294 
00295   regs[ARM_PC_REGNUM] = gdbarch_addr_bits_remove
00296                           (get_regcache_arch (regcache), regs[ARM_PC_REGNUM]);
00297   regcache_raw_supply (regcache, ARM_PC_REGNUM,
00298                        (char *) &regs[ARM_PC_REGNUM]);
00299 }
00300 
00301 /* Store all general registers of the process from the values in
00302    regcache.  */
00303 
00304 static void
00305 store_register (const struct regcache *regcache, int regno)
00306 {
00307   int ret, tid;
00308   elf_gregset_t regs;
00309   
00310   if (REG_VALID != regcache_register_status (regcache, regno))
00311     return;
00312 
00313   /* Get the thread id for the ptrace call.  */
00314   tid = GET_THREAD_ID (inferior_ptid);
00315   
00316   /* Get the general registers from the process.  */
00317   ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
00318   if (ret < 0)
00319     {
00320       warning (_("Unable to fetch general registers."));
00321       return;
00322     }
00323 
00324   if (regno >= ARM_A1_REGNUM && regno <= ARM_PC_REGNUM)
00325     regcache_raw_collect (regcache, regno, (char *) &regs[regno]);
00326   else if (arm_apcs_32 && regno == ARM_PS_REGNUM)
00327     regcache_raw_collect (regcache, regno,
00328                          (char *) &regs[ARM_CPSR_GREGNUM]);
00329   else if (!arm_apcs_32 && regno == ARM_PS_REGNUM)
00330     regcache_raw_collect (regcache, ARM_PC_REGNUM,
00331                          (char *) &regs[ARM_PC_REGNUM]);
00332 
00333   ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
00334   if (ret < 0)
00335     {
00336       warning (_("Unable to store general register."));
00337       return;
00338     }
00339 }
00340 
00341 static void
00342 store_regs (const struct regcache *regcache)
00343 {
00344   int ret, regno, tid;
00345   elf_gregset_t regs;
00346 
00347   /* Get the thread id for the ptrace call.  */
00348   tid = GET_THREAD_ID (inferior_ptid);
00349   
00350   /* Fetch the general registers.  */
00351   ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
00352   if (ret < 0)
00353     {
00354       warning (_("Unable to fetch general registers."));
00355       return;
00356     }
00357 
00358   for (regno = ARM_A1_REGNUM; regno <= ARM_PC_REGNUM; regno++)
00359     {
00360       if (REG_VALID == regcache_register_status (regcache, regno))
00361         regcache_raw_collect (regcache, regno, (char *) &regs[regno]);
00362     }
00363 
00364   if (arm_apcs_32 && REG_VALID == regcache_register_status (regcache, ARM_PS_REGNUM))
00365     regcache_raw_collect (regcache, ARM_PS_REGNUM,
00366                          (char *) &regs[ARM_CPSR_GREGNUM]);
00367 
00368   ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
00369 
00370   if (ret < 0)
00371     {
00372       warning (_("Unable to store general registers."));
00373       return;
00374     }
00375 }
00376 
00377 /* Fetch all WMMX registers of the process and store into
00378    regcache.  */
00379 
00380 #define IWMMXT_REGS_SIZE (16 * 8 + 6 * 4)
00381 
00382 static void
00383 fetch_wmmx_regs (struct regcache *regcache)
00384 {
00385   char regbuf[IWMMXT_REGS_SIZE];
00386   int ret, regno, tid;
00387 
00388   /* Get the thread id for the ptrace call.  */
00389   tid = GET_THREAD_ID (inferior_ptid);
00390 
00391   ret = ptrace (PTRACE_GETWMMXREGS, tid, 0, regbuf);
00392   if (ret < 0)
00393     {
00394       warning (_("Unable to fetch WMMX registers."));
00395       return;
00396     }
00397 
00398   for (regno = 0; regno < 16; regno++)
00399     regcache_raw_supply (regcache, regno + ARM_WR0_REGNUM,
00400                          &regbuf[regno * 8]);
00401 
00402   for (regno = 0; regno < 2; regno++)
00403     regcache_raw_supply (regcache, regno + ARM_WCSSF_REGNUM,
00404                          &regbuf[16 * 8 + regno * 4]);
00405 
00406   for (regno = 0; regno < 4; regno++)
00407     regcache_raw_supply (regcache, regno + ARM_WCGR0_REGNUM,
00408                          &regbuf[16 * 8 + 2 * 4 + regno * 4]);
00409 }
00410 
00411 static void
00412 store_wmmx_regs (const struct regcache *regcache)
00413 {
00414   char regbuf[IWMMXT_REGS_SIZE];
00415   int ret, regno, tid;
00416 
00417   /* Get the thread id for the ptrace call.  */
00418   tid = GET_THREAD_ID (inferior_ptid);
00419 
00420   ret = ptrace (PTRACE_GETWMMXREGS, tid, 0, regbuf);
00421   if (ret < 0)
00422     {
00423       warning (_("Unable to fetch WMMX registers."));
00424       return;
00425     }
00426 
00427   for (regno = 0; regno < 16; regno++)
00428     if (REG_VALID == regcache_register_status (regcache,
00429                                                regno + ARM_WR0_REGNUM))
00430       regcache_raw_collect (regcache, regno + ARM_WR0_REGNUM,
00431                             &regbuf[regno * 8]);
00432 
00433   for (regno = 0; regno < 2; regno++)
00434     if (REG_VALID == regcache_register_status (regcache,
00435                                                regno + ARM_WCSSF_REGNUM))
00436       regcache_raw_collect (regcache, regno + ARM_WCSSF_REGNUM,
00437                             &regbuf[16 * 8 + regno * 4]);
00438 
00439   for (regno = 0; regno < 4; regno++)
00440     if (REG_VALID == regcache_register_status (regcache,
00441                                                regno + ARM_WCGR0_REGNUM))
00442       regcache_raw_collect (regcache, regno + ARM_WCGR0_REGNUM,
00443                             &regbuf[16 * 8 + 2 * 4 + regno * 4]);
00444 
00445   ret = ptrace (PTRACE_SETWMMXREGS, tid, 0, regbuf);
00446 
00447   if (ret < 0)
00448     {
00449       warning (_("Unable to store WMMX registers."));
00450       return;
00451     }
00452 }
00453 
00454 /* Fetch and store VFP Registers.  The kernel object has space for 32
00455    64-bit registers, and the FPSCR.  This is even when on a VFPv2 or
00456    VFPv3D16 target.  */
00457 #define VFP_REGS_SIZE (32 * 8 + 4)
00458 
00459 static void
00460 fetch_vfp_regs (struct regcache *regcache)
00461 {
00462   char regbuf[VFP_REGS_SIZE];
00463   int ret, regno, tid;
00464 
00465   /* Get the thread id for the ptrace call.  */
00466   tid = GET_THREAD_ID (inferior_ptid);
00467 
00468   ret = ptrace (PTRACE_GETVFPREGS, tid, 0, regbuf);
00469   if (ret < 0)
00470     {
00471       warning (_("Unable to fetch VFP registers."));
00472       return;
00473     }
00474 
00475   for (regno = 0; regno < arm_linux_vfp_register_count; regno++)
00476     regcache_raw_supply (regcache, regno + ARM_D0_REGNUM,
00477                          (char *) regbuf + regno * 8);
00478 
00479   regcache_raw_supply (regcache, ARM_FPSCR_REGNUM,
00480                        (char *) regbuf + 32 * 8);
00481 }
00482 
00483 static void
00484 store_vfp_regs (const struct regcache *regcache)
00485 {
00486   char regbuf[VFP_REGS_SIZE];
00487   int ret, regno, tid;
00488 
00489   /* Get the thread id for the ptrace call.  */
00490   tid = GET_THREAD_ID (inferior_ptid);
00491 
00492   ret = ptrace (PTRACE_GETVFPREGS, tid, 0, regbuf);
00493   if (ret < 0)
00494     {
00495       warning (_("Unable to fetch VFP registers (for update)."));
00496       return;
00497     }
00498 
00499   for (regno = 0; regno < arm_linux_vfp_register_count; regno++)
00500     regcache_raw_collect (regcache, regno + ARM_D0_REGNUM,
00501                           (char *) regbuf + regno * 8);
00502 
00503   regcache_raw_collect (regcache, ARM_FPSCR_REGNUM,
00504                         (char *) regbuf + 32 * 8);
00505 
00506   ret = ptrace (PTRACE_SETVFPREGS, tid, 0, regbuf);
00507 
00508   if (ret < 0)
00509     {
00510       warning (_("Unable to store VFP registers."));
00511       return;
00512     }
00513 }
00514 
00515 /* Fetch registers from the child process.  Fetch all registers if
00516    regno == -1, otherwise fetch all general registers or all floating
00517    point registers depending upon the value of regno.  */
00518 
00519 static void
00520 arm_linux_fetch_inferior_registers (struct target_ops *ops,
00521                                     struct regcache *regcache, int regno)
00522 {
00523   if (-1 == regno)
00524     {
00525       fetch_regs (regcache);
00526       fetch_fpregs (regcache);
00527       if (arm_linux_has_wmmx_registers)
00528         fetch_wmmx_regs (regcache);
00529       if (arm_linux_vfp_register_count > 0)
00530         fetch_vfp_regs (regcache);
00531     }
00532   else 
00533     {
00534       if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
00535         fetch_register (regcache, regno);
00536       else if (regno >= ARM_F0_REGNUM && regno <= ARM_FPS_REGNUM)
00537         fetch_fpregister (regcache, regno);
00538       else if (arm_linux_has_wmmx_registers
00539                && regno >= ARM_WR0_REGNUM && regno <= ARM_WCGR7_REGNUM)
00540         fetch_wmmx_regs (regcache);
00541       else if (arm_linux_vfp_register_count > 0
00542                && regno >= ARM_D0_REGNUM
00543                && regno <= ARM_D0_REGNUM + arm_linux_vfp_register_count)
00544         fetch_vfp_regs (regcache);
00545     }
00546 }
00547 
00548 /* Store registers back into the inferior.  Store all registers if
00549    regno == -1, otherwise store all general registers or all floating
00550    point registers depending upon the value of regno.  */
00551 
00552 static void
00553 arm_linux_store_inferior_registers (struct target_ops *ops,
00554                                     struct regcache *regcache, int regno)
00555 {
00556   if (-1 == regno)
00557     {
00558       store_regs (regcache);
00559       store_fpregs (regcache);
00560       if (arm_linux_has_wmmx_registers)
00561         store_wmmx_regs (regcache);
00562       if (arm_linux_vfp_register_count > 0)
00563         store_vfp_regs (regcache);
00564     }
00565   else
00566     {
00567       if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
00568         store_register (regcache, regno);
00569       else if ((regno >= ARM_F0_REGNUM) && (regno <= ARM_FPS_REGNUM))
00570         store_fpregister (regcache, regno);
00571       else if (arm_linux_has_wmmx_registers
00572                && regno >= ARM_WR0_REGNUM && regno <= ARM_WCGR7_REGNUM)
00573         store_wmmx_regs (regcache);
00574       else if (arm_linux_vfp_register_count > 0
00575                && regno >= ARM_D0_REGNUM
00576                && regno <= ARM_D0_REGNUM + arm_linux_vfp_register_count)
00577         store_vfp_regs (regcache);
00578     }
00579 }
00580 
00581 /* Wrapper functions for the standard regset handling, used by
00582    thread debugging.  */
00583 
00584 void
00585 fill_gregset (const struct regcache *regcache,  
00586               gdb_gregset_t *gregsetp, int regno)
00587 {
00588   arm_linux_collect_gregset (NULL, regcache, regno, gregsetp, 0);
00589 }
00590 
00591 void
00592 supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
00593 {
00594   arm_linux_supply_gregset (NULL, regcache, -1, gregsetp, 0);
00595 }
00596 
00597 void
00598 fill_fpregset (const struct regcache *regcache,
00599                gdb_fpregset_t *fpregsetp, int regno)
00600 {
00601   arm_linux_collect_nwfpe (NULL, regcache, regno, fpregsetp, 0);
00602 }
00603 
00604 /* Fill GDB's register array with the floating-point register values
00605    in *fpregsetp.  */
00606 
00607 void
00608 supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
00609 {
00610   arm_linux_supply_nwfpe (NULL, regcache, -1, fpregsetp, 0);
00611 }
00612 
00613 /* Fetch the thread-local storage pointer for libthread_db.  */
00614 
00615 ps_err_e
00616 ps_get_thread_area (const struct ps_prochandle *ph,
00617                     lwpid_t lwpid, int idx, void **base)
00618 {
00619   if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
00620     return PS_ERR;
00621 
00622   /* IDX is the bias from the thread pointer to the beginning of the
00623      thread descriptor.  It has to be subtracted due to implementation
00624      quirks in libthread_db.  */
00625   *base = (void *) ((char *)*base - idx);
00626 
00627   return PS_OK;
00628 }
00629 
00630 static const struct target_desc *
00631 arm_linux_read_description (struct target_ops *ops)
00632 {
00633   CORE_ADDR arm_hwcap = 0;
00634   arm_linux_has_wmmx_registers = 0;
00635   arm_linux_vfp_register_count = 0;
00636 
00637   if (target_auxv_search (ops, AT_HWCAP, &arm_hwcap) != 1)
00638     {
00639       return NULL;
00640     }
00641 
00642   if (arm_hwcap & HWCAP_IWMMXT)
00643     {
00644       arm_linux_has_wmmx_registers = 1;
00645       return tdesc_arm_with_iwmmxt;
00646     }
00647 
00648   if (arm_hwcap & HWCAP_VFP)
00649     {
00650       int pid;
00651       char *buf;
00652       const struct target_desc * result = NULL;
00653 
00654       /* NEON implies VFPv3-D32 or no-VFP unit.  Say that we only support
00655          Neon with VFPv3-D32.  */
00656       if (arm_hwcap & HWCAP_NEON)
00657         {
00658           arm_linux_vfp_register_count = 32;
00659           result = tdesc_arm_with_neon;
00660         }
00661       else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
00662         {
00663           arm_linux_vfp_register_count = 32;
00664           result = tdesc_arm_with_vfpv3;
00665         }
00666       else
00667         {
00668           arm_linux_vfp_register_count = 16;
00669           result = tdesc_arm_with_vfpv2;
00670         }
00671 
00672       /* Now make sure that the kernel supports reading these
00673          registers.  Support was added in 2.6.30.  */
00674       pid = ptid_get_lwp (inferior_ptid);
00675       errno = 0;
00676       buf = alloca (VFP_REGS_SIZE);
00677       if (ptrace (PTRACE_GETVFPREGS, pid, 0, buf) < 0
00678           && errno == EIO)
00679         result = NULL;
00680 
00681       return result;
00682     }
00683 
00684   return NULL;
00685 }
00686 
00687 /* Information describing the hardware breakpoint capabilities.  */
00688 struct arm_linux_hwbp_cap
00689 {
00690   gdb_byte arch;
00691   gdb_byte max_wp_length;
00692   gdb_byte wp_count;
00693   gdb_byte bp_count;
00694 };
00695 
00696 /* Get hold of the Hardware Breakpoint information for the target we are
00697    attached to.  Returns NULL if the kernel doesn't support Hardware 
00698    breakpoints at all, or a pointer to the information structure.  */
00699 static const struct arm_linux_hwbp_cap *
00700 arm_linux_get_hwbp_cap (void)
00701 {
00702   /* The info structure we return.  */
00703   static struct arm_linux_hwbp_cap info;
00704 
00705   /* Is INFO in a good state?  -1 means that no attempt has been made to
00706      initialize INFO; 0 means an attempt has been made, but it failed; 1
00707      means INFO is in an initialized state.  */
00708   static int available = -1;
00709 
00710   if (available == -1)
00711     {
00712       int tid;
00713       unsigned int val;
00714 
00715       tid = GET_THREAD_ID (inferior_ptid);
00716       if (ptrace (PTRACE_GETHBPREGS, tid, 0, &val) < 0)
00717         available = 0;
00718       else
00719         {
00720           info.arch = (gdb_byte)((val >> 24) & 0xff);
00721           info.max_wp_length = (gdb_byte)((val >> 16) & 0xff);
00722           info.wp_count = (gdb_byte)((val >> 8) & 0xff);
00723           info.bp_count = (gdb_byte)(val & 0xff);
00724           available = (info.arch != 0);
00725         }
00726     }
00727 
00728   return available == 1 ? &info : NULL;
00729 }
00730 
00731 /* How many hardware breakpoints are available?  */
00732 static int
00733 arm_linux_get_hw_breakpoint_count (void)
00734 {
00735   const struct arm_linux_hwbp_cap *cap = arm_linux_get_hwbp_cap ();
00736   return cap != NULL ? cap->bp_count : 0;
00737 }
00738 
00739 /* How many hardware watchpoints are available?  */
00740 static int
00741 arm_linux_get_hw_watchpoint_count (void)
00742 {
00743   const struct arm_linux_hwbp_cap *cap = arm_linux_get_hwbp_cap ();
00744   return cap != NULL ? cap->wp_count : 0;
00745 }
00746 
00747 /* Have we got a free break-/watch-point available for use?  Returns -1 if
00748    there is not an appropriate resource available, otherwise returns 1.  */
00749 static int
00750 arm_linux_can_use_hw_breakpoint (int type, int cnt, int ot)
00751 {
00752   if (type == bp_hardware_watchpoint || type == bp_read_watchpoint
00753       || type == bp_access_watchpoint || type == bp_watchpoint)
00754     {
00755       if (cnt + ot > arm_linux_get_hw_watchpoint_count ())
00756         return -1;
00757     }
00758   else if (type == bp_hardware_breakpoint)
00759     {
00760       if (cnt > arm_linux_get_hw_breakpoint_count ())
00761         return -1;
00762     }
00763   else
00764     gdb_assert (FALSE);
00765 
00766   return 1;
00767 }
00768 
00769 /* Enum describing the different types of ARM hardware break-/watch-points.  */
00770 typedef enum
00771 {
00772   arm_hwbp_break = 0,
00773   arm_hwbp_load = 1,
00774   arm_hwbp_store = 2,
00775   arm_hwbp_access = 3
00776 } arm_hwbp_type;
00777 
00778 /* Type describing an ARM Hardware Breakpoint Control register value.  */
00779 typedef unsigned int arm_hwbp_control_t;
00780 
00781 /* Structure used to keep track of hardware break-/watch-points.  */
00782 struct arm_linux_hw_breakpoint
00783 {
00784   /* Address to break on, or being watched.  */
00785   unsigned int address;
00786   /* Control register for break-/watch- point.  */
00787   arm_hwbp_control_t control;
00788 };
00789 
00790 /* Structure containing arrays of the break and watch points which are have
00791    active in each thread.
00792 
00793    The Linux ptrace interface to hardware break-/watch-points presents the 
00794    values in a vector centred around 0 (which is used fo generic information).
00795    Positive indicies refer to breakpoint addresses/control registers, negative
00796    indices to watchpoint addresses/control registers.
00797 
00798    The Linux vector is indexed as follows:
00799       -((i << 1) + 2): Control register for watchpoint i.
00800       -((i << 1) + 1): Address register for watchpoint i.
00801                     0: Information register.
00802        ((i << 1) + 1): Address register for breakpoint i.
00803        ((i << 1) + 2): Control register for breakpoint i.
00804 
00805    This structure is used as a per-thread cache of the state stored by the 
00806    kernel, so that we don't need to keep calling into the kernel to find a 
00807    free breakpoint.
00808 
00809    We treat break-/watch-points with their enable bit clear as being deleted.
00810    */
00811 typedef struct arm_linux_thread_points
00812 {
00813   /* Thread ID.  */
00814   int tid;
00815   /* Breakpoints for thread.  */
00816   struct arm_linux_hw_breakpoint *bpts;
00817   /* Watchpoint for threads.  */
00818   struct arm_linux_hw_breakpoint *wpts;
00819 } *arm_linux_thread_points_p;
00820 DEF_VEC_P (arm_linux_thread_points_p);
00821 
00822 /* Vector of hardware breakpoints for each thread.  */
00823 VEC(arm_linux_thread_points_p) *arm_threads = NULL;
00824 
00825 /* Find the list of hardware break-/watch-points for a thread with id TID.
00826    If no list exists for TID we return NULL if ALLOC_NEW is 0, otherwise we
00827    create a new list and return that.  */
00828 static struct arm_linux_thread_points *
00829 arm_linux_find_breakpoints_by_tid (int tid, int alloc_new)
00830 {
00831   int i;
00832   struct arm_linux_thread_points *t;
00833 
00834   for (i = 0; VEC_iterate (arm_linux_thread_points_p, arm_threads, i, t); ++i)
00835     {
00836       if (t->tid == tid)
00837         return t;
00838     }
00839 
00840   t = NULL;
00841 
00842   if (alloc_new)
00843     {
00844       t = xmalloc (sizeof (struct arm_linux_thread_points));
00845       t->tid = tid;
00846       t->bpts = xzalloc (arm_linux_get_hw_breakpoint_count ()
00847                          * sizeof (struct arm_linux_hw_breakpoint));
00848       t->wpts = xzalloc (arm_linux_get_hw_watchpoint_count ()
00849                          * sizeof (struct arm_linux_hw_breakpoint));
00850       VEC_safe_push (arm_linux_thread_points_p, arm_threads, t);
00851     }
00852 
00853   return t;
00854 }
00855 
00856 /* Initialize an ARM hardware break-/watch-point control register value.
00857    BYTE_ADDRESS_SELECT is the mask of bytes to trigger on; HWBP_TYPE is the 
00858    type of break-/watch-point; ENABLE indicates whether the point is enabled.
00859    */
00860 static arm_hwbp_control_t 
00861 arm_hwbp_control_initialize (unsigned byte_address_select,
00862                              arm_hwbp_type hwbp_type,
00863                              int enable)
00864 {
00865   gdb_assert ((byte_address_select & ~0xffU) == 0);
00866   gdb_assert (hwbp_type != arm_hwbp_break 
00867               || ((byte_address_select & 0xfU) != 0));
00868 
00869   return (byte_address_select << 5) | (hwbp_type << 3) | (3 << 1) | enable;
00870 }
00871 
00872 /* Does the breakpoint control value CONTROL have the enable bit set?  */
00873 static int
00874 arm_hwbp_control_is_enabled (arm_hwbp_control_t control)
00875 {
00876   return control & 0x1;
00877 }
00878 
00879 /* Change a breakpoint control word so that it is in the disabled state.  */
00880 static arm_hwbp_control_t
00881 arm_hwbp_control_disable (arm_hwbp_control_t control)
00882 {
00883   return control & ~0x1;
00884 }
00885 
00886 /* Initialise the hardware breakpoint structure P.  The breakpoint will be
00887    enabled, and will point to the placed address of BP_TGT.  */
00888 static void
00889 arm_linux_hw_breakpoint_initialize (struct gdbarch *gdbarch,
00890                                     struct bp_target_info *bp_tgt,
00891                                     struct arm_linux_hw_breakpoint *p)
00892 {
00893   unsigned mask;
00894   CORE_ADDR address = bp_tgt->placed_address;
00895 
00896   /* We have to create a mask for the control register which says which bits
00897      of the word pointed to by address to break on.  */
00898   if (arm_pc_is_thumb (gdbarch, address))
00899     {
00900       mask = 0x3;
00901       address &= ~1;
00902     }
00903   else
00904     {
00905       mask = 0xf;
00906       address &= ~3;
00907     }
00908 
00909   p->address = (unsigned int) address;
00910   p->control = arm_hwbp_control_initialize (mask, arm_hwbp_break, 1);
00911 }
00912 
00913 /* Get the ARM hardware breakpoint type from the RW value we're given when
00914    asked to set a watchpoint.  */
00915 static arm_hwbp_type 
00916 arm_linux_get_hwbp_type (int rw)
00917 {
00918   if (rw == hw_read)
00919     return arm_hwbp_load;
00920   else if (rw == hw_write)
00921     return arm_hwbp_store;
00922   else
00923     return arm_hwbp_access;
00924 }
00925 
00926 /* Initialize the hardware breakpoint structure P for a watchpoint at ADDR
00927    to LEN.  The type of watchpoint is given in RW.  */
00928 static void
00929 arm_linux_hw_watchpoint_initialize (CORE_ADDR addr, int len, int rw,
00930                                     struct arm_linux_hw_breakpoint *p)
00931 {
00932   const struct arm_linux_hwbp_cap *cap = arm_linux_get_hwbp_cap ();
00933   unsigned mask;
00934 
00935   gdb_assert (cap != NULL);
00936   gdb_assert (cap->max_wp_length != 0);
00937 
00938   mask = (1 << len) - 1;
00939 
00940   p->address = (unsigned int) addr;
00941   p->control = arm_hwbp_control_initialize (mask, 
00942                                             arm_linux_get_hwbp_type (rw), 1);
00943 }
00944 
00945 /* Are two break-/watch-points equal?  */
00946 static int
00947 arm_linux_hw_breakpoint_equal (const struct arm_linux_hw_breakpoint *p1,
00948                                const struct arm_linux_hw_breakpoint *p2)
00949 {
00950   return p1->address == p2->address && p1->control == p2->control;
00951 }
00952 
00953 /* Insert the hardware breakpoint (WATCHPOINT = 0) or watchpoint (WATCHPOINT
00954    =1) BPT for thread TID.  */
00955 static void
00956 arm_linux_insert_hw_breakpoint1 (const struct arm_linux_hw_breakpoint* bpt, 
00957                                 int tid, int watchpoint)
00958 {
00959   struct arm_linux_thread_points *t = arm_linux_find_breakpoints_by_tid (tid, 1);
00960   gdb_byte count, i;
00961   struct arm_linux_hw_breakpoint* bpts;
00962   int dir;
00963 
00964   gdb_assert (t != NULL);
00965 
00966   if (watchpoint)
00967     {
00968       count = arm_linux_get_hw_watchpoint_count ();
00969       bpts = t->wpts;
00970       dir = -1;
00971     }
00972   else
00973     {
00974       count = arm_linux_get_hw_breakpoint_count ();
00975       bpts = t->bpts;
00976       dir = 1;
00977     }
00978 
00979   for (i = 0; i < count; ++i)
00980     if (!arm_hwbp_control_is_enabled (bpts[i].control))
00981       {
00982         errno = 0;
00983         if (ptrace (PTRACE_SETHBPREGS, tid, dir * ((i << 1) + 1), 
00984                     &bpt->address) < 0)
00985           perror_with_name (_("Unexpected error setting breakpoint address"));
00986         if (ptrace (PTRACE_SETHBPREGS, tid, dir * ((i << 1) + 2), 
00987                     &bpt->control) < 0)
00988           perror_with_name (_("Unexpected error setting breakpoint"));
00989 
00990         memcpy (bpts + i, bpt, sizeof (struct arm_linux_hw_breakpoint));
00991         break;
00992       }
00993 
00994   gdb_assert (i != count);
00995 }
00996 
00997 /* Remove the hardware breakpoint (WATCHPOINT = 0) or watchpoint
00998    (WATCHPOINT = 1) BPT for thread TID.  */
00999 static void
01000 arm_linux_remove_hw_breakpoint1 (const struct arm_linux_hw_breakpoint *bpt, 
01001                                  int tid, int watchpoint)
01002 {
01003   struct arm_linux_thread_points *t = arm_linux_find_breakpoints_by_tid (tid, 0);
01004   gdb_byte count, i;
01005   struct arm_linux_hw_breakpoint *bpts;
01006   int dir;
01007 
01008   gdb_assert (t != NULL);
01009 
01010   if (watchpoint)
01011     {
01012       count = arm_linux_get_hw_watchpoint_count ();
01013       bpts = t->wpts;
01014       dir = -1;
01015     }
01016   else
01017     {
01018       count = arm_linux_get_hw_breakpoint_count ();
01019       bpts = t->bpts;
01020       dir = 1;
01021     }
01022 
01023   for (i = 0; i < count; ++i)
01024     if (arm_linux_hw_breakpoint_equal (bpt, bpts + i))
01025       {
01026         errno = 0;
01027         bpts[i].control = arm_hwbp_control_disable (bpts[i].control);
01028         if (ptrace (PTRACE_SETHBPREGS, tid, dir * ((i << 1) + 2), 
01029                     &bpts[i].control) < 0)
01030           perror_with_name (_("Unexpected error clearing breakpoint"));
01031         break;
01032       }
01033 
01034   gdb_assert (i != count);
01035 }
01036 
01037 /* Insert a Hardware breakpoint.  */
01038 static int
01039 arm_linux_insert_hw_breakpoint (struct gdbarch *gdbarch, 
01040                                 struct bp_target_info *bp_tgt)
01041 {
01042   struct lwp_info *lp;
01043   struct arm_linux_hw_breakpoint p;
01044 
01045   if (arm_linux_get_hw_breakpoint_count () == 0)
01046     return -1;
01047 
01048   arm_linux_hw_breakpoint_initialize (gdbarch, bp_tgt, &p);
01049   ALL_LWPS (lp)
01050     arm_linux_insert_hw_breakpoint1 (&p, ptid_get_lwp (lp->ptid), 0);
01051 
01052   return 0;
01053 }
01054 
01055 /* Remove a hardware breakpoint.  */
01056 static int
01057 arm_linux_remove_hw_breakpoint (struct gdbarch *gdbarch, 
01058                                 struct bp_target_info *bp_tgt)
01059 {
01060   struct lwp_info *lp;
01061   struct arm_linux_hw_breakpoint p;
01062 
01063   if (arm_linux_get_hw_breakpoint_count () == 0)
01064     return -1;
01065 
01066   arm_linux_hw_breakpoint_initialize (gdbarch, bp_tgt, &p);
01067   ALL_LWPS (lp)
01068     arm_linux_remove_hw_breakpoint1 (&p, ptid_get_lwp (lp->ptid), 0);
01069 
01070   return 0;
01071 }
01072 
01073 /* Are we able to use a hardware watchpoint for the LEN bytes starting at 
01074    ADDR?  */
01075 static int
01076 arm_linux_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
01077 {
01078   const struct arm_linux_hwbp_cap *cap = arm_linux_get_hwbp_cap ();
01079   CORE_ADDR max_wp_length, aligned_addr;
01080 
01081   /* Can not set watchpoints for zero or negative lengths.  */
01082   if (len <= 0)
01083     return 0;
01084 
01085   /* Need to be able to use the ptrace interface.  */
01086   if (cap == NULL || cap->wp_count == 0)
01087     return 0;
01088 
01089   /* Test that the range [ADDR, ADDR + LEN) fits into the largest address
01090      range covered by a watchpoint.  */
01091   max_wp_length = (CORE_ADDR)cap->max_wp_length;
01092   aligned_addr = addr & ~(max_wp_length - 1);
01093 
01094   if (aligned_addr + max_wp_length < addr + len)
01095     return 0;
01096 
01097   /* The current ptrace interface can only handle watchpoints that are a
01098      power of 2.  */
01099   if ((len & (len - 1)) != 0)
01100     return 0;
01101 
01102   /* All tests passed so we must be able to set a watchpoint.  */
01103   return 1;
01104 }
01105 
01106 /* Insert a Hardware breakpoint.  */
01107 static int
01108 arm_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw,
01109                              struct expression *cond)
01110 {
01111   struct lwp_info *lp;
01112   struct arm_linux_hw_breakpoint p;
01113 
01114   if (arm_linux_get_hw_watchpoint_count () == 0)
01115     return -1;
01116 
01117   arm_linux_hw_watchpoint_initialize (addr, len, rw, &p);
01118   ALL_LWPS (lp)
01119     arm_linux_insert_hw_breakpoint1 (&p, ptid_get_lwp (lp->ptid), 1);
01120 
01121   return 0;
01122 }
01123 
01124 /* Remove a hardware breakpoint.  */
01125 static int
01126 arm_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw,
01127                              struct expression *cond)
01128 {
01129   struct lwp_info *lp;
01130   struct arm_linux_hw_breakpoint p;
01131 
01132   if (arm_linux_get_hw_watchpoint_count () == 0)
01133     return -1;
01134 
01135   arm_linux_hw_watchpoint_initialize (addr, len, rw, &p);
01136   ALL_LWPS (lp)
01137     arm_linux_remove_hw_breakpoint1 (&p, ptid_get_lwp (lp->ptid), 1);
01138 
01139   return 0;
01140 }
01141 
01142 /* What was the data address the target was stopped on accessing.  */
01143 static int
01144 arm_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
01145 {
01146   siginfo_t siginfo;
01147   int slot;
01148 
01149   if (!linux_nat_get_siginfo (inferior_ptid, &siginfo))
01150     return 0;
01151 
01152   /* This must be a hardware breakpoint.  */
01153   if (siginfo.si_signo != SIGTRAP
01154       || (siginfo.si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
01155     return 0;
01156 
01157   /* We must be able to set hardware watchpoints.  */
01158   if (arm_linux_get_hw_watchpoint_count () == 0)
01159     return 0;
01160 
01161   slot = siginfo.si_errno;
01162 
01163   /* If we are in a positive slot then we're looking at a breakpoint and not
01164      a watchpoint.  */
01165   if (slot >= 0)
01166     return 0;
01167 
01168   *addr_p = (CORE_ADDR) (uintptr_t) siginfo.si_addr;
01169   return 1;
01170 }
01171 
01172 /* Has the target been stopped by hitting a watchpoint?  */
01173 static int
01174 arm_linux_stopped_by_watchpoint (void)
01175 {
01176   CORE_ADDR addr;
01177   return arm_linux_stopped_data_address (&current_target, &addr);
01178 }
01179 
01180 static int
01181 arm_linux_watchpoint_addr_within_range (struct target_ops *target,
01182                                         CORE_ADDR addr,
01183                                         CORE_ADDR start, int length)
01184 {
01185   return start <= addr && start + length - 1 >= addr;
01186 }
01187 
01188 /* Handle thread creation.  We need to copy the breakpoints and watchpoints
01189    in the parent thread to the child thread.  */
01190 static void
01191 arm_linux_new_thread (struct lwp_info *lp)
01192 {
01193   int tid = ptid_get_lwp (lp->ptid);
01194   const struct arm_linux_hwbp_cap *info = arm_linux_get_hwbp_cap ();
01195 
01196   if (info != NULL)
01197     {
01198       int i;
01199       struct arm_linux_thread_points *p;
01200       struct arm_linux_hw_breakpoint *bpts;
01201 
01202       if (VEC_empty (arm_linux_thread_points_p, arm_threads))
01203         return;
01204 
01205       /* Get a list of breakpoints from any thread. */
01206       p = VEC_last (arm_linux_thread_points_p, arm_threads);
01207 
01208       /* Copy that thread's breakpoints and watchpoints to the new thread. */
01209       for (i = 0; i < info->bp_count; i++)
01210         if (arm_hwbp_control_is_enabled (p->bpts[i].control))
01211           arm_linux_insert_hw_breakpoint1 (p->bpts + i, tid, 0);
01212       for (i = 0; i < info->wp_count; i++)
01213         if (arm_hwbp_control_is_enabled (p->wpts[i].control))
01214           arm_linux_insert_hw_breakpoint1 (p->wpts + i, tid, 1);
01215     }
01216 }
01217 
01218 /* Handle thread exit.  Tidy up the memory that has been allocated for the
01219    thread.  */
01220 static void
01221 arm_linux_thread_exit (struct thread_info *tp, int silent)
01222 {
01223   const struct arm_linux_hwbp_cap *info = arm_linux_get_hwbp_cap ();
01224 
01225   if (info != NULL)
01226     {
01227       int i;
01228       int tid = ptid_get_lwp (tp->ptid);
01229       struct arm_linux_thread_points *t = NULL, *p;
01230 
01231       for (i = 0; 
01232            VEC_iterate (arm_linux_thread_points_p, arm_threads, i, p); i++)
01233         {
01234           if (p->tid == tid)
01235             {
01236               t = p;
01237               break;
01238             }
01239         }
01240 
01241       if (t == NULL)
01242         return;
01243 
01244       VEC_unordered_remove (arm_linux_thread_points_p, arm_threads, i);
01245 
01246       xfree (t->bpts);
01247       xfree (t->wpts);
01248       xfree (t);
01249     }
01250 }
01251 
01252 void _initialize_arm_linux_nat (void);
01253 
01254 void
01255 _initialize_arm_linux_nat (void)
01256 {
01257   struct target_ops *t;
01258 
01259   /* Fill in the generic GNU/Linux methods.  */
01260   t = linux_target ();
01261 
01262   /* Add our register access methods.  */
01263   t->to_fetch_registers = arm_linux_fetch_inferior_registers;
01264   t->to_store_registers = arm_linux_store_inferior_registers;
01265 
01266   /* Add our hardware breakpoint and watchpoint implementation.  */
01267   t->to_can_use_hw_breakpoint = arm_linux_can_use_hw_breakpoint;
01268   t->to_insert_hw_breakpoint = arm_linux_insert_hw_breakpoint;
01269   t->to_remove_hw_breakpoint = arm_linux_remove_hw_breakpoint;
01270   t->to_region_ok_for_hw_watchpoint = arm_linux_region_ok_for_hw_watchpoint;
01271   t->to_insert_watchpoint = arm_linux_insert_watchpoint;
01272   t->to_remove_watchpoint = arm_linux_remove_watchpoint;
01273   t->to_stopped_by_watchpoint = arm_linux_stopped_by_watchpoint;
01274   t->to_stopped_data_address = arm_linux_stopped_data_address;
01275   t->to_watchpoint_addr_within_range = arm_linux_watchpoint_addr_within_range;
01276 
01277   t->to_read_description = arm_linux_read_description;
01278 
01279   /* Register the target.  */
01280   linux_nat_add_target (t);
01281 
01282   /* Handle thread creation and exit */
01283   observer_attach_thread_exit (arm_linux_thread_exit);
01284   linux_nat_set_new_thread (t, arm_linux_new_thread);
01285 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines