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 30static void grow_expr (struct agent_expr *x, int n); 31 32static void append_const (struct agent_expr *x, LONGEST val, int n); 33 34static LONGEST read_const (struct agent_expr *x, int o, int n); 35 36static void generic_ext (struct agent_expr *x, enum agent_op op, int n); 37 38/* Functions for building expressions. */ 39 40/* Allocate a new, empty agent expression. */ 41struct agent_expr * 42new_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. */ 55void 56free_agent_expr (struct agent_expr *x) 57{ 58 xfree (x->buf); 59 xfree (x); 60} 61 62static void 63do_free_agent_expr_cleanup (void *x) 64{ 65 free_agent_expr (x); 66} 67 68struct cleanup * 69make_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. */ 77static void 78grow_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. */ 92static void 93append_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. */ 109static LONGEST 110read_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. */ 127void 128ax_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. */ 137static void 138generic_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. */ 154void 155ax_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. */ 162void 163ax_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. */ 170void 171ax_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. */ 189int 190ax_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. */ 204void 205ax_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. */ 218void 219ax_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 252void 253ax_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. */ 262void 263ax_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 275 276 277/* Functions for disassembling agent expressions, and otherwise 278 debugging the expression compiler. */ 279 280struct 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. */ 335void 336ax_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. */ 383void 384ax_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} 547