1 /* Functions for manipulating expressions designed to be executed on the agent
2 Copyright 1998, 2000 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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. */
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.) */
31 static void grow_expr (struct agent_expr *x, int n);
33 static void append_const (struct agent_expr *x, LONGEST val, int n);
35 static LONGEST read_const (struct agent_expr *x, int o, int n);
37 static void generic_ext (struct agent_expr *x, enum agent_op op, int n);
39 /* Functions for building expressions. */
41 /* Allocate a new, empty agent expression. */
43 new_agent_expr (scope)
46 struct agent_expr *x = xmalloc (sizeof (*x));
48 x->size = 1; /* Change this to a larger value once
49 reallocation code is tested. */
50 x->buf = xmalloc (x->size);
56 /* Free a agent expression. */
66 do_free_agent_expr_cleanup (void *x)
72 make_cleanup_free_agent_expr (struct agent_expr *x)
74 return make_cleanup (do_free_agent_expr_cleanup, x);
78 /* Make sure that X has room for at least N more bytes. This doesn't
79 affect the length, just the allocated size. */
85 if (x->len + n > x->size)
88 if (x->size < x->len + n)
89 x->size = x->len + n + 10;
90 x->buf = xrealloc (x->buf, x->size);
95 /* Append the low N bytes of VAL as an N-byte integer to the
96 expression X, in big-endian order. */
98 append_const (x, val, n)
106 for (i = n - 1; i >= 0; i--)
108 x->buf[x->len + i] = val & 0xff;
115 /* Extract an N-byte big-endian unsigned integer from expression X at
119 struct agent_expr *x;
125 /* Make sure we're not reading off the end of the expression. */
127 error ("GDB bug: ax-general.c (read_const): incomplete constant");
129 for (i = 0; i < n; i++)
130 accum = (accum << 8) | x->buf[o + i];
136 /* Append a simple operator OP to EXPR. */
139 struct agent_expr *x;
143 x->buf[x->len++] = op;
147 /* Append a sign-extension or zero-extension instruction to EXPR, to
148 extend an N-bit value. */
150 generic_ext (x, op, n)
151 struct agent_expr *x;
155 /* N must fit in a byte. */
156 if (n < 0 || n > 255)
157 error ("GDB bug: ax-general.c (generic_ext): bit count out of range");
158 /* That had better be enough range. */
159 if (sizeof (LONGEST) * 8 > 255)
160 error ("GDB bug: ax-general.c (generic_ext): opcode has inadequate range");
163 x->buf[x->len++] = op;
164 x->buf[x->len++] = n;
168 /* Append a sign-extension instruction to EXPR, to extend an N-bit value. */
171 struct agent_expr *x;
174 generic_ext (x, aop_ext, n);
178 /* Append a zero-extension instruction to EXPR, to extend an N-bit value. */
181 struct agent_expr *x;
184 generic_ext (x, aop_zero_ext, n);
188 /* Append a trace_quick instruction to EXPR, to record N bytes. */
190 ax_trace_quick (x, n)
191 struct agent_expr *x;
194 /* N must fit in a byte. */
195 if (n < 0 || n > 255)
196 error ("GDB bug: ax-general.c (ax_trace_quick): size out of range for trace_quick");
199 x->buf[x->len++] = aop_trace_quick;
200 x->buf[x->len++] = n;
204 /* Append a goto op to EXPR. OP is the actual op (must be aop_goto or
205 aop_if_goto). We assume we don't know the target offset yet,
206 because it's probably a forward branch, so we leave space in EXPR
207 for the target, and return the offset in EXPR of that space, so we
208 can backpatch it once we do know the target offset. Use ax_label
209 to do the backpatching. */
212 struct agent_expr *x;
216 x->buf[x->len + 0] = op;
217 x->buf[x->len + 1] = 0xff;
218 x->buf[x->len + 2] = 0xff;
223 /* Suppose a given call to ax_goto returns some value PATCH. When you
224 know the offset TARGET that goto should jump to, call
225 ax_label (EXPR, PATCH, TARGET)
226 to patch TARGET into the ax_goto instruction. */
228 ax_label (x, patch, target)
229 struct agent_expr *x;
233 /* Make sure the value is in range. Don't accept 0xffff as an
234 offset; that's our magic sentinel value for unpatched branches. */
235 if (target < 0 || target >= 0xffff)
236 error ("GDB bug: ax-general.c (ax_label): label target out of range");
238 x->buf[patch] = (target >> 8) & 0xff;
239 x->buf[patch + 1] = target & 0xff;
243 /* Assemble code to push a constant on the stack. */
246 struct agent_expr *x;
249 static enum agent_op ops[]
251 {aop_const8, aop_const16, aop_const32, aop_const64};
255 /* How big is the number? 'op' keeps track of which opcode to use.
256 Notice that we don't really care whether the original number was
257 signed or unsigned; we always reproduce the value exactly, and
258 use the shortest representation. */
259 for (op = 0, size = 8; size < 64; size *= 2, op++)
260 if (-((LONGEST) 1 << size) <= l && l < ((LONGEST) 1 << size))
263 /* Emit the right opcode... */
264 ax_simple (x, ops[op]);
266 /* Emit the low SIZE bytes as an unsigned number. We know that
267 sign-extending this will yield l. */
268 append_const (x, l, size / 8);
270 /* Now, if it was negative, and not full-sized, sign-extend it. */
271 if (l < 0 && size < 64)
278 struct agent_expr *x;
281 /* FIXME: floating-point support not present yet. */
282 error ("GDB bug: ax-general.c (ax_const_d): floating point not supported yet");
286 /* Assemble code to push the value of register number REG on the
290 struct agent_expr *x;
293 /* Make sure the register number is in range. */
294 if (reg < 0 || reg > 0xffff)
295 error ("GDB bug: ax-general.c (ax_reg): register number out of range");
297 x->buf[x->len] = aop_reg;
298 x->buf[x->len + 1] = (reg >> 8) & 0xff;
299 x->buf[x->len + 2] = (reg) & 0xff;
305 /* Functions for disassembling agent expressions, and otherwise
306 debugging the expression compiler. */
308 struct aop_map aop_map[] =
311 {"float", 0, 0, 0, 0}, /* 0x01 */
312 {"add", 0, 0, 2, 1}, /* 0x02 */
313 {"sub", 0, 0, 2, 1}, /* 0x03 */
314 {"mul", 0, 0, 2, 1}, /* 0x04 */
315 {"div_signed", 0, 0, 2, 1}, /* 0x05 */
316 {"div_unsigned", 0, 0, 2, 1}, /* 0x06 */
317 {"rem_signed", 0, 0, 2, 1}, /* 0x07 */
318 {"rem_unsigned", 0, 0, 2, 1}, /* 0x08 */
319 {"lsh", 0, 0, 2, 1}, /* 0x09 */
320 {"rsh_signed", 0, 0, 2, 1}, /* 0x0a */
321 {"rsh_unsigned", 0, 0, 2, 1}, /* 0x0b */
322 {"trace", 0, 0, 2, 0}, /* 0x0c */
323 {"trace_quick", 1, 0, 1, 1}, /* 0x0d */
324 {"log_not", 0, 0, 1, 1}, /* 0x0e */
325 {"bit_and", 0, 0, 2, 1}, /* 0x0f */
326 {"bit_or", 0, 0, 2, 1}, /* 0x10 */
327 {"bit_xor", 0, 0, 2, 1}, /* 0x11 */
328 {"bit_not", 0, 0, 1, 1}, /* 0x12 */
329 {"equal", 0, 0, 2, 1}, /* 0x13 */
330 {"less_signed", 0, 0, 2, 1}, /* 0x14 */
331 {"less_unsigned", 0, 0, 2, 1}, /* 0x15 */
332 {"ext", 1, 0, 1, 1}, /* 0x16 */
333 {"ref8", 0, 8, 1, 1}, /* 0x17 */
334 {"ref16", 0, 16, 1, 1}, /* 0x18 */
335 {"ref32", 0, 32, 1, 1}, /* 0x19 */
336 {"ref64", 0, 64, 1, 1}, /* 0x1a */
337 {"ref_float", 0, 0, 1, 1}, /* 0x1b */
338 {"ref_double", 0, 0, 1, 1}, /* 0x1c */
339 {"ref_long_double", 0, 0, 1, 1}, /* 0x1d */
340 {"l_to_d", 0, 0, 1, 1}, /* 0x1e */
341 {"d_to_l", 0, 0, 1, 1}, /* 0x1f */
342 {"if_goto", 2, 0, 1, 0}, /* 0x20 */
343 {"goto", 2, 0, 0, 0}, /* 0x21 */
344 {"const8", 1, 8, 0, 1}, /* 0x22 */
345 {"const16", 2, 16, 0, 1}, /* 0x23 */
346 {"const32", 4, 32, 0, 1}, /* 0x24 */
347 {"const64", 8, 64, 0, 1}, /* 0x25 */
348 {"reg", 2, 0, 0, 1}, /* 0x26 */
349 {"end", 0, 0, 0, 0}, /* 0x27 */
350 {"dup", 0, 0, 1, 2}, /* 0x28 */
351 {"pop", 0, 0, 1, 0}, /* 0x29 */
352 {"zero_ext", 1, 0, 1, 1}, /* 0x2a */
353 {"swap", 0, 0, 2, 2}, /* 0x2b */
354 {0, 0, 0, 0, 0}, /* 0x2c */
355 {0, 0, 0, 0, 0}, /* 0x2d */
356 {0, 0, 0, 0, 0}, /* 0x2e */
357 {0, 0, 0, 0, 0}, /* 0x2f */
358 {"trace16", 2, 0, 1, 1}, /* 0x30 */
362 /* Disassemble the expression EXPR, writing to F. */
366 struct agent_expr *x;
371 /* Check the size of the name array against the number of entries in
372 the enum, to catch additions that people didn't sync. */
373 if ((sizeof (aop_map) / sizeof (aop_map[0]))
375 error ("GDB bug: ax-general.c (ax_print): opcode map out of sync");
377 for (i = 0; i < x->len;)
379 enum agent_op op = x->buf[i];
381 if (op >= (sizeof (aop_map) / sizeof (aop_map[0]))
382 || !aop_map[op].name)
384 fprintf_filtered (f, "%3d <bad opcode %02x>\n", i, op);
388 if (i + 1 + aop_map[op].op_size > x->len)
390 fprintf_filtered (f, "%3d <incomplete opcode %s>\n",
391 i, aop_map[op].name);
395 fprintf_filtered (f, "%3d %s", i, aop_map[op].name);
396 if (aop_map[op].op_size > 0)
398 fputs_filtered (" ", f);
400 print_longest (f, 'd', 0,
401 read_const (x, i + 1, aop_map[op].op_size));
403 fprintf_filtered (f, "\n");
404 i += 1 + aop_map[op].op_size;
406 is_float = (op == aop_float);
411 /* Given an agent expression AX, fill in an agent_reqs structure REQS
415 struct agent_expr *ax;
416 struct agent_reqs *reqs;
421 /* Bit vector for registers used. */
422 int reg_mask_len = 1;
423 unsigned char *reg_mask = xmalloc (reg_mask_len * sizeof (reg_mask[0]));
425 /* Jump target table. targets[i] is non-zero iff there is a jump to
427 char *targets = (char *) alloca (ax->len * sizeof (targets[0]));
429 /* Instruction boundary table. boundary[i] is non-zero iff an
430 instruction starts at offset i. */
431 char *boundary = (char *) alloca (ax->len * sizeof (boundary[0]));
433 /* Stack height record. iff either targets[i] or boundary[i] is
434 non-zero, heights[i] is the height the stack should have before
435 executing the bytecode at that point. */
436 int *heights = (int *) alloca (ax->len * sizeof (heights[0]));
438 /* Pointer to a description of the present op. */
441 memset (reg_mask, 0, reg_mask_len * sizeof (reg_mask[0]));
442 memset (targets, 0, ax->len * sizeof (targets[0]));
443 memset (boundary, 0, ax->len * sizeof (boundary[0]));
445 reqs->max_height = reqs->min_height = height = 0;
446 reqs->flaw = agent_flaw_none;
447 reqs->max_data_size = 0;
449 for (i = 0; i < ax->len; i += 1 + op->op_size)
451 if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0])))
453 reqs->flaw = agent_flaw_bad_instruction;
458 op = &aop_map[ax->buf[i]];
462 reqs->flaw = agent_flaw_bad_instruction;
467 if (i + 1 + op->op_size > ax->len)
469 reqs->flaw = agent_flaw_incomplete_instruction;
474 /* If this instruction is a jump target, does the current stack
475 height match the stack height at the jump source? */
476 if (targets[i] && (heights[i] != height))
478 reqs->flaw = agent_flaw_height_mismatch;
486 height -= op->consumed;
487 if (height < reqs->min_height)
488 reqs->min_height = height;
489 height += op->produced;
490 if (height > reqs->max_height)
491 reqs->max_height = height;
493 if (op->data_size > reqs->max_data_size)
494 reqs->max_data_size = op->data_size;
496 /* For jump instructions, check that the target is a valid
497 offset. If it is, record the fact that that location is a
498 jump target, and record the height we expect there. */
499 if (aop_goto == op - aop_map
500 || aop_if_goto == op - aop_map)
502 int target = read_const (ax, i + 1, 2);
503 if (target < 0 || target >= ax->len)
505 reqs->flaw = agent_flaw_bad_jump;
509 /* Have we already found other jumps to the same location? */
510 else if (targets[target])
512 if (heights[i] != height)
514 reqs->flaw = agent_flaw_height_mismatch;
522 heights[target] = height;
526 /* For unconditional jumps with a successor, check that the
527 successor is a target, and pick up its stack height. */
528 if (aop_goto == op - aop_map
533 reqs->flaw = agent_flaw_hole;
538 height = heights[i + 3];
541 /* For reg instructions, record the register in the bit mask. */
542 if (aop_reg == op - aop_map)
544 int reg = read_const (ax, i + 1, 2);
547 /* Grow the bit mask if necessary. */
548 if (byte >= reg_mask_len)
550 /* It's not appropriate to double here. This isn't a
552 int new_len = byte + 1;
553 reg_mask = xrealloc (reg_mask,
554 new_len * sizeof (reg_mask[0]));
555 memset (reg_mask + reg_mask_len, 0,
556 (new_len - reg_mask_len) * sizeof (reg_mask[0]));
557 reg_mask_len = new_len;
560 reg_mask[byte] |= 1 << (reg % 8);
564 /* Check that all the targets are on boundaries. */
565 for (i = 0; i < ax->len; i++)
566 if (targets[i] && !boundary[i])
568 reqs->flaw = agent_flaw_bad_jump;
573 reqs->final_height = height;
574 reqs->reg_mask_len = reg_mask_len;
575 reqs->reg_mask = reg_mask;