GDB (API)
/home/stan/gdb/src/gdb/ax-general.c
Go to the documentation of this file.
00001 /* Functions for manipulating expressions designed to be executed on the agent
00002    Copyright (C) 1998-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 /* Despite what the above comment says about this file being part of
00020    GDB, we would like to keep these functions free of GDB
00021    dependencies, since we want to be able to use them in contexts
00022    outside of GDB (test suites, the stub, etc.)  */
00023 
00024 #include "defs.h"
00025 #include "ax.h"
00026 
00027 #include "value.h"
00028 #include "gdb_string.h"
00029 
00030 #include "user-regs.h"
00031 
00032 static void grow_expr (struct agent_expr *x, int n);
00033 
00034 static void append_const (struct agent_expr *x, LONGEST val, int n);
00035 
00036 static LONGEST read_const (struct agent_expr *x, int o, int n);
00037 
00038 static void generic_ext (struct agent_expr *x, enum agent_op op, int n);
00039 
00040 /* Functions for building expressions.  */
00041 
00042 /* Allocate a new, empty agent expression.  */
00043 struct agent_expr *
00044 new_agent_expr (struct gdbarch *gdbarch, CORE_ADDR scope)
00045 {
00046   struct agent_expr *x = xmalloc (sizeof (*x));
00047 
00048   x->len = 0;
00049   x->size = 1;                  /* Change this to a larger value once
00050                                    reallocation code is tested.  */
00051   x->buf = xmalloc (x->size);
00052 
00053   x->gdbarch = gdbarch;
00054   x->scope = scope;
00055 
00056   /* Bit vector for registers used.  */
00057   x->reg_mask_len = 1;
00058   x->reg_mask = xmalloc (x->reg_mask_len * sizeof (x->reg_mask[0]));
00059   memset (x->reg_mask, 0, x->reg_mask_len * sizeof (x->reg_mask[0]));
00060 
00061   x->tracing = 0;
00062   x->trace_string = 0;
00063 
00064   return x;
00065 }
00066 
00067 /* Free a agent expression.  */
00068 void
00069 free_agent_expr (struct agent_expr *x)
00070 {
00071   xfree (x->buf);
00072   xfree (x->reg_mask);
00073   xfree (x);
00074 }
00075 
00076 static void
00077 do_free_agent_expr_cleanup (void *x)
00078 {
00079   free_agent_expr (x);
00080 }
00081 
00082 struct cleanup *
00083 make_cleanup_free_agent_expr (struct agent_expr *x)
00084 {
00085   return make_cleanup (do_free_agent_expr_cleanup, x);
00086 }
00087 
00088 
00089 /* Make sure that X has room for at least N more bytes.  This doesn't
00090    affect the length, just the allocated size.  */
00091 static void
00092 grow_expr (struct agent_expr *x, int n)
00093 {
00094   if (x->len + n > x->size)
00095     {
00096       x->size *= 2;
00097       if (x->size < x->len + n)
00098         x->size = x->len + n + 10;
00099       x->buf = xrealloc (x->buf, x->size);
00100     }
00101 }
00102 
00103 
00104 /* Append the low N bytes of VAL as an N-byte integer to the
00105    expression X, in big-endian order.  */
00106 static void
00107 append_const (struct agent_expr *x, LONGEST val, int n)
00108 {
00109   int i;
00110 
00111   grow_expr (x, n);
00112   for (i = n - 1; i >= 0; i--)
00113     {
00114       x->buf[x->len + i] = val & 0xff;
00115       val >>= 8;
00116     }
00117   x->len += n;
00118 }
00119 
00120 
00121 /* Extract an N-byte big-endian unsigned integer from expression X at
00122    offset O.  */
00123 static LONGEST
00124 read_const (struct agent_expr *x, int o, int n)
00125 {
00126   int i;
00127   LONGEST accum = 0;
00128 
00129   /* Make sure we're not reading off the end of the expression.  */
00130   if (o + n > x->len)
00131     error (_("GDB bug: ax-general.c (read_const): incomplete constant"));
00132 
00133   for (i = 0; i < n; i++)
00134     accum = (accum << 8) | x->buf[o + i];
00135 
00136   return accum;
00137 }
00138 
00139 
00140 /* Append a simple operator OP to EXPR.  */
00141 void
00142 ax_simple (struct agent_expr *x, enum agent_op op)
00143 {
00144   grow_expr (x, 1);
00145   x->buf[x->len++] = op;
00146 }
00147 
00148 /* Append a pick operator to EXPR.  DEPTH is the stack item to pick,
00149    with 0 being top of stack.  */
00150 
00151 void
00152 ax_pick (struct agent_expr *x, int depth)
00153 {
00154   if (depth < 0 || depth > 255)
00155     error (_("GDB bug: ax-general.c (ax_pick): stack depth out of range"));
00156   ax_simple (x, aop_pick);
00157   append_const (x, 1, depth);
00158 }
00159 
00160 
00161 /* Append a sign-extension or zero-extension instruction to EXPR, to
00162    extend an N-bit value.  */
00163 static void
00164 generic_ext (struct agent_expr *x, enum agent_op op, int n)
00165 {
00166   /* N must fit in a byte.  */
00167   if (n < 0 || n > 255)
00168     error (_("GDB bug: ax-general.c (generic_ext): bit count out of range"));
00169   /* That had better be enough range.  */
00170   if (sizeof (LONGEST) * 8 > 255)
00171     error (_("GDB bug: ax-general.c (generic_ext): "
00172              "opcode has inadequate range"));
00173 
00174   grow_expr (x, 2);
00175   x->buf[x->len++] = op;
00176   x->buf[x->len++] = n;
00177 }
00178 
00179 
00180 /* Append a sign-extension instruction to EXPR, to extend an N-bit value.  */
00181 void
00182 ax_ext (struct agent_expr *x, int n)
00183 {
00184   generic_ext (x, aop_ext, n);
00185 }
00186 
00187 
00188 /* Append a zero-extension instruction to EXPR, to extend an N-bit value.  */
00189 void
00190 ax_zero_ext (struct agent_expr *x, int n)
00191 {
00192   generic_ext (x, aop_zero_ext, n);
00193 }
00194 
00195 
00196 /* Append a trace_quick instruction to EXPR, to record N bytes.  */
00197 void
00198 ax_trace_quick (struct agent_expr *x, int n)
00199 {
00200   /* N must fit in a byte.  */
00201   if (n < 0 || n > 255)
00202     error (_("GDB bug: ax-general.c (ax_trace_quick): "
00203              "size out of range for trace_quick"));
00204 
00205   grow_expr (x, 2);
00206   x->buf[x->len++] = aop_trace_quick;
00207   x->buf[x->len++] = n;
00208 }
00209 
00210 
00211 /* Append a goto op to EXPR.  OP is the actual op (must be aop_goto or
00212    aop_if_goto).  We assume we don't know the target offset yet,
00213    because it's probably a forward branch, so we leave space in EXPR
00214    for the target, and return the offset in EXPR of that space, so we
00215    can backpatch it once we do know the target offset.  Use ax_label
00216    to do the backpatching.  */
00217 int
00218 ax_goto (struct agent_expr *x, enum agent_op op)
00219 {
00220   grow_expr (x, 3);
00221   x->buf[x->len + 0] = op;
00222   x->buf[x->len + 1] = 0xff;
00223   x->buf[x->len + 2] = 0xff;
00224   x->len += 3;
00225   return x->len - 2;
00226 }
00227 
00228 /* Suppose a given call to ax_goto returns some value PATCH.  When you
00229    know the offset TARGET that goto should jump to, call
00230    ax_label (EXPR, PATCH, TARGET)
00231    to patch TARGET into the ax_goto instruction.  */
00232 void
00233 ax_label (struct agent_expr *x, int patch, int target)
00234 {
00235   /* Make sure the value is in range.  Don't accept 0xffff as an
00236      offset; that's our magic sentinel value for unpatched branches.  */
00237   if (target < 0 || target >= 0xffff)
00238     error (_("GDB bug: ax-general.c (ax_label): label target out of range"));
00239 
00240   x->buf[patch] = (target >> 8) & 0xff;
00241   x->buf[patch + 1] = target & 0xff;
00242 }
00243 
00244 
00245 /* Assemble code to push a constant on the stack.  */
00246 void
00247 ax_const_l (struct agent_expr *x, LONGEST l)
00248 {
00249   static enum agent_op ops[]
00250   =
00251   {aop_const8, aop_const16, aop_const32, aop_const64};
00252   int size;
00253   int op;
00254 
00255   /* How big is the number?  'op' keeps track of which opcode to use.
00256      Notice that we don't really care whether the original number was
00257      signed or unsigned; we always reproduce the value exactly, and
00258      use the shortest representation.  */
00259   for (op = 0, size = 8; size < 64; size *= 2, op++)
00260     {
00261       LONGEST lim = ((LONGEST) 1) << (size - 1);
00262 
00263       if (-lim <= l && l <= lim - 1)
00264         break;
00265     }
00266 
00267   /* Emit the right opcode...  */
00268   ax_simple (x, ops[op]);
00269 
00270   /* Emit the low SIZE bytes as an unsigned number.  We know that
00271      sign-extending this will yield l.  */
00272   append_const (x, l, size / 8);
00273 
00274   /* Now, if it was negative, and not full-sized, sign-extend it.  */
00275   if (l < 0 && size < 64)
00276     ax_ext (x, size);
00277 }
00278 
00279 
00280 void
00281 ax_const_d (struct agent_expr *x, LONGEST d)
00282 {
00283   /* FIXME: floating-point support not present yet.  */
00284   error (_("GDB bug: ax-general.c (ax_const_d): "
00285            "floating point not supported yet"));
00286 }
00287 
00288 
00289 /* Assemble code to push the value of register number REG on the
00290    stack.  */
00291 void
00292 ax_reg (struct agent_expr *x, int reg)
00293 {
00294   if (reg >= gdbarch_num_regs (x->gdbarch))
00295     {
00296       /* This is a pseudo-register.  */
00297       if (!gdbarch_ax_pseudo_register_push_stack_p (x->gdbarch))
00298         error (_("'%s' is a pseudo-register; "
00299                  "GDB cannot yet trace its contents."),
00300                user_reg_map_regnum_to_name (x->gdbarch, reg));
00301       if (gdbarch_ax_pseudo_register_push_stack (x->gdbarch, x, reg))
00302         error (_("Trace '%s' failed."),
00303                user_reg_map_regnum_to_name (x->gdbarch, reg));
00304     }
00305   else
00306     {
00307       /* Make sure the register number is in range.  */
00308       if (reg < 0 || reg > 0xffff)
00309         error (_("GDB bug: ax-general.c (ax_reg): "
00310                  "register number out of range"));
00311       grow_expr (x, 3);
00312       x->buf[x->len] = aop_reg;
00313       x->buf[x->len + 1] = (reg >> 8) & 0xff;
00314       x->buf[x->len + 2] = (reg) & 0xff;
00315       x->len += 3;
00316     }
00317 }
00318 
00319 /* Assemble code to operate on a trace state variable.  */
00320 
00321 void
00322 ax_tsv (struct agent_expr *x, enum agent_op op, int num)
00323 {
00324   /* Make sure the tsv number is in range.  */
00325   if (num < 0 || num > 0xffff)
00326     internal_error (__FILE__, __LINE__, 
00327                     _("ax-general.c (ax_tsv): variable "
00328                       "number is %d, out of range"), num);
00329 
00330   grow_expr (x, 3);
00331   x->buf[x->len] = op;
00332   x->buf[x->len + 1] = (num >> 8) & 0xff;
00333   x->buf[x->len + 2] = (num) & 0xff;
00334   x->len += 3;
00335 }
00336 
00337 /* Append a string to the expression.  Note that the string is going
00338    into the bytecodes directly, not on the stack.  As a precaution,
00339    include both length as prefix, and terminate with a NUL.  (The NUL
00340    is counted in the length.)  */
00341 
00342 void
00343 ax_string (struct agent_expr *x, const char *str, int slen)
00344 {
00345   int i;
00346 
00347   /* Make sure the string length is reasonable.  */
00348   if (slen < 0 || slen > 0xffff)
00349     internal_error (__FILE__, __LINE__, 
00350                     _("ax-general.c (ax_string): string "
00351                       "length is %d, out of allowed range"), slen);
00352 
00353   grow_expr (x, 2 + slen + 1);
00354   x->buf[x->len++] = ((slen + 1) >> 8) & 0xff;
00355   x->buf[x->len++] = (slen + 1) & 0xff;
00356   for (i = 0; i < slen; ++i)
00357     x->buf[x->len++] = str[i];
00358   x->buf[x->len++] = '\0';
00359 }
00360 
00361 
00362 
00363 /* Functions for disassembling agent expressions, and otherwise
00364    debugging the expression compiler.  */
00365 
00366 struct aop_map aop_map[] =
00367 {
00368   {0, 0, 0, 0, 0}
00369 #define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE) \
00370   , { # NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED }
00371 #include "ax.def"
00372 #undef DEFOP
00373 };
00374 
00375 
00376 /* Disassemble the expression EXPR, writing to F.  */
00377 void
00378 ax_print (struct ui_file *f, struct agent_expr *x)
00379 {
00380   int i;
00381 
00382   fprintf_filtered (f, _("Scope: %s\n"), paddress (x->gdbarch, x->scope));
00383   fprintf_filtered (f, _("Reg mask:"));
00384   for (i = 0; i < x->reg_mask_len; ++i)
00385     fprintf_filtered (f, _(" %02x"), x->reg_mask[i]);
00386   fprintf_filtered (f, _("\n"));
00387 
00388   /* Check the size of the name array against the number of entries in
00389      the enum, to catch additions that people didn't sync.  */
00390   if ((sizeof (aop_map) / sizeof (aop_map[0]))
00391       != aop_last)
00392     error (_("GDB bug: ax-general.c (ax_print): opcode map out of sync"));
00393 
00394   for (i = 0; i < x->len;)
00395     {
00396       enum agent_op op = x->buf[i];
00397 
00398       if (op >= (sizeof (aop_map) / sizeof (aop_map[0]))
00399           || !aop_map[op].name)
00400         {
00401           fprintf_filtered (f, _("%3d  <bad opcode %02x>\n"), i, op);
00402           i++;
00403           continue;
00404         }
00405       if (i + 1 + aop_map[op].op_size > x->len)
00406         {
00407           fprintf_filtered (f, _("%3d  <incomplete opcode %s>\n"),
00408                             i, aop_map[op].name);
00409           break;
00410         }
00411 
00412       fprintf_filtered (f, "%3d  %s", i, aop_map[op].name);
00413       if (aop_map[op].op_size > 0)
00414         {
00415           fputs_filtered (" ", f);
00416 
00417           print_longest (f, 'd', 0,
00418                          read_const (x, i + 1, aop_map[op].op_size));
00419         }
00420       /* Handle the complicated printf arguments specially.  */
00421       else if (op == aop_printf)
00422         {
00423           int slen, nargs;
00424 
00425           i++;
00426           nargs = x->buf[i++];
00427           slen = x->buf[i++];
00428           slen = slen * 256 + x->buf[i++];
00429           fprintf_filtered (f, _(" \"%s\", %d args"),
00430                             &(x->buf[i]), nargs);
00431           i += slen - 1;
00432         }
00433       fprintf_filtered (f, "\n");
00434       i += 1 + aop_map[op].op_size;
00435     }
00436 }
00437 
00438 /* Add register REG to the register mask for expression AX.  */
00439 void
00440 ax_reg_mask (struct agent_expr *ax, int reg)
00441 {
00442   if (reg >= gdbarch_num_regs (ax->gdbarch))
00443     {
00444       /* This is a pseudo-register.  */
00445       if (!gdbarch_ax_pseudo_register_collect_p (ax->gdbarch))
00446         error (_("'%s' is a pseudo-register; "
00447                  "GDB cannot yet trace its contents."),
00448                user_reg_map_regnum_to_name (ax->gdbarch, reg));
00449       if (gdbarch_ax_pseudo_register_collect (ax->gdbarch, ax, reg))
00450         error (_("Trace '%s' failed."),
00451                user_reg_map_regnum_to_name (ax->gdbarch, reg));
00452     }
00453   else
00454     {
00455       int byte = reg / 8;
00456 
00457       /* Grow the bit mask if necessary.  */
00458       if (byte >= ax->reg_mask_len)
00459         {
00460           /* It's not appropriate to double here.  This isn't a
00461              string buffer.  */
00462           int new_len = byte + 1;
00463           unsigned char *new_reg_mask = xrealloc (ax->reg_mask,
00464                                                   new_len
00465                                                   * sizeof (ax->reg_mask[0]));
00466           memset (new_reg_mask + ax->reg_mask_len, 0,
00467                   (new_len - ax->reg_mask_len) * sizeof (ax->reg_mask[0]));
00468           ax->reg_mask_len = new_len;
00469           ax->reg_mask = new_reg_mask;
00470         }
00471 
00472       ax->reg_mask[byte] |= 1 << (reg % 8);
00473     }
00474 }
00475 
00476 /* Given an agent expression AX, fill in requirements and other descriptive
00477    bits.  */
00478 void
00479 ax_reqs (struct agent_expr *ax)
00480 {
00481   int i;
00482   int height;
00483 
00484   /* Jump target table.  targets[i] is non-zero iff we have found a
00485      jump to offset i.  */
00486   char *targets = (char *) alloca (ax->len * sizeof (targets[0]));
00487 
00488   /* Instruction boundary table.  boundary[i] is non-zero iff our scan
00489      has reached an instruction starting at offset i.  */
00490   char *boundary = (char *) alloca (ax->len * sizeof (boundary[0]));
00491 
00492   /* Stack height record.  If either targets[i] or boundary[i] is
00493      non-zero, heights[i] is the height the stack should have before
00494      executing the bytecode at that point.  */
00495   int *heights = (int *) alloca (ax->len * sizeof (heights[0]));
00496 
00497   /* Pointer to a description of the present op.  */
00498   struct aop_map *op;
00499 
00500   memset (targets, 0, ax->len * sizeof (targets[0]));
00501   memset (boundary, 0, ax->len * sizeof (boundary[0]));
00502 
00503   ax->max_height = ax->min_height = height = 0;
00504   ax->flaw = agent_flaw_none;
00505   ax->max_data_size = 0;
00506 
00507   for (i = 0; i < ax->len; i += 1 + op->op_size)
00508     {
00509       if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0])))
00510         {
00511           ax->flaw = agent_flaw_bad_instruction;
00512           return;
00513         }
00514 
00515       op = &aop_map[ax->buf[i]];
00516 
00517       if (!op->name)
00518         {
00519           ax->flaw = agent_flaw_bad_instruction;
00520           return;
00521         }
00522 
00523       if (i + 1 + op->op_size > ax->len)
00524         {
00525           ax->flaw = agent_flaw_incomplete_instruction;
00526           return;
00527         }
00528 
00529       /* If this instruction is a forward jump target, does the
00530          current stack height match the stack height at the jump
00531          source?  */
00532       if (targets[i] && (heights[i] != height))
00533         {
00534           ax->flaw = agent_flaw_height_mismatch;
00535           return;
00536         }
00537 
00538       boundary[i] = 1;
00539       heights[i] = height;
00540 
00541       height -= op->consumed;
00542       if (height < ax->min_height)
00543         ax->min_height = height;
00544       height += op->produced;
00545       if (height > ax->max_height)
00546         ax->max_height = height;
00547 
00548       if (op->data_size > ax->max_data_size)
00549         ax->max_data_size = op->data_size;
00550 
00551       /* For jump instructions, check that the target is a valid
00552          offset.  If it is, record the fact that that location is a
00553          jump target, and record the height we expect there.  */
00554       if (aop_goto == op - aop_map
00555           || aop_if_goto == op - aop_map)
00556         {
00557           int target = read_const (ax, i + 1, 2);
00558           if (target < 0 || target >= ax->len)
00559             {
00560               ax->flaw = agent_flaw_bad_jump;
00561               return;
00562             }
00563 
00564           /* Do we have any information about what the stack height
00565              should be at the target?  */
00566           if (targets[target] || boundary[target])
00567             {
00568               if (heights[target] != height)
00569                 {
00570                   ax->flaw = agent_flaw_height_mismatch;
00571                   return;
00572                 }
00573             }
00574 
00575           /* Record the target, along with the stack height we expect.  */
00576           targets[target] = 1;
00577           heights[target] = height;
00578         }
00579 
00580       /* For unconditional jumps with a successor, check that the
00581          successor is a target, and pick up its stack height.  */
00582       if (aop_goto == op - aop_map
00583           && i + 3 < ax->len)
00584         {
00585           if (!targets[i + 3])
00586             {
00587               ax->flaw = agent_flaw_hole;
00588               return;
00589             }
00590 
00591           height = heights[i + 3];
00592         }
00593 
00594       /* For reg instructions, record the register in the bit mask.  */
00595       if (aop_reg == op - aop_map)
00596         {
00597           int reg = read_const (ax, i + 1, 2);
00598 
00599           ax_reg_mask (ax, reg);
00600         }
00601     }
00602 
00603   /* Check that all the targets are on boundaries.  */
00604   for (i = 0; i < ax->len; i++)
00605     if (targets[i] && !boundary[i])
00606       {
00607         ax->flaw = agent_flaw_bad_jump;
00608         return;
00609       }
00610 
00611   ax->final_height = height;
00612 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines