xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/ax-general.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* Functions for manipulating expressions designed to be executed on the agent
2    Copyright (C) 1998-2023 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 #include "gdbarch.h"
27 
28 #include "value.h"
29 #include "user-regs.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 agent_expr::agent_expr (struct gdbarch *gdbarch, CORE_ADDR scope)
42 {
43   this->len = 0;
44   this->size = 1;		/* Change this to a larger value once
45 				   reallocation code is tested.  */
46   this->buf = (unsigned char *) xmalloc (this->size);
47 
48   this->gdbarch = gdbarch;
49   this->scope = scope;
50 
51   /* Bit vector for registers used.  */
52   this->reg_mask_len = 1;
53   this->reg_mask = XCNEWVEC (unsigned char, this->reg_mask_len);
54 
55   this->tracing = 0;
56   this->trace_string = 0;
57 }
58 
59 agent_expr::~agent_expr ()
60 {
61   xfree (this->buf);
62   xfree (this->reg_mask);
63 }
64 
65 /* Make sure that X has room for at least N more bytes.  This doesn't
66    affect the length, just the allocated size.  */
67 static void
68 grow_expr (struct agent_expr *x, int n)
69 {
70   if (x->len + n > x->size)
71     {
72       x->size *= 2;
73       if (x->size < x->len + n)
74 	x->size = x->len + n + 10;
75       x->buf = (unsigned char *) xrealloc (x->buf, x->size);
76     }
77 }
78 
79 
80 /* Append the low N bytes of VAL as an N-byte integer to the
81    expression X, in big-endian order.  */
82 static void
83 append_const (struct agent_expr *x, LONGEST val, int n)
84 {
85   int i;
86 
87   grow_expr (x, n);
88   for (i = n - 1; i >= 0; i--)
89     {
90       x->buf[x->len + i] = val & 0xff;
91       val >>= 8;
92     }
93   x->len += n;
94 }
95 
96 
97 /* Extract an N-byte big-endian unsigned integer from expression X at
98    offset O.  */
99 static LONGEST
100 read_const (struct agent_expr *x, int o, int n)
101 {
102   int i;
103   LONGEST accum = 0;
104 
105   /* Make sure we're not reading off the end of the expression.  */
106   if (o + n > x->len)
107     error (_("GDB bug: ax-general.c (read_const): incomplete constant"));
108 
109   for (i = 0; i < n; i++)
110     accum = (accum << 8) | x->buf[o + i];
111 
112   return accum;
113 }
114 
115 /* See ax.h.  */
116 
117 void
118 ax_raw_byte (struct agent_expr *x, gdb_byte byte)
119 {
120   grow_expr (x, 1);
121   x->buf[x->len++] = byte;
122 }
123 
124 /* Append a simple operator OP to EXPR.  */
125 void
126 ax_simple (struct agent_expr *x, enum agent_op op)
127 {
128   ax_raw_byte (x, op);
129 }
130 
131 /* Append a pick operator to EXPR.  DEPTH is the stack item to pick,
132    with 0 being top of stack.  */
133 
134 void
135 ax_pick (struct agent_expr *x, int depth)
136 {
137   if (depth < 0 || depth > 255)
138     error (_("GDB bug: ax-general.c (ax_pick): stack depth out of range"));
139   ax_simple (x, aop_pick);
140   append_const (x, 1, depth);
141 }
142 
143 
144 /* Append a sign-extension or zero-extension instruction to EXPR, to
145    extend an N-bit value.  */
146 static void
147 generic_ext (struct agent_expr *x, enum agent_op op, int n)
148 {
149   /* N must fit in a byte.  */
150   if (n < 0 || n > 255)
151     error (_("GDB bug: ax-general.c (generic_ext): bit count out of range"));
152   /* That had better be enough range.  */
153   if (sizeof (LONGEST) * 8 > 255)
154     error (_("GDB bug: ax-general.c (generic_ext): "
155 	     "opcode has inadequate range"));
156 
157   grow_expr (x, 2);
158   x->buf[x->len++] = op;
159   x->buf[x->len++] = n;
160 }
161 
162 
163 /* Append a sign-extension instruction to EXPR, to extend an N-bit value.  */
164 void
165 ax_ext (struct agent_expr *x, int n)
166 {
167   generic_ext (x, aop_ext, n);
168 }
169 
170 
171 /* Append a zero-extension instruction to EXPR, to extend an N-bit value.  */
172 void
173 ax_zero_ext (struct agent_expr *x, int n)
174 {
175   generic_ext (x, aop_zero_ext, n);
176 }
177 
178 
179 /* Append a trace_quick instruction to EXPR, to record N bytes.  */
180 void
181 ax_trace_quick (struct agent_expr *x, int n)
182 {
183   /* N must fit in a byte.  */
184   if (n < 0 || n > 255)
185     error (_("GDB bug: ax-general.c (ax_trace_quick): "
186 	     "size out of range for trace_quick"));
187 
188   grow_expr (x, 2);
189   x->buf[x->len++] = aop_trace_quick;
190   x->buf[x->len++] = n;
191 }
192 
193 
194 /* Append a goto op to EXPR.  OP is the actual op (must be aop_goto or
195    aop_if_goto).  We assume we don't know the target offset yet,
196    because it's probably a forward branch, so we leave space in EXPR
197    for the target, and return the offset in EXPR of that space, so we
198    can backpatch it once we do know the target offset.  Use ax_label
199    to do the backpatching.  */
200 int
201 ax_goto (struct agent_expr *x, enum agent_op op)
202 {
203   grow_expr (x, 3);
204   x->buf[x->len + 0] = op;
205   x->buf[x->len + 1] = 0xff;
206   x->buf[x->len + 2] = 0xff;
207   x->len += 3;
208   return x->len - 2;
209 }
210 
211 /* Suppose a given call to ax_goto returns some value PATCH.  When you
212    know the offset TARGET that goto should jump to, call
213    ax_label (EXPR, PATCH, TARGET)
214    to patch TARGET into the ax_goto instruction.  */
215 void
216 ax_label (struct agent_expr *x, int patch, int target)
217 {
218   /* Make sure the value is in range.  Don't accept 0xffff as an
219      offset; that's our magic sentinel value for unpatched branches.  */
220   if (target < 0 || target >= 0xffff)
221     error (_("GDB bug: ax-general.c (ax_label): label target out of range"));
222 
223   x->buf[patch] = (target >> 8) & 0xff;
224   x->buf[patch + 1] = target & 0xff;
225 }
226 
227 
228 /* Assemble code to push a constant on the stack.  */
229 void
230 ax_const_l (struct agent_expr *x, LONGEST l)
231 {
232   static enum agent_op ops[]
233   =
234   {aop_const8, aop_const16, aop_const32, aop_const64};
235   int size;
236   int op;
237 
238   /* How big is the number?  'op' keeps track of which opcode to use.
239      Notice that we don't really care whether the original number was
240      signed or unsigned; we always reproduce the value exactly, and
241      use the shortest representation.  */
242   for (op = 0, size = 8; size < 64; size *= 2, op++)
243     {
244       LONGEST lim = ((LONGEST) 1) << (size - 1);
245 
246       if (-lim <= l && l <= lim - 1)
247 	break;
248     }
249 
250   /* Emit the right opcode...  */
251   ax_simple (x, ops[op]);
252 
253   /* Emit the low SIZE bytes as an unsigned number.  We know that
254      sign-extending this will yield l.  */
255   append_const (x, l, size / 8);
256 
257   /* Now, if it was negative, and not full-sized, sign-extend it.  */
258   if (l < 0 && size < 64)
259     ax_ext (x, size);
260 }
261 
262 
263 void
264 ax_const_d (struct agent_expr *x, LONGEST d)
265 {
266   /* FIXME: floating-point support not present yet.  */
267   error (_("GDB bug: ax-general.c (ax_const_d): "
268 	   "floating point not supported yet"));
269 }
270 
271 
272 /* Assemble code to push the value of register number REG on the
273    stack.  */
274 void
275 ax_reg (struct agent_expr *x, int reg)
276 {
277   if (reg >= gdbarch_num_regs (x->gdbarch))
278     {
279       /* This is a pseudo-register.  */
280       if (!gdbarch_ax_pseudo_register_push_stack_p (x->gdbarch))
281 	error (_("'%s' is a pseudo-register; "
282 		 "GDB cannot yet trace its contents."),
283 	       user_reg_map_regnum_to_name (x->gdbarch, reg));
284       if (gdbarch_ax_pseudo_register_push_stack (x->gdbarch, x, reg))
285 	error (_("Trace '%s' failed."),
286 	       user_reg_map_regnum_to_name (x->gdbarch, reg));
287     }
288   else
289     {
290       /* Get the remote register number.  */
291       reg = gdbarch_remote_register_number (x->gdbarch, reg);
292 
293       /* Make sure the register number is in range.  */
294       if (reg < 0 || reg > 0xffff)
295 	error (_("GDB bug: ax-general.c (ax_reg): "
296 		 "register number out of range"));
297       grow_expr (x, 3);
298       x->buf[x->len] = aop_reg;
299       x->buf[x->len + 1] = (reg >> 8) & 0xff;
300       x->buf[x->len + 2] = (reg) & 0xff;
301       x->len += 3;
302     }
303 }
304 
305 /* Assemble code to operate on a trace state variable.  */
306 
307 void
308 ax_tsv (struct agent_expr *x, enum agent_op op, int num)
309 {
310   /* Make sure the tsv number is in range.  */
311   if (num < 0 || num > 0xffff)
312     internal_error (_("ax-general.c (ax_tsv): variable "
313 		      "number is %d, out of range"), num);
314 
315   grow_expr (x, 3);
316   x->buf[x->len] = op;
317   x->buf[x->len + 1] = (num >> 8) & 0xff;
318   x->buf[x->len + 2] = (num) & 0xff;
319   x->len += 3;
320 }
321 
322 /* Append a string to the expression.  Note that the string is going
323    into the bytecodes directly, not on the stack.  As a precaution,
324    include both length as prefix, and terminate with a NUL.  (The NUL
325    is counted in the length.)  */
326 
327 void
328 ax_string (struct agent_expr *x, const char *str, int slen)
329 {
330   int i;
331 
332   /* Make sure the string length is reasonable.  */
333   if (slen < 0 || slen > 0xffff)
334     internal_error (_("ax-general.c (ax_string): string "
335 		      "length is %d, out of allowed range"), slen);
336 
337   grow_expr (x, 2 + slen + 1);
338   x->buf[x->len++] = ((slen + 1) >> 8) & 0xff;
339   x->buf[x->len++] = (slen + 1) & 0xff;
340   for (i = 0; i < slen; ++i)
341     x->buf[x->len++] = str[i];
342   x->buf[x->len++] = '\0';
343 }
344 
345 
346 
347 /* Functions for disassembling agent expressions, and otherwise
348    debugging the expression compiler.  */
349 
350 struct aop_map aop_map[] =
351 {
352   {0, 0, 0, 0, 0}
353 #define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE) \
354   , { # NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED }
355 #include "gdbsupport/ax.def"
356 #undef DEFOP
357 };
358 
359 
360 /* Disassemble the expression EXPR, writing to F.  */
361 void
362 ax_print (struct ui_file *f, struct agent_expr *x)
363 {
364   int i;
365 
366   gdb_printf (f, _("Scope: %s\n"), paddress (x->gdbarch, x->scope));
367   gdb_printf (f, _("Reg mask:"));
368   for (i = 0; i < x->reg_mask_len; ++i)
369     gdb_printf (f, _(" %02x"), x->reg_mask[i]);
370   gdb_printf (f, _("\n"));
371 
372   /* Check the size of the name array against the number of entries in
373      the enum, to catch additions that people didn't sync.  */
374   if ((sizeof (aop_map) / sizeof (aop_map[0]))
375       != aop_last)
376     error (_("GDB bug: ax-general.c (ax_print): opcode map out of sync"));
377 
378   for (i = 0; i < x->len;)
379     {
380       enum agent_op op = (enum agent_op) x->buf[i];
381 
382       if (op >= (sizeof (aop_map) / sizeof (aop_map[0]))
383 	  || !aop_map[op].name)
384 	{
385 	  gdb_printf (f, _("%3d  <bad opcode %02x>\n"), i, op);
386 	  i++;
387 	  continue;
388 	}
389       if (i + 1 + aop_map[op].op_size > x->len)
390 	{
391 	  gdb_printf (f, _("%3d  <incomplete opcode %s>\n"),
392 		      i, aop_map[op].name);
393 	  break;
394 	}
395 
396       gdb_printf (f, "%3d  %s", i, aop_map[op].name);
397       if (aop_map[op].op_size > 0)
398 	{
399 	  gdb_puts (" ", f);
400 
401 	  print_longest (f, 'd', 0,
402 			 read_const (x, i + 1, aop_map[op].op_size));
403 	}
404       /* Handle the complicated printf arguments specially.  */
405       else if (op == aop_printf)
406 	{
407 	  int slen, nargs;
408 
409 	  i++;
410 	  nargs = x->buf[i++];
411 	  slen = x->buf[i++];
412 	  slen = slen * 256 + x->buf[i++];
413 	  gdb_printf (f, _(" \"%s\", %d args"),
414 		      &(x->buf[i]), nargs);
415 	  i += slen - 1;
416 	}
417       gdb_printf (f, "\n");
418       i += 1 + aop_map[op].op_size;
419     }
420 }
421 
422 /* Add register REG to the register mask for expression AX.  */
423 void
424 ax_reg_mask (struct agent_expr *ax, int reg)
425 {
426   if (reg >= gdbarch_num_regs (ax->gdbarch))
427     {
428       /* This is a pseudo-register.  */
429       if (!gdbarch_ax_pseudo_register_collect_p (ax->gdbarch))
430 	error (_("'%s' is a pseudo-register; "
431 		 "GDB cannot yet trace its contents."),
432 	       user_reg_map_regnum_to_name (ax->gdbarch, reg));
433       if (gdbarch_ax_pseudo_register_collect (ax->gdbarch, ax, reg))
434 	error (_("Trace '%s' failed."),
435 	       user_reg_map_regnum_to_name (ax->gdbarch, reg));
436     }
437   else
438     {
439       int byte;
440 
441       /* Get the remote register number.  */
442       reg = gdbarch_remote_register_number (ax->gdbarch, reg);
443       byte = reg / 8;
444 
445       /* Grow the bit mask if necessary.  */
446       if (byte >= ax->reg_mask_len)
447 	{
448 	  /* It's not appropriate to double here.  This isn't a
449 	     string buffer.  */
450 	  int new_len = byte + 1;
451 	  unsigned char *new_reg_mask
452 	    = XRESIZEVEC (unsigned char, ax->reg_mask, new_len);
453 
454 	  memset (new_reg_mask + ax->reg_mask_len, 0,
455 		  (new_len - ax->reg_mask_len) * sizeof (ax->reg_mask[0]));
456 	  ax->reg_mask_len = new_len;
457 	  ax->reg_mask = new_reg_mask;
458 	}
459 
460       ax->reg_mask[byte] |= 1 << (reg % 8);
461     }
462 }
463 
464 /* Given an agent expression AX, fill in requirements and other descriptive
465    bits.  */
466 void
467 ax_reqs (struct agent_expr *ax)
468 {
469   int i;
470   int height;
471 
472   /* Jump target table.  targets[i] is non-zero iff we have found a
473      jump to offset i.  */
474   char *targets = (char *) alloca (ax->len * sizeof (targets[0]));
475 
476   /* Instruction boundary table.  boundary[i] is non-zero iff our scan
477      has reached an instruction starting at offset i.  */
478   char *boundary = (char *) alloca (ax->len * sizeof (boundary[0]));
479 
480   /* Stack height record.  If either targets[i] or boundary[i] is
481      non-zero, heights[i] is the height the stack should have before
482      executing the bytecode at that point.  */
483   int *heights = (int *) alloca (ax->len * sizeof (heights[0]));
484 
485   /* Pointer to a description of the present op.  */
486   struct aop_map *op;
487 
488   memset (targets, 0, ax->len * sizeof (targets[0]));
489   memset (boundary, 0, ax->len * sizeof (boundary[0]));
490 
491   ax->max_height = ax->min_height = height = 0;
492   ax->flaw = agent_flaw_none;
493   ax->max_data_size = 0;
494 
495   for (i = 0; i < ax->len; i += 1 + op->op_size)
496     {
497       if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0])))
498 	{
499 	  ax->flaw = agent_flaw_bad_instruction;
500 	  return;
501 	}
502 
503       op = &aop_map[ax->buf[i]];
504 
505       if (!op->name)
506 	{
507 	  ax->flaw = agent_flaw_bad_instruction;
508 	  return;
509 	}
510 
511       if (i + 1 + op->op_size > ax->len)
512 	{
513 	  ax->flaw = agent_flaw_incomplete_instruction;
514 	  return;
515 	}
516 
517       /* If this instruction is a forward jump target, does the
518 	 current stack height match the stack height at the jump
519 	 source?  */
520       if (targets[i] && (heights[i] != height))
521 	{
522 	  ax->flaw = agent_flaw_height_mismatch;
523 	  return;
524 	}
525 
526       boundary[i] = 1;
527       heights[i] = height;
528 
529       height -= op->consumed;
530       if (height < ax->min_height)
531 	ax->min_height = height;
532       height += op->produced;
533       if (height > ax->max_height)
534 	ax->max_height = height;
535 
536       if (op->data_size > ax->max_data_size)
537 	ax->max_data_size = op->data_size;
538 
539       /* For jump instructions, check that the target is a valid
540 	 offset.  If it is, record the fact that that location is a
541 	 jump target, and record the height we expect there.  */
542       if (aop_goto == op - aop_map
543 	  || aop_if_goto == op - aop_map)
544 	{
545 	  int target = read_const (ax, i + 1, 2);
546 	  if (target < 0 || target >= ax->len)
547 	    {
548 	      ax->flaw = agent_flaw_bad_jump;
549 	      return;
550 	    }
551 
552 	  /* Do we have any information about what the stack height
553 	     should be at the target?  */
554 	  if (targets[target] || boundary[target])
555 	    {
556 	      if (heights[target] != height)
557 		{
558 		  ax->flaw = agent_flaw_height_mismatch;
559 		  return;
560 		}
561 	    }
562 
563 	  /* Record the target, along with the stack height we expect.  */
564 	  targets[target] = 1;
565 	  heights[target] = height;
566 	}
567 
568       /* For unconditional jumps with a successor, check that the
569 	 successor is a target, and pick up its stack height.  */
570       if (aop_goto == op - aop_map
571 	  && i + 3 < ax->len)
572 	{
573 	  if (!targets[i + 3])
574 	    {
575 	      ax->flaw = agent_flaw_hole;
576 	      return;
577 	    }
578 
579 	  height = heights[i + 3];
580 	}
581 
582       /* For reg instructions, record the register in the bit mask.  */
583       if (aop_reg == op - aop_map)
584 	{
585 	  int reg = read_const (ax, i + 1, 2);
586 
587 	  ax_reg_mask (ax, reg);
588 	}
589     }
590 
591   /* Check that all the targets are on boundaries.  */
592   for (i = 0; i < ax->len; i++)
593     if (targets[i] && !boundary[i])
594       {
595 	ax->flaw = agent_flaw_bad_jump;
596 	return;
597       }
598 
599   ax->final_height = height;
600 }
601