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
32static void grow_expr (struct agent_expr *x, int n);
33
34static void append_const (struct agent_expr *x, LONGEST val, int n);
35
36static LONGEST read_const (struct agent_expr *x, int o, int n);
37
38static 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.  */
43struct agent_expr *
44new_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.  */
57void
58free_agent_expr (struct agent_expr *x)
59{
60  xfree (x->buf);
61  xfree (x);
62}
63
64static void
65do_free_agent_expr_cleanup (void *x)
66{
67  free_agent_expr (x);
68}
69
70struct cleanup *
71make_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.  */
79static void
80grow_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.  */
94static void
95append_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.  */
111static LONGEST
112read_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.  */
129void
130ax_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.  */
139static void
140generic_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.  */
156void
157ax_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.  */
164void
165ax_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.  */
172void
173ax_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.  */
191int
192ax_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.  */
206void
207ax_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.  */
220void
221ax_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
250void
251ax_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.  */
260void
261ax_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
278struct 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.  */
333void
334ax_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.  */
381void
382ax_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