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