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