1 1.1 christos /* Functions for manipulating expressions designed to be executed on the agent 2 1.11 christos Copyright (C) 1998-2024 Free Software Foundation, Inc. 3 1.1 christos 4 1.1 christos This file is part of GDB. 5 1.1 christos 6 1.1 christos This program is free software; you can redistribute it and/or modify 7 1.1 christos it under the terms of the GNU General Public License as published by 8 1.1 christos the Free Software Foundation; either version 3 of the License, or 9 1.1 christos (at your option) any later version. 10 1.1 christos 11 1.1 christos This program is distributed in the hope that it will be useful, 12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 christos GNU General Public License for more details. 15 1.1 christos 16 1.1 christos You should have received a copy of the GNU General Public License 17 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 1.1 christos 19 1.1 christos /* Despite what the above comment says about this file being part of 20 1.1 christos GDB, we would like to keep these functions free of GDB 21 1.1 christos dependencies, since we want to be able to use them in contexts 22 1.1 christos outside of GDB (test suites, the stub, etc.) */ 23 1.1 christos 24 1.1 christos #include "ax.h" 25 1.9 christos #include "gdbarch.h" 26 1.1 christos 27 1.1 christos #include "value.h" 28 1.1 christos #include "user-regs.h" 29 1.1 christos 30 1.1 christos static void append_const (struct agent_expr *x, LONGEST val, int n); 31 1.1 christos 32 1.1 christos static LONGEST read_const (struct agent_expr *x, int o, int n); 33 1.1 christos 34 1.1 christos static void generic_ext (struct agent_expr *x, enum agent_op op, int n); 35 1.1 christos 36 1.1 christos /* Functions for building expressions. */ 38 1.1 christos 39 1.1 christos /* Append the low N bytes of VAL as an N-byte integer to the 40 1.1 christos expression X, in big-endian order. */ 41 1.1 christos static void 42 1.1 christos append_const (struct agent_expr *x, LONGEST val, int n) 43 1.11 christos { 44 1.11 christos size_t len = x->buf.size (); 45 1.11 christos x->buf.resize (len + n); 46 1.1 christos for (int i = n - 1; i >= 0; i--) 47 1.11 christos { 48 1.1 christos x->buf[len + i] = val & 0xff; 49 1.1 christos val >>= 8; 50 1.1 christos } 51 1.1 christos } 52 1.1 christos 53 1.1 christos 54 1.1 christos /* Extract an N-byte big-endian unsigned integer from expression X at 55 1.1 christos offset O. */ 56 1.1 christos static LONGEST 57 1.1 christos read_const (struct agent_expr *x, int o, int n) 58 1.1 christos { 59 1.1 christos int i; 60 1.1 christos LONGEST accum = 0; 61 1.1 christos 62 1.11 christos /* Make sure we're not reading off the end of the expression. */ 63 1.1 christos if (o + n > x->buf.size ()) 64 1.1 christos error (_("GDB bug: ax-general.c (read_const): incomplete constant")); 65 1.1 christos 66 1.1 christos for (i = 0; i < n; i++) 67 1.1 christos accum = (accum << 8) | x->buf[o + i]; 68 1.1 christos 69 1.1 christos return accum; 70 1.1 christos } 71 1.6 christos 72 1.6 christos /* See ax.h. */ 73 1.6 christos 74 1.6 christos void 75 1.6 christos ax_raw_byte (struct agent_expr *x, gdb_byte byte) 76 1.11 christos { 77 1.6 christos x->buf.push_back (byte); 78 1.1 christos } 79 1.1 christos 80 1.1 christos /* Append a simple operator OP to EXPR. */ 81 1.1 christos void 82 1.1 christos ax_simple (struct agent_expr *x, enum agent_op op) 83 1.6 christos { 84 1.1 christos ax_raw_byte (x, op); 85 1.1 christos } 86 1.1 christos 87 1.1 christos /* Append a pick operator to EXPR. DEPTH is the stack item to pick, 88 1.1 christos with 0 being top of stack. */ 89 1.1 christos 90 1.1 christos void 91 1.1 christos ax_pick (struct agent_expr *x, int depth) 92 1.1 christos { 93 1.1 christos if (depth < 0 || depth > 255) 94 1.1 christos error (_("GDB bug: ax-general.c (ax_pick): stack depth out of range")); 95 1.1 christos ax_simple (x, aop_pick); 96 1.1 christos append_const (x, 1, depth); 97 1.1 christos } 98 1.1 christos 99 1.1 christos 100 1.1 christos /* Append a sign-extension or zero-extension instruction to EXPR, to 101 1.1 christos extend an N-bit value. */ 102 1.1 christos static void 103 1.1 christos generic_ext (struct agent_expr *x, enum agent_op op, int n) 104 1.1 christos { 105 1.1 christos /* N must fit in a byte. */ 106 1.1 christos if (n < 0 || n > 255) 107 1.1 christos error (_("GDB bug: ax-general.c (generic_ext): bit count out of range")); 108 1.1 christos /* That had better be enough range. */ 109 1.1 christos if (sizeof (LONGEST) * 8 > 255) 110 1.1 christos error (_("GDB bug: ax-general.c (generic_ext): " 111 1.1 christos "opcode has inadequate range")); 112 1.11 christos 113 1.11 christos x->buf.push_back (op); 114 1.1 christos x->buf.push_back (n); 115 1.1 christos } 116 1.1 christos 117 1.1 christos 118 1.1 christos /* Append a sign-extension instruction to EXPR, to extend an N-bit value. */ 119 1.1 christos void 120 1.1 christos ax_ext (struct agent_expr *x, int n) 121 1.1 christos { 122 1.1 christos generic_ext (x, aop_ext, n); 123 1.1 christos } 124 1.1 christos 125 1.1 christos 126 1.1 christos /* Append a zero-extension instruction to EXPR, to extend an N-bit value. */ 127 1.1 christos void 128 1.1 christos ax_zero_ext (struct agent_expr *x, int n) 129 1.1 christos { 130 1.1 christos generic_ext (x, aop_zero_ext, n); 131 1.1 christos } 132 1.1 christos 133 1.1 christos 134 1.1 christos /* Append a trace_quick instruction to EXPR, to record N bytes. */ 135 1.1 christos void 136 1.1 christos ax_trace_quick (struct agent_expr *x, int n) 137 1.1 christos { 138 1.1 christos /* N must fit in a byte. */ 139 1.1 christos if (n < 0 || n > 255) 140 1.1 christos error (_("GDB bug: ax-general.c (ax_trace_quick): " 141 1.1 christos "size out of range for trace_quick")); 142 1.11 christos 143 1.11 christos x->buf.push_back (aop_trace_quick); 144 1.1 christos x->buf.push_back (n); 145 1.1 christos } 146 1.1 christos 147 1.1 christos 148 1.1 christos /* Append a goto op to EXPR. OP is the actual op (must be aop_goto or 149 1.1 christos aop_if_goto). We assume we don't know the target offset yet, 150 1.1 christos because it's probably a forward branch, so we leave space in EXPR 151 1.1 christos for the target, and return the offset in EXPR of that space, so we 152 1.1 christos can backpatch it once we do know the target offset. Use ax_label 153 1.1 christos to do the backpatching. */ 154 1.1 christos int 155 1.1 christos ax_goto (struct agent_expr *x, enum agent_op op) 156 1.11 christos { 157 1.11 christos x->buf.push_back (op); 158 1.11 christos x->buf.push_back (0xff); 159 1.11 christos x->buf.push_back (0xff); 160 1.1 christos return x->buf.size () - 2; 161 1.1 christos } 162 1.1 christos 163 1.1 christos /* Suppose a given call to ax_goto returns some value PATCH. When you 164 1.1 christos know the offset TARGET that goto should jump to, call 165 1.1 christos ax_label (EXPR, PATCH, TARGET) 166 1.1 christos to patch TARGET into the ax_goto instruction. */ 167 1.1 christos void 168 1.1 christos ax_label (struct agent_expr *x, int patch, int target) 169 1.1 christos { 170 1.1 christos /* Make sure the value is in range. Don't accept 0xffff as an 171 1.1 christos offset; that's our magic sentinel value for unpatched branches. */ 172 1.1 christos if (target < 0 || target >= 0xffff) 173 1.1 christos error (_("GDB bug: ax-general.c (ax_label): label target out of range")); 174 1.1 christos 175 1.1 christos x->buf[patch] = (target >> 8) & 0xff; 176 1.1 christos x->buf[patch + 1] = target & 0xff; 177 1.1 christos } 178 1.1 christos 179 1.1 christos 180 1.1 christos /* Assemble code to push a constant on the stack. */ 181 1.1 christos void 182 1.1 christos ax_const_l (struct agent_expr *x, LONGEST l) 183 1.1 christos { 184 1.1 christos static enum agent_op ops[] 185 1.1 christos = 186 1.1 christos {aop_const8, aop_const16, aop_const32, aop_const64}; 187 1.1 christos int size; 188 1.1 christos int op; 189 1.1 christos 190 1.1 christos /* How big is the number? 'op' keeps track of which opcode to use. 191 1.1 christos Notice that we don't really care whether the original number was 192 1.1 christos signed or unsigned; we always reproduce the value exactly, and 193 1.1 christos use the shortest representation. */ 194 1.1 christos for (op = 0, size = 8; size < 64; size *= 2, op++) 195 1.1 christos { 196 1.1 christos LONGEST lim = ((LONGEST) 1) << (size - 1); 197 1.1 christos 198 1.10 christos if (-lim <= l && l <= lim - 1) 199 1.1 christos break; 200 1.1 christos } 201 1.1 christos 202 1.1 christos /* Emit the right opcode... */ 203 1.1 christos ax_simple (x, ops[op]); 204 1.1 christos 205 1.1 christos /* Emit the low SIZE bytes as an unsigned number. We know that 206 1.1 christos sign-extending this will yield l. */ 207 1.1 christos append_const (x, l, size / 8); 208 1.1 christos 209 1.1 christos /* Now, if it was negative, and not full-sized, sign-extend it. */ 210 1.1 christos if (l < 0 && size < 64) 211 1.1 christos ax_ext (x, size); 212 1.1 christos } 213 1.1 christos 214 1.1 christos 215 1.1 christos void 216 1.1 christos ax_const_d (struct agent_expr *x, LONGEST d) 217 1.1 christos { 218 1.1 christos /* FIXME: floating-point support not present yet. */ 219 1.1 christos error (_("GDB bug: ax-general.c (ax_const_d): " 220 1.1 christos "floating point not supported yet")); 221 1.1 christos } 222 1.1 christos 223 1.1 christos 224 1.1 christos /* Assemble code to push the value of register number REG on the 225 1.1 christos stack. */ 226 1.1 christos void 227 1.1 christos ax_reg (struct agent_expr *x, int reg) 228 1.1 christos { 229 1.1 christos if (reg >= gdbarch_num_regs (x->gdbarch)) 230 1.1 christos { 231 1.1 christos /* This is a pseudo-register. */ 232 1.1 christos if (!gdbarch_ax_pseudo_register_push_stack_p (x->gdbarch)) 233 1.1 christos error (_("'%s' is a pseudo-register; " 234 1.1 christos "GDB cannot yet trace its contents."), 235 1.1 christos user_reg_map_regnum_to_name (x->gdbarch, reg)); 236 1.1 christos if (gdbarch_ax_pseudo_register_push_stack (x->gdbarch, x, reg)) 237 1.1 christos error (_("Trace '%s' failed."), 238 1.1 christos user_reg_map_regnum_to_name (x->gdbarch, reg)); 239 1.1 christos } 240 1.1 christos else 241 1.6 christos { 242 1.6 christos /* Get the remote register number. */ 243 1.6 christos reg = gdbarch_remote_register_number (x->gdbarch, reg); 244 1.1 christos 245 1.1 christos /* Make sure the register number is in range. */ 246 1.10 christos if (reg < 0 || reg > 0xffff) 247 1.1 christos error (_("GDB bug: ax-general.c (ax_reg): " 248 1.11 christos "register number out of range")); 249 1.11 christos x->buf.push_back (aop_reg); 250 1.11 christos x->buf.push_back ((reg >> 8) & 0xff); 251 1.1 christos x->buf.push_back ((reg) & 0xff); 252 1.1 christos } 253 1.1 christos } 254 1.1 christos 255 1.1 christos /* Assemble code to operate on a trace state variable. */ 256 1.1 christos 257 1.1 christos void 258 1.1 christos ax_tsv (struct agent_expr *x, enum agent_op op, int num) 259 1.1 christos { 260 1.1 christos /* Make sure the tsv number is in range. */ 261 1.10 christos if (num < 0 || num > 0xffff) 262 1.1 christos internal_error (_("ax-general.c (ax_tsv): variable " 263 1.1 christos "number is %d, out of range"), num); 264 1.11 christos 265 1.11 christos x->buf.push_back (op); 266 1.11 christos x->buf.push_back ((num >> 8) & 0xff); 267 1.1 christos x->buf.push_back ((num) & 0xff); 268 1.1 christos } 269 1.1 christos 270 1.1 christos /* Append a string to the expression. Note that the string is going 271 1.1 christos into the bytecodes directly, not on the stack. As a precaution, 272 1.1 christos include both length as prefix, and terminate with a NUL. (The NUL 273 1.1 christos is counted in the length.) */ 274 1.1 christos 275 1.1 christos void 276 1.1 christos ax_string (struct agent_expr *x, const char *str, int slen) 277 1.1 christos { 278 1.1 christos int i; 279 1.1 christos 280 1.1 christos /* Make sure the string length is reasonable. */ 281 1.10 christos if (slen < 0 || slen > 0xffff) 282 1.1 christos internal_error (_("ax-general.c (ax_string): string " 283 1.1 christos "length is %d, out of allowed range"), slen); 284 1.11 christos 285 1.11 christos x->buf.push_back (((slen + 1) >> 8) & 0xff); 286 1.1 christos x->buf.push_back ((slen + 1) & 0xff); 287 1.11 christos for (i = 0; i < slen; ++i) 288 1.11 christos x->buf.push_back (str[i]); 289 1.1 christos x->buf.push_back ('\0'); 290 1.1 christos } 291 1.1 christos 292 1.1 christos 294 1.1 christos 295 1.1 christos /* Functions for disassembling agent expressions, and otherwise 296 1.11 christos debugging the expression compiler. */ 297 1.11 christos 298 1.11 christos /* An entry in the opcode map. */ 299 1.11 christos struct aop_map 300 1.11 christos { 301 1.11 christos 302 1.11 christos /* The name of the opcode. Null means that this entry is not a 303 1.11 christos valid opcode --- a hole in the opcode space. */ 304 1.11 christos const char *name; 305 1.11 christos 306 1.11 christos /* All opcodes take no operands from the bytecode stream, or take 307 1.11 christos unsigned integers of various sizes. If this is a positive number 308 1.11 christos n, then the opcode is followed by an n-byte operand, which should 309 1.11 christos be printed as an unsigned integer. If this is zero, then the 310 1.11 christos opcode takes no operands from the bytecode stream. 311 1.11 christos 312 1.11 christos If we get more complicated opcodes in the future, don't add other 313 1.11 christos magic values of this; that's a crock. Add an `enum encoding' 314 1.11 christos field to this, or something like that. */ 315 1.11 christos int op_size; 316 1.11 christos 317 1.11 christos /* The size of the data operated upon, in bits, for bytecodes that 318 1.11 christos care about that (ref and const). Zero for all others. */ 319 1.11 christos int data_size; 320 1.11 christos 321 1.11 christos /* Number of stack elements consumed, and number produced. */ 322 1.11 christos int consumed, produced; 323 1.11 christos }; 324 1.11 christos 325 1.11 christos /* Map of the bytecodes, indexed by bytecode number. */ 326 1.1 christos 327 1.1 christos static struct aop_map aop_map[] = 328 1.1 christos { 329 1.1 christos {0, 0, 0, 0, 0} 330 1.9 christos #define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE) \ 331 1.1 christos , { # NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED } 332 1.1 christos #include "gdbsupport/ax.def" 333 1.1 christos #undef DEFOP 334 1.1 christos }; 335 1.1 christos 336 1.1 christos 337 1.1 christos /* Disassemble the expression EXPR, writing to F. */ 338 1.1 christos void 339 1.1 christos ax_print (struct ui_file *f, struct agent_expr *x) 340 1.1 christos { 341 1.10 christos int i; 342 1.10 christos 343 1.11 christos gdb_printf (f, _("Scope: %s\n"), paddress (x->gdbarch, x->scope)); 344 1.11 christos gdb_printf (f, _("Reg mask:")); 345 1.11 christos for (i = 0; i < x->reg_mask.size (); ++i) 346 1.11 christos { 347 1.11 christos if ((i % 8) == 0) 348 1.11 christos gdb_printf (f, " "); 349 1.10 christos gdb_printf (f, _("%d"), (int) x->reg_mask[i]); 350 1.1 christos } 351 1.11 christos gdb_printf (f, _("\n")); 352 1.1 christos 353 1.6 christos for (i = 0; i < x->buf.size ();) 354 1.1 christos { 355 1.11 christos enum agent_op op = (enum agent_op) x->buf[i]; 356 1.1 christos 357 1.10 christos if (op >= ARRAY_SIZE (aop_map) || aop_map[op].name == nullptr) 358 1.1 christos { 359 1.1 christos gdb_printf (f, _("%3d <bad opcode %02x>\n"), i, op); 360 1.1 christos i++; 361 1.11 christos continue; 362 1.1 christos } 363 1.10 christos if (i + 1 + aop_map[op].op_size > x->buf.size ()) 364 1.10 christos { 365 1.1 christos gdb_printf (f, _("%3d <incomplete opcode %s>\n"), 366 1.1 christos i, aop_map[op].name); 367 1.1 christos break; 368 1.10 christos } 369 1.1 christos 370 1.1 christos gdb_printf (f, "%3d %s", i, aop_map[op].name); 371 1.10 christos if (aop_map[op].op_size > 0) 372 1.1 christos { 373 1.1 christos gdb_puts (" ", f); 374 1.1 christos 375 1.1 christos print_longest (f, 'd', 0, 376 1.1 christos read_const (x, i + 1, aop_map[op].op_size)); 377 1.1 christos } 378 1.1 christos /* Handle the complicated printf arguments specially. */ 379 1.1 christos else if (op == aop_printf) 380 1.1 christos { 381 1.1 christos int slen, nargs; 382 1.1 christos 383 1.1 christos i++; 384 1.1 christos nargs = x->buf[i++]; 385 1.10 christos slen = x->buf[i++]; 386 1.10 christos slen = slen * 256 + x->buf[i++]; 387 1.1 christos gdb_printf (f, _(" \"%s\", %d args"), 388 1.1 christos &(x->buf[i]), nargs); 389 1.10 christos i += slen - 1; 390 1.1 christos } 391 1.1 christos gdb_printf (f, "\n"); 392 1.1 christos i += 1 + aop_map[op].op_size; 393 1.1 christos } 394 1.1 christos } 395 1.1 christos 396 1.1 christos /* Add register REG to the register mask for expression AX. */ 397 1.1 christos void 398 1.1 christos ax_reg_mask (struct agent_expr *ax, int reg) 399 1.1 christos { 400 1.1 christos if (reg >= gdbarch_num_regs (ax->gdbarch)) 401 1.1 christos { 402 1.1 christos /* This is a pseudo-register. */ 403 1.1 christos if (!gdbarch_ax_pseudo_register_collect_p (ax->gdbarch)) 404 1.1 christos error (_("'%s' is a pseudo-register; " 405 1.1 christos "GDB cannot yet trace its contents."), 406 1.1 christos user_reg_map_regnum_to_name (ax->gdbarch, reg)); 407 1.1 christos if (gdbarch_ax_pseudo_register_collect (ax->gdbarch, ax, reg)) 408 1.1 christos error (_("Trace '%s' failed."), 409 1.1 christos user_reg_map_regnum_to_name (ax->gdbarch, reg)); 410 1.1 christos } 411 1.6 christos else 412 1.6 christos { 413 1.1 christos /* Get the remote register number. */ 414 1.1 christos reg = gdbarch_remote_register_number (ax->gdbarch, reg); 415 1.11 christos 416 1.11 christos /* Grow the bit mask if necessary. */ 417 1.1 christos if (reg >= ax->reg_mask.size ()) 418 1.11 christos ax->reg_mask.resize (reg + 1); 419 1.1 christos 420 1.1 christos ax->reg_mask[reg] = true; 421 1.1 christos } 422 1.1 christos } 423 1.1 christos 424 1.1 christos /* Given an agent expression AX, fill in requirements and other descriptive 425 1.1 christos bits. */ 426 1.1 christos void 427 1.1 christos ax_reqs (struct agent_expr *ax) 428 1.1 christos { 429 1.1 christos int i; 430 1.1 christos int height; 431 1.1 christos 432 1.11 christos /* Jump target table. targets[i] is non-zero iff we have found a 433 1.1 christos jump to offset i. */ 434 1.1 christos char *targets = (char *) alloca (ax->buf.size () * sizeof (targets[0])); 435 1.1 christos 436 1.11 christos /* Instruction boundary table. boundary[i] is non-zero iff our scan 437 1.1 christos has reached an instruction starting at offset i. */ 438 1.1 christos char *boundary = (char *) alloca (ax->buf.size () * sizeof (boundary[0])); 439 1.1 christos 440 1.1 christos /* Stack height record. If either targets[i] or boundary[i] is 441 1.11 christos non-zero, heights[i] is the height the stack should have before 442 1.1 christos executing the bytecode at that point. */ 443 1.1 christos int *heights = (int *) alloca (ax->buf.size () * sizeof (heights[0])); 444 1.1 christos 445 1.1 christos /* Pointer to a description of the present op. */ 446 1.11 christos struct aop_map *op; 447 1.11 christos 448 1.1 christos memset (targets, 0, ax->buf.size () * sizeof (targets[0])); 449 1.1 christos memset (boundary, 0, ax->buf.size () * sizeof (boundary[0])); 450 1.1 christos 451 1.1 christos ax->max_height = ax->min_height = height = 0; 452 1.1 christos ax->flaw = agent_flaw_none; 453 1.11 christos ax->max_data_size = 0; 454 1.1 christos 455 1.11 christos for (i = 0; i < ax->buf.size (); i += 1 + op->op_size) 456 1.1 christos { 457 1.1 christos if (ax->buf[i] >= ARRAY_SIZE (aop_map)) 458 1.1 christos { 459 1.1 christos ax->flaw = agent_flaw_bad_instruction; 460 1.1 christos return; 461 1.1 christos } 462 1.1 christos 463 1.1 christos op = &aop_map[ax->buf[i]]; 464 1.1 christos 465 1.1 christos if (!op->name) 466 1.1 christos { 467 1.1 christos ax->flaw = agent_flaw_bad_instruction; 468 1.1 christos return; 469 1.11 christos } 470 1.1 christos 471 1.1 christos if (i + 1 + op->op_size > ax->buf.size ()) 472 1.1 christos { 473 1.1 christos ax->flaw = agent_flaw_incomplete_instruction; 474 1.1 christos return; 475 1.1 christos } 476 1.10 christos 477 1.10 christos /* If this instruction is a forward jump target, does the 478 1.1 christos current stack height match the stack height at the jump 479 1.1 christos source? */ 480 1.1 christos if (targets[i] && (heights[i] != height)) 481 1.1 christos { 482 1.1 christos ax->flaw = agent_flaw_height_mismatch; 483 1.1 christos return; 484 1.1 christos } 485 1.1 christos 486 1.1 christos boundary[i] = 1; 487 1.1 christos heights[i] = height; 488 1.1 christos 489 1.1 christos height -= op->consumed; 490 1.1 christos if (height < ax->min_height) 491 1.1 christos ax->min_height = height; 492 1.1 christos height += op->produced; 493 1.1 christos if (height > ax->max_height) 494 1.1 christos ax->max_height = height; 495 1.1 christos 496 1.1 christos if (op->data_size > ax->max_data_size) 497 1.1 christos ax->max_data_size = op->data_size; 498 1.10 christos 499 1.10 christos /* For jump instructions, check that the target is a valid 500 1.1 christos offset. If it is, record the fact that that location is a 501 1.1 christos jump target, and record the height we expect there. */ 502 1.1 christos if (aop_goto == op - aop_map 503 1.1 christos || aop_if_goto == op - aop_map) 504 1.11 christos { 505 1.1 christos int target = read_const (ax, i + 1, 2); 506 1.1 christos if (target < 0 || target >= ax->buf.size ()) 507 1.1 christos { 508 1.1 christos ax->flaw = agent_flaw_bad_jump; 509 1.1 christos return; 510 1.1 christos } 511 1.10 christos 512 1.1 christos /* Do we have any information about what the stack height 513 1.1 christos should be at the target? */ 514 1.1 christos if (targets[target] || boundary[target]) 515 1.1 christos { 516 1.1 christos if (heights[target] != height) 517 1.1 christos { 518 1.1 christos ax->flaw = agent_flaw_height_mismatch; 519 1.1 christos return; 520 1.1 christos } 521 1.10 christos } 522 1.10 christos 523 1.10 christos /* Record the target, along with the stack height we expect. */ 524 1.1 christos targets[target] = 1; 525 1.1 christos heights[target] = height; 526 1.1 christos } 527 1.10 christos 528 1.1 christos /* For unconditional jumps with a successor, check that the 529 1.11 christos successor is a target, and pick up its stack height. */ 530 1.1 christos if (aop_goto == op - aop_map 531 1.1 christos && i + 3 < ax->buf.size ()) 532 1.1 christos { 533 1.1 christos if (!targets[i + 3]) 534 1.1 christos { 535 1.1 christos ax->flaw = agent_flaw_hole; 536 1.1 christos return; 537 1.1 christos } 538 1.1 christos 539 1.1 christos height = heights[i + 3]; 540 1.1 christos } 541 1.1 christos 542 1.1 christos /* For reg instructions, record the register in the bit mask. */ 543 1.1 christos if (aop_reg == op - aop_map) 544 1.1 christos { 545 1.1 christos int reg = read_const (ax, i + 1, 2); 546 1.1 christos 547 1.1 christos ax_reg_mask (ax, reg); 548 1.1 christos } 549 1.1 christos } 550 1.11 christos 551 1.1 christos /* Check that all the targets are on boundaries. */ 552 1.1 christos for (i = 0; i < ax->buf.size (); i++) 553 1.1 christos if (targets[i] && !boundary[i]) 554 1.1 christos { 555 1.1 christos ax->flaw = agent_flaw_bad_jump; 556 1.1 christos return; 557 1.1 christos } 558 1.1 christos 559 ax->final_height = height; 560 } 561