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