GDB (API)
/home/stan/gdb/src/gdb/hppa-linux-nat.c
Go to the documentation of this file.
00001 /* Functions specific to running GDB native on HPPA running GNU/Linux.
00002 
00003    Copyright (C) 2004-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "gdbcore.h"
00022 #include "regcache.h"
00023 #include "gdb_string.h"
00024 #include "inferior.h"
00025 #include "target.h"
00026 #include "linux-nat.h"
00027 
00028 #include <sys/procfs.h>
00029 #include <sys/ptrace.h>
00030 #include <linux/version.h>
00031 
00032 #include <asm/ptrace.h>
00033 #include "hppa-linux-offsets.h"
00034 
00035 #include "hppa-tdep.h"
00036 
00037 /* Prototypes for supply_gregset etc.  */
00038 #include "gregset.h"
00039 
00040 /* These must match the order of the register names.
00041 
00042    Some sort of lookup table is needed because the offsets associated
00043    with the registers are all over the board.  */
00044 
00045 static const int u_offsets[] =
00046   {
00047     /* general registers */
00048     -1,
00049     PT_GR1,
00050     PT_GR2,
00051     PT_GR3,
00052     PT_GR4,
00053     PT_GR5,
00054     PT_GR6,
00055     PT_GR7,
00056     PT_GR8,
00057     PT_GR9,
00058     PT_GR10,
00059     PT_GR11,
00060     PT_GR12,
00061     PT_GR13,
00062     PT_GR14,
00063     PT_GR15,
00064     PT_GR16,
00065     PT_GR17,
00066     PT_GR18,
00067     PT_GR19,
00068     PT_GR20,
00069     PT_GR21,
00070     PT_GR22,
00071     PT_GR23,
00072     PT_GR24,
00073     PT_GR25,
00074     PT_GR26,
00075     PT_GR27,
00076     PT_GR28,
00077     PT_GR29,
00078     PT_GR30,
00079     PT_GR31,
00080 
00081     PT_SAR,
00082     PT_IAOQ0,
00083     PT_IASQ0,
00084     PT_IAOQ1,
00085     PT_IASQ1,
00086     -1, /* eiem */
00087     PT_IIR,
00088     PT_ISR,
00089     PT_IOR,
00090     PT_PSW,
00091     -1, /* goto */
00092 
00093     PT_SR4,
00094     PT_SR0,
00095     PT_SR1,
00096     PT_SR2,
00097     PT_SR3,
00098     PT_SR5,
00099     PT_SR6,
00100     PT_SR7,
00101 
00102     -1, /* cr0 */
00103     -1, /* pid0 */
00104     -1, /* pid1 */
00105     -1, /* ccr */
00106     -1, /* pid2 */
00107     -1, /* pid3 */
00108     -1, /* cr24 */
00109     -1, /* cr25 */
00110     -1, /* cr26 */
00111     PT_CR27,
00112     -1, /* cr28 */
00113     -1, /* cr29 */
00114     -1, /* cr30 */
00115 
00116     /* Floating point regs.  */
00117     PT_FR0,  PT_FR0 + 4,
00118     PT_FR1,  PT_FR1 + 4,
00119     PT_FR2,  PT_FR2 + 4,
00120     PT_FR3,  PT_FR3 + 4,
00121     PT_FR4,  PT_FR4 + 4,
00122     PT_FR5,  PT_FR5 + 4,
00123     PT_FR6,  PT_FR6 + 4,
00124     PT_FR7,  PT_FR7 + 4,
00125     PT_FR8,  PT_FR8 + 4,
00126     PT_FR9,  PT_FR9 + 4,
00127     PT_FR10, PT_FR10 + 4,
00128     PT_FR11, PT_FR11 + 4,
00129     PT_FR12, PT_FR12 + 4,
00130     PT_FR13, PT_FR13 + 4,
00131     PT_FR14, PT_FR14 + 4,
00132     PT_FR15, PT_FR15 + 4,
00133     PT_FR16, PT_FR16 + 4,
00134     PT_FR17, PT_FR17 + 4,
00135     PT_FR18, PT_FR18 + 4,
00136     PT_FR19, PT_FR19 + 4,
00137     PT_FR20, PT_FR20 + 4,
00138     PT_FR21, PT_FR21 + 4,
00139     PT_FR22, PT_FR22 + 4,
00140     PT_FR23, PT_FR23 + 4,
00141     PT_FR24, PT_FR24 + 4,
00142     PT_FR25, PT_FR25 + 4,
00143     PT_FR26, PT_FR26 + 4,
00144     PT_FR27, PT_FR27 + 4,
00145     PT_FR28, PT_FR28 + 4,
00146     PT_FR29, PT_FR29 + 4,
00147     PT_FR30, PT_FR30 + 4,
00148     PT_FR31, PT_FR31 + 4,
00149   };
00150 
00151 static CORE_ADDR
00152 hppa_linux_register_addr (int regno, CORE_ADDR blockend)
00153 {
00154   CORE_ADDR addr;
00155 
00156   if ((unsigned) regno >= ARRAY_SIZE (u_offsets))
00157     error (_("Invalid register number %d."), regno);
00158 
00159   if (u_offsets[regno] == -1)
00160     addr = 0;
00161   else
00162     {
00163       addr = (CORE_ADDR) u_offsets[regno];
00164     }
00165 
00166   return addr;
00167 }
00168 
00169 /*
00170  * Registers saved in a coredump:
00171  * gr0..gr31
00172  * sr0..sr7
00173  * iaoq0..iaoq1
00174  * iasq0..iasq1
00175  * sar, iir, isr, ior, ipsw
00176  * cr0, cr24..cr31
00177  * cr8,9,12,13
00178  * cr10, cr15
00179  */
00180 #define GR_REGNUM(_n)   (HPPA_R0_REGNUM+_n)
00181 #define TR_REGNUM(_n)   (HPPA_TR0_REGNUM+_n)
00182 static const int greg_map[] =
00183   {
00184     GR_REGNUM(0), GR_REGNUM(1), GR_REGNUM(2), GR_REGNUM(3),
00185     GR_REGNUM(4), GR_REGNUM(5), GR_REGNUM(6), GR_REGNUM(7),
00186     GR_REGNUM(8), GR_REGNUM(9), GR_REGNUM(10), GR_REGNUM(11),
00187     GR_REGNUM(12), GR_REGNUM(13), GR_REGNUM(14), GR_REGNUM(15),
00188     GR_REGNUM(16), GR_REGNUM(17), GR_REGNUM(18), GR_REGNUM(19),
00189     GR_REGNUM(20), GR_REGNUM(21), GR_REGNUM(22), GR_REGNUM(23),
00190     GR_REGNUM(24), GR_REGNUM(25), GR_REGNUM(26), GR_REGNUM(27),
00191     GR_REGNUM(28), GR_REGNUM(29), GR_REGNUM(30), GR_REGNUM(31),
00192 
00193     HPPA_SR4_REGNUM+1, HPPA_SR4_REGNUM+2, HPPA_SR4_REGNUM+3, HPPA_SR4_REGNUM+4,
00194     HPPA_SR4_REGNUM, HPPA_SR4_REGNUM+5, HPPA_SR4_REGNUM+6, HPPA_SR4_REGNUM+7,
00195 
00196     HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM,
00197     HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM,
00198 
00199     HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM,
00200     HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM,
00201 
00202     TR_REGNUM(0), TR_REGNUM(1), TR_REGNUM(2), TR_REGNUM(3),
00203     TR_REGNUM(4), TR_REGNUM(5), TR_REGNUM(6), TR_REGNUM(7),
00204 
00205     HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM,
00206     HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM,
00207   };
00208 
00209 
00210 
00211 /* Fetch one register.  */
00212 
00213 static void
00214 fetch_register (struct regcache *regcache, int regno)
00215 {
00216   struct gdbarch *gdbarch = get_regcache_arch (regcache);
00217   int tid;
00218   int val;
00219 
00220   if (gdbarch_cannot_fetch_register (gdbarch, regno))
00221     {
00222       regcache_raw_supply (regcache, regno, NULL);
00223       return;
00224     }
00225 
00226   /* GNU/Linux LWP ID's are process ID's.  */
00227   tid = ptid_get_lwp (inferior_ptid);
00228   if (tid == 0)
00229     tid = ptid_get_pid (inferior_ptid); /* Not a threaded program.  */
00230 
00231   errno = 0;
00232   val = ptrace (PTRACE_PEEKUSER, tid, hppa_linux_register_addr (regno, 0), 0);
00233   if (errno != 0)
00234     error (_("Couldn't read register %s (#%d): %s."), 
00235            gdbarch_register_name (gdbarch, regno),
00236            regno, safe_strerror (errno));
00237 
00238   regcache_raw_supply (regcache, regno, &val);
00239 }
00240 
00241 /* Store one register.  */
00242 
00243 static void
00244 store_register (const struct regcache *regcache, int regno)
00245 {
00246   struct gdbarch *gdbarch = get_regcache_arch (regcache);
00247   int tid;
00248   int val;
00249 
00250   if (gdbarch_cannot_store_register (gdbarch, regno))
00251     return;
00252 
00253   /* GNU/Linux LWP ID's are process ID's.  */
00254   tid = ptid_get_lwp (inferior_ptid);
00255   if (tid == 0)
00256     tid = ptid_get_pid (inferior_ptid); /* Not a threaded program.  */
00257 
00258   errno = 0;
00259   regcache_raw_collect (regcache, regno, &val);
00260   ptrace (PTRACE_POKEUSER, tid, hppa_linux_register_addr (regno, 0), val);
00261   if (errno != 0)
00262     error (_("Couldn't write register %s (#%d): %s."),
00263            gdbarch_register_name (gdbarch, regno),
00264            regno, safe_strerror (errno));
00265 }
00266 
00267 /* Fetch registers from the child process.  Fetch all registers if
00268    regno == -1, otherwise fetch all general registers or all floating
00269    point registers depending upon the value of regno.  */
00270 
00271 static void
00272 hppa_linux_fetch_inferior_registers (struct target_ops *ops,
00273                                      struct regcache *regcache, int regno)
00274 {
00275   if (-1 == regno)
00276     {
00277       for (regno = 0;
00278            regno < gdbarch_num_regs (get_regcache_arch (regcache));
00279            regno++)
00280         fetch_register (regcache, regno);
00281     }
00282   else 
00283     {
00284       fetch_register (regcache, regno);
00285     }
00286 }
00287 
00288 /* Store registers back into the inferior.  Store all registers if
00289    regno == -1, otherwise store all general registers or all floating
00290    point registers depending upon the value of regno.  */
00291 
00292 static void
00293 hppa_linux_store_inferior_registers (struct target_ops *ops,
00294                                      struct regcache *regcache, int regno)
00295 {
00296   if (-1 == regno)
00297     {
00298       for (regno = 0;
00299            regno < gdbarch_num_regs (get_regcache_arch (regcache));
00300            regno++)
00301         store_register (regcache, regno);
00302     }
00303   else
00304     {
00305       store_register (regcache, regno);
00306     }
00307 }
00308 
00309 /* Fill GDB's register array with the general-purpose register values
00310    in *gregsetp.  */
00311 
00312 void
00313 supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
00314 {
00315   int i;
00316   const greg_t *regp = (const elf_greg_t *) gregsetp;
00317 
00318   for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
00319     {
00320       int regno = greg_map[i];
00321       regcache_raw_supply (regcache, regno, regp);
00322     }
00323 }
00324 
00325 /* Fill register regno (if it is a general-purpose register) in
00326    *gregsetp with the appropriate value from GDB's register array.
00327    If regno is -1, do this for all registers.  */
00328 
00329 void
00330 fill_gregset (const struct regcache *regcache,
00331               gdb_gregset_t *gregsetp, int regno)
00332 {
00333   int i;
00334 
00335   for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++)
00336     {
00337       int mregno = greg_map[i];
00338 
00339       if (regno == -1 || regno == mregno)
00340         {
00341           regcache_raw_collect(regcache, mregno, &(*gregsetp)[i]);
00342         }
00343     }
00344 }
00345 
00346 /*  Given a pointer to a floating point register set in /proc format
00347    (fpregset_t *), unpack the register contents and supply them as gdb's
00348    idea of the current floating point register values.  */
00349 
00350 void
00351 supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
00352 {
00353   int regi;
00354   const char *from;
00355 
00356   for (regi = 0; regi <= 31; regi++)
00357     {
00358       from = (const char *) &((*fpregsetp)[regi]);
00359       regcache_raw_supply (regcache, 2*regi + HPPA_FP0_REGNUM, from);
00360       regcache_raw_supply (regcache, 2*regi + HPPA_FP0_REGNUM + 1, from + 4);
00361     }
00362 }
00363 
00364 /*  Given a pointer to a floating point register set in /proc format
00365    (fpregset_t *), update the register specified by REGNO from gdb's idea
00366    of the current floating point register set.  If REGNO is -1, update
00367    them all.  */
00368 
00369 void
00370 fill_fpregset (const struct regcache *regcache,
00371                gdb_fpregset_t *fpregsetp, int regno)
00372 {
00373   int i;
00374 
00375   for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 32 * 2; i++)
00376    {
00377       /* Gross.  fpregset_t is double, registers[x] has single
00378          precision reg.  */
00379       char *to = (char *) &((*fpregsetp)[(i - HPPA_FP0_REGNUM) / 2]);
00380       if ((i - HPPA_FP0_REGNUM) & 1)
00381         to += 4;
00382       regcache_raw_collect (regcache, i, to);
00383    }
00384 }
00385 
00386 void _initialize_hppa_linux_nat (void);
00387 
00388 void
00389 _initialize_hppa_linux_nat (void)
00390 {
00391   struct target_ops *t;
00392 
00393   /* Fill in the generic GNU/Linux methods.  */
00394   t = linux_target ();
00395 
00396   /* Add our register access methods.  */
00397   t->to_fetch_registers = hppa_linux_fetch_inferior_registers;
00398   t->to_store_registers = hppa_linux_store_inferior_registers;
00399 
00400   /* Register the target.  */
00401   linux_nat_add_target (t);
00402 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines