xref: /dragonfly/contrib/gdb-7/gdb/ax-general.c (revision dca3c15d)
1 /* Functions for manipulating expressions designed to be executed on the agent
2    Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009
3    Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 /* Despite what the above comment says about this file being part of
21    GDB, we would like to keep these functions free of GDB
22    dependencies, since we want to be able to use them in contexts
23    outside of GDB (test suites, the stub, etc.)  */
24 
25 #include "defs.h"
26 #include "ax.h"
27 
28 #include "value.h"
29 #include "gdb_string.h"
30 
31 static void grow_expr (struct agent_expr *x, int n);
32 
33 static void append_const (struct agent_expr *x, LONGEST val, int n);
34 
35 static LONGEST read_const (struct agent_expr *x, int o, int n);
36 
37 static void generic_ext (struct agent_expr *x, enum agent_op op, int n);
38 
39 /* Functions for building expressions.  */
40 
41 /* Allocate a new, empty agent expression.  */
42 struct agent_expr *
43 new_agent_expr (CORE_ADDR scope)
44 {
45   struct agent_expr *x = xmalloc (sizeof (*x));
46   x->len = 0;
47   x->size = 1;			/* Change this to a larger value once
48 				   reallocation code is tested.  */
49   x->buf = xmalloc (x->size);
50   x->scope = scope;
51 
52   return x;
53 }
54 
55 /* Free a agent expression.  */
56 void
57 free_agent_expr (struct agent_expr *x)
58 {
59   xfree (x->buf);
60   xfree (x);
61 }
62 
63 static void
64 do_free_agent_expr_cleanup (void *x)
65 {
66   free_agent_expr (x);
67 }
68 
69 struct cleanup *
70 make_cleanup_free_agent_expr (struct agent_expr *x)
71 {
72   return make_cleanup (do_free_agent_expr_cleanup, x);
73 }
74 
75 
76 /* Make sure that X has room for at least N more bytes.  This doesn't
77    affect the length, just the allocated size.  */
78 static void
79 grow_expr (struct agent_expr *x, int n)
80 {
81   if (x->len + n > x->size)
82     {
83       x->size *= 2;
84       if (x->size < x->len + n)
85 	x->size = x->len + n + 10;
86       x->buf = xrealloc (x->buf, x->size);
87     }
88 }
89 
90 
91 /* Append the low N bytes of VAL as an N-byte integer to the
92    expression X, in big-endian order.  */
93 static void
94 append_const (struct agent_expr *x, LONGEST val, int n)
95 {
96   int i;
97 
98   grow_expr (x, n);
99   for (i = n - 1; i >= 0; i--)
100     {
101       x->buf[x->len + i] = val & 0xff;
102       val >>= 8;
103     }
104   x->len += n;
105 }
106 
107 
108 /* Extract an N-byte big-endian unsigned integer from expression X at
109    offset O.  */
110 static LONGEST
111 read_const (struct agent_expr *x, int o, int n)
112 {
113   int i;
114   LONGEST accum = 0;
115 
116   /* Make sure we're not reading off the end of the expression.  */
117   if (o + n > x->len)
118     error (_("GDB bug: ax-general.c (read_const): incomplete constant"));
119 
120   for (i = 0; i < n; i++)
121     accum = (accum << 8) | x->buf[o + i];
122 
123   return accum;
124 }
125 
126 
127 /* Append a simple operator OP to EXPR.  */
128 void
129 ax_simple (struct agent_expr *x, enum agent_op op)
130 {
131   grow_expr (x, 1);
132   x->buf[x->len++] = op;
133 }
134 
135 
136 /* Append a sign-extension or zero-extension instruction to EXPR, to
137    extend an N-bit value.  */
138 static void
139 generic_ext (struct agent_expr *x, enum agent_op op, int n)
140 {
141   /* N must fit in a byte.  */
142   if (n < 0 || n > 255)
143     error (_("GDB bug: ax-general.c (generic_ext): bit count out of range"));
144   /* That had better be enough range.  */
145   if (sizeof (LONGEST) * 8 > 255)
146     error (_("GDB bug: ax-general.c (generic_ext): opcode has inadequate range"));
147 
148   grow_expr (x, 2);
149   x->buf[x->len++] = op;
150   x->buf[x->len++] = n;
151 }
152 
153 
154 /* Append a sign-extension instruction to EXPR, to extend an N-bit value.  */
155 void
156 ax_ext (struct agent_expr *x, int n)
157 {
158   generic_ext (x, aop_ext, n);
159 }
160 
161 
162 /* Append a zero-extension instruction to EXPR, to extend an N-bit value.  */
163 void
164 ax_zero_ext (struct agent_expr *x, int n)
165 {
166   generic_ext (x, aop_zero_ext, n);
167 }
168 
169 
170 /* Append a trace_quick instruction to EXPR, to record N bytes.  */
171 void
172 ax_trace_quick (struct agent_expr *x, int n)
173 {
174   /* N must fit in a byte.  */
175   if (n < 0 || n > 255)
176     error (_("GDB bug: ax-general.c (ax_trace_quick): size out of range for trace_quick"));
177 
178   grow_expr (x, 2);
179   x->buf[x->len++] = aop_trace_quick;
180   x->buf[x->len++] = n;
181 }
182 
183 
184 /* Append a goto op to EXPR.  OP is the actual op (must be aop_goto or
185    aop_if_goto).  We assume we don't know the target offset yet,
186    because it's probably a forward branch, so we leave space in EXPR
187    for the target, and return the offset in EXPR of that space, so we
188    can backpatch it once we do know the target offset.  Use ax_label
189    to do the backpatching.  */
190 int
191 ax_goto (struct agent_expr *x, enum agent_op op)
192 {
193   grow_expr (x, 3);
194   x->buf[x->len + 0] = op;
195   x->buf[x->len + 1] = 0xff;
196   x->buf[x->len + 2] = 0xff;
197   x->len += 3;
198   return x->len - 2;
199 }
200 
201 /* Suppose a given call to ax_goto returns some value PATCH.  When you
202    know the offset TARGET that goto should jump to, call
203    ax_label (EXPR, PATCH, TARGET)
204    to patch TARGET into the ax_goto instruction.  */
205 void
206 ax_label (struct agent_expr *x, int patch, int target)
207 {
208   /* Make sure the value is in range.  Don't accept 0xffff as an
209      offset; that's our magic sentinel value for unpatched branches.  */
210   if (target < 0 || target >= 0xffff)
211     error (_("GDB bug: ax-general.c (ax_label): label target out of range"));
212 
213   x->buf[patch] = (target >> 8) & 0xff;
214   x->buf[patch + 1] = target & 0xff;
215 }
216 
217 
218 /* Assemble code to push a constant on the stack.  */
219 void
220 ax_const_l (struct agent_expr *x, LONGEST l)
221 {
222   static enum agent_op ops[]
223   =
224   {aop_const8, aop_const16, aop_const32, aop_const64};
225   int size;
226   int op;
227 
228   /* How big is the number?  'op' keeps track of which opcode to use.
229      Notice that we don't really care whether the original number was
230      signed or unsigned; we always reproduce the value exactly, and
231      use the shortest representation.  */
232   for (op = 0, size = 8; size < 64; size *= 2, op++)
233     {
234       LONGEST lim = 1 << (size - 1);
235 
236       if (-lim <= l && l <= lim - 1)
237         break;
238     }
239 
240   /* Emit the right opcode... */
241   ax_simple (x, ops[op]);
242 
243   /* Emit the low SIZE bytes as an unsigned number.  We know that
244      sign-extending this will yield l.  */
245   append_const (x, l, size / 8);
246 
247   /* Now, if it was negative, and not full-sized, sign-extend it.  */
248   if (l < 0 && size < 64)
249     ax_ext (x, size);
250 }
251 
252 
253 void
254 ax_const_d (struct agent_expr *x, LONGEST d)
255 {
256   /* FIXME: floating-point support not present yet.  */
257   error (_("GDB bug: ax-general.c (ax_const_d): floating point not supported yet"));
258 }
259 
260 
261 /* Assemble code to push the value of register number REG on the
262    stack.  */
263 void
264 ax_reg (struct agent_expr *x, int reg)
265 {
266   /* Make sure the register number is in range.  */
267   if (reg < 0 || reg > 0xffff)
268     error (_("GDB bug: ax-general.c (ax_reg): register number out of range"));
269   grow_expr (x, 3);
270   x->buf[x->len] = aop_reg;
271   x->buf[x->len + 1] = (reg >> 8) & 0xff;
272   x->buf[x->len + 2] = (reg) & 0xff;
273   x->len += 3;
274 }
275 
276 
277 
278 /* Functions for disassembling agent expressions, and otherwise
279    debugging the expression compiler.  */
280 
281 struct aop_map aop_map[] =
282 {
283   {0, 0, 0, 0, 0},
284   {"float", 0, 0, 0, 0},	/* 0x01 */
285   {"add", 0, 0, 2, 1},		/* 0x02 */
286   {"sub", 0, 0, 2, 1},		/* 0x03 */
287   {"mul", 0, 0, 2, 1},		/* 0x04 */
288   {"div_signed", 0, 0, 2, 1},	/* 0x05 */
289   {"div_unsigned", 0, 0, 2, 1},	/* 0x06 */
290   {"rem_signed", 0, 0, 2, 1},	/* 0x07 */
291   {"rem_unsigned", 0, 0, 2, 1},	/* 0x08 */
292   {"lsh", 0, 0, 2, 1},		/* 0x09 */
293   {"rsh_signed", 0, 0, 2, 1},	/* 0x0a */
294   {"rsh_unsigned", 0, 0, 2, 1},	/* 0x0b */
295   {"trace", 0, 0, 2, 0},	/* 0x0c */
296   {"trace_quick", 1, 0, 1, 1},	/* 0x0d */
297   {"log_not", 0, 0, 1, 1},	/* 0x0e */
298   {"bit_and", 0, 0, 2, 1},	/* 0x0f */
299   {"bit_or", 0, 0, 2, 1},	/* 0x10 */
300   {"bit_xor", 0, 0, 2, 1},	/* 0x11 */
301   {"bit_not", 0, 0, 1, 1},	/* 0x12 */
302   {"equal", 0, 0, 2, 1},	/* 0x13 */
303   {"less_signed", 0, 0, 2, 1},	/* 0x14 */
304   {"less_unsigned", 0, 0, 2, 1},	/* 0x15 */
305   {"ext", 1, 0, 1, 1},		/* 0x16 */
306   {"ref8", 0, 8, 1, 1},		/* 0x17 */
307   {"ref16", 0, 16, 1, 1},	/* 0x18 */
308   {"ref32", 0, 32, 1, 1},	/* 0x19 */
309   {"ref64", 0, 64, 1, 1},	/* 0x1a */
310   {"ref_float", 0, 0, 1, 1},	/* 0x1b */
311   {"ref_double", 0, 0, 1, 1},	/* 0x1c */
312   {"ref_long_double", 0, 0, 1, 1},	/* 0x1d */
313   {"l_to_d", 0, 0, 1, 1},	/* 0x1e */
314   {"d_to_l", 0, 0, 1, 1},	/* 0x1f */
315   {"if_goto", 2, 0, 1, 0},	/* 0x20 */
316   {"goto", 2, 0, 0, 0},		/* 0x21 */
317   {"const8", 1, 8, 0, 1},	/* 0x22 */
318   {"const16", 2, 16, 0, 1},	/* 0x23 */
319   {"const32", 4, 32, 0, 1},	/* 0x24 */
320   {"const64", 8, 64, 0, 1},	/* 0x25 */
321   {"reg", 2, 0, 0, 1},		/* 0x26 */
322   {"end", 0, 0, 0, 0},		/* 0x27 */
323   {"dup", 0, 0, 1, 2},		/* 0x28 */
324   {"pop", 0, 0, 1, 0},		/* 0x29 */
325   {"zero_ext", 1, 0, 1, 1},	/* 0x2a */
326   {"swap", 0, 0, 2, 2},		/* 0x2b */
327   {0, 0, 0, 0, 0},		/* 0x2c */
328   {0, 0, 0, 0, 0},		/* 0x2d */
329   {0, 0, 0, 0, 0},		/* 0x2e */
330   {0, 0, 0, 0, 0},		/* 0x2f */
331   {"trace16", 2, 0, 1, 1},	/* 0x30 */
332 };
333 
334 
335 /* Disassemble the expression EXPR, writing to F.  */
336 void
337 ax_print (struct ui_file *f, struct agent_expr *x)
338 {
339   int i;
340   int is_float = 0;
341 
342   /* Check the size of the name array against the number of entries in
343      the enum, to catch additions that people didn't sync.  */
344   if ((sizeof (aop_map) / sizeof (aop_map[0]))
345       != aop_last)
346     error (_("GDB bug: ax-general.c (ax_print): opcode map out of sync"));
347 
348   for (i = 0; i < x->len;)
349     {
350       enum agent_op op = x->buf[i];
351 
352       if (op >= (sizeof (aop_map) / sizeof (aop_map[0]))
353 	  || !aop_map[op].name)
354 	{
355 	  fprintf_filtered (f, _("%3d  <bad opcode %02x>\n"), i, op);
356 	  i++;
357 	  continue;
358 	}
359       if (i + 1 + aop_map[op].op_size > x->len)
360 	{
361 	  fprintf_filtered (f, _("%3d  <incomplete opcode %s>\n"),
362 			    i, aop_map[op].name);
363 	  break;
364 	}
365 
366       fprintf_filtered (f, "%3d  %s", i, aop_map[op].name);
367       if (aop_map[op].op_size > 0)
368 	{
369 	  fputs_filtered (" ", f);
370 
371 	  print_longest (f, 'd', 0,
372 			 read_const (x, i + 1, aop_map[op].op_size));
373 	}
374       fprintf_filtered (f, "\n");
375       i += 1 + aop_map[op].op_size;
376 
377       is_float = (op == aop_float);
378     }
379 }
380 
381 
382 /* Given an agent expression AX, fill in an agent_reqs structure REQS
383    describing it.  */
384 void
385 ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
386 {
387   int i;
388   int height;
389 
390   /* Bit vector for registers used.  */
391   int reg_mask_len = 1;
392   unsigned char *reg_mask = xmalloc (reg_mask_len * sizeof (reg_mask[0]));
393 
394   /* Jump target table.  targets[i] is non-zero iff we have found a
395      jump to offset i.  */
396   char *targets = (char *) alloca (ax->len * sizeof (targets[0]));
397 
398   /* Instruction boundary table.  boundary[i] is non-zero iff our scan
399      has reached an instruction starting at offset i.  */
400   char *boundary = (char *) alloca (ax->len * sizeof (boundary[0]));
401 
402   /* Stack height record.  If either targets[i] or boundary[i] is
403      non-zero, heights[i] is the height the stack should have before
404      executing the bytecode at that point.  */
405   int *heights = (int *) alloca (ax->len * sizeof (heights[0]));
406 
407   /* Pointer to a description of the present op.  */
408   struct aop_map *op;
409 
410   memset (reg_mask, 0, reg_mask_len * sizeof (reg_mask[0]));
411   memset (targets, 0, ax->len * sizeof (targets[0]));
412   memset (boundary, 0, ax->len * sizeof (boundary[0]));
413 
414   reqs->max_height = reqs->min_height = height = 0;
415   reqs->flaw = agent_flaw_none;
416   reqs->max_data_size = 0;
417 
418   for (i = 0; i < ax->len; i += 1 + op->op_size)
419     {
420       if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0])))
421 	{
422 	  reqs->flaw = agent_flaw_bad_instruction;
423 	  xfree (reg_mask);
424 	  return;
425 	}
426 
427       op = &aop_map[ax->buf[i]];
428 
429       if (!op->name)
430 	{
431 	  reqs->flaw = agent_flaw_bad_instruction;
432 	  xfree (reg_mask);
433 	  return;
434 	}
435 
436       if (i + 1 + op->op_size > ax->len)
437 	{
438 	  reqs->flaw = agent_flaw_incomplete_instruction;
439 	  xfree (reg_mask);
440 	  return;
441 	}
442 
443       /* If this instruction is a forward jump target, does the
444          current stack height match the stack height at the jump
445          source?  */
446       if (targets[i] && (heights[i] != height))
447 	{
448 	  reqs->flaw = agent_flaw_height_mismatch;
449 	  xfree (reg_mask);
450 	  return;
451 	}
452 
453       boundary[i] = 1;
454       heights[i] = height;
455 
456       height -= op->consumed;
457       if (height < reqs->min_height)
458 	reqs->min_height = height;
459       height += op->produced;
460       if (height > reqs->max_height)
461 	reqs->max_height = height;
462 
463       if (op->data_size > reqs->max_data_size)
464 	reqs->max_data_size = op->data_size;
465 
466       /* For jump instructions, check that the target is a valid
467          offset.  If it is, record the fact that that location is a
468          jump target, and record the height we expect there.  */
469       if (aop_goto == op - aop_map
470 	  || aop_if_goto == op - aop_map)
471 	{
472 	  int target = read_const (ax, i + 1, 2);
473 	  if (target < 0 || target >= ax->len)
474 	    {
475 	      reqs->flaw = agent_flaw_bad_jump;
476 	      xfree (reg_mask);
477 	      return;
478 	    }
479 
480 	  /* Do we have any information about what the stack height
481              should be at the target?  */
482 	  if (targets[target] || boundary[target])
483 	    {
484 	      if (heights[target] != height)
485 		{
486 		  reqs->flaw = agent_flaw_height_mismatch;
487 		  xfree (reg_mask);
488 		  return;
489 		}
490 	    }
491 
492           /* Record the target, along with the stack height we expect.  */
493           targets[target] = 1;
494           heights[target] = height;
495 	}
496 
497       /* For unconditional jumps with a successor, check that the
498          successor is a target, and pick up its stack height.  */
499       if (aop_goto == op - aop_map
500 	  && i + 3 < ax->len)
501 	{
502 	  if (!targets[i + 3])
503 	    {
504 	      reqs->flaw = agent_flaw_hole;
505 	      xfree (reg_mask);
506 	      return;
507 	    }
508 
509 	  height = heights[i + 3];
510 	}
511 
512       /* For reg instructions, record the register in the bit mask.  */
513       if (aop_reg == op - aop_map)
514 	{
515 	  int reg = read_const (ax, i + 1, 2);
516 	  int byte = reg / 8;
517 
518 	  /* Grow the bit mask if necessary.  */
519 	  if (byte >= reg_mask_len)
520 	    {
521 	      /* It's not appropriate to double here.  This isn't a
522 	         string buffer.  */
523 	      int new_len = byte + 1;
524 	      reg_mask = xrealloc (reg_mask,
525 				   new_len * sizeof (reg_mask[0]));
526 	      memset (reg_mask + reg_mask_len, 0,
527 		      (new_len - reg_mask_len) * sizeof (reg_mask[0]));
528 	      reg_mask_len = new_len;
529 	    }
530 
531 	  reg_mask[byte] |= 1 << (reg % 8);
532 	}
533     }
534 
535   /* Check that all the targets are on boundaries.  */
536   for (i = 0; i < ax->len; i++)
537     if (targets[i] && !boundary[i])
538       {
539 	reqs->flaw = agent_flaw_bad_jump;
540 	xfree (reg_mask);
541 	return;
542       }
543 
544   reqs->final_height = height;
545   reqs->reg_mask_len = reg_mask_len;
546   reqs->reg_mask = reg_mask;
547 }
548