GDB (API)
/home/stan/gdb/src/gdb/common/mips-linux-watch.c
Go to the documentation of this file.
00001 /* Copyright (C) 2009-2013 Free Software Foundation, Inc.
00002 
00003    This file is part of GDB.
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 3 of the License, or
00008    (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00017 
00018 #include <sys/ptrace.h>
00019 #include "mips-linux-watch.h"
00020 #include "gdb_assert.h"
00021 
00022 /* Assuming usable watch registers REGS, return the irw_mask of
00023    register N.  */
00024 
00025 uint32_t
00026 mips_linux_watch_get_irw_mask (struct pt_watch_regs *regs, int n)
00027 {
00028   switch (regs->style)
00029     {
00030     case pt_watch_style_mips32:
00031       return regs->mips32.watch_masks[n] & IRW_MASK;
00032     case pt_watch_style_mips64:
00033       return regs->mips64.watch_masks[n] & IRW_MASK;
00034     default:
00035       internal_error (__FILE__, __LINE__,
00036                       _("Unrecognized watch register style"));
00037     }
00038 }
00039 
00040 /* Assuming usable watch registers REGS, return the reg_mask of
00041    register N.  */
00042 
00043 static uint32_t
00044 get_reg_mask (struct pt_watch_regs *regs, int n)
00045 {
00046   switch (regs->style)
00047     {
00048     case pt_watch_style_mips32:
00049       return regs->mips32.watch_masks[n] & ~IRW_MASK;
00050     case pt_watch_style_mips64:
00051       return regs->mips64.watch_masks[n] & ~IRW_MASK;
00052     default:
00053       internal_error (__FILE__, __LINE__,
00054                       _("Unrecognized watch register style"));
00055     }
00056 }
00057 
00058 /* Assuming usable watch registers REGS, return the num_valid.  */
00059 
00060 uint32_t
00061 mips_linux_watch_get_num_valid (struct pt_watch_regs *regs)
00062 {
00063   switch (regs->style)
00064     {
00065     case pt_watch_style_mips32:
00066       return regs->mips32.num_valid;
00067     case pt_watch_style_mips64:
00068       return regs->mips64.num_valid;
00069     default:
00070       internal_error (__FILE__, __LINE__,
00071                       _("Unrecognized watch register style"));
00072     }
00073 }
00074 
00075 /* Assuming usable watch registers REGS, return the watchlo of
00076    register N.  */
00077 
00078 CORE_ADDR
00079 mips_linux_watch_get_watchlo (struct pt_watch_regs *regs, int n)
00080 {
00081   switch (regs->style)
00082     {
00083     case pt_watch_style_mips32:
00084       return regs->mips32.watchlo[n];
00085     case pt_watch_style_mips64:
00086       return regs->mips64.watchlo[n];
00087     default:
00088       internal_error (__FILE__, __LINE__,
00089                       _("Unrecognized watch register style"));
00090     }
00091 }
00092 
00093 /* Assuming usable watch registers REGS, set watchlo of register N to
00094    VALUE.  */
00095 
00096 void
00097 mips_linux_watch_set_watchlo (struct pt_watch_regs *regs, int n,
00098                               CORE_ADDR value)
00099 {
00100   switch (regs->style)
00101     {
00102     case pt_watch_style_mips32:
00103       /*  The cast will never throw away bits as 64 bit addresses can
00104           never be used on a 32 bit kernel.  */
00105       regs->mips32.watchlo[n] = (uint32_t) value;
00106       break;
00107     case pt_watch_style_mips64:
00108       regs->mips64.watchlo[n] = value;
00109       break;
00110     default:
00111       internal_error (__FILE__, __LINE__,
00112                       _("Unrecognized watch register style"));
00113     }
00114 }
00115 
00116 /* Assuming usable watch registers REGS, return the watchhi of
00117    register N.  */
00118 
00119 uint32_t
00120 mips_linux_watch_get_watchhi (struct pt_watch_regs *regs, int n)
00121 {
00122   switch (regs->style)
00123     {
00124     case pt_watch_style_mips32:
00125       return regs->mips32.watchhi[n];
00126     case pt_watch_style_mips64:
00127       return regs->mips64.watchhi[n];
00128     default:
00129       internal_error (__FILE__, __LINE__,
00130                       _("Unrecognized watch register style"));
00131     }
00132 }
00133 
00134 /* Assuming usable watch registers REGS, set watchhi of register N to
00135    VALUE.  */
00136 
00137 void
00138 mips_linux_watch_set_watchhi (struct pt_watch_regs *regs, int n,
00139                               uint16_t value)
00140 {
00141   switch (regs->style)
00142     {
00143     case pt_watch_style_mips32:
00144       regs->mips32.watchhi[n] = value;
00145       break;
00146     case pt_watch_style_mips64:
00147       regs->mips64.watchhi[n] = value;
00148       break;
00149     default:
00150       internal_error (__FILE__, __LINE__,
00151                       _("Unrecognized watch register style"));
00152     }
00153 }
00154 
00155 /* Read the watch registers of process LWPID and store it in
00156    WATCH_READBACK.  Save true to *WATCH_READBACK_VALID if watch
00157    registers are valid.  Return 1 if watch registers are usable.
00158    Cached information is used unless FORCE is true.  */
00159 
00160 int
00161 mips_linux_read_watch_registers (long lwpid,
00162                                  struct pt_watch_regs *watch_readback,
00163                                  int *watch_readback_valid, int force)
00164 {
00165   if (force || *watch_readback_valid == 0)
00166     {
00167       if (ptrace (PTRACE_GET_WATCH_REGS, lwpid, watch_readback) == -1)
00168         {
00169           *watch_readback_valid = -1;
00170           return 0;
00171         }
00172       switch (watch_readback->style)
00173         {
00174         case pt_watch_style_mips32:
00175           if (watch_readback->mips32.num_valid == 0)
00176             {
00177               *watch_readback_valid = -1;
00178               return 0;
00179             }
00180           break;
00181         case pt_watch_style_mips64:
00182           if (watch_readback->mips64.num_valid == 0)
00183             {
00184               *watch_readback_valid = -1;
00185               return 0;
00186             }
00187           break;
00188         default:
00189           *watch_readback_valid = -1;
00190           return 0;
00191         }
00192       /* Watch registers appear to be usable.  */
00193       *watch_readback_valid = 1;
00194     }
00195   return (*watch_readback_valid == 1) ? 1 : 0;
00196 }
00197 
00198 /* Convert GDB's TYPE to an IRW mask.  */
00199 
00200 uint32_t
00201 mips_linux_watch_type_to_irw (int type)
00202 {
00203   switch (type)
00204     {
00205     case hw_write:
00206       return W_MASK;
00207     case hw_read:
00208       return R_MASK;
00209     case hw_access:
00210       return (W_MASK | R_MASK);
00211     default:
00212       return 0;
00213     }
00214 }
00215 
00216 /* Set any low order bits in MASK that are not set.  */
00217 
00218 static CORE_ADDR
00219 fill_mask (CORE_ADDR mask)
00220 {
00221   CORE_ADDR f = 1;
00222 
00223   while (f && f < mask)
00224     {
00225       mask |= f;
00226       f <<= 1;
00227     }
00228   return mask;
00229 }
00230 
00231 /* Try to add a single watch to the specified registers REGS.  The
00232    address of added watch is ADDR, the length is LEN, and the mask
00233    is IRW.  Return 1 on success, 0 on failure.  */
00234 
00235 int
00236 mips_linux_watch_try_one_watch (struct pt_watch_regs *regs,
00237                                 CORE_ADDR addr, int len, uint32_t irw)
00238 {
00239   CORE_ADDR base_addr, last_byte, break_addr, segment_len;
00240   CORE_ADDR mask_bits, t_low;
00241   uint16_t t_hi;
00242   int i, free_watches;
00243   struct pt_watch_regs regs_copy;
00244 
00245   if (len <= 0)
00246     return 0;
00247 
00248   last_byte = addr + len - 1;
00249   mask_bits = fill_mask (addr ^ last_byte) | IRW_MASK;
00250   base_addr = addr & ~mask_bits;
00251 
00252   /* Check to see if it is covered by current registers.  */
00253   for (i = 0; i < mips_linux_watch_get_num_valid (regs); i++)
00254     {
00255       t_low = mips_linux_watch_get_watchlo (regs, i);
00256       if (t_low != 0 && irw == ((uint32_t) t_low & irw))
00257         {
00258           t_hi = mips_linux_watch_get_watchhi (regs, i) | IRW_MASK;
00259           t_low &= ~(CORE_ADDR) t_hi;
00260           if (addr >= t_low && last_byte <= (t_low + t_hi))
00261             return 1;
00262         }
00263     }
00264   /* Try to find an empty register.  */
00265   free_watches = 0;
00266   for (i = 0; i < mips_linux_watch_get_num_valid (regs); i++)
00267     {
00268       t_low = mips_linux_watch_get_watchlo (regs, i);
00269       if (t_low == 0
00270           && irw == (mips_linux_watch_get_irw_mask (regs, i) & irw))
00271         {
00272           if (mask_bits <= (get_reg_mask (regs, i) | IRW_MASK))
00273             {
00274               /* It fits, we'll take it.  */
00275               mips_linux_watch_set_watchlo (regs, i, base_addr | irw);
00276               mips_linux_watch_set_watchhi (regs, i, mask_bits & ~IRW_MASK);
00277               return 1;
00278             }
00279           else
00280             {
00281               /* It doesn't fit, but has the proper IRW capabilities.  */
00282               free_watches++;
00283             }
00284         }
00285     }
00286   if (free_watches > 1)
00287     {
00288       /* Try to split it across several registers.  */
00289       regs_copy = *regs;
00290       for (i = 0; i < mips_linux_watch_get_num_valid (&regs_copy); i++)
00291         {
00292           t_low = mips_linux_watch_get_watchlo (&regs_copy, i);
00293           t_hi = get_reg_mask (&regs_copy, i) | IRW_MASK;
00294           if (t_low == 0 && irw == (t_hi & irw))
00295             {
00296               t_low = addr & ~(CORE_ADDR) t_hi;
00297               break_addr = t_low + t_hi + 1;
00298               if (break_addr >= addr + len)
00299                 segment_len = len;
00300               else
00301                 segment_len = break_addr - addr;
00302               mask_bits = fill_mask (addr ^ (addr + segment_len - 1));
00303               mips_linux_watch_set_watchlo (&regs_copy, i,
00304                                             (addr & ~mask_bits) | irw);
00305               mips_linux_watch_set_watchhi (&regs_copy, i,
00306                                             mask_bits & ~IRW_MASK);
00307               if (break_addr >= addr + len)
00308                 {
00309                   *regs = regs_copy;
00310                   return 1;
00311                 }
00312               len = addr + len - break_addr;
00313               addr = break_addr;
00314             }
00315         }
00316     }
00317   /* It didn't fit anywhere, we failed.  */
00318   return 0;
00319 }
00320 
00321 /* Fill in the watch registers REGS with the currently cached
00322    watches CURRENT_WATCHES.  */
00323 
00324 void
00325 mips_linux_watch_populate_regs (struct mips_watchpoint *current_watches,
00326                                 struct pt_watch_regs *regs)
00327 {
00328   struct mips_watchpoint *w;
00329   int i;
00330 
00331   /* Clear them out.  */
00332   for (i = 0; i < mips_linux_watch_get_num_valid (regs); i++)
00333     {
00334       mips_linux_watch_set_watchlo (regs, i, 0);
00335       mips_linux_watch_set_watchhi (regs, i, 0);
00336     }
00337 
00338   w = current_watches;
00339   while (w)
00340     {
00341       uint32_t irw = mips_linux_watch_type_to_irw (w->type);
00342 
00343       i = mips_linux_watch_try_one_watch (regs, w->addr, w->len, irw);
00344       /* They must all fit, because we previously calculated that they
00345          would.  */
00346       gdb_assert (i);
00347       w = w->next;
00348     }
00349 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines