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