Cleanup free_agent_expr cleanups.
[deliverable/binutils-gdb.git] / gdb / ax-general.c
1 /* Functions for manipulating expressions designed to be executed on the agent
2 Copyright 1998, 2000 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,
19 Boston, MA 02111-1307, USA. */
20
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.) */
25
26 #include "defs.h"
27 #include "ax.h"
28
29 #include "value.h"
30
31 static void grow_expr PARAMS ((struct agent_expr * x, int n));
32
33 static void append_const PARAMS ((struct agent_expr * x, LONGEST val, int n));
34
35 static LONGEST read_const PARAMS ((struct agent_expr * x, int o, int n));
36
37 static void generic_ext PARAMS ((struct agent_expr * x, enum agent_op op, int n));
38 \f
39 /* Functions for building expressions. */
40
41 /* Allocate a new, empty agent expression. */
42 struct agent_expr *
43 new_agent_expr (scope)
44 CORE_ADDR scope;
45 {
46 struct agent_expr *x = xmalloc (sizeof (*x));
47 x->len = 0;
48 x->size = 1; /* Change this to a larger value once
49 reallocation code is tested. */
50 x->buf = xmalloc (x->size);
51 x->scope = scope;
52
53 return x;
54 }
55
56 /* Free a agent expression. */
57 void
58 free_agent_expr (x)
59 struct agent_expr *x;
60 {
61 free (x->buf);
62 free (x);
63 }
64
65 static void
66 do_free_agent_expr_cleanup (void *x)
67 {
68 free_agent_expr (x);
69 }
70
71 struct cleanup *
72 make_cleanup_free_agent_expr (struct agent_expr *x)
73 {
74 return make_cleanup (do_free_agent_expr_cleanup, x);
75 }
76
77
78 /* Make sure that X has room for at least N more bytes. This doesn't
79 affect the length, just the allocated size. */
80 static void
81 grow_expr (x, n)
82 struct agent_expr *x;
83 int n;
84 {
85 if (x->len + n > x->size)
86 {
87 x->size *= 2;
88 if (x->size < x->len + n)
89 x->size = x->len + n + 10;
90 x->buf = xrealloc (x->buf, x->size);
91 }
92 }
93
94
95 /* Append the low N bytes of VAL as an N-byte integer to the
96 expression X, in big-endian order. */
97 static void
98 append_const (x, val, n)
99 struct agent_expr *x;
100 LONGEST val;
101 int n;
102 {
103 int i;
104
105 grow_expr (x, n);
106 for (i = n - 1; i >= 0; i--)
107 {
108 x->buf[x->len + i] = val & 0xff;
109 val >>= 8;
110 }
111 x->len += n;
112 }
113
114
115 /* Extract an N-byte big-endian unsigned integer from expression X at
116 offset O. */
117 static LONGEST
118 read_const (x, o, n)
119 struct agent_expr *x;
120 int o, n;
121 {
122 int i;
123 LONGEST accum = 0;
124
125 /* Make sure we're not reading off the end of the expression. */
126 if (o + n > x->len)
127 error ("GDB bug: ax-general.c (read_const): incomplete constant");
128
129 for (i = 0; i < n; i++)
130 accum = (accum << 8) | x->buf[o + i];
131
132 return accum;
133 }
134
135
136 /* Append a simple operator OP to EXPR. */
137 void
138 ax_simple (x, op)
139 struct agent_expr *x;
140 enum agent_op op;
141 {
142 grow_expr (x, 1);
143 x->buf[x->len++] = op;
144 }
145
146
147 /* Append a sign-extension or zero-extension instruction to EXPR, to
148 extend an N-bit value. */
149 static void
150 generic_ext (x, op, n)
151 struct agent_expr *x;
152 enum agent_op op;
153 int n;
154 {
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");
161
162 grow_expr (x, 2);
163 x->buf[x->len++] = op;
164 x->buf[x->len++] = n;
165 }
166
167
168 /* Append a sign-extension instruction to EXPR, to extend an N-bit value. */
169 void
170 ax_ext (x, n)
171 struct agent_expr *x;
172 int n;
173 {
174 generic_ext (x, aop_ext, n);
175 }
176
177
178 /* Append a zero-extension instruction to EXPR, to extend an N-bit value. */
179 void
180 ax_zero_ext (x, n)
181 struct agent_expr *x;
182 int n;
183 {
184 generic_ext (x, aop_zero_ext, n);
185 }
186
187
188 /* Append a trace_quick instruction to EXPR, to record N bytes. */
189 void
190 ax_trace_quick (x, n)
191 struct agent_expr *x;
192 int n;
193 {
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");
197
198 grow_expr (x, 2);
199 x->buf[x->len++] = aop_trace_quick;
200 x->buf[x->len++] = n;
201 }
202
203
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. */
210 int
211 ax_goto (x, op)
212 struct agent_expr *x;
213 enum agent_op op;
214 {
215 grow_expr (x, 3);
216 x->buf[x->len + 0] = op;
217 x->buf[x->len + 1] = 0xff;
218 x->buf[x->len + 2] = 0xff;
219 x->len += 3;
220 return x->len - 2;
221 }
222
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. */
227 void
228 ax_label (x, patch, target)
229 struct agent_expr *x;
230 int patch;
231 int target;
232 {
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");
237
238 x->buf[patch] = (target >> 8) & 0xff;
239 x->buf[patch + 1] = target & 0xff;
240 }
241
242
243 /* Assemble code to push a constant on the stack. */
244 void
245 ax_const_l (x, l)
246 struct agent_expr *x;
247 LONGEST l;
248 {
249 static enum agent_op ops[]
250 =
251 {aop_const8, aop_const16, aop_const32, aop_const64};
252 int size;
253 int op;
254
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))
261 break;
262
263 /* Emit the right opcode... */
264 ax_simple (x, ops[op]);
265
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);
269
270 /* Now, if it was negative, and not full-sized, sign-extend it. */
271 if (l < 0 && size < 64)
272 ax_ext (x, size);
273 }
274
275
276 void
277 ax_const_d (x, d)
278 struct agent_expr *x;
279 LONGEST d;
280 {
281 /* FIXME: floating-point support not present yet. */
282 error ("GDB bug: ax-general.c (ax_const_d): floating point not supported yet");
283 }
284
285
286 /* Assemble code to push the value of register number REG on the
287 stack. */
288 void
289 ax_reg (x, reg)
290 struct agent_expr *x;
291 int 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): register number out of range");
296 grow_expr (x, 3);
297 x->buf[x->len] = aop_reg;
298 x->buf[x->len + 1] = (reg >> 8) & 0xff;
299 x->buf[x->len + 2] = (reg) & 0xff;
300 x->len += 3;
301 }
302 \f
303
304
305 /* Functions for disassembling agent expressions, and otherwise
306 debugging the expression compiler. */
307
308 struct aop_map aop_map[] =
309 {
310 {0, 0, 0, 0, 0},
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 */
359 };
360
361
362 /* Disassemble the expression EXPR, writing to F. */
363 void
364 ax_print (f, x)
365 struct ui_file *f;
366 struct agent_expr *x;
367 {
368 int i;
369 int is_float = 0;
370
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]))
374 != aop_last)
375 error ("GDB bug: ax-general.c (ax_print): opcode map out of sync");
376
377 for (i = 0; i < x->len;)
378 {
379 enum agent_op op = x->buf[i];
380
381 if (op >= (sizeof (aop_map) / sizeof (aop_map[0]))
382 || !aop_map[op].name)
383 {
384 fprintf_filtered (f, "%3d <bad opcode %02x>\n", i, op);
385 i++;
386 continue;
387 }
388 if (i + 1 + aop_map[op].op_size > x->len)
389 {
390 fprintf_filtered (f, "%3d <incomplete opcode %s>\n",
391 i, aop_map[op].name);
392 break;
393 }
394
395 fprintf_filtered (f, "%3d %s", i, aop_map[op].name);
396 if (aop_map[op].op_size > 0)
397 {
398 fputs_filtered (" ", f);
399
400 print_longest (f, 'd', 0,
401 read_const (x, i + 1, aop_map[op].op_size));
402 }
403 fprintf_filtered (f, "\n");
404 i += 1 + aop_map[op].op_size;
405
406 is_float = (op == aop_float);
407 }
408 }
409
410
411 /* Given an agent expression AX, fill in an agent_reqs structure REQS
412 describing it. */
413 void
414 ax_reqs (ax, reqs)
415 struct agent_expr *ax;
416 struct agent_reqs *reqs;
417 {
418 int i;
419 int height;
420
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]));
424
425 /* Jump target table. targets[i] is non-zero iff there is a jump to
426 offset i. */
427 char *targets = (char *) alloca (ax->len * sizeof (targets[0]));
428
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]));
432
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]));
437
438 /* Pointer to a description of the present op. */
439 struct aop_map *op;
440
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]));
444
445 reqs->max_height = reqs->min_height = height = 0;
446 reqs->flaw = agent_flaw_none;
447 reqs->max_data_size = 0;
448
449 for (i = 0; i < ax->len; i += 1 + op->op_size)
450 {
451 if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0])))
452 {
453 reqs->flaw = agent_flaw_bad_instruction;
454 free (reg_mask);
455 return;
456 }
457
458 op = &aop_map[ax->buf[i]];
459
460 if (!op->name)
461 {
462 reqs->flaw = agent_flaw_bad_instruction;
463 free (reg_mask);
464 return;
465 }
466
467 if (i + 1 + op->op_size > ax->len)
468 {
469 reqs->flaw = agent_flaw_incomplete_instruction;
470 free (reg_mask);
471 return;
472 }
473
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))
477 {
478 reqs->flaw = agent_flaw_height_mismatch;
479 free (reg_mask);
480 return;
481 }
482
483 boundary[i] = 1;
484 heights[i] = height;
485
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;
492
493 if (op->data_size > reqs->max_data_size)
494 reqs->max_data_size = op->data_size;
495
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)
501 {
502 int target = read_const (ax, i + 1, 2);
503 if (target < 0 || target >= ax->len)
504 {
505 reqs->flaw = agent_flaw_bad_jump;
506 free (reg_mask);
507 return;
508 }
509 /* Have we already found other jumps to the same location? */
510 else if (targets[target])
511 {
512 if (heights[i] != height)
513 {
514 reqs->flaw = agent_flaw_height_mismatch;
515 free (reg_mask);
516 return;
517 }
518 }
519 else
520 {
521 targets[target] = 1;
522 heights[target] = height;
523 }
524 }
525
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
529 && i + 3 < ax->len)
530 {
531 if (!targets[i + 3])
532 {
533 reqs->flaw = agent_flaw_hole;
534 free (reg_mask);
535 return;
536 }
537
538 height = heights[i + 3];
539 }
540
541 /* For reg instructions, record the register in the bit mask. */
542 if (aop_reg == op - aop_map)
543 {
544 int reg = read_const (ax, i + 1, 2);
545 int byte = reg / 8;
546
547 /* Grow the bit mask if necessary. */
548 if (byte >= reg_mask_len)
549 {
550 /* It's not appropriate to double here. This isn't a
551 string buffer. */
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;
558 }
559
560 reg_mask[byte] |= 1 << (reg % 8);
561 }
562 }
563
564 /* Check that all the targets are on boundaries. */
565 for (i = 0; i < ax->len; i++)
566 if (targets[i] && !boundary[i])
567 {
568 reqs->flaw = agent_flaw_bad_jump;
569 free (reg_mask);
570 return;
571 }
572
573 reqs->final_height = height;
574 reqs->reg_mask_len = reg_mask_len;
575 reqs->reg_mask = reg_mask;
576 }
This page took 0.059152 seconds and 5 git commands to generate.