1 /* Functions for manipulating expressions designed to be executed on the agent
2 Copyright 1998 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 PARAMS ((struct agent_expr * x, int n));
33 static void append_const PARAMS ((struct agent_expr * x, LONGEST val, int n));
35 static LONGEST read_const PARAMS ((struct agent_expr * x, int o, int n));
37 static void generic_ext PARAMS ((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 /* Make sure that X has room for at least N more bytes. This doesn't
67 affect the length, just the allocated size. */
73 if (x->len + n > x->size)
76 if (x->size < x->len + n)
77 x->size = x->len + n + 10;
78 x->buf = xrealloc (x->buf, x->size);
83 /* Append the low N bytes of VAL as an N-byte integer to the
84 expression X, in big-endian order. */
86 append_const (x, val, n)
94 for (i = n - 1; i >= 0; i--)
96 x->buf[x->len + i] = val & 0xff;
103 /* Extract an N-byte big-endian unsigned integer from expression X at
107 struct agent_expr *x;
113 /* Make sure we're not reading off the end of the expression. */
115 error ("GDB bug: ax-general.c (read_const): incomplete constant");
117 for (i = 0; i < n; i++)
118 accum = (accum << 8) | x->buf[o + i];
124 /* Append a simple operator OP to EXPR. */
127 struct agent_expr *x;
131 x->buf[x->len++] = op;
135 /* Append a sign-extension or zero-extension instruction to EXPR, to
136 extend an N-bit value. */
138 generic_ext (x, op, n)
139 struct agent_expr *x;
143 /* N must fit in a byte. */
144 if (n < 0 || n > 255)
145 error ("GDB bug: ax-general.c (generic_ext): bit count out of range");
146 /* That had better be enough range. */
147 if (sizeof (LONGEST) * 8 > 255)
148 error ("GDB bug: ax-general.c (generic_ext): opcode has inadequate range");
151 x->buf[x->len++] = op;
152 x->buf[x->len++] = n;
156 /* Append a sign-extension instruction to EXPR, to extend an N-bit value. */
159 struct agent_expr *x;
162 generic_ext (x, aop_ext, n);
166 /* Append a zero-extension instruction to EXPR, to extend an N-bit value. */
169 struct agent_expr *x;
172 generic_ext (x, aop_zero_ext, n);
176 /* Append a trace_quick instruction to EXPR, to record N bytes. */
178 ax_trace_quick (x, n)
179 struct agent_expr *x;
182 /* N must fit in a byte. */
183 if (n < 0 || n > 255)
184 error ("GDB bug: ax-general.c (ax_trace_quick): size out of range for trace_quick");
187 x->buf[x->len++] = aop_trace_quick;
188 x->buf[x->len++] = n;
192 /* Append a goto op to EXPR. OP is the actual op (must be aop_goto or
193 aop_if_goto). We assume we don't know the target offset yet,
194 because it's probably a forward branch, so we leave space in EXPR
195 for the target, and return the offset in EXPR of that space, so we
196 can backpatch it once we do know the target offset. Use ax_label
197 to do the backpatching. */
200 struct agent_expr *x;
204 x->buf[x->len + 0] = op;
205 x->buf[x->len + 1] = 0xff;
206 x->buf[x->len + 2] = 0xff;
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. */
216 ax_label (x, patch, target)
217 struct agent_expr *x;
221 /* Make sure the value is in range. Don't accept 0xffff as an
222 offset; that's our magic sentinel value for unpatched branches. */
223 if (target < 0 || target >= 0xffff)
224 error ("GDB bug: ax-general.c (ax_label): label target out of range");
226 x->buf[patch] = (target >> 8) & 0xff;
227 x->buf[patch + 1] = target & 0xff;
231 /* Assemble code to push a constant on the stack. */
234 struct agent_expr *x;
237 static enum agent_op ops[]
239 {aop_const8, aop_const16, aop_const32, aop_const64};
243 /* How big is the number? 'op' keeps track of which opcode to use.
244 Notice that we don't really care whether the original number was
245 signed or unsigned; we always reproduce the value exactly, and
246 use the shortest representation. */
247 for (op = 0, size = 8; size < 64; size *= 2, op++)
248 if (-((LONGEST) 1 << size) <= l && l < ((LONGEST) 1 << size))
251 /* Emit the right opcode... */
252 ax_simple (x, ops[op]);
254 /* Emit the low SIZE bytes as an unsigned number. We know that
255 sign-extending this will yield l. */
256 append_const (x, l, size / 8);
258 /* Now, if it was negative, and not full-sized, sign-extend it. */
259 if (l < 0 && size < 64)
266 struct agent_expr *x;
269 /* FIXME: floating-point support not present yet. */
270 error ("GDB bug: ax-general.c (ax_const_d): floating point not supported yet");
274 /* Assemble code to push the value of register number REG on the
278 struct agent_expr *x;
281 /* Make sure the register number is in range. */
282 if (reg < 0 || reg > 0xffff)
283 error ("GDB bug: ax-general.c (ax_reg): register number out of range");
285 x->buf[x->len] = aop_reg;
286 x->buf[x->len + 1] = (reg >> 8) & 0xff;
287 x->buf[x->len + 2] = (reg) & 0xff;
293 /* Functions for disassembling agent expressions, and otherwise
294 debugging the expression compiler. */
296 struct aop_map aop_map[] =
299 {"float", 0, 0, 0, 0}, /* 0x01 */
300 {"add", 0, 0, 2, 1}, /* 0x02 */
301 {"sub", 0, 0, 2, 1}, /* 0x03 */
302 {"mul", 0, 0, 2, 1}, /* 0x04 */
303 {"div_signed", 0, 0, 2, 1}, /* 0x05 */
304 {"div_unsigned", 0, 0, 2, 1}, /* 0x06 */
305 {"rem_signed", 0, 0, 2, 1}, /* 0x07 */
306 {"rem_unsigned", 0, 0, 2, 1}, /* 0x08 */
307 {"lsh", 0, 0, 2, 1}, /* 0x09 */
308 {"rsh_signed", 0, 0, 2, 1}, /* 0x0a */
309 {"rsh_unsigned", 0, 0, 2, 1}, /* 0x0b */
310 {"trace", 0, 0, 2, 0}, /* 0x0c */
311 {"trace_quick", 1, 0, 1, 1}, /* 0x0d */
312 {"log_not", 0, 0, 1, 1}, /* 0x0e */
313 {"bit_and", 0, 0, 2, 1}, /* 0x0f */
314 {"bit_or", 0, 0, 2, 1}, /* 0x10 */
315 {"bit_xor", 0, 0, 2, 1}, /* 0x11 */
316 {"bit_not", 0, 0, 1, 1}, /* 0x12 */
317 {"equal", 0, 0, 2, 1}, /* 0x13 */
318 {"less_signed", 0, 0, 2, 1}, /* 0x14 */
319 {"less_unsigned", 0, 0, 2, 1}, /* 0x15 */
320 {"ext", 1, 0, 1, 1}, /* 0x16 */
321 {"ref8", 0, 8, 1, 1}, /* 0x17 */
322 {"ref16", 0, 16, 1, 1}, /* 0x18 */
323 {"ref32", 0, 32, 1, 1}, /* 0x19 */
324 {"ref64", 0, 64, 1, 1}, /* 0x1a */
325 {"ref_float", 0, 0, 1, 1}, /* 0x1b */
326 {"ref_double", 0, 0, 1, 1}, /* 0x1c */
327 {"ref_long_double", 0, 0, 1, 1}, /* 0x1d */
328 {"l_to_d", 0, 0, 1, 1}, /* 0x1e */
329 {"d_to_l", 0, 0, 1, 1}, /* 0x1f */
330 {"if_goto", 2, 0, 1, 0}, /* 0x20 */
331 {"goto", 2, 0, 0, 0}, /* 0x21 */
332 {"const8", 1, 8, 0, 1}, /* 0x22 */
333 {"const16", 2, 16, 0, 1}, /* 0x23 */
334 {"const32", 4, 32, 0, 1}, /* 0x24 */
335 {"const64", 8, 64, 0, 1}, /* 0x25 */
336 {"reg", 2, 0, 0, 1}, /* 0x26 */
337 {"end", 0, 0, 0, 0}, /* 0x27 */
338 {"dup", 0, 0, 1, 2}, /* 0x28 */
339 {"pop", 0, 0, 1, 0}, /* 0x29 */
340 {"zero_ext", 1, 0, 1, 1}, /* 0x2a */
341 {"swap", 0, 0, 2, 2}, /* 0x2b */
342 {0, 0, 0, 0, 0}, /* 0x2c */
343 {0, 0, 0, 0, 0}, /* 0x2d */
344 {0, 0, 0, 0, 0}, /* 0x2e */
345 {0, 0, 0, 0, 0}, /* 0x2f */
346 {"trace16", 2, 0, 1, 1}, /* 0x30 */
350 /* Disassemble the expression EXPR, writing to F. */
354 struct agent_expr *x;
359 /* Check the size of the name array against the number of entries in
360 the enum, to catch additions that people didn't sync. */
361 if ((sizeof (aop_map) / sizeof (aop_map[0]))
363 error ("GDB bug: ax-general.c (ax_print): opcode map out of sync");
365 for (i = 0; i < x->len;)
367 enum agent_op op = x->buf[i];
369 if (op >= (sizeof (aop_map) / sizeof (aop_map[0]))
370 || !aop_map[op].name)
372 fprintf_filtered (f, "%3d <bad opcode %02x>\n", i, op);
376 if (i + 1 + aop_map[op].op_size > x->len)
378 fprintf_filtered (f, "%3d <incomplete opcode %s>\n",
379 i, aop_map[op].name);
383 fprintf_filtered (f, "%3d %s", i, aop_map[op].name);
384 if (aop_map[op].op_size > 0)
386 fputs_filtered (" ", f);
388 print_longest (f, 'd', 0,
389 read_const (x, i + 1, aop_map[op].op_size));
391 fprintf_filtered (f, "\n");
392 i += 1 + aop_map[op].op_size;
394 is_float = (op == aop_float);
399 /* Given an agent expression AX, fill in an agent_reqs structure REQS
403 struct agent_expr *ax;
404 struct agent_reqs *reqs;
409 /* Bit vector for registers used. */
410 int reg_mask_len = 1;
411 unsigned char *reg_mask = xmalloc (reg_mask_len * sizeof (reg_mask[0]));
413 /* Jump target table. targets[i] is non-zero iff there is a jump to
415 char *targets = (char *) alloca (ax->len * sizeof (targets[0]));
417 /* Instruction boundary table. boundary[i] is non-zero iff an
418 instruction starts at offset i. */
419 char *boundary = (char *) alloca (ax->len * sizeof (boundary[0]));
421 /* Stack height record. iff either targets[i] or boundary[i] is
422 non-zero, heights[i] is the height the stack should have before
423 executing the bytecode at that point. */
424 int *heights = (int *) alloca (ax->len * sizeof (heights[0]));
426 /* Pointer to a description of the present op. */
429 memset (reg_mask, 0, reg_mask_len * sizeof (reg_mask[0]));
430 memset (targets, 0, ax->len * sizeof (targets[0]));
431 memset (boundary, 0, ax->len * sizeof (boundary[0]));
433 reqs->max_height = reqs->min_height = height = 0;
434 reqs->flaw = agent_flaw_none;
435 reqs->max_data_size = 0;
437 for (i = 0; i < ax->len; i += 1 + op->op_size)
439 if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0])))
441 reqs->flaw = agent_flaw_bad_instruction;
446 op = &aop_map[ax->buf[i]];
450 reqs->flaw = agent_flaw_bad_instruction;
455 if (i + 1 + op->op_size > ax->len)
457 reqs->flaw = agent_flaw_incomplete_instruction;
462 /* If this instruction is a jump target, does the current stack
463 height match the stack height at the jump source? */
464 if (targets[i] && (heights[i] != height))
466 reqs->flaw = agent_flaw_height_mismatch;
474 height -= op->consumed;
475 if (height < reqs->min_height)
476 reqs->min_height = height;
477 height += op->produced;
478 if (height > reqs->max_height)
479 reqs->max_height = height;
481 if (op->data_size > reqs->max_data_size)
482 reqs->max_data_size = op->data_size;
484 /* For jump instructions, check that the target is a valid
485 offset. If it is, record the fact that that location is a
486 jump target, and record the height we expect there. */
487 if (aop_goto == op - aop_map
488 || aop_if_goto == op - aop_map)
490 int target = read_const (ax, i + 1, 2);
491 if (target < 0 || target >= ax->len)
493 reqs->flaw = agent_flaw_bad_jump;
497 /* Have we already found other jumps to the same location? */
498 else if (targets[target])
500 if (heights[i] != height)
502 reqs->flaw = agent_flaw_height_mismatch;
510 heights[target] = height;
514 /* For unconditional jumps with a successor, check that the
515 successor is a target, and pick up its stack height. */
516 if (aop_goto == op - aop_map
521 reqs->flaw = agent_flaw_hole;
526 height = heights[i + 3];
529 /* For reg instructions, record the register in the bit mask. */
530 if (aop_reg == op - aop_map)
532 int reg = read_const (ax, i + 1, 2);
535 /* Grow the bit mask if necessary. */
536 if (byte >= reg_mask_len)
538 /* It's not appropriate to double here. This isn't a
540 int new_len = byte + 1;
541 reg_mask = xrealloc (reg_mask,
542 new_len * sizeof (reg_mask[0]));
543 memset (reg_mask + reg_mask_len, 0,
544 (new_len - reg_mask_len) * sizeof (reg_mask[0]));
545 reg_mask_len = new_len;
548 reg_mask[byte] |= 1 << (reg % 8);
552 /* Check that all the targets are on boundaries. */
553 for (i = 0; i < ax->len; i++)
554 if (targets[i] && !boundary[i])
556 reqs->flaw = agent_flaw_bad_jump;
561 reqs->final_height = height;
562 reqs->reg_mask_len = reg_mask_len;
563 reqs->reg_mask = reg_mask;