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