GDB (API)
|
00001 /* Functions for manipulating expressions designed to be executed on the agent 00002 Copyright (C) 1998-2013 Free Software Foundation, Inc. 00003 00004 This file is part of GDB. 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00018 00019 /* Despite what the above comment says about this file being part of 00020 GDB, we would like to keep these functions free of GDB 00021 dependencies, since we want to be able to use them in contexts 00022 outside of GDB (test suites, the stub, etc.) */ 00023 00024 #include "defs.h" 00025 #include "ax.h" 00026 00027 #include "value.h" 00028 #include "gdb_string.h" 00029 00030 #include "user-regs.h" 00031 00032 static void grow_expr (struct agent_expr *x, int n); 00033 00034 static void append_const (struct agent_expr *x, LONGEST val, int n); 00035 00036 static LONGEST read_const (struct agent_expr *x, int o, int n); 00037 00038 static void generic_ext (struct agent_expr *x, enum agent_op op, int n); 00039 00040 /* Functions for building expressions. */ 00041 00042 /* Allocate a new, empty agent expression. */ 00043 struct agent_expr * 00044 new_agent_expr (struct gdbarch *gdbarch, CORE_ADDR scope) 00045 { 00046 struct agent_expr *x = xmalloc (sizeof (*x)); 00047 00048 x->len = 0; 00049 x->size = 1; /* Change this to a larger value once 00050 reallocation code is tested. */ 00051 x->buf = xmalloc (x->size); 00052 00053 x->gdbarch = gdbarch; 00054 x->scope = scope; 00055 00056 /* Bit vector for registers used. */ 00057 x->reg_mask_len = 1; 00058 x->reg_mask = xmalloc (x->reg_mask_len * sizeof (x->reg_mask[0])); 00059 memset (x->reg_mask, 0, x->reg_mask_len * sizeof (x->reg_mask[0])); 00060 00061 x->tracing = 0; 00062 x->trace_string = 0; 00063 00064 return x; 00065 } 00066 00067 /* Free a agent expression. */ 00068 void 00069 free_agent_expr (struct agent_expr *x) 00070 { 00071 xfree (x->buf); 00072 xfree (x->reg_mask); 00073 xfree (x); 00074 } 00075 00076 static void 00077 do_free_agent_expr_cleanup (void *x) 00078 { 00079 free_agent_expr (x); 00080 } 00081 00082 struct cleanup * 00083 make_cleanup_free_agent_expr (struct agent_expr *x) 00084 { 00085 return make_cleanup (do_free_agent_expr_cleanup, x); 00086 } 00087 00088 00089 /* Make sure that X has room for at least N more bytes. This doesn't 00090 affect the length, just the allocated size. */ 00091 static void 00092 grow_expr (struct agent_expr *x, int n) 00093 { 00094 if (x->len + n > x->size) 00095 { 00096 x->size *= 2; 00097 if (x->size < x->len + n) 00098 x->size = x->len + n + 10; 00099 x->buf = xrealloc (x->buf, x->size); 00100 } 00101 } 00102 00103 00104 /* Append the low N bytes of VAL as an N-byte integer to the 00105 expression X, in big-endian order. */ 00106 static void 00107 append_const (struct agent_expr *x, LONGEST val, int n) 00108 { 00109 int i; 00110 00111 grow_expr (x, n); 00112 for (i = n - 1; i >= 0; i--) 00113 { 00114 x->buf[x->len + i] = val & 0xff; 00115 val >>= 8; 00116 } 00117 x->len += n; 00118 } 00119 00120 00121 /* Extract an N-byte big-endian unsigned integer from expression X at 00122 offset O. */ 00123 static LONGEST 00124 read_const (struct agent_expr *x, int o, int n) 00125 { 00126 int i; 00127 LONGEST accum = 0; 00128 00129 /* Make sure we're not reading off the end of the expression. */ 00130 if (o + n > x->len) 00131 error (_("GDB bug: ax-general.c (read_const): incomplete constant")); 00132 00133 for (i = 0; i < n; i++) 00134 accum = (accum << 8) | x->buf[o + i]; 00135 00136 return accum; 00137 } 00138 00139 00140 /* Append a simple operator OP to EXPR. */ 00141 void 00142 ax_simple (struct agent_expr *x, enum agent_op op) 00143 { 00144 grow_expr (x, 1); 00145 x->buf[x->len++] = op; 00146 } 00147 00148 /* Append a pick operator to EXPR. DEPTH is the stack item to pick, 00149 with 0 being top of stack. */ 00150 00151 void 00152 ax_pick (struct agent_expr *x, int depth) 00153 { 00154 if (depth < 0 || depth > 255) 00155 error (_("GDB bug: ax-general.c (ax_pick): stack depth out of range")); 00156 ax_simple (x, aop_pick); 00157 append_const (x, 1, depth); 00158 } 00159 00160 00161 /* Append a sign-extension or zero-extension instruction to EXPR, to 00162 extend an N-bit value. */ 00163 static void 00164 generic_ext (struct agent_expr *x, enum agent_op op, int n) 00165 { 00166 /* N must fit in a byte. */ 00167 if (n < 0 || n > 255) 00168 error (_("GDB bug: ax-general.c (generic_ext): bit count out of range")); 00169 /* That had better be enough range. */ 00170 if (sizeof (LONGEST) * 8 > 255) 00171 error (_("GDB bug: ax-general.c (generic_ext): " 00172 "opcode has inadequate range")); 00173 00174 grow_expr (x, 2); 00175 x->buf[x->len++] = op; 00176 x->buf[x->len++] = n; 00177 } 00178 00179 00180 /* Append a sign-extension instruction to EXPR, to extend an N-bit value. */ 00181 void 00182 ax_ext (struct agent_expr *x, int n) 00183 { 00184 generic_ext (x, aop_ext, n); 00185 } 00186 00187 00188 /* Append a zero-extension instruction to EXPR, to extend an N-bit value. */ 00189 void 00190 ax_zero_ext (struct agent_expr *x, int n) 00191 { 00192 generic_ext (x, aop_zero_ext, n); 00193 } 00194 00195 00196 /* Append a trace_quick instruction to EXPR, to record N bytes. */ 00197 void 00198 ax_trace_quick (struct agent_expr *x, int n) 00199 { 00200 /* N must fit in a byte. */ 00201 if (n < 0 || n > 255) 00202 error (_("GDB bug: ax-general.c (ax_trace_quick): " 00203 "size out of range for trace_quick")); 00204 00205 grow_expr (x, 2); 00206 x->buf[x->len++] = aop_trace_quick; 00207 x->buf[x->len++] = n; 00208 } 00209 00210 00211 /* Append a goto op to EXPR. OP is the actual op (must be aop_goto or 00212 aop_if_goto). We assume we don't know the target offset yet, 00213 because it's probably a forward branch, so we leave space in EXPR 00214 for the target, and return the offset in EXPR of that space, so we 00215 can backpatch it once we do know the target offset. Use ax_label 00216 to do the backpatching. */ 00217 int 00218 ax_goto (struct agent_expr *x, enum agent_op op) 00219 { 00220 grow_expr (x, 3); 00221 x->buf[x->len + 0] = op; 00222 x->buf[x->len + 1] = 0xff; 00223 x->buf[x->len + 2] = 0xff; 00224 x->len += 3; 00225 return x->len - 2; 00226 } 00227 00228 /* Suppose a given call to ax_goto returns some value PATCH. When you 00229 know the offset TARGET that goto should jump to, call 00230 ax_label (EXPR, PATCH, TARGET) 00231 to patch TARGET into the ax_goto instruction. */ 00232 void 00233 ax_label (struct agent_expr *x, int patch, int target) 00234 { 00235 /* Make sure the value is in range. Don't accept 0xffff as an 00236 offset; that's our magic sentinel value for unpatched branches. */ 00237 if (target < 0 || target >= 0xffff) 00238 error (_("GDB bug: ax-general.c (ax_label): label target out of range")); 00239 00240 x->buf[patch] = (target >> 8) & 0xff; 00241 x->buf[patch + 1] = target & 0xff; 00242 } 00243 00244 00245 /* Assemble code to push a constant on the stack. */ 00246 void 00247 ax_const_l (struct agent_expr *x, LONGEST l) 00248 { 00249 static enum agent_op ops[] 00250 = 00251 {aop_const8, aop_const16, aop_const32, aop_const64}; 00252 int size; 00253 int op; 00254 00255 /* How big is the number? 'op' keeps track of which opcode to use. 00256 Notice that we don't really care whether the original number was 00257 signed or unsigned; we always reproduce the value exactly, and 00258 use the shortest representation. */ 00259 for (op = 0, size = 8; size < 64; size *= 2, op++) 00260 { 00261 LONGEST lim = ((LONGEST) 1) << (size - 1); 00262 00263 if (-lim <= l && l <= lim - 1) 00264 break; 00265 } 00266 00267 /* Emit the right opcode... */ 00268 ax_simple (x, ops[op]); 00269 00270 /* Emit the low SIZE bytes as an unsigned number. We know that 00271 sign-extending this will yield l. */ 00272 append_const (x, l, size / 8); 00273 00274 /* Now, if it was negative, and not full-sized, sign-extend it. */ 00275 if (l < 0 && size < 64) 00276 ax_ext (x, size); 00277 } 00278 00279 00280 void 00281 ax_const_d (struct agent_expr *x, LONGEST d) 00282 { 00283 /* FIXME: floating-point support not present yet. */ 00284 error (_("GDB bug: ax-general.c (ax_const_d): " 00285 "floating point not supported yet")); 00286 } 00287 00288 00289 /* Assemble code to push the value of register number REG on the 00290 stack. */ 00291 void 00292 ax_reg (struct agent_expr *x, int reg) 00293 { 00294 if (reg >= gdbarch_num_regs (x->gdbarch)) 00295 { 00296 /* This is a pseudo-register. */ 00297 if (!gdbarch_ax_pseudo_register_push_stack_p (x->gdbarch)) 00298 error (_("'%s' is a pseudo-register; " 00299 "GDB cannot yet trace its contents."), 00300 user_reg_map_regnum_to_name (x->gdbarch, reg)); 00301 if (gdbarch_ax_pseudo_register_push_stack (x->gdbarch, x, reg)) 00302 error (_("Trace '%s' failed."), 00303 user_reg_map_regnum_to_name (x->gdbarch, reg)); 00304 } 00305 else 00306 { 00307 /* Make sure the register number is in range. */ 00308 if (reg < 0 || reg > 0xffff) 00309 error (_("GDB bug: ax-general.c (ax_reg): " 00310 "register number out of range")); 00311 grow_expr (x, 3); 00312 x->buf[x->len] = aop_reg; 00313 x->buf[x->len + 1] = (reg >> 8) & 0xff; 00314 x->buf[x->len + 2] = (reg) & 0xff; 00315 x->len += 3; 00316 } 00317 } 00318 00319 /* Assemble code to operate on a trace state variable. */ 00320 00321 void 00322 ax_tsv (struct agent_expr *x, enum agent_op op, int num) 00323 { 00324 /* Make sure the tsv number is in range. */ 00325 if (num < 0 || num > 0xffff) 00326 internal_error (__FILE__, __LINE__, 00327 _("ax-general.c (ax_tsv): variable " 00328 "number is %d, out of range"), num); 00329 00330 grow_expr (x, 3); 00331 x->buf[x->len] = op; 00332 x->buf[x->len + 1] = (num >> 8) & 0xff; 00333 x->buf[x->len + 2] = (num) & 0xff; 00334 x->len += 3; 00335 } 00336 00337 /* Append a string to the expression. Note that the string is going 00338 into the bytecodes directly, not on the stack. As a precaution, 00339 include both length as prefix, and terminate with a NUL. (The NUL 00340 is counted in the length.) */ 00341 00342 void 00343 ax_string (struct agent_expr *x, const char *str, int slen) 00344 { 00345 int i; 00346 00347 /* Make sure the string length is reasonable. */ 00348 if (slen < 0 || slen > 0xffff) 00349 internal_error (__FILE__, __LINE__, 00350 _("ax-general.c (ax_string): string " 00351 "length is %d, out of allowed range"), slen); 00352 00353 grow_expr (x, 2 + slen + 1); 00354 x->buf[x->len++] = ((slen + 1) >> 8) & 0xff; 00355 x->buf[x->len++] = (slen + 1) & 0xff; 00356 for (i = 0; i < slen; ++i) 00357 x->buf[x->len++] = str[i]; 00358 x->buf[x->len++] = '\0'; 00359 } 00360 00361 00362 00363 /* Functions for disassembling agent expressions, and otherwise 00364 debugging the expression compiler. */ 00365 00366 struct aop_map aop_map[] = 00367 { 00368 {0, 0, 0, 0, 0} 00369 #define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE) \ 00370 , { # NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED } 00371 #include "ax.def" 00372 #undef DEFOP 00373 }; 00374 00375 00376 /* Disassemble the expression EXPR, writing to F. */ 00377 void 00378 ax_print (struct ui_file *f, struct agent_expr *x) 00379 { 00380 int i; 00381 00382 fprintf_filtered (f, _("Scope: %s\n"), paddress (x->gdbarch, x->scope)); 00383 fprintf_filtered (f, _("Reg mask:")); 00384 for (i = 0; i < x->reg_mask_len; ++i) 00385 fprintf_filtered (f, _(" %02x"), x->reg_mask[i]); 00386 fprintf_filtered (f, _("\n")); 00387 00388 /* Check the size of the name array against the number of entries in 00389 the enum, to catch additions that people didn't sync. */ 00390 if ((sizeof (aop_map) / sizeof (aop_map[0])) 00391 != aop_last) 00392 error (_("GDB bug: ax-general.c (ax_print): opcode map out of sync")); 00393 00394 for (i = 0; i < x->len;) 00395 { 00396 enum agent_op op = x->buf[i]; 00397 00398 if (op >= (sizeof (aop_map) / sizeof (aop_map[0])) 00399 || !aop_map[op].name) 00400 { 00401 fprintf_filtered (f, _("%3d <bad opcode %02x>\n"), i, op); 00402 i++; 00403 continue; 00404 } 00405 if (i + 1 + aop_map[op].op_size > x->len) 00406 { 00407 fprintf_filtered (f, _("%3d <incomplete opcode %s>\n"), 00408 i, aop_map[op].name); 00409 break; 00410 } 00411 00412 fprintf_filtered (f, "%3d %s", i, aop_map[op].name); 00413 if (aop_map[op].op_size > 0) 00414 { 00415 fputs_filtered (" ", f); 00416 00417 print_longest (f, 'd', 0, 00418 read_const (x, i + 1, aop_map[op].op_size)); 00419 } 00420 /* Handle the complicated printf arguments specially. */ 00421 else if (op == aop_printf) 00422 { 00423 int slen, nargs; 00424 00425 i++; 00426 nargs = x->buf[i++]; 00427 slen = x->buf[i++]; 00428 slen = slen * 256 + x->buf[i++]; 00429 fprintf_filtered (f, _(" \"%s\", %d args"), 00430 &(x->buf[i]), nargs); 00431 i += slen - 1; 00432 } 00433 fprintf_filtered (f, "\n"); 00434 i += 1 + aop_map[op].op_size; 00435 } 00436 } 00437 00438 /* Add register REG to the register mask for expression AX. */ 00439 void 00440 ax_reg_mask (struct agent_expr *ax, int reg) 00441 { 00442 if (reg >= gdbarch_num_regs (ax->gdbarch)) 00443 { 00444 /* This is a pseudo-register. */ 00445 if (!gdbarch_ax_pseudo_register_collect_p (ax->gdbarch)) 00446 error (_("'%s' is a pseudo-register; " 00447 "GDB cannot yet trace its contents."), 00448 user_reg_map_regnum_to_name (ax->gdbarch, reg)); 00449 if (gdbarch_ax_pseudo_register_collect (ax->gdbarch, ax, reg)) 00450 error (_("Trace '%s' failed."), 00451 user_reg_map_regnum_to_name (ax->gdbarch, reg)); 00452 } 00453 else 00454 { 00455 int byte = reg / 8; 00456 00457 /* Grow the bit mask if necessary. */ 00458 if (byte >= ax->reg_mask_len) 00459 { 00460 /* It's not appropriate to double here. This isn't a 00461 string buffer. */ 00462 int new_len = byte + 1; 00463 unsigned char *new_reg_mask = xrealloc (ax->reg_mask, 00464 new_len 00465 * sizeof (ax->reg_mask[0])); 00466 memset (new_reg_mask + ax->reg_mask_len, 0, 00467 (new_len - ax->reg_mask_len) * sizeof (ax->reg_mask[0])); 00468 ax->reg_mask_len = new_len; 00469 ax->reg_mask = new_reg_mask; 00470 } 00471 00472 ax->reg_mask[byte] |= 1 << (reg % 8); 00473 } 00474 } 00475 00476 /* Given an agent expression AX, fill in requirements and other descriptive 00477 bits. */ 00478 void 00479 ax_reqs (struct agent_expr *ax) 00480 { 00481 int i; 00482 int height; 00483 00484 /* Jump target table. targets[i] is non-zero iff we have found a 00485 jump to offset i. */ 00486 char *targets = (char *) alloca (ax->len * sizeof (targets[0])); 00487 00488 /* Instruction boundary table. boundary[i] is non-zero iff our scan 00489 has reached an instruction starting at offset i. */ 00490 char *boundary = (char *) alloca (ax->len * sizeof (boundary[0])); 00491 00492 /* Stack height record. If either targets[i] or boundary[i] is 00493 non-zero, heights[i] is the height the stack should have before 00494 executing the bytecode at that point. */ 00495 int *heights = (int *) alloca (ax->len * sizeof (heights[0])); 00496 00497 /* Pointer to a description of the present op. */ 00498 struct aop_map *op; 00499 00500 memset (targets, 0, ax->len * sizeof (targets[0])); 00501 memset (boundary, 0, ax->len * sizeof (boundary[0])); 00502 00503 ax->max_height = ax->min_height = height = 0; 00504 ax->flaw = agent_flaw_none; 00505 ax->max_data_size = 0; 00506 00507 for (i = 0; i < ax->len; i += 1 + op->op_size) 00508 { 00509 if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0]))) 00510 { 00511 ax->flaw = agent_flaw_bad_instruction; 00512 return; 00513 } 00514 00515 op = &aop_map[ax->buf[i]]; 00516 00517 if (!op->name) 00518 { 00519 ax->flaw = agent_flaw_bad_instruction; 00520 return; 00521 } 00522 00523 if (i + 1 + op->op_size > ax->len) 00524 { 00525 ax->flaw = agent_flaw_incomplete_instruction; 00526 return; 00527 } 00528 00529 /* If this instruction is a forward jump target, does the 00530 current stack height match the stack height at the jump 00531 source? */ 00532 if (targets[i] && (heights[i] != height)) 00533 { 00534 ax->flaw = agent_flaw_height_mismatch; 00535 return; 00536 } 00537 00538 boundary[i] = 1; 00539 heights[i] = height; 00540 00541 height -= op->consumed; 00542 if (height < ax->min_height) 00543 ax->min_height = height; 00544 height += op->produced; 00545 if (height > ax->max_height) 00546 ax->max_height = height; 00547 00548 if (op->data_size > ax->max_data_size) 00549 ax->max_data_size = op->data_size; 00550 00551 /* For jump instructions, check that the target is a valid 00552 offset. If it is, record the fact that that location is a 00553 jump target, and record the height we expect there. */ 00554 if (aop_goto == op - aop_map 00555 || aop_if_goto == op - aop_map) 00556 { 00557 int target = read_const (ax, i + 1, 2); 00558 if (target < 0 || target >= ax->len) 00559 { 00560 ax->flaw = agent_flaw_bad_jump; 00561 return; 00562 } 00563 00564 /* Do we have any information about what the stack height 00565 should be at the target? */ 00566 if (targets[target] || boundary[target]) 00567 { 00568 if (heights[target] != height) 00569 { 00570 ax->flaw = agent_flaw_height_mismatch; 00571 return; 00572 } 00573 } 00574 00575 /* Record the target, along with the stack height we expect. */ 00576 targets[target] = 1; 00577 heights[target] = height; 00578 } 00579 00580 /* For unconditional jumps with a successor, check that the 00581 successor is a target, and pick up its stack height. */ 00582 if (aop_goto == op - aop_map 00583 && i + 3 < ax->len) 00584 { 00585 if (!targets[i + 3]) 00586 { 00587 ax->flaw = agent_flaw_hole; 00588 return; 00589 } 00590 00591 height = heights[i + 3]; 00592 } 00593 00594 /* For reg instructions, record the register in the bit mask. */ 00595 if (aop_reg == op - aop_map) 00596 { 00597 int reg = read_const (ax, i + 1, 2); 00598 00599 ax_reg_mask (ax, reg); 00600 } 00601 } 00602 00603 /* Check that all the targets are on boundaries. */ 00604 for (i = 0; i < ax->len; i++) 00605 if (targets[i] && !boundary[i]) 00606 { 00607 ax->flaw = agent_flaw_bad_jump; 00608 return; 00609 } 00610 00611 ax->final_height = height; 00612 }