GDB (API)
|
00001 /* Tracing functionality for remote targets in custom GDB protocol 00002 00003 Copyright (C) 1997-2013 Free Software Foundation, Inc. 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #include "defs.h" 00021 #include "arch-utils.h" 00022 #include "symtab.h" 00023 #include "frame.h" 00024 #include "gdbtypes.h" 00025 #include "expression.h" 00026 #include "gdbcmd.h" 00027 #include "value.h" 00028 #include "target.h" 00029 #include "language.h" 00030 #include "gdb_string.h" 00031 #include "inferior.h" 00032 #include "breakpoint.h" 00033 #include "tracepoint.h" 00034 #include "linespec.h" 00035 #include "regcache.h" 00036 #include "completer.h" 00037 #include "block.h" 00038 #include "dictionary.h" 00039 #include "observer.h" 00040 #include "user-regs.h" 00041 #include "valprint.h" 00042 #include "gdbcore.h" 00043 #include "objfiles.h" 00044 #include "filenames.h" 00045 #include "gdbthread.h" 00046 #include "stack.h" 00047 #include "gdbcore.h" 00048 #include "remote.h" 00049 #include "source.h" 00050 #include "ax.h" 00051 #include "ax-gdb.h" 00052 #include "memrange.h" 00053 #include "exceptions.h" 00054 #include "cli/cli-utils.h" 00055 #include "probe.h" 00056 #include "ctf.h" 00057 #include "completer.h" 00058 #include "filestuff.h" 00059 00060 /* readline include files */ 00061 #include "readline/readline.h" 00062 #include "readline/history.h" 00063 00064 /* readline defines this. */ 00065 #undef savestring 00066 00067 #include <unistd.h> 00068 00069 #ifndef O_LARGEFILE 00070 #define O_LARGEFILE 0 00071 #endif 00072 00073 /* Maximum length of an agent aexpression. 00074 This accounts for the fact that packets are limited to 400 bytes 00075 (which includes everything -- including the checksum), and assumes 00076 the worst case of maximum length for each of the pieces of a 00077 continuation packet. 00078 00079 NOTE: expressions get mem2hex'ed otherwise this would be twice as 00080 large. (400 - 31)/2 == 184 */ 00081 #define MAX_AGENT_EXPR_LEN 184 00082 00083 /* A hook used to notify the UI of tracepoint operations. */ 00084 00085 void (*deprecated_trace_find_hook) (char *arg, int from_tty); 00086 void (*deprecated_trace_start_stop_hook) (int start, int from_tty); 00087 00088 /* 00089 Tracepoint.c: 00090 00091 This module defines the following debugger commands: 00092 trace : set a tracepoint on a function, line, or address. 00093 info trace : list all debugger-defined tracepoints. 00094 delete trace : delete one or more tracepoints. 00095 enable trace : enable one or more tracepoints. 00096 disable trace : disable one or more tracepoints. 00097 actions : specify actions to be taken at a tracepoint. 00098 passcount : specify a pass count for a tracepoint. 00099 tstart : start a trace experiment. 00100 tstop : stop a trace experiment. 00101 tstatus : query the status of a trace experiment. 00102 tfind : find a trace frame in the trace buffer. 00103 tdump : print everything collected at the current tracepoint. 00104 save-tracepoints : write tracepoint setup into a file. 00105 00106 This module defines the following user-visible debugger variables: 00107 $trace_frame : sequence number of trace frame currently being debugged. 00108 $trace_line : source line of trace frame currently being debugged. 00109 $trace_file : source file of trace frame currently being debugged. 00110 $tracepoint : tracepoint number of trace frame currently being debugged. 00111 */ 00112 00113 00114 /* ======= Important global variables: ======= */ 00115 00116 /* The list of all trace state variables. We don't retain pointers to 00117 any of these for any reason - API is by name or number only - so it 00118 works to have a vector of objects. */ 00119 00120 typedef struct trace_state_variable tsv_s; 00121 DEF_VEC_O(tsv_s); 00122 00123 static VEC(tsv_s) *tvariables; 00124 00125 /* The next integer to assign to a variable. */ 00126 00127 static int next_tsv_number = 1; 00128 00129 /* Number of last traceframe collected. */ 00130 static int traceframe_number; 00131 00132 /* Tracepoint for last traceframe collected. */ 00133 static int tracepoint_number; 00134 00135 /* Symbol for function for last traceframe collected. */ 00136 static struct symbol *traceframe_fun; 00137 00138 /* Symtab and line for last traceframe collected. */ 00139 static struct symtab_and_line traceframe_sal; 00140 00141 /* The traceframe info of the current traceframe. NULL if we haven't 00142 yet attempted to fetch it, or if the target does not support 00143 fetching this object, or if we're not inspecting a traceframe 00144 presently. */ 00145 static struct traceframe_info *traceframe_info; 00146 00147 /* Tracing command lists. */ 00148 static struct cmd_list_element *tfindlist; 00149 00150 /* List of expressions to collect by default at each tracepoint hit. */ 00151 char *default_collect = ""; 00152 00153 static int disconnected_tracing; 00154 00155 /* This variable controls whether we ask the target for a linear or 00156 circular trace buffer. */ 00157 00158 static int circular_trace_buffer; 00159 00160 /* This variable is the requested trace buffer size, or -1 to indicate 00161 that we don't care and leave it up to the target to set a size. */ 00162 00163 static int trace_buffer_size = -1; 00164 00165 /* Textual notes applying to the current and/or future trace runs. */ 00166 00167 char *trace_user = NULL; 00168 00169 /* Textual notes applying to the current and/or future trace runs. */ 00170 00171 char *trace_notes = NULL; 00172 00173 /* Textual notes applying to the stopping of a trace. */ 00174 00175 char *trace_stop_notes = NULL; 00176 00177 /* ======= Important command functions: ======= */ 00178 static void trace_actions_command (char *, int); 00179 static void trace_start_command (char *, int); 00180 static void trace_stop_command (char *, int); 00181 static void trace_status_command (char *, int); 00182 static void trace_find_command (char *, int); 00183 static void trace_find_pc_command (char *, int); 00184 static void trace_find_tracepoint_command (char *, int); 00185 static void trace_find_line_command (char *, int); 00186 static void trace_find_range_command (char *, int); 00187 static void trace_find_outside_command (char *, int); 00188 static void trace_dump_command (char *, int); 00189 00190 /* support routines */ 00191 00192 struct collection_list; 00193 static void add_aexpr (struct collection_list *, struct agent_expr *); 00194 static char *mem2hex (gdb_byte *, char *, int); 00195 static void add_register (struct collection_list *collection, 00196 unsigned int regno); 00197 00198 static void free_uploaded_tps (struct uploaded_tp **utpp); 00199 static void free_uploaded_tsvs (struct uploaded_tsv **utsvp); 00200 00201 static struct command_line * 00202 all_tracepoint_actions_and_cleanup (struct breakpoint *t); 00203 00204 extern void _initialize_tracepoint (void); 00205 00206 static struct trace_status trace_status; 00207 00208 char *stop_reason_names[] = { 00209 "tunknown", 00210 "tnotrun", 00211 "tstop", 00212 "tfull", 00213 "tdisconnected", 00214 "tpasscount", 00215 "terror" 00216 }; 00217 00218 struct trace_status * 00219 current_trace_status (void) 00220 { 00221 return &trace_status; 00222 } 00223 00224 /* Destroy INFO. */ 00225 00226 static void 00227 free_traceframe_info (struct traceframe_info *info) 00228 { 00229 if (info != NULL) 00230 { 00231 VEC_free (mem_range_s, info->memory); 00232 VEC_free (int, info->tvars); 00233 00234 xfree (info); 00235 } 00236 } 00237 00238 /* Free and clear the traceframe info cache of the current 00239 traceframe. */ 00240 00241 static void 00242 clear_traceframe_info (void) 00243 { 00244 free_traceframe_info (traceframe_info); 00245 traceframe_info = NULL; 00246 } 00247 00248 /* Set traceframe number to NUM. */ 00249 static void 00250 set_traceframe_num (int num) 00251 { 00252 traceframe_number = num; 00253 set_internalvar_integer (lookup_internalvar ("trace_frame"), num); 00254 } 00255 00256 /* Set tracepoint number to NUM. */ 00257 static void 00258 set_tracepoint_num (int num) 00259 { 00260 tracepoint_number = num; 00261 set_internalvar_integer (lookup_internalvar ("tracepoint"), num); 00262 } 00263 00264 /* Set externally visible debug variables for querying/printing 00265 the traceframe context (line, function, file). */ 00266 00267 static void 00268 set_traceframe_context (struct frame_info *trace_frame) 00269 { 00270 CORE_ADDR trace_pc; 00271 00272 /* Save as globals for internal use. */ 00273 if (trace_frame != NULL 00274 && get_frame_pc_if_available (trace_frame, &trace_pc)) 00275 { 00276 traceframe_sal = find_pc_line (trace_pc, 0); 00277 traceframe_fun = find_pc_function (trace_pc); 00278 00279 /* Save linenumber as "$trace_line", a debugger variable visible to 00280 users. */ 00281 set_internalvar_integer (lookup_internalvar ("trace_line"), 00282 traceframe_sal.line); 00283 } 00284 else 00285 { 00286 init_sal (&traceframe_sal); 00287 traceframe_fun = NULL; 00288 set_internalvar_integer (lookup_internalvar ("trace_line"), -1); 00289 } 00290 00291 /* Save func name as "$trace_func", a debugger variable visible to 00292 users. */ 00293 if (traceframe_fun == NULL 00294 || SYMBOL_LINKAGE_NAME (traceframe_fun) == NULL) 00295 clear_internalvar (lookup_internalvar ("trace_func")); 00296 else 00297 set_internalvar_string (lookup_internalvar ("trace_func"), 00298 SYMBOL_LINKAGE_NAME (traceframe_fun)); 00299 00300 /* Save file name as "$trace_file", a debugger variable visible to 00301 users. */ 00302 if (traceframe_sal.symtab == NULL) 00303 clear_internalvar (lookup_internalvar ("trace_file")); 00304 else 00305 set_internalvar_string (lookup_internalvar ("trace_file"), 00306 symtab_to_filename_for_display (traceframe_sal.symtab)); 00307 } 00308 00309 /* Create a new trace state variable with the given name. */ 00310 00311 struct trace_state_variable * 00312 create_trace_state_variable (const char *name) 00313 { 00314 struct trace_state_variable tsv; 00315 00316 memset (&tsv, 0, sizeof (tsv)); 00317 tsv.name = xstrdup (name); 00318 tsv.number = next_tsv_number++; 00319 return VEC_safe_push (tsv_s, tvariables, &tsv); 00320 } 00321 00322 /* Look for a trace state variable of the given name. */ 00323 00324 struct trace_state_variable * 00325 find_trace_state_variable (const char *name) 00326 { 00327 struct trace_state_variable *tsv; 00328 int ix; 00329 00330 for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) 00331 if (strcmp (name, tsv->name) == 0) 00332 return tsv; 00333 00334 return NULL; 00335 } 00336 00337 /* Look for a trace state variable of the given number. Return NULL if 00338 not found. */ 00339 00340 struct trace_state_variable * 00341 find_trace_state_variable_by_number (int number) 00342 { 00343 struct trace_state_variable *tsv; 00344 int ix; 00345 00346 for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) 00347 if (tsv->number == number) 00348 return tsv; 00349 00350 return NULL; 00351 } 00352 00353 static void 00354 delete_trace_state_variable (const char *name) 00355 { 00356 struct trace_state_variable *tsv; 00357 int ix; 00358 00359 for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) 00360 if (strcmp (name, tsv->name) == 0) 00361 { 00362 observer_notify_tsv_deleted (tsv); 00363 00364 xfree ((void *)tsv->name); 00365 VEC_unordered_remove (tsv_s, tvariables, ix); 00366 00367 return; 00368 } 00369 00370 warning (_("No trace variable named \"$%s\", not deleting"), name); 00371 } 00372 00373 /* Throws an error if NAME is not valid syntax for a trace state 00374 variable's name. */ 00375 00376 void 00377 validate_trace_state_variable_name (const char *name) 00378 { 00379 const char *p; 00380 00381 if (*name == '\0') 00382 error (_("Must supply a non-empty variable name")); 00383 00384 /* All digits in the name is reserved for value history 00385 references. */ 00386 for (p = name; isdigit (*p); p++) 00387 ; 00388 if (*p == '\0') 00389 error (_("$%s is not a valid trace state variable name"), name); 00390 00391 for (p = name; isalnum (*p) || *p == '_'; p++) 00392 ; 00393 if (*p != '\0') 00394 error (_("$%s is not a valid trace state variable name"), name); 00395 } 00396 00397 /* The 'tvariable' command collects a name and optional expression to 00398 evaluate into an initial value. */ 00399 00400 static void 00401 trace_variable_command (char *args, int from_tty) 00402 { 00403 struct cleanup *old_chain; 00404 LONGEST initval = 0; 00405 struct trace_state_variable *tsv; 00406 char *name, *p; 00407 00408 if (!args || !*args) 00409 error_no_arg (_("Syntax is $NAME [ = EXPR ]")); 00410 00411 /* Only allow two syntaxes; "$name" and "$name=value". */ 00412 p = skip_spaces (args); 00413 00414 if (*p++ != '$') 00415 error (_("Name of trace variable should start with '$'")); 00416 00417 name = p; 00418 while (isalnum (*p) || *p == '_') 00419 p++; 00420 name = savestring (name, p - name); 00421 old_chain = make_cleanup (xfree, name); 00422 00423 p = skip_spaces (p); 00424 if (*p != '=' && *p != '\0') 00425 error (_("Syntax must be $NAME [ = EXPR ]")); 00426 00427 validate_trace_state_variable_name (name); 00428 00429 if (*p == '=') 00430 initval = value_as_long (parse_and_eval (++p)); 00431 00432 /* If the variable already exists, just change its initial value. */ 00433 tsv = find_trace_state_variable (name); 00434 if (tsv) 00435 { 00436 if (tsv->initial_value != initval) 00437 { 00438 tsv->initial_value = initval; 00439 observer_notify_tsv_modified (tsv); 00440 } 00441 printf_filtered (_("Trace state variable $%s " 00442 "now has initial value %s.\n"), 00443 tsv->name, plongest (tsv->initial_value)); 00444 do_cleanups (old_chain); 00445 return; 00446 } 00447 00448 /* Create a new variable. */ 00449 tsv = create_trace_state_variable (name); 00450 tsv->initial_value = initval; 00451 00452 observer_notify_tsv_created (tsv); 00453 00454 printf_filtered (_("Trace state variable $%s " 00455 "created, with initial value %s.\n"), 00456 tsv->name, plongest (tsv->initial_value)); 00457 00458 do_cleanups (old_chain); 00459 } 00460 00461 static void 00462 delete_trace_variable_command (char *args, int from_tty) 00463 { 00464 int ix; 00465 char **argv; 00466 struct cleanup *back_to; 00467 00468 if (args == NULL) 00469 { 00470 if (query (_("Delete all trace state variables? "))) 00471 VEC_free (tsv_s, tvariables); 00472 dont_repeat (); 00473 observer_notify_tsv_deleted (NULL); 00474 return; 00475 } 00476 00477 argv = gdb_buildargv (args); 00478 back_to = make_cleanup_freeargv (argv); 00479 00480 for (ix = 0; argv[ix] != NULL; ix++) 00481 { 00482 if (*argv[ix] == '$') 00483 delete_trace_state_variable (argv[ix] + 1); 00484 else 00485 warning (_("Name \"%s\" not prefixed with '$', ignoring"), argv[ix]); 00486 } 00487 00488 do_cleanups (back_to); 00489 00490 dont_repeat (); 00491 } 00492 00493 void 00494 tvariables_info_1 (void) 00495 { 00496 struct trace_state_variable *tsv; 00497 int ix; 00498 int count = 0; 00499 struct cleanup *back_to; 00500 struct ui_out *uiout = current_uiout; 00501 00502 if (VEC_length (tsv_s, tvariables) == 0 && !ui_out_is_mi_like_p (uiout)) 00503 { 00504 printf_filtered (_("No trace state variables.\n")); 00505 return; 00506 } 00507 00508 /* Try to acquire values from the target. */ 00509 for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix, ++count) 00510 tsv->value_known = target_get_trace_state_variable_value (tsv->number, 00511 &(tsv->value)); 00512 00513 back_to = make_cleanup_ui_out_table_begin_end (uiout, 3, 00514 count, "trace-variables"); 00515 ui_out_table_header (uiout, 15, ui_left, "name", "Name"); 00516 ui_out_table_header (uiout, 11, ui_left, "initial", "Initial"); 00517 ui_out_table_header (uiout, 11, ui_left, "current", "Current"); 00518 00519 ui_out_table_body (uiout); 00520 00521 for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) 00522 { 00523 struct cleanup *back_to2; 00524 char *c; 00525 char *name; 00526 00527 back_to2 = make_cleanup_ui_out_tuple_begin_end (uiout, "variable"); 00528 00529 name = concat ("$", tsv->name, (char *) NULL); 00530 make_cleanup (xfree, name); 00531 ui_out_field_string (uiout, "name", name); 00532 ui_out_field_string (uiout, "initial", plongest (tsv->initial_value)); 00533 00534 if (tsv->value_known) 00535 c = plongest (tsv->value); 00536 else if (ui_out_is_mi_like_p (uiout)) 00537 /* For MI, we prefer not to use magic string constants, but rather 00538 omit the field completely. The difference between unknown and 00539 undefined does not seem important enough to represent. */ 00540 c = NULL; 00541 else if (current_trace_status ()->running || traceframe_number >= 0) 00542 /* The value is/was defined, but we don't have it. */ 00543 c = "<unknown>"; 00544 else 00545 /* It is not meaningful to ask about the value. */ 00546 c = "<undefined>"; 00547 if (c) 00548 ui_out_field_string (uiout, "current", c); 00549 ui_out_text (uiout, "\n"); 00550 00551 do_cleanups (back_to2); 00552 } 00553 00554 do_cleanups (back_to); 00555 } 00556 00557 /* List all the trace state variables. */ 00558 00559 static void 00560 tvariables_info (char *args, int from_tty) 00561 { 00562 tvariables_info_1 (); 00563 } 00564 00565 /* Stash definitions of tsvs into the given file. */ 00566 00567 void 00568 save_trace_state_variables (struct ui_file *fp) 00569 { 00570 struct trace_state_variable *tsv; 00571 int ix; 00572 00573 for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) 00574 { 00575 fprintf_unfiltered (fp, "tvariable $%s", tsv->name); 00576 if (tsv->initial_value) 00577 fprintf_unfiltered (fp, " = %s", plongest (tsv->initial_value)); 00578 fprintf_unfiltered (fp, "\n"); 00579 } 00580 } 00581 00582 /* ACTIONS functions: */ 00583 00584 /* The three functions: 00585 collect_pseudocommand, 00586 while_stepping_pseudocommand, and 00587 end_actions_pseudocommand 00588 are placeholders for "commands" that are actually ONLY to be used 00589 within a tracepoint action list. If the actual function is ever called, 00590 it means that somebody issued the "command" at the top level, 00591 which is always an error. */ 00592 00593 static void 00594 end_actions_pseudocommand (char *args, int from_tty) 00595 { 00596 error (_("This command cannot be used at the top level.")); 00597 } 00598 00599 static void 00600 while_stepping_pseudocommand (char *args, int from_tty) 00601 { 00602 error (_("This command can only be used in a tracepoint actions list.")); 00603 } 00604 00605 static void 00606 collect_pseudocommand (char *args, int from_tty) 00607 { 00608 error (_("This command can only be used in a tracepoint actions list.")); 00609 } 00610 00611 static void 00612 teval_pseudocommand (char *args, int from_tty) 00613 { 00614 error (_("This command can only be used in a tracepoint actions list.")); 00615 } 00616 00617 /* Parse any collection options, such as /s for strings. */ 00618 00619 const char * 00620 decode_agent_options (const char *exp, int *trace_string) 00621 { 00622 struct value_print_options opts; 00623 00624 *trace_string = 0; 00625 00626 if (*exp != '/') 00627 return exp; 00628 00629 /* Call this to borrow the print elements default for collection 00630 size. */ 00631 get_user_print_options (&opts); 00632 00633 exp++; 00634 if (*exp == 's') 00635 { 00636 if (target_supports_string_tracing ()) 00637 { 00638 /* Allow an optional decimal number giving an explicit maximum 00639 string length, defaulting it to the "print elements" value; 00640 so "collect/s80 mystr" gets at most 80 bytes of string. */ 00641 *trace_string = opts.print_max; 00642 exp++; 00643 if (*exp >= '0' && *exp <= '9') 00644 *trace_string = atoi (exp); 00645 while (*exp >= '0' && *exp <= '9') 00646 exp++; 00647 } 00648 else 00649 error (_("Target does not support \"/s\" option for string tracing.")); 00650 } 00651 else 00652 error (_("Undefined collection format \"%c\"."), *exp); 00653 00654 exp = skip_spaces_const (exp); 00655 00656 return exp; 00657 } 00658 00659 /* Enter a list of actions for a tracepoint. */ 00660 static void 00661 trace_actions_command (char *args, int from_tty) 00662 { 00663 struct tracepoint *t; 00664 struct command_line *l; 00665 00666 t = get_tracepoint_by_number (&args, NULL, 1); 00667 if (t) 00668 { 00669 char *tmpbuf = 00670 xstrprintf ("Enter actions for tracepoint %d, one per line.", 00671 t->base.number); 00672 struct cleanup *cleanups = make_cleanup (xfree, tmpbuf); 00673 00674 l = read_command_lines (tmpbuf, from_tty, 1, 00675 check_tracepoint_command, t); 00676 do_cleanups (cleanups); 00677 breakpoint_set_commands (&t->base, l); 00678 } 00679 /* else just return */ 00680 } 00681 00682 /* Report the results of checking the agent expression, as errors or 00683 internal errors. */ 00684 00685 static void 00686 report_agent_reqs_errors (struct agent_expr *aexpr) 00687 { 00688 /* All of the "flaws" are serious bytecode generation issues that 00689 should never occur. */ 00690 if (aexpr->flaw != agent_flaw_none) 00691 internal_error (__FILE__, __LINE__, _("expression is malformed")); 00692 00693 /* If analysis shows a stack underflow, GDB must have done something 00694 badly wrong in its bytecode generation. */ 00695 if (aexpr->min_height < 0) 00696 internal_error (__FILE__, __LINE__, 00697 _("expression has min height < 0")); 00698 00699 /* Issue this error if the stack is predicted to get too deep. The 00700 limit is rather arbitrary; a better scheme might be for the 00701 target to report how much stack it will have available. The 00702 depth roughly corresponds to parenthesization, so a limit of 20 00703 amounts to 20 levels of expression nesting, which is actually 00704 a pretty big hairy expression. */ 00705 if (aexpr->max_height > 20) 00706 error (_("Expression is too complicated.")); 00707 } 00708 00709 /* worker function */ 00710 void 00711 validate_actionline (const char *line, struct breakpoint *b) 00712 { 00713 struct cmd_list_element *c; 00714 struct expression *exp = NULL; 00715 struct cleanup *old_chain = NULL; 00716 const char *tmp_p; 00717 const char *p; 00718 struct bp_location *loc; 00719 struct agent_expr *aexpr; 00720 struct tracepoint *t = (struct tracepoint *) b; 00721 00722 /* If EOF is typed, *line is NULL. */ 00723 if (line == NULL) 00724 return; 00725 00726 p = skip_spaces_const (line); 00727 00728 /* Symbol lookup etc. */ 00729 if (*p == '\0') /* empty line: just prompt for another line. */ 00730 return; 00731 00732 if (*p == '#') /* comment line */ 00733 return; 00734 00735 c = lookup_cmd (&p, cmdlist, "", -1, 1); 00736 if (c == 0) 00737 error (_("`%s' is not a tracepoint action, or is ambiguous."), p); 00738 00739 if (cmd_cfunc_eq (c, collect_pseudocommand)) 00740 { 00741 int trace_string = 0; 00742 00743 if (*p == '/') 00744 p = decode_agent_options (p, &trace_string); 00745 00746 do 00747 { /* Repeat over a comma-separated list. */ 00748 QUIT; /* Allow user to bail out with ^C. */ 00749 p = skip_spaces_const (p); 00750 00751 if (*p == '$') /* Look for special pseudo-symbols. */ 00752 { 00753 if (0 == strncasecmp ("reg", p + 1, 3) 00754 || 0 == strncasecmp ("arg", p + 1, 3) 00755 || 0 == strncasecmp ("loc", p + 1, 3) 00756 || 0 == strncasecmp ("_ret", p + 1, 4) 00757 || 0 == strncasecmp ("_sdata", p + 1, 6)) 00758 { 00759 p = strchr (p, ','); 00760 continue; 00761 } 00762 /* else fall thru, treat p as an expression and parse it! */ 00763 } 00764 tmp_p = p; 00765 for (loc = t->base.loc; loc; loc = loc->next) 00766 { 00767 p = tmp_p; 00768 exp = parse_exp_1 (&p, loc->address, 00769 block_for_pc (loc->address), 1); 00770 old_chain = make_cleanup (free_current_contents, &exp); 00771 00772 if (exp->elts[0].opcode == OP_VAR_VALUE) 00773 { 00774 if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST) 00775 { 00776 error (_("constant `%s' (value %s) " 00777 "will not be collected."), 00778 SYMBOL_PRINT_NAME (exp->elts[2].symbol), 00779 plongest (SYMBOL_VALUE (exp->elts[2].symbol))); 00780 } 00781 else if (SYMBOL_CLASS (exp->elts[2].symbol) 00782 == LOC_OPTIMIZED_OUT) 00783 { 00784 error (_("`%s' is optimized away " 00785 "and cannot be collected."), 00786 SYMBOL_PRINT_NAME (exp->elts[2].symbol)); 00787 } 00788 } 00789 00790 /* We have something to collect, make sure that the expr to 00791 bytecode translator can handle it and that it's not too 00792 long. */ 00793 aexpr = gen_trace_for_expr (loc->address, exp, trace_string); 00794 make_cleanup_free_agent_expr (aexpr); 00795 00796 if (aexpr->len > MAX_AGENT_EXPR_LEN) 00797 error (_("Expression is too complicated.")); 00798 00799 ax_reqs (aexpr); 00800 00801 report_agent_reqs_errors (aexpr); 00802 00803 do_cleanups (old_chain); 00804 } 00805 } 00806 while (p && *p++ == ','); 00807 } 00808 00809 else if (cmd_cfunc_eq (c, teval_pseudocommand)) 00810 { 00811 do 00812 { /* Repeat over a comma-separated list. */ 00813 QUIT; /* Allow user to bail out with ^C. */ 00814 p = skip_spaces_const (p); 00815 00816 tmp_p = p; 00817 for (loc = t->base.loc; loc; loc = loc->next) 00818 { 00819 p = tmp_p; 00820 00821 /* Only expressions are allowed for this action. */ 00822 exp = parse_exp_1 (&p, loc->address, 00823 block_for_pc (loc->address), 1); 00824 old_chain = make_cleanup (free_current_contents, &exp); 00825 00826 /* We have something to evaluate, make sure that the expr to 00827 bytecode translator can handle it and that it's not too 00828 long. */ 00829 aexpr = gen_eval_for_expr (loc->address, exp); 00830 make_cleanup_free_agent_expr (aexpr); 00831 00832 if (aexpr->len > MAX_AGENT_EXPR_LEN) 00833 error (_("Expression is too complicated.")); 00834 00835 ax_reqs (aexpr); 00836 report_agent_reqs_errors (aexpr); 00837 00838 do_cleanups (old_chain); 00839 } 00840 } 00841 while (p && *p++ == ','); 00842 } 00843 00844 else if (cmd_cfunc_eq (c, while_stepping_pseudocommand)) 00845 { 00846 char *endp; 00847 00848 p = skip_spaces_const (p); 00849 t->step_count = strtol (p, &endp, 0); 00850 if (endp == p || t->step_count == 0) 00851 error (_("while-stepping step count `%s' is malformed."), line); 00852 p = endp; 00853 } 00854 00855 else if (cmd_cfunc_eq (c, end_actions_pseudocommand)) 00856 ; 00857 00858 else 00859 error (_("`%s' is not a supported tracepoint action."), line); 00860 } 00861 00862 enum { 00863 memrange_absolute = -1 00864 }; 00865 00866 /* MEMRANGE functions: */ 00867 00868 static int memrange_cmp (const void *, const void *); 00869 00870 /* Compare memranges for qsort. */ 00871 static int 00872 memrange_cmp (const void *va, const void *vb) 00873 { 00874 const struct memrange *a = va, *b = vb; 00875 00876 if (a->type < b->type) 00877 return -1; 00878 if (a->type > b->type) 00879 return 1; 00880 if (a->type == memrange_absolute) 00881 { 00882 if ((bfd_vma) a->start < (bfd_vma) b->start) 00883 return -1; 00884 if ((bfd_vma) a->start > (bfd_vma) b->start) 00885 return 1; 00886 } 00887 else 00888 { 00889 if (a->start < b->start) 00890 return -1; 00891 if (a->start > b->start) 00892 return 1; 00893 } 00894 return 0; 00895 } 00896 00897 /* Sort the memrange list using qsort, and merge adjacent memranges. */ 00898 static void 00899 memrange_sortmerge (struct collection_list *memranges) 00900 { 00901 int a, b; 00902 00903 qsort (memranges->list, memranges->next_memrange, 00904 sizeof (struct memrange), memrange_cmp); 00905 if (memranges->next_memrange > 0) 00906 { 00907 for (a = 0, b = 1; b < memranges->next_memrange; b++) 00908 { 00909 /* If memrange b overlaps or is adjacent to memrange a, 00910 merge them. */ 00911 if (memranges->list[a].type == memranges->list[b].type 00912 && memranges->list[b].start <= memranges->list[a].end) 00913 { 00914 if (memranges->list[b].end > memranges->list[a].end) 00915 memranges->list[a].end = memranges->list[b].end; 00916 continue; /* next b, same a */ 00917 } 00918 a++; /* next a */ 00919 if (a != b) 00920 memcpy (&memranges->list[a], &memranges->list[b], 00921 sizeof (struct memrange)); 00922 } 00923 memranges->next_memrange = a + 1; 00924 } 00925 } 00926 00927 /* Add a register to a collection list. */ 00928 static void 00929 add_register (struct collection_list *collection, unsigned int regno) 00930 { 00931 if (info_verbose) 00932 printf_filtered ("collect register %d\n", regno); 00933 if (regno >= (8 * sizeof (collection->regs_mask))) 00934 error (_("Internal: register number %d too large for tracepoint"), 00935 regno); 00936 collection->regs_mask[regno / 8] |= 1 << (regno % 8); 00937 } 00938 00939 /* Add a memrange to a collection list. */ 00940 static void 00941 add_memrange (struct collection_list *memranges, 00942 int type, bfd_signed_vma base, 00943 unsigned long len) 00944 { 00945 if (info_verbose) 00946 { 00947 printf_filtered ("(%d,", type); 00948 printf_vma (base); 00949 printf_filtered (",%ld)\n", len); 00950 } 00951 00952 /* type: memrange_absolute == memory, other n == basereg */ 00953 memranges->list[memranges->next_memrange].type = type; 00954 /* base: addr if memory, offset if reg relative. */ 00955 memranges->list[memranges->next_memrange].start = base; 00956 /* len: we actually save end (base + len) for convenience */ 00957 memranges->list[memranges->next_memrange].end = base + len; 00958 memranges->next_memrange++; 00959 if (memranges->next_memrange >= memranges->listsize) 00960 { 00961 memranges->listsize *= 2; 00962 memranges->list = xrealloc (memranges->list, 00963 memranges->listsize); 00964 } 00965 00966 if (type != memrange_absolute) /* Better collect the base register! */ 00967 add_register (memranges, type); 00968 } 00969 00970 /* Add a symbol to a collection list. */ 00971 static void 00972 collect_symbol (struct collection_list *collect, 00973 struct symbol *sym, 00974 struct gdbarch *gdbarch, 00975 long frame_regno, long frame_offset, 00976 CORE_ADDR scope, 00977 int trace_string) 00978 { 00979 unsigned long len; 00980 unsigned int reg; 00981 bfd_signed_vma offset; 00982 int treat_as_expr = 0; 00983 00984 len = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))); 00985 switch (SYMBOL_CLASS (sym)) 00986 { 00987 default: 00988 printf_filtered ("%s: don't know symbol class %d\n", 00989 SYMBOL_PRINT_NAME (sym), 00990 SYMBOL_CLASS (sym)); 00991 break; 00992 case LOC_CONST: 00993 printf_filtered ("constant %s (value %s) will not be collected.\n", 00994 SYMBOL_PRINT_NAME (sym), plongest (SYMBOL_VALUE (sym))); 00995 break; 00996 case LOC_STATIC: 00997 offset = SYMBOL_VALUE_ADDRESS (sym); 00998 if (info_verbose) 00999 { 01000 char tmp[40]; 01001 01002 sprintf_vma (tmp, offset); 01003 printf_filtered ("LOC_STATIC %s: collect %ld bytes at %s.\n", 01004 SYMBOL_PRINT_NAME (sym), len, 01005 tmp /* address */); 01006 } 01007 /* A struct may be a C++ class with static fields, go to general 01008 expression handling. */ 01009 if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT) 01010 treat_as_expr = 1; 01011 else 01012 add_memrange (collect, memrange_absolute, offset, len); 01013 break; 01014 case LOC_REGISTER: 01015 reg = SYMBOL_REGISTER_OPS (sym)->register_number (sym, gdbarch); 01016 if (info_verbose) 01017 printf_filtered ("LOC_REG[parm] %s: ", 01018 SYMBOL_PRINT_NAME (sym)); 01019 add_register (collect, reg); 01020 /* Check for doubles stored in two registers. */ 01021 /* FIXME: how about larger types stored in 3 or more regs? */ 01022 if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT && 01023 len > register_size (gdbarch, reg)) 01024 add_register (collect, reg + 1); 01025 break; 01026 case LOC_REF_ARG: 01027 printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n"); 01028 printf_filtered (" (will not collect %s)\n", 01029 SYMBOL_PRINT_NAME (sym)); 01030 break; 01031 case LOC_ARG: 01032 reg = frame_regno; 01033 offset = frame_offset + SYMBOL_VALUE (sym); 01034 if (info_verbose) 01035 { 01036 printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset ", 01037 SYMBOL_PRINT_NAME (sym), len); 01038 printf_vma (offset); 01039 printf_filtered (" from frame ptr reg %d\n", reg); 01040 } 01041 add_memrange (collect, reg, offset, len); 01042 break; 01043 case LOC_REGPARM_ADDR: 01044 reg = SYMBOL_VALUE (sym); 01045 offset = 0; 01046 if (info_verbose) 01047 { 01048 printf_filtered ("LOC_REGPARM_ADDR %s: Collect %ld bytes at offset ", 01049 SYMBOL_PRINT_NAME (sym), len); 01050 printf_vma (offset); 01051 printf_filtered (" from reg %d\n", reg); 01052 } 01053 add_memrange (collect, reg, offset, len); 01054 break; 01055 case LOC_LOCAL: 01056 reg = frame_regno; 01057 offset = frame_offset + SYMBOL_VALUE (sym); 01058 if (info_verbose) 01059 { 01060 printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset ", 01061 SYMBOL_PRINT_NAME (sym), len); 01062 printf_vma (offset); 01063 printf_filtered (" from frame ptr reg %d\n", reg); 01064 } 01065 add_memrange (collect, reg, offset, len); 01066 break; 01067 01068 case LOC_UNRESOLVED: 01069 treat_as_expr = 1; 01070 break; 01071 01072 case LOC_OPTIMIZED_OUT: 01073 printf_filtered ("%s has been optimized out of existence.\n", 01074 SYMBOL_PRINT_NAME (sym)); 01075 break; 01076 01077 case LOC_COMPUTED: 01078 treat_as_expr = 1; 01079 break; 01080 } 01081 01082 /* Expressions are the most general case. */ 01083 if (treat_as_expr) 01084 { 01085 struct agent_expr *aexpr; 01086 struct cleanup *old_chain1 = NULL; 01087 01088 aexpr = gen_trace_for_var (scope, gdbarch, sym, trace_string); 01089 01090 /* It can happen that the symbol is recorded as a computed 01091 location, but it's been optimized away and doesn't actually 01092 have a location expression. */ 01093 if (!aexpr) 01094 { 01095 printf_filtered ("%s has been optimized out of existence.\n", 01096 SYMBOL_PRINT_NAME (sym)); 01097 return; 01098 } 01099 01100 old_chain1 = make_cleanup_free_agent_expr (aexpr); 01101 01102 ax_reqs (aexpr); 01103 01104 report_agent_reqs_errors (aexpr); 01105 01106 discard_cleanups (old_chain1); 01107 add_aexpr (collect, aexpr); 01108 01109 /* Take care of the registers. */ 01110 if (aexpr->reg_mask_len > 0) 01111 { 01112 int ndx1, ndx2; 01113 01114 for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++) 01115 { 01116 QUIT; /* Allow user to bail out with ^C. */ 01117 if (aexpr->reg_mask[ndx1] != 0) 01118 { 01119 /* Assume chars have 8 bits. */ 01120 for (ndx2 = 0; ndx2 < 8; ndx2++) 01121 if (aexpr->reg_mask[ndx1] & (1 << ndx2)) 01122 /* It's used -- record it. */ 01123 add_register (collect, ndx1 * 8 + ndx2); 01124 } 01125 } 01126 } 01127 } 01128 } 01129 01130 /* Data to be passed around in the calls to the locals and args 01131 iterators. */ 01132 01133 struct add_local_symbols_data 01134 { 01135 struct collection_list *collect; 01136 struct gdbarch *gdbarch; 01137 CORE_ADDR pc; 01138 long frame_regno; 01139 long frame_offset; 01140 int count; 01141 int trace_string; 01142 }; 01143 01144 /* The callback for the locals and args iterators. */ 01145 01146 static void 01147 do_collect_symbol (const char *print_name, 01148 struct symbol *sym, 01149 void *cb_data) 01150 { 01151 struct add_local_symbols_data *p = cb_data; 01152 01153 collect_symbol (p->collect, sym, p->gdbarch, p->frame_regno, 01154 p->frame_offset, p->pc, p->trace_string); 01155 p->count++; 01156 01157 VEC_safe_push (char_ptr, p->collect->wholly_collected, 01158 xstrdup (print_name)); 01159 } 01160 01161 /* Add all locals (or args) symbols to collection list. */ 01162 static void 01163 add_local_symbols (struct collection_list *collect, 01164 struct gdbarch *gdbarch, CORE_ADDR pc, 01165 long frame_regno, long frame_offset, int type, 01166 int trace_string) 01167 { 01168 struct block *block; 01169 struct add_local_symbols_data cb_data; 01170 01171 cb_data.collect = collect; 01172 cb_data.gdbarch = gdbarch; 01173 cb_data.pc = pc; 01174 cb_data.frame_regno = frame_regno; 01175 cb_data.frame_offset = frame_offset; 01176 cb_data.count = 0; 01177 cb_data.trace_string = trace_string; 01178 01179 if (type == 'L') 01180 { 01181 block = block_for_pc (pc); 01182 if (block == NULL) 01183 { 01184 warning (_("Can't collect locals; " 01185 "no symbol table info available.\n")); 01186 return; 01187 } 01188 01189 iterate_over_block_local_vars (block, do_collect_symbol, &cb_data); 01190 if (cb_data.count == 0) 01191 warning (_("No locals found in scope.")); 01192 } 01193 else 01194 { 01195 pc = get_pc_function_start (pc); 01196 block = block_for_pc (pc); 01197 if (block == NULL) 01198 { 01199 warning (_("Can't collect args; no symbol table info available.")); 01200 return; 01201 } 01202 01203 iterate_over_block_arg_vars (block, do_collect_symbol, &cb_data); 01204 if (cb_data.count == 0) 01205 warning (_("No args found in scope.")); 01206 } 01207 } 01208 01209 static void 01210 add_static_trace_data (struct collection_list *collection) 01211 { 01212 if (info_verbose) 01213 printf_filtered ("collect static trace data\n"); 01214 collection->strace_data = 1; 01215 } 01216 01217 /* worker function */ 01218 static void 01219 clear_collection_list (struct collection_list *list) 01220 { 01221 int ndx; 01222 01223 list->next_memrange = 0; 01224 for (ndx = 0; ndx < list->next_aexpr_elt; ndx++) 01225 { 01226 free_agent_expr (list->aexpr_list[ndx]); 01227 list->aexpr_list[ndx] = NULL; 01228 } 01229 list->next_aexpr_elt = 0; 01230 memset (list->regs_mask, 0, sizeof (list->regs_mask)); 01231 list->strace_data = 0; 01232 01233 xfree (list->aexpr_list); 01234 xfree (list->list); 01235 01236 VEC_free (char_ptr, list->wholly_collected); 01237 VEC_free (char_ptr, list->computed); 01238 } 01239 01240 /* A cleanup wrapper for function clear_collection_list. */ 01241 01242 static void 01243 do_clear_collection_list (void *list) 01244 { 01245 struct collection_list *l = list; 01246 01247 clear_collection_list (l); 01248 } 01249 01250 /* Initialize collection_list CLIST. */ 01251 01252 static void 01253 init_collection_list (struct collection_list *clist) 01254 { 01255 memset (clist, 0, sizeof *clist); 01256 01257 clist->listsize = 128; 01258 clist->list = xcalloc (clist->listsize, 01259 sizeof (struct memrange)); 01260 01261 clist->aexpr_listsize = 128; 01262 clist->aexpr_list = xcalloc (clist->aexpr_listsize, 01263 sizeof (struct agent_expr *)); 01264 } 01265 01266 /* Reduce a collection list to string form (for gdb protocol). */ 01267 static char ** 01268 stringify_collection_list (struct collection_list *list) 01269 { 01270 char temp_buf[2048]; 01271 char tmp2[40]; 01272 int count; 01273 int ndx = 0; 01274 char *(*str_list)[]; 01275 char *end; 01276 long i; 01277 01278 count = 1 + 1 + list->next_memrange + list->next_aexpr_elt + 1; 01279 str_list = (char *(*)[]) xmalloc (count * sizeof (char *)); 01280 01281 if (list->strace_data) 01282 { 01283 if (info_verbose) 01284 printf_filtered ("\nCollecting static trace data\n"); 01285 end = temp_buf; 01286 *end++ = 'L'; 01287 (*str_list)[ndx] = savestring (temp_buf, end - temp_buf); 01288 ndx++; 01289 } 01290 01291 for (i = sizeof (list->regs_mask) - 1; i > 0; i--) 01292 if (list->regs_mask[i] != 0) /* Skip leading zeroes in regs_mask. */ 01293 break; 01294 if (list->regs_mask[i] != 0) /* Prepare to send regs_mask to the stub. */ 01295 { 01296 if (info_verbose) 01297 printf_filtered ("\nCollecting registers (mask): 0x"); 01298 end = temp_buf; 01299 *end++ = 'R'; 01300 for (; i >= 0; i--) 01301 { 01302 QUIT; /* Allow user to bail out with ^C. */ 01303 if (info_verbose) 01304 printf_filtered ("%02X", list->regs_mask[i]); 01305 sprintf (end, "%02X", list->regs_mask[i]); 01306 end += 2; 01307 } 01308 (*str_list)[ndx] = xstrdup (temp_buf); 01309 ndx++; 01310 } 01311 if (info_verbose) 01312 printf_filtered ("\n"); 01313 if (list->next_memrange > 0 && info_verbose) 01314 printf_filtered ("Collecting memranges: \n"); 01315 for (i = 0, count = 0, end = temp_buf; i < list->next_memrange; i++) 01316 { 01317 QUIT; /* Allow user to bail out with ^C. */ 01318 sprintf_vma (tmp2, list->list[i].start); 01319 if (info_verbose) 01320 { 01321 printf_filtered ("(%d, %s, %ld)\n", 01322 list->list[i].type, 01323 tmp2, 01324 (long) (list->list[i].end - list->list[i].start)); 01325 } 01326 if (count + 27 > MAX_AGENT_EXPR_LEN) 01327 { 01328 (*str_list)[ndx] = savestring (temp_buf, count); 01329 ndx++; 01330 count = 0; 01331 end = temp_buf; 01332 } 01333 01334 { 01335 bfd_signed_vma length = list->list[i].end - list->list[i].start; 01336 01337 /* The "%X" conversion specifier expects an unsigned argument, 01338 so passing -1 (memrange_absolute) to it directly gives you 01339 "FFFFFFFF" (or more, depending on sizeof (unsigned)). 01340 Special-case it. */ 01341 if (list->list[i].type == memrange_absolute) 01342 sprintf (end, "M-1,%s,%lX", tmp2, (long) length); 01343 else 01344 sprintf (end, "M%X,%s,%lX", list->list[i].type, tmp2, (long) length); 01345 } 01346 01347 count += strlen (end); 01348 end = temp_buf + count; 01349 } 01350 01351 for (i = 0; i < list->next_aexpr_elt; i++) 01352 { 01353 QUIT; /* Allow user to bail out with ^C. */ 01354 if ((count + 10 + 2 * list->aexpr_list[i]->len) > MAX_AGENT_EXPR_LEN) 01355 { 01356 (*str_list)[ndx] = savestring (temp_buf, count); 01357 ndx++; 01358 count = 0; 01359 end = temp_buf; 01360 } 01361 sprintf (end, "X%08X,", list->aexpr_list[i]->len); 01362 end += 10; /* 'X' + 8 hex digits + ',' */ 01363 count += 10; 01364 01365 end = mem2hex (list->aexpr_list[i]->buf, 01366 end, list->aexpr_list[i]->len); 01367 count += 2 * list->aexpr_list[i]->len; 01368 } 01369 01370 if (count != 0) 01371 { 01372 (*str_list)[ndx] = savestring (temp_buf, count); 01373 ndx++; 01374 count = 0; 01375 end = temp_buf; 01376 } 01377 (*str_list)[ndx] = NULL; 01378 01379 if (ndx == 0) 01380 { 01381 xfree (str_list); 01382 return NULL; 01383 } 01384 else 01385 return *str_list; 01386 } 01387 01388 /* Add the printed expression EXP to *LIST. */ 01389 01390 static void 01391 append_exp (struct expression *exp, VEC(char_ptr) **list) 01392 { 01393 struct ui_file *tmp_stream = mem_fileopen (); 01394 char *text; 01395 01396 print_expression (exp, tmp_stream); 01397 01398 text = ui_file_xstrdup (tmp_stream, NULL); 01399 01400 VEC_safe_push (char_ptr, *list, text); 01401 ui_file_delete (tmp_stream); 01402 } 01403 01404 static void 01405 encode_actions_1 (struct command_line *action, 01406 struct bp_location *tloc, 01407 int frame_reg, 01408 LONGEST frame_offset, 01409 struct collection_list *collect, 01410 struct collection_list *stepping_list) 01411 { 01412 const char *action_exp; 01413 struct expression *exp = NULL; 01414 int i; 01415 struct value *tempval; 01416 struct cmd_list_element *cmd; 01417 struct agent_expr *aexpr; 01418 01419 for (; action; action = action->next) 01420 { 01421 QUIT; /* Allow user to bail out with ^C. */ 01422 action_exp = action->line; 01423 action_exp = skip_spaces_const (action_exp); 01424 01425 cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1); 01426 if (cmd == 0) 01427 error (_("Bad action list item: %s"), action_exp); 01428 01429 if (cmd_cfunc_eq (cmd, collect_pseudocommand)) 01430 { 01431 int trace_string = 0; 01432 01433 if (*action_exp == '/') 01434 action_exp = decode_agent_options (action_exp, &trace_string); 01435 01436 do 01437 { /* Repeat over a comma-separated list. */ 01438 QUIT; /* Allow user to bail out with ^C. */ 01439 action_exp = skip_spaces_const (action_exp); 01440 01441 if (0 == strncasecmp ("$reg", action_exp, 4)) 01442 { 01443 for (i = 0; i < gdbarch_num_regs (tloc->gdbarch); i++) 01444 add_register (collect, i); 01445 action_exp = strchr (action_exp, ','); /* more? */ 01446 } 01447 else if (0 == strncasecmp ("$arg", action_exp, 4)) 01448 { 01449 add_local_symbols (collect, 01450 tloc->gdbarch, 01451 tloc->address, 01452 frame_reg, 01453 frame_offset, 01454 'A', 01455 trace_string); 01456 action_exp = strchr (action_exp, ','); /* more? */ 01457 } 01458 else if (0 == strncasecmp ("$loc", action_exp, 4)) 01459 { 01460 add_local_symbols (collect, 01461 tloc->gdbarch, 01462 tloc->address, 01463 frame_reg, 01464 frame_offset, 01465 'L', 01466 trace_string); 01467 action_exp = strchr (action_exp, ','); /* more? */ 01468 } 01469 else if (0 == strncasecmp ("$_ret", action_exp, 5)) 01470 { 01471 struct cleanup *old_chain1 = NULL; 01472 01473 aexpr = gen_trace_for_return_address (tloc->address, 01474 tloc->gdbarch, 01475 trace_string); 01476 01477 old_chain1 = make_cleanup_free_agent_expr (aexpr); 01478 01479 ax_reqs (aexpr); 01480 report_agent_reqs_errors (aexpr); 01481 01482 discard_cleanups (old_chain1); 01483 add_aexpr (collect, aexpr); 01484 01485 /* take care of the registers */ 01486 if (aexpr->reg_mask_len > 0) 01487 { 01488 int ndx1, ndx2; 01489 01490 for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++) 01491 { 01492 QUIT; /* allow user to bail out with ^C */ 01493 if (aexpr->reg_mask[ndx1] != 0) 01494 { 01495 /* assume chars have 8 bits */ 01496 for (ndx2 = 0; ndx2 < 8; ndx2++) 01497 if (aexpr->reg_mask[ndx1] & (1 << ndx2)) 01498 /* it's used -- record it */ 01499 add_register (collect, 01500 ndx1 * 8 + ndx2); 01501 } 01502 } 01503 } 01504 01505 action_exp = strchr (action_exp, ','); /* more? */ 01506 } 01507 else if (0 == strncasecmp ("$_sdata", action_exp, 7)) 01508 { 01509 add_static_trace_data (collect); 01510 action_exp = strchr (action_exp, ','); /* more? */ 01511 } 01512 else 01513 { 01514 unsigned long addr; 01515 struct cleanup *old_chain = NULL; 01516 struct cleanup *old_chain1 = NULL; 01517 01518 exp = parse_exp_1 (&action_exp, tloc->address, 01519 block_for_pc (tloc->address), 1); 01520 old_chain = make_cleanup (free_current_contents, &exp); 01521 01522 switch (exp->elts[0].opcode) 01523 { 01524 case OP_REGISTER: 01525 { 01526 const char *name = &exp->elts[2].string; 01527 01528 i = user_reg_map_name_to_regnum (tloc->gdbarch, 01529 name, strlen (name)); 01530 if (i == -1) 01531 internal_error (__FILE__, __LINE__, 01532 _("Register $%s not available"), 01533 name); 01534 if (info_verbose) 01535 printf_filtered ("OP_REGISTER: "); 01536 add_register (collect, i); 01537 break; 01538 } 01539 01540 case UNOP_MEMVAL: 01541 /* Safe because we know it's a simple expression. */ 01542 tempval = evaluate_expression (exp); 01543 addr = value_address (tempval); 01544 /* Initialize the TYPE_LENGTH if it is a typedef. */ 01545 check_typedef (exp->elts[1].type); 01546 add_memrange (collect, memrange_absolute, addr, 01547 TYPE_LENGTH (exp->elts[1].type)); 01548 append_exp (exp, &collect->computed); 01549 break; 01550 01551 case OP_VAR_VALUE: 01552 { 01553 struct symbol *sym = exp->elts[2].symbol; 01554 char_ptr name = (char_ptr) SYMBOL_NATURAL_NAME (sym); 01555 01556 collect_symbol (collect, 01557 exp->elts[2].symbol, 01558 tloc->gdbarch, 01559 frame_reg, 01560 frame_offset, 01561 tloc->address, 01562 trace_string); 01563 VEC_safe_push (char_ptr, 01564 collect->wholly_collected, 01565 name); 01566 } 01567 break; 01568 01569 default: /* Full-fledged expression. */ 01570 aexpr = gen_trace_for_expr (tloc->address, exp, 01571 trace_string); 01572 01573 old_chain1 = make_cleanup_free_agent_expr (aexpr); 01574 01575 ax_reqs (aexpr); 01576 01577 report_agent_reqs_errors (aexpr); 01578 01579 discard_cleanups (old_chain1); 01580 add_aexpr (collect, aexpr); 01581 01582 /* Take care of the registers. */ 01583 if (aexpr->reg_mask_len > 0) 01584 { 01585 int ndx1; 01586 int ndx2; 01587 01588 for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++) 01589 { 01590 QUIT; /* Allow user to bail out with ^C. */ 01591 if (aexpr->reg_mask[ndx1] != 0) 01592 { 01593 /* Assume chars have 8 bits. */ 01594 for (ndx2 = 0; ndx2 < 8; ndx2++) 01595 if (aexpr->reg_mask[ndx1] & (1 << ndx2)) 01596 /* It's used -- record it. */ 01597 add_register (collect, 01598 ndx1 * 8 + ndx2); 01599 } 01600 } 01601 } 01602 01603 append_exp (exp, &collect->computed); 01604 break; 01605 } /* switch */ 01606 do_cleanups (old_chain); 01607 } /* do */ 01608 } 01609 while (action_exp && *action_exp++ == ','); 01610 } /* if */ 01611 else if (cmd_cfunc_eq (cmd, teval_pseudocommand)) 01612 { 01613 do 01614 { /* Repeat over a comma-separated list. */ 01615 QUIT; /* Allow user to bail out with ^C. */ 01616 action_exp = skip_spaces_const (action_exp); 01617 01618 { 01619 struct cleanup *old_chain = NULL; 01620 struct cleanup *old_chain1 = NULL; 01621 01622 exp = parse_exp_1 (&action_exp, tloc->address, 01623 block_for_pc (tloc->address), 1); 01624 old_chain = make_cleanup (free_current_contents, &exp); 01625 01626 aexpr = gen_eval_for_expr (tloc->address, exp); 01627 old_chain1 = make_cleanup_free_agent_expr (aexpr); 01628 01629 ax_reqs (aexpr); 01630 report_agent_reqs_errors (aexpr); 01631 01632 discard_cleanups (old_chain1); 01633 /* Even though we're not officially collecting, add 01634 to the collect list anyway. */ 01635 add_aexpr (collect, aexpr); 01636 01637 do_cleanups (old_chain); 01638 } /* do */ 01639 } 01640 while (action_exp && *action_exp++ == ','); 01641 } /* if */ 01642 else if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand)) 01643 { 01644 /* We check against nested while-stepping when setting 01645 breakpoint action, so no way to run into nested 01646 here. */ 01647 gdb_assert (stepping_list); 01648 01649 encode_actions_1 (action->body_list[0], tloc, frame_reg, 01650 frame_offset, stepping_list, NULL); 01651 } 01652 else 01653 error (_("Invalid tracepoint command '%s'"), action->line); 01654 } /* for */ 01655 } 01656 01657 /* Encode actions of tracepoint TLOC->owner and fill TRACEPOINT_LIST 01658 and STEPPING_LIST. Return a cleanup pointer to clean up both 01659 TRACEPOINT_LIST and STEPPING_LIST. */ 01660 01661 struct cleanup * 01662 encode_actions_and_make_cleanup (struct bp_location *tloc, 01663 struct collection_list *tracepoint_list, 01664 struct collection_list *stepping_list) 01665 { 01666 char *default_collect_line = NULL; 01667 struct command_line *actions; 01668 struct command_line *default_collect_action = NULL; 01669 int frame_reg; 01670 LONGEST frame_offset; 01671 struct cleanup *back_to, *return_chain; 01672 01673 return_chain = make_cleanup (null_cleanup, NULL); 01674 init_collection_list (tracepoint_list); 01675 init_collection_list (stepping_list); 01676 01677 make_cleanup (do_clear_collection_list, tracepoint_list); 01678 make_cleanup (do_clear_collection_list, stepping_list); 01679 01680 back_to = make_cleanup (null_cleanup, NULL); 01681 gdbarch_virtual_frame_pointer (tloc->gdbarch, 01682 tloc->address, &frame_reg, &frame_offset); 01683 01684 actions = all_tracepoint_actions_and_cleanup (tloc->owner); 01685 01686 encode_actions_1 (actions, tloc, frame_reg, frame_offset, 01687 tracepoint_list, stepping_list); 01688 01689 memrange_sortmerge (tracepoint_list); 01690 memrange_sortmerge (stepping_list); 01691 01692 do_cleanups (back_to); 01693 return return_chain; 01694 } 01695 01696 /* Render all actions into gdb protocol. */ 01697 01698 void 01699 encode_actions_rsp (struct bp_location *tloc, char ***tdp_actions, 01700 char ***stepping_actions) 01701 { 01702 struct collection_list tracepoint_list, stepping_list; 01703 struct cleanup *cleanup; 01704 01705 *tdp_actions = NULL; 01706 *stepping_actions = NULL; 01707 01708 cleanup = encode_actions_and_make_cleanup (tloc, &tracepoint_list, 01709 &stepping_list); 01710 01711 *tdp_actions = stringify_collection_list (&tracepoint_list); 01712 *stepping_actions = stringify_collection_list (&stepping_list); 01713 01714 do_cleanups (cleanup); 01715 } 01716 01717 static void 01718 add_aexpr (struct collection_list *collect, struct agent_expr *aexpr) 01719 { 01720 if (collect->next_aexpr_elt >= collect->aexpr_listsize) 01721 { 01722 collect->aexpr_list = 01723 xrealloc (collect->aexpr_list, 01724 2 * collect->aexpr_listsize * sizeof (struct agent_expr *)); 01725 collect->aexpr_listsize *= 2; 01726 } 01727 collect->aexpr_list[collect->next_aexpr_elt] = aexpr; 01728 collect->next_aexpr_elt++; 01729 } 01730 01731 static void 01732 process_tracepoint_on_disconnect (void) 01733 { 01734 VEC(breakpoint_p) *tp_vec = NULL; 01735 int ix; 01736 struct breakpoint *b; 01737 int has_pending_p = 0; 01738 01739 /* Check whether we still have pending tracepoint. If we have, warn the 01740 user that pending tracepoint will no longer work. */ 01741 tp_vec = all_tracepoints (); 01742 for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++) 01743 { 01744 if (b->loc == NULL) 01745 { 01746 has_pending_p = 1; 01747 break; 01748 } 01749 else 01750 { 01751 struct bp_location *loc1; 01752 01753 for (loc1 = b->loc; loc1; loc1 = loc1->next) 01754 { 01755 if (loc1->shlib_disabled) 01756 { 01757 has_pending_p = 1; 01758 break; 01759 } 01760 } 01761 01762 if (has_pending_p) 01763 break; 01764 } 01765 } 01766 VEC_free (breakpoint_p, tp_vec); 01767 01768 if (has_pending_p) 01769 warning (_("Pending tracepoints will not be resolved while" 01770 " GDB is disconnected\n")); 01771 } 01772 01773 /* Reset local state of tracing. */ 01774 01775 void 01776 trace_reset_local_state (void) 01777 { 01778 set_traceframe_num (-1); 01779 set_tracepoint_num (-1); 01780 set_traceframe_context (NULL); 01781 clear_traceframe_info (); 01782 } 01783 01784 void 01785 start_tracing (char *notes) 01786 { 01787 VEC(breakpoint_p) *tp_vec = NULL; 01788 int ix; 01789 struct breakpoint *b; 01790 struct trace_state_variable *tsv; 01791 int any_enabled = 0, num_to_download = 0; 01792 int ret; 01793 01794 tp_vec = all_tracepoints (); 01795 01796 /* No point in tracing without any tracepoints... */ 01797 if (VEC_length (breakpoint_p, tp_vec) == 0) 01798 { 01799 VEC_free (breakpoint_p, tp_vec); 01800 error (_("No tracepoints defined, not starting trace")); 01801 } 01802 01803 for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++) 01804 { 01805 struct tracepoint *t = (struct tracepoint *) b; 01806 struct bp_location *loc; 01807 01808 if (b->enable_state == bp_enabled) 01809 any_enabled = 1; 01810 01811 if ((b->type == bp_fast_tracepoint 01812 ? may_insert_fast_tracepoints 01813 : may_insert_tracepoints)) 01814 ++num_to_download; 01815 else 01816 warning (_("May not insert %stracepoints, skipping tracepoint %d"), 01817 (b->type == bp_fast_tracepoint ? "fast " : ""), b->number); 01818 } 01819 01820 if (!any_enabled) 01821 { 01822 if (target_supports_enable_disable_tracepoint ()) 01823 warning (_("No tracepoints enabled")); 01824 else 01825 { 01826 /* No point in tracing with only disabled tracepoints that 01827 cannot be re-enabled. */ 01828 VEC_free (breakpoint_p, tp_vec); 01829 error (_("No tracepoints enabled, not starting trace")); 01830 } 01831 } 01832 01833 if (num_to_download <= 0) 01834 { 01835 VEC_free (breakpoint_p, tp_vec); 01836 error (_("No tracepoints that may be downloaded, not starting trace")); 01837 } 01838 01839 target_trace_init (); 01840 01841 for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++) 01842 { 01843 struct tracepoint *t = (struct tracepoint *) b; 01844 struct bp_location *loc; 01845 int bp_location_downloaded = 0; 01846 01847 /* Clear `inserted' flag. */ 01848 for (loc = b->loc; loc; loc = loc->next) 01849 loc->inserted = 0; 01850 01851 if ((b->type == bp_fast_tracepoint 01852 ? !may_insert_fast_tracepoints 01853 : !may_insert_tracepoints)) 01854 continue; 01855 01856 t->number_on_target = 0; 01857 01858 for (loc = b->loc; loc; loc = loc->next) 01859 { 01860 /* Since tracepoint locations are never duplicated, `inserted' 01861 flag should be zero. */ 01862 gdb_assert (!loc->inserted); 01863 01864 target_download_tracepoint (loc); 01865 01866 loc->inserted = 1; 01867 bp_location_downloaded = 1; 01868 } 01869 01870 t->number_on_target = b->number; 01871 01872 for (loc = b->loc; loc; loc = loc->next) 01873 if (loc->probe != NULL) 01874 loc->probe->pops->set_semaphore (loc->probe, loc->gdbarch); 01875 01876 if (bp_location_downloaded) 01877 observer_notify_breakpoint_modified (b); 01878 } 01879 VEC_free (breakpoint_p, tp_vec); 01880 01881 /* Send down all the trace state variables too. */ 01882 for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) 01883 { 01884 target_download_trace_state_variable (tsv); 01885 } 01886 01887 /* Tell target to treat text-like sections as transparent. */ 01888 target_trace_set_readonly_regions (); 01889 /* Set some mode flags. */ 01890 target_set_disconnected_tracing (disconnected_tracing); 01891 target_set_circular_trace_buffer (circular_trace_buffer); 01892 target_set_trace_buffer_size (trace_buffer_size); 01893 01894 if (!notes) 01895 notes = trace_notes; 01896 ret = target_set_trace_notes (trace_user, notes, NULL); 01897 01898 if (!ret && (trace_user || notes)) 01899 warning (_("Target does not support trace user/notes, info ignored")); 01900 01901 /* Now insert traps and begin collecting data. */ 01902 target_trace_start (); 01903 01904 /* Reset our local state. */ 01905 trace_reset_local_state (); 01906 current_trace_status()->running = 1; 01907 } 01908 01909 /* The tstart command requests the target to start a new trace run. 01910 The command passes any arguments it has to the target verbatim, as 01911 an optional "trace note". This is useful as for instance a warning 01912 to other users if the trace runs disconnected, and you don't want 01913 anybody else messing with the target. */ 01914 01915 static void 01916 trace_start_command (char *args, int from_tty) 01917 { 01918 dont_repeat (); /* Like "run", dangerous to repeat accidentally. */ 01919 01920 if (current_trace_status ()->running) 01921 { 01922 if (from_tty 01923 && !query (_("A trace is running already. Start a new run? "))) 01924 error (_("New trace run not started.")); 01925 } 01926 01927 start_tracing (args); 01928 } 01929 01930 /* The tstop command stops the tracing run. The command passes any 01931 supplied arguments to the target verbatim as a "stop note"; if the 01932 target supports trace notes, then it will be reported back as part 01933 of the trace run's status. */ 01934 01935 static void 01936 trace_stop_command (char *args, int from_tty) 01937 { 01938 if (!current_trace_status ()->running) 01939 error (_("Trace is not running.")); 01940 01941 stop_tracing (args); 01942 } 01943 01944 void 01945 stop_tracing (char *note) 01946 { 01947 int ret; 01948 VEC(breakpoint_p) *tp_vec = NULL; 01949 int ix; 01950 struct breakpoint *t; 01951 01952 target_trace_stop (); 01953 01954 tp_vec = all_tracepoints (); 01955 for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++) 01956 { 01957 struct bp_location *loc; 01958 01959 if ((t->type == bp_fast_tracepoint 01960 ? !may_insert_fast_tracepoints 01961 : !may_insert_tracepoints)) 01962 continue; 01963 01964 for (loc = t->loc; loc; loc = loc->next) 01965 { 01966 /* GDB can be totally absent in some disconnected trace scenarios, 01967 but we don't really care if this semaphore goes out of sync. 01968 That's why we are decrementing it here, but not taking care 01969 in other places. */ 01970 if (loc->probe != NULL) 01971 loc->probe->pops->clear_semaphore (loc->probe, loc->gdbarch); 01972 } 01973 } 01974 01975 VEC_free (breakpoint_p, tp_vec); 01976 01977 if (!note) 01978 note = trace_stop_notes; 01979 ret = target_set_trace_notes (NULL, NULL, note); 01980 01981 if (!ret && note) 01982 warning (_("Target does not support trace notes, note ignored")); 01983 01984 /* Should change in response to reply? */ 01985 current_trace_status ()->running = 0; 01986 } 01987 01988 /* tstatus command */ 01989 static void 01990 trace_status_command (char *args, int from_tty) 01991 { 01992 struct trace_status *ts = current_trace_status (); 01993 int status, ix; 01994 VEC(breakpoint_p) *tp_vec = NULL; 01995 struct breakpoint *t; 01996 01997 status = target_get_trace_status (ts); 01998 01999 if (status == -1) 02000 { 02001 if (ts->filename != NULL) 02002 printf_filtered (_("Using a trace file.\n")); 02003 else 02004 { 02005 printf_filtered (_("Trace can not be run on this target.\n")); 02006 return; 02007 } 02008 } 02009 02010 if (!ts->running_known) 02011 { 02012 printf_filtered (_("Run/stop status is unknown.\n")); 02013 } 02014 else if (ts->running) 02015 { 02016 printf_filtered (_("Trace is running on the target.\n")); 02017 } 02018 else 02019 { 02020 switch (ts->stop_reason) 02021 { 02022 case trace_never_run: 02023 printf_filtered (_("No trace has been run on the target.\n")); 02024 break; 02025 case tstop_command: 02026 if (ts->stop_desc) 02027 printf_filtered (_("Trace stopped by a tstop command (%s).\n"), 02028 ts->stop_desc); 02029 else 02030 printf_filtered (_("Trace stopped by a tstop command.\n")); 02031 break; 02032 case trace_buffer_full: 02033 printf_filtered (_("Trace stopped because the buffer was full.\n")); 02034 break; 02035 case trace_disconnected: 02036 printf_filtered (_("Trace stopped because of disconnection.\n")); 02037 break; 02038 case tracepoint_passcount: 02039 printf_filtered (_("Trace stopped by tracepoint %d.\n"), 02040 ts->stopping_tracepoint); 02041 break; 02042 case tracepoint_error: 02043 if (ts->stopping_tracepoint) 02044 printf_filtered (_("Trace stopped by an " 02045 "error (%s, tracepoint %d).\n"), 02046 ts->stop_desc, ts->stopping_tracepoint); 02047 else 02048 printf_filtered (_("Trace stopped by an error (%s).\n"), 02049 ts->stop_desc); 02050 break; 02051 case trace_stop_reason_unknown: 02052 printf_filtered (_("Trace stopped for an unknown reason.\n")); 02053 break; 02054 default: 02055 printf_filtered (_("Trace stopped for some other reason (%d).\n"), 02056 ts->stop_reason); 02057 break; 02058 } 02059 } 02060 02061 if (ts->traceframes_created >= 0 02062 && ts->traceframe_count != ts->traceframes_created) 02063 { 02064 printf_filtered (_("Buffer contains %d trace " 02065 "frames (of %d created total).\n"), 02066 ts->traceframe_count, ts->traceframes_created); 02067 } 02068 else if (ts->traceframe_count >= 0) 02069 { 02070 printf_filtered (_("Collected %d trace frames.\n"), 02071 ts->traceframe_count); 02072 } 02073 02074 if (ts->buffer_free >= 0) 02075 { 02076 if (ts->buffer_size >= 0) 02077 { 02078 printf_filtered (_("Trace buffer has %d bytes of %d bytes free"), 02079 ts->buffer_free, ts->buffer_size); 02080 if (ts->buffer_size > 0) 02081 printf_filtered (_(" (%d%% full)"), 02082 ((int) ((((long long) (ts->buffer_size 02083 - ts->buffer_free)) * 100) 02084 / ts->buffer_size))); 02085 printf_filtered (_(".\n")); 02086 } 02087 else 02088 printf_filtered (_("Trace buffer has %d bytes free.\n"), 02089 ts->buffer_free); 02090 } 02091 02092 if (ts->disconnected_tracing) 02093 printf_filtered (_("Trace will continue if GDB disconnects.\n")); 02094 else 02095 printf_filtered (_("Trace will stop if GDB disconnects.\n")); 02096 02097 if (ts->circular_buffer) 02098 printf_filtered (_("Trace buffer is circular.\n")); 02099 02100 if (ts->user_name && strlen (ts->user_name) > 0) 02101 printf_filtered (_("Trace user is %s.\n"), ts->user_name); 02102 02103 if (ts->notes && strlen (ts->notes) > 0) 02104 printf_filtered (_("Trace notes: %s.\n"), ts->notes); 02105 02106 /* Now report on what we're doing with tfind. */ 02107 if (traceframe_number >= 0) 02108 printf_filtered (_("Looking at trace frame %d, tracepoint %d.\n"), 02109 traceframe_number, tracepoint_number); 02110 else 02111 printf_filtered (_("Not looking at any trace frame.\n")); 02112 02113 /* Report start/stop times if supplied. */ 02114 if (ts->start_time) 02115 { 02116 if (ts->stop_time) 02117 { 02118 LONGEST run_time = ts->stop_time - ts->start_time; 02119 02120 /* Reporting a run time is more readable than two long numbers. */ 02121 printf_filtered (_("Trace started at %ld.%06ld secs, stopped %ld.%06ld secs later.\n"), 02122 (long int) (ts->start_time / 1000000), 02123 (long int) (ts->start_time % 1000000), 02124 (long int) (run_time / 1000000), 02125 (long int) (run_time % 1000000)); 02126 } 02127 else 02128 printf_filtered (_("Trace started at %ld.%06ld secs.\n"), 02129 (long int) (ts->start_time / 1000000), 02130 (long int) (ts->start_time % 1000000)); 02131 } 02132 else if (ts->stop_time) 02133 printf_filtered (_("Trace stopped at %ld.%06ld secs.\n"), 02134 (long int) (ts->stop_time / 1000000), 02135 (long int) (ts->stop_time % 1000000)); 02136 02137 /* Now report any per-tracepoint status available. */ 02138 tp_vec = all_tracepoints (); 02139 02140 for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++) 02141 target_get_tracepoint_status (t, NULL); 02142 02143 VEC_free (breakpoint_p, tp_vec); 02144 } 02145 02146 /* Report the trace status to uiout, in a way suitable for MI, and not 02147 suitable for CLI. If ON_STOP is true, suppress a few fields that 02148 are not meaningful in the -trace-stop response. 02149 02150 The implementation is essentially parallel to trace_status_command, but 02151 merging them will result in unreadable code. */ 02152 void 02153 trace_status_mi (int on_stop) 02154 { 02155 struct ui_out *uiout = current_uiout; 02156 struct trace_status *ts = current_trace_status (); 02157 int status; 02158 02159 status = target_get_trace_status (ts); 02160 02161 if (status == -1 && ts->filename == NULL) 02162 { 02163 ui_out_field_string (uiout, "supported", "0"); 02164 return; 02165 } 02166 02167 if (ts->filename != NULL) 02168 ui_out_field_string (uiout, "supported", "file"); 02169 else if (!on_stop) 02170 ui_out_field_string (uiout, "supported", "1"); 02171 02172 if (ts->filename != NULL) 02173 ui_out_field_string (uiout, "trace-file", ts->filename); 02174 02175 gdb_assert (ts->running_known); 02176 02177 if (ts->running) 02178 { 02179 ui_out_field_string (uiout, "running", "1"); 02180 02181 /* Unlike CLI, do not show the state of 'disconnected-tracing' variable. 02182 Given that the frontend gets the status either on -trace-stop, or from 02183 -trace-status after re-connection, it does not seem like this 02184 information is necessary for anything. It is not necessary for either 02185 figuring the vital state of the target nor for navigation of trace 02186 frames. If the frontend wants to show the current state is some 02187 configure dialog, it can request the value when such dialog is 02188 invoked by the user. */ 02189 } 02190 else 02191 { 02192 char *stop_reason = NULL; 02193 int stopping_tracepoint = -1; 02194 02195 if (!on_stop) 02196 ui_out_field_string (uiout, "running", "0"); 02197 02198 if (ts->stop_reason != trace_stop_reason_unknown) 02199 { 02200 switch (ts->stop_reason) 02201 { 02202 case tstop_command: 02203 stop_reason = "request"; 02204 break; 02205 case trace_buffer_full: 02206 stop_reason = "overflow"; 02207 break; 02208 case trace_disconnected: 02209 stop_reason = "disconnection"; 02210 break; 02211 case tracepoint_passcount: 02212 stop_reason = "passcount"; 02213 stopping_tracepoint = ts->stopping_tracepoint; 02214 break; 02215 case tracepoint_error: 02216 stop_reason = "error"; 02217 stopping_tracepoint = ts->stopping_tracepoint; 02218 break; 02219 } 02220 02221 if (stop_reason) 02222 { 02223 ui_out_field_string (uiout, "stop-reason", stop_reason); 02224 if (stopping_tracepoint != -1) 02225 ui_out_field_int (uiout, "stopping-tracepoint", 02226 stopping_tracepoint); 02227 if (ts->stop_reason == tracepoint_error) 02228 ui_out_field_string (uiout, "error-description", 02229 ts->stop_desc); 02230 } 02231 } 02232 } 02233 02234 if (ts->traceframe_count != -1) 02235 ui_out_field_int (uiout, "frames", ts->traceframe_count); 02236 if (ts->traceframes_created != -1) 02237 ui_out_field_int (uiout, "frames-created", ts->traceframes_created); 02238 if (ts->buffer_size != -1) 02239 ui_out_field_int (uiout, "buffer-size", ts->buffer_size); 02240 if (ts->buffer_free != -1) 02241 ui_out_field_int (uiout, "buffer-free", ts->buffer_free); 02242 02243 ui_out_field_int (uiout, "disconnected", ts->disconnected_tracing); 02244 ui_out_field_int (uiout, "circular", ts->circular_buffer); 02245 02246 ui_out_field_string (uiout, "user-name", ts->user_name); 02247 ui_out_field_string (uiout, "notes", ts->notes); 02248 02249 { 02250 char buf[100]; 02251 02252 xsnprintf (buf, sizeof buf, "%ld.%06ld", 02253 (long int) (ts->start_time / 1000000), 02254 (long int) (ts->start_time % 1000000)); 02255 ui_out_field_string (uiout, "start-time", buf); 02256 xsnprintf (buf, sizeof buf, "%ld.%06ld", 02257 (long int) (ts->stop_time / 1000000), 02258 (long int) (ts->stop_time % 1000000)); 02259 ui_out_field_string (uiout, "stop-time", buf); 02260 } 02261 } 02262 02263 /* Check if a trace run is ongoing. If so, and FROM_TTY, query the 02264 user if she really wants to detach. */ 02265 02266 void 02267 query_if_trace_running (int from_tty) 02268 { 02269 if (!from_tty) 02270 return; 02271 02272 /* It can happen that the target that was tracing went away on its 02273 own, and we didn't notice. Get a status update, and if the 02274 current target doesn't even do tracing, then assume it's not 02275 running anymore. */ 02276 if (target_get_trace_status (current_trace_status ()) < 0) 02277 current_trace_status ()->running = 0; 02278 02279 /* If running interactively, give the user the option to cancel and 02280 then decide what to do differently with the run. Scripts are 02281 just going to disconnect and let the target deal with it, 02282 according to how it's been instructed previously via 02283 disconnected-tracing. */ 02284 if (current_trace_status ()->running) 02285 { 02286 process_tracepoint_on_disconnect (); 02287 02288 if (current_trace_status ()->disconnected_tracing) 02289 { 02290 if (!query (_("Trace is running and will " 02291 "continue after detach; detach anyway? "))) 02292 error (_("Not confirmed.")); 02293 } 02294 else 02295 { 02296 if (!query (_("Trace is running but will " 02297 "stop on detach; detach anyway? "))) 02298 error (_("Not confirmed.")); 02299 } 02300 } 02301 } 02302 02303 /* This function handles the details of what to do about an ongoing 02304 tracing run if the user has asked to detach or otherwise disconnect 02305 from the target. */ 02306 02307 void 02308 disconnect_tracing (void) 02309 { 02310 /* Also we want to be out of tfind mode, otherwise things can get 02311 confusing upon reconnection. Just use these calls instead of 02312 full tfind_1 behavior because we're in the middle of detaching, 02313 and there's no point to updating current stack frame etc. */ 02314 trace_reset_local_state (); 02315 } 02316 02317 /* Worker function for the various flavors of the tfind command. */ 02318 void 02319 tfind_1 (enum trace_find_type type, int num, 02320 CORE_ADDR addr1, CORE_ADDR addr2, 02321 int from_tty) 02322 { 02323 int target_frameno = -1, target_tracept = -1; 02324 struct frame_id old_frame_id = null_frame_id; 02325 struct tracepoint *tp; 02326 struct ui_out *uiout = current_uiout; 02327 02328 /* Only try to get the current stack frame if we have a chance of 02329 succeeding. In particular, if we're trying to get a first trace 02330 frame while all threads are running, it's not going to succeed, 02331 so leave it with a default value and let the frame comparison 02332 below (correctly) decide to print out the source location of the 02333 trace frame. */ 02334 if (!(type == tfind_number && num == -1) 02335 && (has_stack_frames () || traceframe_number >= 0)) 02336 old_frame_id = get_frame_id (get_current_frame ()); 02337 02338 target_frameno = target_trace_find (type, num, addr1, addr2, 02339 &target_tracept); 02340 02341 if (type == tfind_number 02342 && num == -1 02343 && target_frameno == -1) 02344 { 02345 /* We told the target to get out of tfind mode, and it did. */ 02346 } 02347 else if (target_frameno == -1) 02348 { 02349 /* A request for a non-existent trace frame has failed. 02350 Our response will be different, depending on FROM_TTY: 02351 02352 If FROM_TTY is true, meaning that this command was 02353 typed interactively by the user, then give an error 02354 and DO NOT change the state of traceframe_number etc. 02355 02356 However if FROM_TTY is false, meaning that we're either 02357 in a script, a loop, or a user-defined command, then 02358 DON'T give an error, but DO change the state of 02359 traceframe_number etc. to invalid. 02360 02361 The rationalle is that if you typed the command, you 02362 might just have committed a typo or something, and you'd 02363 like to NOT lose your current debugging state. However 02364 if you're in a user-defined command or especially in a 02365 loop, then you need a way to detect that the command 02366 failed WITHOUT aborting. This allows you to write 02367 scripts that search thru the trace buffer until the end, 02368 and then continue on to do something else. */ 02369 02370 if (from_tty) 02371 error (_("Target failed to find requested trace frame.")); 02372 else 02373 { 02374 if (info_verbose) 02375 printf_filtered ("End of trace buffer.\n"); 02376 #if 0 /* dubious now? */ 02377 /* The following will not recurse, since it's 02378 special-cased. */ 02379 trace_find_command ("-1", from_tty); 02380 #endif 02381 } 02382 } 02383 02384 tp = get_tracepoint_by_number_on_target (target_tracept); 02385 02386 reinit_frame_cache (); 02387 target_dcache_invalidate (); 02388 02389 set_tracepoint_num (tp ? tp->base.number : target_tracept); 02390 02391 if (target_frameno != get_traceframe_number ()) 02392 observer_notify_traceframe_changed (target_frameno, tracepoint_number); 02393 02394 set_current_traceframe (target_frameno); 02395 02396 if (target_frameno == -1) 02397 set_traceframe_context (NULL); 02398 else 02399 set_traceframe_context (get_current_frame ()); 02400 02401 if (traceframe_number >= 0) 02402 { 02403 /* Use different branches for MI and CLI to make CLI messages 02404 i18n-eable. */ 02405 if (ui_out_is_mi_like_p (uiout)) 02406 { 02407 ui_out_field_string (uiout, "found", "1"); 02408 ui_out_field_int (uiout, "tracepoint", tracepoint_number); 02409 ui_out_field_int (uiout, "traceframe", traceframe_number); 02410 } 02411 else 02412 { 02413 printf_unfiltered (_("Found trace frame %d, tracepoint %d\n"), 02414 traceframe_number, tracepoint_number); 02415 } 02416 } 02417 else 02418 { 02419 if (ui_out_is_mi_like_p (uiout)) 02420 ui_out_field_string (uiout, "found", "0"); 02421 else if (type == tfind_number && num == -1) 02422 printf_unfiltered (_("No longer looking at any trace frame\n")); 02423 else /* This case may never occur, check. */ 02424 printf_unfiltered (_("No trace frame found\n")); 02425 } 02426 02427 /* If we're in nonstop mode and getting out of looking at trace 02428 frames, there won't be any current frame to go back to and 02429 display. */ 02430 if (from_tty 02431 && (has_stack_frames () || traceframe_number >= 0)) 02432 { 02433 enum print_what print_what; 02434 02435 /* NOTE: in imitation of the step command, try to determine 02436 whether we have made a transition from one function to 02437 another. If so, we'll print the "stack frame" (ie. the new 02438 function and it's arguments) -- otherwise we'll just show the 02439 new source line. */ 02440 02441 if (frame_id_eq (old_frame_id, 02442 get_frame_id (get_current_frame ()))) 02443 print_what = SRC_LINE; 02444 else 02445 print_what = SRC_AND_LOC; 02446 02447 print_stack_frame (get_selected_frame (NULL), 1, print_what, 1); 02448 do_displays (); 02449 } 02450 } 02451 02452 /* trace_find_command takes a trace frame number n, 02453 sends "QTFrame:<n>" to the target, 02454 and accepts a reply that may contain several optional pieces 02455 of information: a frame number, a tracepoint number, and an 02456 indication of whether this is a trap frame or a stepping frame. 02457 02458 The minimal response is just "OK" (which indicates that the 02459 target does not give us a frame number or a tracepoint number). 02460 Instead of that, the target may send us a string containing 02461 any combination of: 02462 F<hexnum> (gives the selected frame number) 02463 T<hexnum> (gives the selected tracepoint number) 02464 */ 02465 02466 /* tfind command */ 02467 static void 02468 trace_find_command (char *args, int from_tty) 02469 { /* This should only be called with a numeric argument. */ 02470 int frameno = -1; 02471 02472 if (current_trace_status ()->running 02473 && current_trace_status ()->filename == NULL) 02474 error (_("May not look at trace frames while trace is running.")); 02475 02476 if (args == 0 || *args == 0) 02477 { /* TFIND with no args means find NEXT trace frame. */ 02478 if (traceframe_number == -1) 02479 frameno = 0; /* "next" is first one. */ 02480 else 02481 frameno = traceframe_number + 1; 02482 } 02483 else if (0 == strcmp (args, "-")) 02484 { 02485 if (traceframe_number == -1) 02486 error (_("not debugging trace buffer")); 02487 else if (from_tty && traceframe_number == 0) 02488 error (_("already at start of trace buffer")); 02489 02490 frameno = traceframe_number - 1; 02491 } 02492 /* A hack to work around eval's need for fp to have been collected. */ 02493 else if (0 == strcmp (args, "-1")) 02494 frameno = -1; 02495 else 02496 frameno = parse_and_eval_long (args); 02497 02498 if (frameno < -1) 02499 error (_("invalid input (%d is less than zero)"), frameno); 02500 02501 tfind_1 (tfind_number, frameno, 0, 0, from_tty); 02502 } 02503 02504 /* tfind end */ 02505 static void 02506 trace_find_end_command (char *args, int from_tty) 02507 { 02508 trace_find_command ("-1", from_tty); 02509 } 02510 02511 /* tfind start */ 02512 static void 02513 trace_find_start_command (char *args, int from_tty) 02514 { 02515 trace_find_command ("0", from_tty); 02516 } 02517 02518 /* tfind pc command */ 02519 static void 02520 trace_find_pc_command (char *args, int from_tty) 02521 { 02522 CORE_ADDR pc; 02523 02524 if (current_trace_status ()->running 02525 && current_trace_status ()->filename == NULL) 02526 error (_("May not look at trace frames while trace is running.")); 02527 02528 if (args == 0 || *args == 0) 02529 pc = regcache_read_pc (get_current_regcache ()); 02530 else 02531 pc = parse_and_eval_address (args); 02532 02533 tfind_1 (tfind_pc, 0, pc, 0, from_tty); 02534 } 02535 02536 /* tfind tracepoint command */ 02537 static void 02538 trace_find_tracepoint_command (char *args, int from_tty) 02539 { 02540 int tdp; 02541 struct tracepoint *tp; 02542 02543 if (current_trace_status ()->running 02544 && current_trace_status ()->filename == NULL) 02545 error (_("May not look at trace frames while trace is running.")); 02546 02547 if (args == 0 || *args == 0) 02548 { 02549 if (tracepoint_number == -1) 02550 error (_("No current tracepoint -- please supply an argument.")); 02551 else 02552 tdp = tracepoint_number; /* Default is current TDP. */ 02553 } 02554 else 02555 tdp = parse_and_eval_long (args); 02556 02557 /* If we have the tracepoint on hand, use the number that the 02558 target knows about (which may be different if we disconnected 02559 and reconnected). */ 02560 tp = get_tracepoint (tdp); 02561 if (tp) 02562 tdp = tp->number_on_target; 02563 02564 tfind_1 (tfind_tp, tdp, 0, 0, from_tty); 02565 } 02566 02567 /* TFIND LINE command: 02568 02569 This command will take a sourceline for argument, just like BREAK 02570 or TRACE (ie. anything that "decode_line_1" can handle). 02571 02572 With no argument, this command will find the next trace frame 02573 corresponding to a source line OTHER THAN THE CURRENT ONE. */ 02574 02575 static void 02576 trace_find_line_command (char *args, int from_tty) 02577 { 02578 static CORE_ADDR start_pc, end_pc; 02579 struct symtabs_and_lines sals; 02580 struct symtab_and_line sal; 02581 struct cleanup *old_chain; 02582 02583 if (current_trace_status ()->running 02584 && current_trace_status ()->filename == NULL) 02585 error (_("May not look at trace frames while trace is running.")); 02586 02587 if (args == 0 || *args == 0) 02588 { 02589 sal = find_pc_line (get_frame_pc (get_current_frame ()), 0); 02590 sals.nelts = 1; 02591 sals.sals = (struct symtab_and_line *) 02592 xmalloc (sizeof (struct symtab_and_line)); 02593 sals.sals[0] = sal; 02594 } 02595 else 02596 { 02597 sals = decode_line_with_current_source (args, DECODE_LINE_FUNFIRSTLINE); 02598 sal = sals.sals[0]; 02599 } 02600 02601 old_chain = make_cleanup (xfree, sals.sals); 02602 if (sal.symtab == 0) 02603 error (_("No line number information available.")); 02604 02605 if (sal.line > 0 && find_line_pc_range (sal, &start_pc, &end_pc)) 02606 { 02607 if (start_pc == end_pc) 02608 { 02609 printf_filtered ("Line %d of \"%s\"", 02610 sal.line, 02611 symtab_to_filename_for_display (sal.symtab)); 02612 wrap_here (" "); 02613 printf_filtered (" is at address "); 02614 print_address (get_current_arch (), start_pc, gdb_stdout); 02615 wrap_here (" "); 02616 printf_filtered (" but contains no code.\n"); 02617 sal = find_pc_line (start_pc, 0); 02618 if (sal.line > 0 02619 && find_line_pc_range (sal, &start_pc, &end_pc) 02620 && start_pc != end_pc) 02621 printf_filtered ("Attempting to find line %d instead.\n", 02622 sal.line); 02623 else 02624 error (_("Cannot find a good line.")); 02625 } 02626 } 02627 else 02628 /* Is there any case in which we get here, and have an address 02629 which the user would want to see? If we have debugging 02630 symbols and no line numbers? */ 02631 error (_("Line number %d is out of range for \"%s\"."), 02632 sal.line, symtab_to_filename_for_display (sal.symtab)); 02633 02634 /* Find within range of stated line. */ 02635 if (args && *args) 02636 tfind_1 (tfind_range, 0, start_pc, end_pc - 1, from_tty); 02637 else 02638 tfind_1 (tfind_outside, 0, start_pc, end_pc - 1, from_tty); 02639 do_cleanups (old_chain); 02640 } 02641 02642 /* tfind range command */ 02643 static void 02644 trace_find_range_command (char *args, int from_tty) 02645 { 02646 static CORE_ADDR start, stop; 02647 char *tmp; 02648 02649 if (current_trace_status ()->running 02650 && current_trace_status ()->filename == NULL) 02651 error (_("May not look at trace frames while trace is running.")); 02652 02653 if (args == 0 || *args == 0) 02654 { /* XXX FIXME: what should default behavior be? */ 02655 printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n"); 02656 return; 02657 } 02658 02659 if (0 != (tmp = strchr (args, ','))) 02660 { 02661 *tmp++ = '\0'; /* Terminate start address. */ 02662 tmp = skip_spaces (tmp); 02663 start = parse_and_eval_address (args); 02664 stop = parse_and_eval_address (tmp); 02665 } 02666 else 02667 { /* No explicit end address? */ 02668 start = parse_and_eval_address (args); 02669 stop = start + 1; /* ??? */ 02670 } 02671 02672 tfind_1 (tfind_range, 0, start, stop, from_tty); 02673 } 02674 02675 /* tfind outside command */ 02676 static void 02677 trace_find_outside_command (char *args, int from_tty) 02678 { 02679 CORE_ADDR start, stop; 02680 char *tmp; 02681 02682 if (current_trace_status ()->running 02683 && current_trace_status ()->filename == NULL) 02684 error (_("May not look at trace frames while trace is running.")); 02685 02686 if (args == 0 || *args == 0) 02687 { /* XXX FIXME: what should default behavior be? */ 02688 printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n"); 02689 return; 02690 } 02691 02692 if (0 != (tmp = strchr (args, ','))) 02693 { 02694 *tmp++ = '\0'; /* Terminate start address. */ 02695 tmp = skip_spaces (tmp); 02696 start = parse_and_eval_address (args); 02697 stop = parse_and_eval_address (tmp); 02698 } 02699 else 02700 { /* No explicit end address? */ 02701 start = parse_and_eval_address (args); 02702 stop = start + 1; /* ??? */ 02703 } 02704 02705 tfind_1 (tfind_outside, 0, start, stop, from_tty); 02706 } 02707 02708 /* info scope command: list the locals for a scope. */ 02709 static void 02710 scope_info (char *args, int from_tty) 02711 { 02712 struct symtabs_and_lines sals; 02713 struct symbol *sym; 02714 struct minimal_symbol *msym; 02715 struct block *block; 02716 const char *symname; 02717 char *save_args = args; 02718 struct block_iterator iter; 02719 int j, count = 0; 02720 struct gdbarch *gdbarch; 02721 int regno; 02722 02723 if (args == 0 || *args == 0) 02724 error (_("requires an argument (function, " 02725 "line or *addr) to define a scope")); 02726 02727 sals = decode_line_1 (&args, DECODE_LINE_FUNFIRSTLINE, NULL, 0); 02728 if (sals.nelts == 0) 02729 return; /* Presumably decode_line_1 has already warned. */ 02730 02731 /* Resolve line numbers to PC. */ 02732 resolve_sal_pc (&sals.sals[0]); 02733 block = block_for_pc (sals.sals[0].pc); 02734 02735 while (block != 0) 02736 { 02737 QUIT; /* Allow user to bail out with ^C. */ 02738 ALL_BLOCK_SYMBOLS (block, iter, sym) 02739 { 02740 QUIT; /* Allow user to bail out with ^C. */ 02741 if (count == 0) 02742 printf_filtered ("Scope for %s:\n", save_args); 02743 count++; 02744 02745 symname = SYMBOL_PRINT_NAME (sym); 02746 if (symname == NULL || *symname == '\0') 02747 continue; /* Probably botched, certainly useless. */ 02748 02749 gdbarch = get_objfile_arch (SYMBOL_SYMTAB (sym)->objfile); 02750 02751 printf_filtered ("Symbol %s is ", symname); 02752 02753 if (SYMBOL_COMPUTED_OPS (sym) != NULL) 02754 SYMBOL_COMPUTED_OPS (sym)->describe_location (sym, 02755 BLOCK_START (block), 02756 gdb_stdout); 02757 else 02758 { 02759 switch (SYMBOL_CLASS (sym)) 02760 { 02761 default: 02762 case LOC_UNDEF: /* Messed up symbol? */ 02763 printf_filtered ("a bogus symbol, class %d.\n", 02764 SYMBOL_CLASS (sym)); 02765 count--; /* Don't count this one. */ 02766 continue; 02767 case LOC_CONST: 02768 printf_filtered ("a constant with value %s (%s)", 02769 plongest (SYMBOL_VALUE (sym)), 02770 hex_string (SYMBOL_VALUE (sym))); 02771 break; 02772 case LOC_CONST_BYTES: 02773 printf_filtered ("constant bytes: "); 02774 if (SYMBOL_TYPE (sym)) 02775 for (j = 0; j < TYPE_LENGTH (SYMBOL_TYPE (sym)); j++) 02776 fprintf_filtered (gdb_stdout, " %02x", 02777 (unsigned) SYMBOL_VALUE_BYTES (sym)[j]); 02778 break; 02779 case LOC_STATIC: 02780 printf_filtered ("in static storage at address "); 02781 printf_filtered ("%s", paddress (gdbarch, 02782 SYMBOL_VALUE_ADDRESS (sym))); 02783 break; 02784 case LOC_REGISTER: 02785 /* GDBARCH is the architecture associated with the objfile 02786 the symbol is defined in; the target architecture may be 02787 different, and may provide additional registers. However, 02788 we do not know the target architecture at this point. 02789 We assume the objfile architecture will contain all the 02790 standard registers that occur in debug info in that 02791 objfile. */ 02792 regno = SYMBOL_REGISTER_OPS (sym)->register_number (sym, 02793 gdbarch); 02794 02795 if (SYMBOL_IS_ARGUMENT (sym)) 02796 printf_filtered ("an argument in register $%s", 02797 gdbarch_register_name (gdbarch, regno)); 02798 else 02799 printf_filtered ("a local variable in register $%s", 02800 gdbarch_register_name (gdbarch, regno)); 02801 break; 02802 case LOC_ARG: 02803 printf_filtered ("an argument at stack/frame offset %s", 02804 plongest (SYMBOL_VALUE (sym))); 02805 break; 02806 case LOC_LOCAL: 02807 printf_filtered ("a local variable at frame offset %s", 02808 plongest (SYMBOL_VALUE (sym))); 02809 break; 02810 case LOC_REF_ARG: 02811 printf_filtered ("a reference argument at offset %s", 02812 plongest (SYMBOL_VALUE (sym))); 02813 break; 02814 case LOC_REGPARM_ADDR: 02815 /* Note comment at LOC_REGISTER. */ 02816 regno = SYMBOL_REGISTER_OPS (sym)->register_number (sym, 02817 gdbarch); 02818 printf_filtered ("the address of an argument, in register $%s", 02819 gdbarch_register_name (gdbarch, regno)); 02820 break; 02821 case LOC_TYPEDEF: 02822 printf_filtered ("a typedef.\n"); 02823 continue; 02824 case LOC_LABEL: 02825 printf_filtered ("a label at address "); 02826 printf_filtered ("%s", paddress (gdbarch, 02827 SYMBOL_VALUE_ADDRESS (sym))); 02828 break; 02829 case LOC_BLOCK: 02830 printf_filtered ("a function at address "); 02831 printf_filtered ("%s", 02832 paddress (gdbarch, BLOCK_START (SYMBOL_BLOCK_VALUE (sym)))); 02833 break; 02834 case LOC_UNRESOLVED: 02835 msym = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (sym), 02836 NULL, NULL); 02837 if (msym == NULL) 02838 printf_filtered ("Unresolved Static"); 02839 else 02840 { 02841 printf_filtered ("static storage at address "); 02842 printf_filtered ("%s", 02843 paddress (gdbarch, 02844 SYMBOL_VALUE_ADDRESS (msym))); 02845 } 02846 break; 02847 case LOC_OPTIMIZED_OUT: 02848 printf_filtered ("optimized out.\n"); 02849 continue; 02850 case LOC_COMPUTED: 02851 gdb_assert_not_reached (_("LOC_COMPUTED variable missing a method")); 02852 } 02853 } 02854 if (SYMBOL_TYPE (sym)) 02855 printf_filtered (", length %d.\n", 02856 TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)))); 02857 } 02858 if (BLOCK_FUNCTION (block)) 02859 break; 02860 else 02861 block = BLOCK_SUPERBLOCK (block); 02862 } 02863 if (count <= 0) 02864 printf_filtered ("Scope for %s contains no locals or arguments.\n", 02865 save_args); 02866 } 02867 02868 /* Helper for trace_dump_command. Dump the action list starting at 02869 ACTION. STEPPING_ACTIONS is true if we're iterating over the 02870 actions of the body of a while-stepping action. STEPPING_FRAME is 02871 set if the current traceframe was determined to be a while-stepping 02872 traceframe. */ 02873 02874 static void 02875 trace_dump_actions (struct command_line *action, 02876 int stepping_actions, int stepping_frame, 02877 int from_tty) 02878 { 02879 const char *action_exp, *next_comma; 02880 02881 for (; action != NULL; action = action->next) 02882 { 02883 struct cmd_list_element *cmd; 02884 02885 QUIT; /* Allow user to bail out with ^C. */ 02886 action_exp = action->line; 02887 action_exp = skip_spaces_const (action_exp); 02888 02889 /* The collection actions to be done while stepping are 02890 bracketed by the commands "while-stepping" and "end". */ 02891 02892 if (*action_exp == '#') /* comment line */ 02893 continue; 02894 02895 cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1); 02896 if (cmd == 0) 02897 error (_("Bad action list item: %s"), action_exp); 02898 02899 if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand)) 02900 { 02901 int i; 02902 02903 for (i = 0; i < action->body_count; ++i) 02904 trace_dump_actions (action->body_list[i], 02905 1, stepping_frame, from_tty); 02906 } 02907 else if (cmd_cfunc_eq (cmd, collect_pseudocommand)) 02908 { 02909 /* Display the collected data. 02910 For the trap frame, display only what was collected at 02911 the trap. Likewise for stepping frames, display only 02912 what was collected while stepping. This means that the 02913 two boolean variables, STEPPING_FRAME and 02914 STEPPING_ACTIONS should be equal. */ 02915 if (stepping_frame == stepping_actions) 02916 { 02917 char *cmd = NULL; 02918 struct cleanup *old_chain 02919 = make_cleanup (free_current_contents, &cmd); 02920 int trace_string = 0; 02921 02922 if (*action_exp == '/') 02923 action_exp = decode_agent_options (action_exp, &trace_string); 02924 02925 do 02926 { /* Repeat over a comma-separated list. */ 02927 QUIT; /* Allow user to bail out with ^C. */ 02928 if (*action_exp == ',') 02929 action_exp++; 02930 action_exp = skip_spaces_const (action_exp); 02931 02932 next_comma = strchr (action_exp, ','); 02933 02934 if (0 == strncasecmp (action_exp, "$reg", 4)) 02935 registers_info (NULL, from_tty); 02936 else if (0 == strncasecmp (action_exp, "$_ret", 5)) 02937 ; 02938 else if (0 == strncasecmp (action_exp, "$loc", 4)) 02939 locals_info (NULL, from_tty); 02940 else if (0 == strncasecmp (action_exp, "$arg", 4)) 02941 args_info (NULL, from_tty); 02942 else 02943 { /* variable */ 02944 if (next_comma != NULL) 02945 { 02946 size_t len = next_comma - action_exp; 02947 02948 cmd = xrealloc (cmd, len + 1); 02949 memcpy (cmd, action_exp, len); 02950 cmd[len] = 0; 02951 } 02952 else 02953 { 02954 size_t len = strlen (action_exp); 02955 02956 cmd = xrealloc (cmd, len + 1); 02957 memcpy (cmd, action_exp, len + 1); 02958 } 02959 02960 printf_filtered ("%s = ", cmd); 02961 output_command_const (cmd, from_tty); 02962 printf_filtered ("\n"); 02963 } 02964 action_exp = next_comma; 02965 } 02966 while (action_exp && *action_exp == ','); 02967 02968 do_cleanups (old_chain); 02969 } 02970 } 02971 } 02972 } 02973 02974 /* Return bp_location of the tracepoint associated with the current 02975 traceframe. Set *STEPPING_FRAME_P to 1 if the current traceframe 02976 is a stepping traceframe. */ 02977 02978 struct bp_location * 02979 get_traceframe_location (int *stepping_frame_p) 02980 { 02981 struct tracepoint *t; 02982 struct bp_location *tloc; 02983 struct regcache *regcache; 02984 02985 if (tracepoint_number == -1) 02986 error (_("No current trace frame.")); 02987 02988 t = get_tracepoint (tracepoint_number); 02989 02990 if (t == NULL) 02991 error (_("No known tracepoint matches 'current' tracepoint #%d."), 02992 tracepoint_number); 02993 02994 /* The current frame is a trap frame if the frame PC is equal to the 02995 tracepoint PC. If not, then the current frame was collected 02996 during single-stepping. */ 02997 regcache = get_current_regcache (); 02998 02999 /* If the traceframe's address matches any of the tracepoint's 03000 locations, assume it is a direct hit rather than a while-stepping 03001 frame. (FIXME this is not reliable, should record each frame's 03002 type.) */ 03003 for (tloc = t->base.loc; tloc; tloc = tloc->next) 03004 if (tloc->address == regcache_read_pc (regcache)) 03005 { 03006 *stepping_frame_p = 0; 03007 return tloc; 03008 } 03009 03010 /* If this is a stepping frame, we don't know which location 03011 triggered. The first is as good (or bad) a guess as any... */ 03012 *stepping_frame_p = 1; 03013 return t->base.loc; 03014 } 03015 03016 /* Return all the actions, including default collect, of a tracepoint 03017 T. It constructs cleanups into the chain, and leaves the caller to 03018 handle them (call do_cleanups). */ 03019 03020 static struct command_line * 03021 all_tracepoint_actions_and_cleanup (struct breakpoint *t) 03022 { 03023 struct command_line *actions; 03024 03025 actions = breakpoint_commands (t); 03026 03027 /* If there are default expressions to collect, make up a collect 03028 action and prepend to the action list to encode. Note that since 03029 validation is per-tracepoint (local var "xyz" might be valid for 03030 one tracepoint and not another, etc), we make up the action on 03031 the fly, and don't cache it. */ 03032 if (*default_collect) 03033 { 03034 struct command_line *default_collect_action; 03035 char *default_collect_line; 03036 03037 default_collect_line = xstrprintf ("collect %s", default_collect); 03038 make_cleanup (xfree, default_collect_line); 03039 03040 validate_actionline (default_collect_line, t); 03041 default_collect_action = xmalloc (sizeof (struct command_line)); 03042 make_cleanup (xfree, default_collect_action); 03043 default_collect_action->next = actions; 03044 default_collect_action->line = default_collect_line; 03045 actions = default_collect_action; 03046 } 03047 03048 return actions; 03049 } 03050 03051 /* The tdump command. */ 03052 03053 static void 03054 trace_dump_command (char *args, int from_tty) 03055 { 03056 int stepping_frame = 0; 03057 struct bp_location *loc; 03058 struct cleanup *old_chain; 03059 struct command_line *actions; 03060 03061 /* This throws an error is not inspecting a trace frame. */ 03062 loc = get_traceframe_location (&stepping_frame); 03063 03064 printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n", 03065 tracepoint_number, traceframe_number); 03066 03067 old_chain = make_cleanup (null_cleanup, NULL); 03068 03069 /* This command only makes sense for the current frame, not the 03070 selected frame. */ 03071 make_cleanup_restore_current_thread (); 03072 select_frame (get_current_frame ()); 03073 03074 actions = all_tracepoint_actions_and_cleanup (loc->owner); 03075 03076 trace_dump_actions (actions, 0, stepping_frame, from_tty); 03077 03078 do_cleanups (old_chain); 03079 } 03080 03081 /* Encode a piece of a tracepoint's source-level definition in a form 03082 that is suitable for both protocol and saving in files. */ 03083 /* This version does not do multiple encodes for long strings; it should 03084 return an offset to the next piece to encode. FIXME */ 03085 03086 extern int 03087 encode_source_string (int tpnum, ULONGEST addr, 03088 char *srctype, char *src, char *buf, int buf_size) 03089 { 03090 if (80 + strlen (srctype) > buf_size) 03091 error (_("Buffer too small for source encoding")); 03092 sprintf (buf, "%x:%s:%s:%x:%x:", 03093 tpnum, phex_nz (addr, sizeof (addr)), 03094 srctype, 0, (int) strlen (src)); 03095 if (strlen (buf) + strlen (src) * 2 >= buf_size) 03096 error (_("Source string too long for buffer")); 03097 bin2hex ((gdb_byte *) src, buf + strlen (buf), 0); 03098 return -1; 03099 } 03100 03101 /* Free trace file writer. */ 03102 03103 static void 03104 trace_file_writer_xfree (void *arg) 03105 { 03106 struct trace_file_writer *writer = arg; 03107 03108 writer->ops->dtor (writer); 03109 xfree (writer); 03110 } 03111 03112 /* TFILE trace writer. */ 03113 03114 struct tfile_trace_file_writer 03115 { 03116 struct trace_file_writer base; 03117 03118 /* File pointer to tfile trace file. */ 03119 FILE *fp; 03120 /* Path name of the tfile trace file. */ 03121 char *pathname; 03122 }; 03123 03124 /* This is the implementation of trace_file_write_ops method 03125 target_save. We just call the generic target 03126 target_save_trace_data to do target-side saving. */ 03127 03128 static int 03129 tfile_target_save (struct trace_file_writer *self, 03130 const char *filename) 03131 { 03132 int err = target_save_trace_data (filename); 03133 03134 return (err >= 0); 03135 } 03136 03137 /* This is the implementation of trace_file_write_ops method 03138 dtor. */ 03139 03140 static void 03141 tfile_dtor (struct trace_file_writer *self) 03142 { 03143 struct tfile_trace_file_writer *writer 03144 = (struct tfile_trace_file_writer *) self; 03145 03146 xfree (writer->pathname); 03147 03148 if (writer->fp != NULL) 03149 fclose (writer->fp); 03150 } 03151 03152 /* This is the implementation of trace_file_write_ops method 03153 start. It creates the trace file FILENAME and registers some 03154 cleanups. */ 03155 03156 static void 03157 tfile_start (struct trace_file_writer *self, const char *filename) 03158 { 03159 struct tfile_trace_file_writer *writer 03160 = (struct tfile_trace_file_writer *) self; 03161 03162 writer->pathname = tilde_expand (filename); 03163 writer->fp = gdb_fopen_cloexec (writer->pathname, "wb"); 03164 if (writer->fp == NULL) 03165 error (_("Unable to open file '%s' for saving trace data (%s)"), 03166 writer->pathname, safe_strerror (errno)); 03167 } 03168 03169 /* This is the implementation of trace_file_write_ops method 03170 write_header. Write the TFILE header. */ 03171 03172 static void 03173 tfile_write_header (struct trace_file_writer *self) 03174 { 03175 struct tfile_trace_file_writer *writer 03176 = (struct tfile_trace_file_writer *) self; 03177 int written; 03178 03179 /* Write a file header, with a high-bit-set char to indicate a 03180 binary file, plus a hint as what this file is, and a version 03181 number in case of future needs. */ 03182 written = fwrite ("\x7fTRACE0\n", 8, 1, writer->fp); 03183 if (written < 1) 03184 perror_with_name (writer->pathname); 03185 } 03186 03187 /* This is the implementation of trace_file_write_ops method 03188 write_regblock_type. Write the size of register block. */ 03189 03190 static void 03191 tfile_write_regblock_type (struct trace_file_writer *self, int size) 03192 { 03193 struct tfile_trace_file_writer *writer 03194 = (struct tfile_trace_file_writer *) self; 03195 03196 fprintf (writer->fp, "R %x\n", size); 03197 } 03198 03199 /* This is the implementation of trace_file_write_ops method 03200 write_status. */ 03201 03202 static void 03203 tfile_write_status (struct trace_file_writer *self, 03204 struct trace_status *ts) 03205 { 03206 struct tfile_trace_file_writer *writer 03207 = (struct tfile_trace_file_writer *) self; 03208 03209 fprintf (writer->fp, "status %c;%s", 03210 (ts->running ? '1' : '0'), stop_reason_names[ts->stop_reason]); 03211 if (ts->stop_reason == tracepoint_error 03212 || ts->stop_reason == tstop_command) 03213 { 03214 char *buf = (char *) alloca (strlen (ts->stop_desc) * 2 + 1); 03215 03216 bin2hex ((gdb_byte *) ts->stop_desc, buf, 0); 03217 fprintf (writer->fp, ":%s", buf); 03218 } 03219 fprintf (writer->fp, ":%x", ts->stopping_tracepoint); 03220 if (ts->traceframe_count >= 0) 03221 fprintf (writer->fp, ";tframes:%x", ts->traceframe_count); 03222 if (ts->traceframes_created >= 0) 03223 fprintf (writer->fp, ";tcreated:%x", ts->traceframes_created); 03224 if (ts->buffer_free >= 0) 03225 fprintf (writer->fp, ";tfree:%x", ts->buffer_free); 03226 if (ts->buffer_size >= 0) 03227 fprintf (writer->fp, ";tsize:%x", ts->buffer_size); 03228 if (ts->disconnected_tracing) 03229 fprintf (writer->fp, ";disconn:%x", ts->disconnected_tracing); 03230 if (ts->circular_buffer) 03231 fprintf (writer->fp, ";circular:%x", ts->circular_buffer); 03232 if (ts->start_time) 03233 { 03234 fprintf (writer->fp, ";starttime:%s", 03235 phex_nz (ts->start_time, sizeof (ts->start_time))); 03236 } 03237 if (ts->stop_time) 03238 { 03239 fprintf (writer->fp, ";stoptime:%s", 03240 phex_nz (ts->stop_time, sizeof (ts->stop_time))); 03241 } 03242 if (ts->notes != NULL) 03243 { 03244 char *buf = (char *) alloca (strlen (ts->notes) * 2 + 1); 03245 03246 bin2hex ((gdb_byte *) ts->notes, buf, 0); 03247 fprintf (writer->fp, ";notes:%s", buf); 03248 } 03249 if (ts->user_name != NULL) 03250 { 03251 char *buf = (char *) alloca (strlen (ts->user_name) * 2 + 1); 03252 03253 bin2hex ((gdb_byte *) ts->user_name, buf, 0); 03254 fprintf (writer->fp, ";username:%s", buf); 03255 } 03256 fprintf (writer->fp, "\n"); 03257 } 03258 03259 /* This is the implementation of trace_file_write_ops method 03260 write_uploaded_tsv. */ 03261 03262 static void 03263 tfile_write_uploaded_tsv (struct trace_file_writer *self, 03264 struct uploaded_tsv *utsv) 03265 { 03266 char *buf = ""; 03267 struct tfile_trace_file_writer *writer 03268 = (struct tfile_trace_file_writer *) self; 03269 03270 if (utsv->name) 03271 { 03272 buf = (char *) xmalloc (strlen (utsv->name) * 2 + 1); 03273 bin2hex ((gdb_byte *) (utsv->name), buf, 0); 03274 } 03275 03276 fprintf (writer->fp, "tsv %x:%s:%x:%s\n", 03277 utsv->number, phex_nz (utsv->initial_value, 8), 03278 utsv->builtin, buf); 03279 03280 if (utsv->name) 03281 xfree (buf); 03282 } 03283 03284 #define MAX_TRACE_UPLOAD 2000 03285 03286 /* This is the implementation of trace_file_write_ops method 03287 write_uploaded_tp. */ 03288 03289 static void 03290 tfile_write_uploaded_tp (struct trace_file_writer *self, 03291 struct uploaded_tp *utp) 03292 { 03293 struct tfile_trace_file_writer *writer 03294 = (struct tfile_trace_file_writer *) self; 03295 int a; 03296 char *act; 03297 char buf[MAX_TRACE_UPLOAD]; 03298 03299 fprintf (writer->fp, "tp T%x:%s:%c:%x:%x", 03300 utp->number, phex_nz (utp->addr, sizeof (utp->addr)), 03301 (utp->enabled ? 'E' : 'D'), utp->step, utp->pass); 03302 if (utp->type == bp_fast_tracepoint) 03303 fprintf (writer->fp, ":F%x", utp->orig_size); 03304 if (utp->cond) 03305 fprintf (writer->fp, 03306 ":X%x,%s", (unsigned int) strlen (utp->cond) / 2, 03307 utp->cond); 03308 fprintf (writer->fp, "\n"); 03309 for (a = 0; VEC_iterate (char_ptr, utp->actions, a, act); ++a) 03310 fprintf (writer->fp, "tp A%x:%s:%s\n", 03311 utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act); 03312 for (a = 0; VEC_iterate (char_ptr, utp->step_actions, a, act); ++a) 03313 fprintf (writer->fp, "tp S%x:%s:%s\n", 03314 utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act); 03315 if (utp->at_string) 03316 { 03317 encode_source_string (utp->number, utp->addr, 03318 "at", utp->at_string, buf, MAX_TRACE_UPLOAD); 03319 fprintf (writer->fp, "tp Z%s\n", buf); 03320 } 03321 if (utp->cond_string) 03322 { 03323 encode_source_string (utp->number, utp->addr, 03324 "cond", utp->cond_string, 03325 buf, MAX_TRACE_UPLOAD); 03326 fprintf (writer->fp, "tp Z%s\n", buf); 03327 } 03328 for (a = 0; VEC_iterate (char_ptr, utp->cmd_strings, a, act); ++a) 03329 { 03330 encode_source_string (utp->number, utp->addr, "cmd", act, 03331 buf, MAX_TRACE_UPLOAD); 03332 fprintf (writer->fp, "tp Z%s\n", buf); 03333 } 03334 fprintf (writer->fp, "tp V%x:%s:%x:%s\n", 03335 utp->number, phex_nz (utp->addr, sizeof (utp->addr)), 03336 utp->hit_count, 03337 phex_nz (utp->traceframe_usage, 03338 sizeof (utp->traceframe_usage))); 03339 } 03340 03341 /* This is the implementation of trace_file_write_ops method 03342 write_definition_end. */ 03343 03344 static void 03345 tfile_write_definition_end (struct trace_file_writer *self) 03346 { 03347 struct tfile_trace_file_writer *writer 03348 = (struct tfile_trace_file_writer *) self; 03349 03350 fprintf (writer->fp, "\n"); 03351 } 03352 03353 /* This is the implementation of trace_file_write_ops method 03354 write_raw_data. */ 03355 03356 static void 03357 tfile_write_raw_data (struct trace_file_writer *self, gdb_byte *buf, 03358 LONGEST len) 03359 { 03360 struct tfile_trace_file_writer *writer 03361 = (struct tfile_trace_file_writer *) self; 03362 03363 if (fwrite (buf, len, 1, writer->fp) < 1) 03364 perror_with_name (writer->pathname); 03365 } 03366 03367 /* This is the implementation of trace_file_write_ops method 03368 end. */ 03369 03370 static void 03371 tfile_end (struct trace_file_writer *self) 03372 { 03373 struct tfile_trace_file_writer *writer 03374 = (struct tfile_trace_file_writer *) self; 03375 uint32_t gotten = 0; 03376 03377 /* Mark the end of trace data. */ 03378 if (fwrite (&gotten, 4, 1, writer->fp) < 1) 03379 perror_with_name (writer->pathname); 03380 } 03381 03382 /* Operations to write trace buffers into TFILE format. */ 03383 03384 static const struct trace_file_write_ops tfile_write_ops = 03385 { 03386 tfile_dtor, 03387 tfile_target_save, 03388 tfile_start, 03389 tfile_write_header, 03390 tfile_write_regblock_type, 03391 tfile_write_status, 03392 tfile_write_uploaded_tsv, 03393 tfile_write_uploaded_tp, 03394 tfile_write_definition_end, 03395 tfile_write_raw_data, 03396 NULL, 03397 tfile_end, 03398 }; 03399 03400 /* Helper macros. */ 03401 03402 #define TRACE_WRITE_R_BLOCK(writer, buf, size) \ 03403 writer->ops->frame_ops->write_r_block ((writer), (buf), (size)) 03404 #define TRACE_WRITE_M_BLOCK_HEADER(writer, addr, size) \ 03405 writer->ops->frame_ops->write_m_block_header ((writer), (addr), \ 03406 (size)) 03407 #define TRACE_WRITE_M_BLOCK_MEMORY(writer, buf, size) \ 03408 writer->ops->frame_ops->write_m_block_memory ((writer), (buf), \ 03409 (size)) 03410 #define TRACE_WRITE_V_BLOCK(writer, num, val) \ 03411 writer->ops->frame_ops->write_v_block ((writer), (num), (val)) 03412 03413 /* Save tracepoint data to file named FILENAME through WRITER. WRITER 03414 determines the trace file format. If TARGET_DOES_SAVE is non-zero, 03415 the save is performed on the target, otherwise GDB obtains all trace 03416 data and saves it locally. */ 03417 03418 static void 03419 trace_save (const char *filename, struct trace_file_writer *writer, 03420 int target_does_save) 03421 { 03422 struct trace_status *ts = current_trace_status (); 03423 int status; 03424 struct uploaded_tp *uploaded_tps = NULL, *utp; 03425 struct uploaded_tsv *uploaded_tsvs = NULL, *utsv; 03426 03427 ULONGEST offset = 0; 03428 gdb_byte buf[MAX_TRACE_UPLOAD]; 03429 #define MAX_TRACE_UPLOAD 2000 03430 int written; 03431 enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); 03432 03433 /* If the target is to save the data to a file on its own, then just 03434 send the command and be done with it. */ 03435 if (target_does_save) 03436 { 03437 if (!writer->ops->target_save (writer, filename)) 03438 error (_("Target failed to save trace data to '%s'."), 03439 filename); 03440 return; 03441 } 03442 03443 /* Get the trace status first before opening the file, so if the 03444 target is losing, we can get out without touching files. */ 03445 status = target_get_trace_status (ts); 03446 03447 writer->ops->start (writer, filename); 03448 03449 writer->ops->write_header (writer); 03450 03451 /* Write descriptive info. */ 03452 03453 /* Write out the size of a register block. */ 03454 writer->ops->write_regblock_type (writer, trace_regblock_size); 03455 03456 /* Write out status of the tracing run (aka "tstatus" info). */ 03457 writer->ops->write_status (writer, ts); 03458 03459 /* Note that we want to upload tracepoints and save those, rather 03460 than simply writing out the local ones, because the user may have 03461 changed tracepoints in GDB in preparation for a future tracing 03462 run, or maybe just mass-deleted all types of breakpoints as part 03463 of cleaning up. So as not to contaminate the session, leave the 03464 data in its uploaded form, don't make into real tracepoints. */ 03465 03466 /* Get trace state variables first, they may be checked when parsing 03467 uploaded commands. */ 03468 03469 target_upload_trace_state_variables (&uploaded_tsvs); 03470 03471 for (utsv = uploaded_tsvs; utsv; utsv = utsv->next) 03472 writer->ops->write_uploaded_tsv (writer, utsv); 03473 03474 free_uploaded_tsvs (&uploaded_tsvs); 03475 03476 target_upload_tracepoints (&uploaded_tps); 03477 03478 for (utp = uploaded_tps; utp; utp = utp->next) 03479 target_get_tracepoint_status (NULL, utp); 03480 03481 for (utp = uploaded_tps; utp; utp = utp->next) 03482 writer->ops->write_uploaded_tp (writer, utp); 03483 03484 free_uploaded_tps (&uploaded_tps); 03485 03486 /* Mark the end of the definition section. */ 03487 writer->ops->write_definition_end (writer); 03488 03489 /* Get and write the trace data proper. */ 03490 while (1) 03491 { 03492 LONGEST gotten = 0; 03493 03494 /* The writer supports writing the contents of trace buffer 03495 directly to trace file. Don't parse the contents of trace 03496 buffer. */ 03497 if (writer->ops->write_trace_buffer != NULL) 03498 { 03499 /* We ask for big blocks, in the hopes of efficiency, but 03500 will take less if the target has packet size limitations 03501 or some such. */ 03502 gotten = target_get_raw_trace_data (buf, offset, 03503 MAX_TRACE_UPLOAD); 03504 if (gotten < 0) 03505 error (_("Failure to get requested trace buffer data")); 03506 /* No more data is forthcoming, we're done. */ 03507 if (gotten == 0) 03508 break; 03509 03510 writer->ops->write_trace_buffer (writer, buf, gotten); 03511 03512 offset += gotten; 03513 } 03514 else 03515 { 03516 uint16_t tp_num; 03517 uint32_t tf_size; 03518 /* Parse the trace buffers according to how data are stored 03519 in trace buffer in GDBserver. */ 03520 03521 gotten = target_get_raw_trace_data (buf, offset, 6); 03522 03523 if (gotten == 0) 03524 break; 03525 03526 /* Read the first six bytes in, which is the tracepoint 03527 number and trace frame size. */ 03528 tp_num = (uint16_t) 03529 extract_unsigned_integer (&buf[0], 2, byte_order); 03530 03531 tf_size = (uint32_t) 03532 extract_unsigned_integer (&buf[2], 4, byte_order); 03533 03534 writer->ops->frame_ops->start (writer, tp_num); 03535 gotten = 6; 03536 03537 if (tf_size > 0) 03538 { 03539 unsigned int block; 03540 03541 offset += 6; 03542 03543 for (block = 0; block < tf_size; ) 03544 { 03545 gdb_byte block_type; 03546 03547 /* We'll fetch one block each time, in order to 03548 handle the extremely large 'M' block. We first 03549 fetch one byte to get the type of the block. */ 03550 gotten = target_get_raw_trace_data (buf, offset, 1); 03551 if (gotten < 1) 03552 error (_("Failure to get requested trace buffer data")); 03553 03554 gotten = 1; 03555 block += 1; 03556 offset += 1; 03557 03558 block_type = buf[0]; 03559 switch (block_type) 03560 { 03561 case 'R': 03562 gotten 03563 = target_get_raw_trace_data (buf, offset, 03564 trace_regblock_size); 03565 if (gotten < trace_regblock_size) 03566 error (_("Failure to get requested trace" 03567 " buffer data")); 03568 03569 TRACE_WRITE_R_BLOCK (writer, buf, 03570 trace_regblock_size); 03571 break; 03572 case 'M': 03573 { 03574 unsigned short mlen; 03575 ULONGEST addr; 03576 LONGEST t; 03577 int j; 03578 03579 t = target_get_raw_trace_data (buf,offset, 10); 03580 if (t < 10) 03581 error (_("Failure to get requested trace" 03582 " buffer data")); 03583 03584 offset += 10; 03585 block += 10; 03586 03587 gotten = 0; 03588 addr = (ULONGEST) 03589 extract_unsigned_integer (buf, 8, 03590 byte_order); 03591 mlen = (unsigned short) 03592 extract_unsigned_integer (&buf[8], 2, 03593 byte_order); 03594 03595 TRACE_WRITE_M_BLOCK_HEADER (writer, addr, 03596 mlen); 03597 03598 /* The memory contents in 'M' block may be 03599 very large. Fetch the data from the target 03600 and write them into file one by one. */ 03601 for (j = 0; j < mlen; ) 03602 { 03603 unsigned int read_length; 03604 03605 if (mlen - j > MAX_TRACE_UPLOAD) 03606 read_length = MAX_TRACE_UPLOAD; 03607 else 03608 read_length = mlen - j; 03609 03610 t = target_get_raw_trace_data (buf, 03611 offset + j, 03612 read_length); 03613 if (t < read_length) 03614 error (_("Failure to get requested" 03615 " trace buffer data")); 03616 03617 TRACE_WRITE_M_BLOCK_MEMORY (writer, buf, 03618 read_length); 03619 03620 j += read_length; 03621 gotten += read_length; 03622 } 03623 03624 break; 03625 } 03626 case 'V': 03627 { 03628 int vnum; 03629 LONGEST val; 03630 03631 gotten 03632 = target_get_raw_trace_data (buf, offset, 03633 12); 03634 if (gotten < 12) 03635 error (_("Failure to get requested" 03636 " trace buffer data")); 03637 03638 vnum = (int) extract_signed_integer (buf, 03639 4, 03640 byte_order); 03641 val 03642 = extract_signed_integer (&buf[4], 8, 03643 byte_order); 03644 03645 TRACE_WRITE_V_BLOCK (writer, vnum, val); 03646 } 03647 break; 03648 default: 03649 error (_("Unknown block type '%c' (0x%x) in" 03650 " trace frame"), 03651 block_type, block_type); 03652 } 03653 03654 block += gotten; 03655 offset += gotten; 03656 } 03657 } 03658 else 03659 offset += gotten; 03660 03661 writer->ops->frame_ops->end (writer); 03662 } 03663 } 03664 03665 writer->ops->end (writer); 03666 } 03667 03668 /* Return a trace writer for TFILE format. */ 03669 03670 static struct trace_file_writer * 03671 tfile_trace_file_writer_new (void) 03672 { 03673 struct tfile_trace_file_writer *writer 03674 = xmalloc (sizeof (struct tfile_trace_file_writer)); 03675 03676 writer->base.ops = &tfile_write_ops; 03677 writer->fp = NULL; 03678 writer->pathname = NULL; 03679 03680 return (struct trace_file_writer *) writer; 03681 } 03682 03683 static void 03684 trace_save_command (char *args, int from_tty) 03685 { 03686 int target_does_save = 0; 03687 char **argv; 03688 char *filename = NULL; 03689 struct cleanup *back_to; 03690 int generate_ctf = 0; 03691 struct trace_file_writer *writer = NULL; 03692 03693 if (args == NULL) 03694 error_no_arg (_("file in which to save trace data")); 03695 03696 argv = gdb_buildargv (args); 03697 back_to = make_cleanup_freeargv (argv); 03698 03699 for (; *argv; ++argv) 03700 { 03701 if (strcmp (*argv, "-r") == 0) 03702 target_does_save = 1; 03703 if (strcmp (*argv, "-ctf") == 0) 03704 generate_ctf = 1; 03705 else if (**argv == '-') 03706 error (_("unknown option `%s'"), *argv); 03707 else 03708 filename = *argv; 03709 } 03710 03711 if (!filename) 03712 error_no_arg (_("file in which to save trace data")); 03713 03714 if (generate_ctf) 03715 writer = ctf_trace_file_writer_new (); 03716 else 03717 writer = tfile_trace_file_writer_new (); 03718 03719 make_cleanup (trace_file_writer_xfree, writer); 03720 03721 trace_save (filename, writer, target_does_save); 03722 03723 if (from_tty) 03724 printf_filtered (_("Trace data saved to %s '%s'.\n"), 03725 generate_ctf ? "directory" : "file", filename); 03726 03727 do_cleanups (back_to); 03728 } 03729 03730 /* Save the trace data to file FILENAME of tfile format. */ 03731 03732 void 03733 trace_save_tfile (const char *filename, int target_does_save) 03734 { 03735 struct trace_file_writer *writer; 03736 struct cleanup *back_to; 03737 03738 writer = tfile_trace_file_writer_new (); 03739 back_to = make_cleanup (trace_file_writer_xfree, writer); 03740 trace_save (filename, writer, target_does_save); 03741 do_cleanups (back_to); 03742 } 03743 03744 /* Save the trace data to dir DIRNAME of ctf format. */ 03745 03746 void 03747 trace_save_ctf (const char *dirname, int target_does_save) 03748 { 03749 struct trace_file_writer *writer; 03750 struct cleanup *back_to; 03751 03752 writer = ctf_trace_file_writer_new (); 03753 back_to = make_cleanup (trace_file_writer_xfree, writer); 03754 03755 trace_save (dirname, writer, target_does_save); 03756 do_cleanups (back_to); 03757 } 03758 03759 /* Tell the target what to do with an ongoing tracing run if GDB 03760 disconnects for some reason. */ 03761 03762 static void 03763 set_disconnected_tracing (char *args, int from_tty, 03764 struct cmd_list_element *c) 03765 { 03766 target_set_disconnected_tracing (disconnected_tracing); 03767 } 03768 03769 static void 03770 set_circular_trace_buffer (char *args, int from_tty, 03771 struct cmd_list_element *c) 03772 { 03773 target_set_circular_trace_buffer (circular_trace_buffer); 03774 } 03775 03776 static void 03777 set_trace_buffer_size (char *args, int from_tty, 03778 struct cmd_list_element *c) 03779 { 03780 target_set_trace_buffer_size (trace_buffer_size); 03781 } 03782 03783 static void 03784 set_trace_user (char *args, int from_tty, 03785 struct cmd_list_element *c) 03786 { 03787 int ret; 03788 03789 ret = target_set_trace_notes (trace_user, NULL, NULL); 03790 03791 if (!ret) 03792 warning (_("Target does not support trace notes, user ignored")); 03793 } 03794 03795 static void 03796 set_trace_notes (char *args, int from_tty, 03797 struct cmd_list_element *c) 03798 { 03799 int ret; 03800 03801 ret = target_set_trace_notes (NULL, trace_notes, NULL); 03802 03803 if (!ret) 03804 warning (_("Target does not support trace notes, note ignored")); 03805 } 03806 03807 static void 03808 set_trace_stop_notes (char *args, int from_tty, 03809 struct cmd_list_element *c) 03810 { 03811 int ret; 03812 03813 ret = target_set_trace_notes (NULL, NULL, trace_stop_notes); 03814 03815 if (!ret) 03816 warning (_("Target does not support trace notes, stop note ignored")); 03817 } 03818 03819 /* Convert the memory pointed to by mem into hex, placing result in buf. 03820 * Return a pointer to the last char put in buf (null) 03821 * "stolen" from sparc-stub.c 03822 */ 03823 03824 static const char hexchars[] = "0123456789abcdef"; 03825 03826 static char * 03827 mem2hex (gdb_byte *mem, char *buf, int count) 03828 { 03829 gdb_byte ch; 03830 03831 while (count-- > 0) 03832 { 03833 ch = *mem++; 03834 03835 *buf++ = hexchars[ch >> 4]; 03836 *buf++ = hexchars[ch & 0xf]; 03837 } 03838 03839 *buf = 0; 03840 03841 return buf; 03842 } 03843 03844 int 03845 get_traceframe_number (void) 03846 { 03847 return traceframe_number; 03848 } 03849 03850 int 03851 get_tracepoint_number (void) 03852 { 03853 return tracepoint_number; 03854 } 03855 03856 /* Make the traceframe NUM be the current trace frame. Does nothing 03857 if NUM is already current. */ 03858 03859 void 03860 set_current_traceframe (int num) 03861 { 03862 int newnum; 03863 03864 if (traceframe_number == num) 03865 { 03866 /* Nothing to do. */ 03867 return; 03868 } 03869 03870 newnum = target_trace_find (tfind_number, num, 0, 0, NULL); 03871 03872 if (newnum != num) 03873 warning (_("could not change traceframe")); 03874 03875 set_traceframe_num (newnum); 03876 03877 /* Changing the traceframe changes our view of registers and of the 03878 frame chain. */ 03879 registers_changed (); 03880 03881 clear_traceframe_info (); 03882 } 03883 03884 /* Make the traceframe NUM be the current trace frame, and do nothing 03885 more. */ 03886 03887 void 03888 set_traceframe_number (int num) 03889 { 03890 traceframe_number = num; 03891 } 03892 03893 /* A cleanup used when switching away and back from tfind mode. */ 03894 03895 struct current_traceframe_cleanup 03896 { 03897 /* The traceframe we were inspecting. */ 03898 int traceframe_number; 03899 }; 03900 03901 static void 03902 do_restore_current_traceframe_cleanup (void *arg) 03903 { 03904 struct current_traceframe_cleanup *old = arg; 03905 03906 set_current_traceframe (old->traceframe_number); 03907 } 03908 03909 static void 03910 restore_current_traceframe_cleanup_dtor (void *arg) 03911 { 03912 struct current_traceframe_cleanup *old = arg; 03913 03914 xfree (old); 03915 } 03916 03917 struct cleanup * 03918 make_cleanup_restore_current_traceframe (void) 03919 { 03920 struct current_traceframe_cleanup *old; 03921 03922 old = xmalloc (sizeof (struct current_traceframe_cleanup)); 03923 old->traceframe_number = traceframe_number; 03924 03925 return make_cleanup_dtor (do_restore_current_traceframe_cleanup, old, 03926 restore_current_traceframe_cleanup_dtor); 03927 } 03928 03929 struct cleanup * 03930 make_cleanup_restore_traceframe_number (void) 03931 { 03932 return make_cleanup_restore_integer (&traceframe_number); 03933 } 03934 03935 /* Given a number and address, return an uploaded tracepoint with that 03936 number, creating if necessary. */ 03937 03938 struct uploaded_tp * 03939 get_uploaded_tp (int num, ULONGEST addr, struct uploaded_tp **utpp) 03940 { 03941 struct uploaded_tp *utp; 03942 03943 for (utp = *utpp; utp; utp = utp->next) 03944 if (utp->number == num && utp->addr == addr) 03945 return utp; 03946 utp = (struct uploaded_tp *) xmalloc (sizeof (struct uploaded_tp)); 03947 memset (utp, 0, sizeof (struct uploaded_tp)); 03948 utp->number = num; 03949 utp->addr = addr; 03950 utp->actions = NULL; 03951 utp->step_actions = NULL; 03952 utp->cmd_strings = NULL; 03953 utp->next = *utpp; 03954 *utpp = utp; 03955 return utp; 03956 } 03957 03958 static void 03959 free_uploaded_tps (struct uploaded_tp **utpp) 03960 { 03961 struct uploaded_tp *next_one; 03962 03963 while (*utpp) 03964 { 03965 next_one = (*utpp)->next; 03966 xfree (*utpp); 03967 *utpp = next_one; 03968 } 03969 } 03970 03971 /* Given a number and address, return an uploaded tracepoint with that 03972 number, creating if necessary. */ 03973 03974 struct uploaded_tsv * 03975 get_uploaded_tsv (int num, struct uploaded_tsv **utsvp) 03976 { 03977 struct uploaded_tsv *utsv; 03978 03979 for (utsv = *utsvp; utsv; utsv = utsv->next) 03980 if (utsv->number == num) 03981 return utsv; 03982 utsv = (struct uploaded_tsv *) xmalloc (sizeof (struct uploaded_tsv)); 03983 memset (utsv, 0, sizeof (struct uploaded_tsv)); 03984 utsv->number = num; 03985 utsv->next = *utsvp; 03986 *utsvp = utsv; 03987 return utsv; 03988 } 03989 03990 static void 03991 free_uploaded_tsvs (struct uploaded_tsv **utsvp) 03992 { 03993 struct uploaded_tsv *next_one; 03994 03995 while (*utsvp) 03996 { 03997 next_one = (*utsvp)->next; 03998 xfree (*utsvp); 03999 *utsvp = next_one; 04000 } 04001 } 04002 04003 /* FIXME this function is heuristic and will miss the cases where the 04004 conditional is semantically identical but differs in whitespace, 04005 such as "x == 0" vs "x==0". */ 04006 04007 static int 04008 cond_string_is_same (char *str1, char *str2) 04009 { 04010 if (str1 == NULL || str2 == NULL) 04011 return (str1 == str2); 04012 04013 return (strcmp (str1, str2) == 0); 04014 } 04015 04016 /* Look for an existing tracepoint that seems similar enough to the 04017 uploaded one. Enablement isn't compared, because the user can 04018 toggle that freely, and may have done so in anticipation of the 04019 next trace run. Return the location of matched tracepoint. */ 04020 04021 static struct bp_location * 04022 find_matching_tracepoint_location (struct uploaded_tp *utp) 04023 { 04024 VEC(breakpoint_p) *tp_vec = all_tracepoints (); 04025 int ix; 04026 struct breakpoint *b; 04027 struct bp_location *loc; 04028 04029 for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++) 04030 { 04031 struct tracepoint *t = (struct tracepoint *) b; 04032 04033 if (b->type == utp->type 04034 && t->step_count == utp->step 04035 && t->pass_count == utp->pass 04036 && cond_string_is_same (t->base.cond_string, utp->cond_string) 04037 /* FIXME also test actions. */ 04038 ) 04039 { 04040 /* Scan the locations for an address match. */ 04041 for (loc = b->loc; loc; loc = loc->next) 04042 { 04043 if (loc->address == utp->addr) 04044 return loc; 04045 } 04046 } 04047 } 04048 return NULL; 04049 } 04050 04051 /* Given a list of tracepoints uploaded from a target, attempt to 04052 match them up with existing tracepoints, and create new ones if not 04053 found. */ 04054 04055 void 04056 merge_uploaded_tracepoints (struct uploaded_tp **uploaded_tps) 04057 { 04058 struct uploaded_tp *utp; 04059 /* A set of tracepoints which are modified. */ 04060 VEC(breakpoint_p) *modified_tp = NULL; 04061 int ix; 04062 struct breakpoint *b; 04063 04064 /* Look for GDB tracepoints that match up with our uploaded versions. */ 04065 for (utp = *uploaded_tps; utp; utp = utp->next) 04066 { 04067 struct bp_location *loc; 04068 struct tracepoint *t; 04069 04070 loc = find_matching_tracepoint_location (utp); 04071 if (loc) 04072 { 04073 int found = 0; 04074 04075 /* Mark this location as already inserted. */ 04076 loc->inserted = 1; 04077 t = (struct tracepoint *) loc->owner; 04078 printf_filtered (_("Assuming tracepoint %d is same " 04079 "as target's tracepoint %d at %s.\n"), 04080 loc->owner->number, utp->number, 04081 paddress (loc->gdbarch, utp->addr)); 04082 04083 /* The tracepoint LOC->owner was modified (the location LOC 04084 was marked as inserted in the target). Save it in 04085 MODIFIED_TP if not there yet. The 'breakpoint-modified' 04086 observers will be notified later once for each tracepoint 04087 saved in MODIFIED_TP. */ 04088 for (ix = 0; 04089 VEC_iterate (breakpoint_p, modified_tp, ix, b); 04090 ix++) 04091 if (b == loc->owner) 04092 { 04093 found = 1; 04094 break; 04095 } 04096 if (!found) 04097 VEC_safe_push (breakpoint_p, modified_tp, loc->owner); 04098 } 04099 else 04100 { 04101 t = create_tracepoint_from_upload (utp); 04102 if (t) 04103 printf_filtered (_("Created tracepoint %d for " 04104 "target's tracepoint %d at %s.\n"), 04105 t->base.number, utp->number, 04106 paddress (get_current_arch (), utp->addr)); 04107 else 04108 printf_filtered (_("Failed to create tracepoint for target's " 04109 "tracepoint %d at %s, skipping it.\n"), 04110 utp->number, 04111 paddress (get_current_arch (), utp->addr)); 04112 } 04113 /* Whether found or created, record the number used by the 04114 target, to help with mapping target tracepoints back to their 04115 counterparts here. */ 04116 if (t) 04117 t->number_on_target = utp->number; 04118 } 04119 04120 /* Notify 'breakpoint-modified' observer that at least one of B's 04121 locations was changed. */ 04122 for (ix = 0; VEC_iterate (breakpoint_p, modified_tp, ix, b); ix++) 04123 observer_notify_breakpoint_modified (b); 04124 04125 VEC_free (breakpoint_p, modified_tp); 04126 free_uploaded_tps (uploaded_tps); 04127 } 04128 04129 /* Trace state variables don't have much to identify them beyond their 04130 name, so just use that to detect matches. */ 04131 04132 static struct trace_state_variable * 04133 find_matching_tsv (struct uploaded_tsv *utsv) 04134 { 04135 if (!utsv->name) 04136 return NULL; 04137 04138 return find_trace_state_variable (utsv->name); 04139 } 04140 04141 static struct trace_state_variable * 04142 create_tsv_from_upload (struct uploaded_tsv *utsv) 04143 { 04144 const char *namebase; 04145 char *buf; 04146 int try_num = 0; 04147 struct trace_state_variable *tsv; 04148 struct cleanup *old_chain; 04149 04150 if (utsv->name) 04151 { 04152 namebase = utsv->name; 04153 buf = xstrprintf ("%s", namebase); 04154 } 04155 else 04156 { 04157 namebase = "__tsv"; 04158 buf = xstrprintf ("%s_%d", namebase, try_num++); 04159 } 04160 04161 /* Fish for a name that is not in use. */ 04162 /* (should check against all internal vars?) */ 04163 while (find_trace_state_variable (buf)) 04164 { 04165 xfree (buf); 04166 buf = xstrprintf ("%s_%d", namebase, try_num++); 04167 } 04168 04169 old_chain = make_cleanup (xfree, buf); 04170 04171 /* We have an available name, create the variable. */ 04172 tsv = create_trace_state_variable (buf); 04173 tsv->initial_value = utsv->initial_value; 04174 tsv->builtin = utsv->builtin; 04175 04176 observer_notify_tsv_created (tsv); 04177 04178 do_cleanups (old_chain); 04179 04180 return tsv; 04181 } 04182 04183 /* Given a list of uploaded trace state variables, try to match them 04184 up with existing variables, or create additional ones. */ 04185 04186 void 04187 merge_uploaded_trace_state_variables (struct uploaded_tsv **uploaded_tsvs) 04188 { 04189 int ix; 04190 struct uploaded_tsv *utsv; 04191 struct trace_state_variable *tsv; 04192 int highest; 04193 04194 /* Most likely some numbers will have to be reassigned as part of 04195 the merge, so clear them all in anticipation. */ 04196 for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) 04197 tsv->number = 0; 04198 04199 for (utsv = *uploaded_tsvs; utsv; utsv = utsv->next) 04200 { 04201 tsv = find_matching_tsv (utsv); 04202 if (tsv) 04203 { 04204 if (info_verbose) 04205 printf_filtered (_("Assuming trace state variable $%s " 04206 "is same as target's variable %d.\n"), 04207 tsv->name, utsv->number); 04208 } 04209 else 04210 { 04211 tsv = create_tsv_from_upload (utsv); 04212 if (info_verbose) 04213 printf_filtered (_("Created trace state variable " 04214 "$%s for target's variable %d.\n"), 04215 tsv->name, utsv->number); 04216 } 04217 /* Give precedence to numberings that come from the target. */ 04218 if (tsv) 04219 tsv->number = utsv->number; 04220 } 04221 04222 /* Renumber everything that didn't get a target-assigned number. */ 04223 highest = 0; 04224 for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) 04225 if (tsv->number > highest) 04226 highest = tsv->number; 04227 04228 ++highest; 04229 for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix) 04230 if (tsv->number == 0) 04231 tsv->number = highest++; 04232 04233 free_uploaded_tsvs (uploaded_tsvs); 04234 } 04235 04236 /* target tfile command */ 04237 04238 static struct target_ops tfile_ops; 04239 04240 /* Fill in tfile_ops with its defined operations and properties. */ 04241 04242 #define TRACE_HEADER_SIZE 8 04243 04244 static char *trace_filename; 04245 static int trace_fd = -1; 04246 static off_t trace_frames_offset; 04247 static off_t cur_offset; 04248 static int cur_data_size; 04249 int trace_regblock_size; 04250 04251 static void tfile_interp_line (char *line, 04252 struct uploaded_tp **utpp, 04253 struct uploaded_tsv **utsvp); 04254 04255 /* Read SIZE bytes into READBUF from the trace frame, starting at 04256 TRACE_FD's current position. Note that this call `read' 04257 underneath, hence it advances the file's seek position. Throws an 04258 error if the `read' syscall fails, or less than SIZE bytes are 04259 read. */ 04260 04261 static void 04262 tfile_read (gdb_byte *readbuf, int size) 04263 { 04264 int gotten; 04265 04266 gotten = read (trace_fd, readbuf, size); 04267 if (gotten < 0) 04268 perror_with_name (trace_filename); 04269 else if (gotten < size) 04270 error (_("Premature end of file while reading trace file")); 04271 } 04272 04273 static void 04274 tfile_open (char *filename, int from_tty) 04275 { 04276 volatile struct gdb_exception ex; 04277 char *temp; 04278 struct cleanup *old_chain; 04279 int flags; 04280 int scratch_chan; 04281 char header[TRACE_HEADER_SIZE]; 04282 char linebuf[1000]; /* Should be max remote packet size or so. */ 04283 gdb_byte byte; 04284 int bytes, i; 04285 struct trace_status *ts; 04286 struct uploaded_tp *uploaded_tps = NULL; 04287 struct uploaded_tsv *uploaded_tsvs = NULL; 04288 04289 target_preopen (from_tty); 04290 if (!filename) 04291 error (_("No trace file specified.")); 04292 04293 filename = tilde_expand (filename); 04294 if (!IS_ABSOLUTE_PATH(filename)) 04295 { 04296 temp = concat (current_directory, "/", filename, (char *) NULL); 04297 xfree (filename); 04298 filename = temp; 04299 } 04300 04301 old_chain = make_cleanup (xfree, filename); 04302 04303 flags = O_BINARY | O_LARGEFILE; 04304 flags |= O_RDONLY; 04305 scratch_chan = gdb_open_cloexec (filename, flags, 0); 04306 if (scratch_chan < 0) 04307 perror_with_name (filename); 04308 04309 /* Looks semi-reasonable. Toss the old trace file and work on the new. */ 04310 04311 discard_cleanups (old_chain); /* Don't free filename any more. */ 04312 unpush_target (&tfile_ops); 04313 04314 trace_filename = xstrdup (filename); 04315 trace_fd = scratch_chan; 04316 04317 bytes = 0; 04318 /* Read the file header and test for validity. */ 04319 tfile_read ((gdb_byte *) &header, TRACE_HEADER_SIZE); 04320 04321 bytes += TRACE_HEADER_SIZE; 04322 if (!(header[0] == 0x7f 04323 && (strncmp (header + 1, "TRACE0\n", 7) == 0))) 04324 error (_("File is not a valid trace file.")); 04325 04326 push_target (&tfile_ops); 04327 04328 trace_regblock_size = 0; 04329 ts = current_trace_status (); 04330 /* We know we're working with a file. Record its name. */ 04331 ts->filename = trace_filename; 04332 /* Set defaults in case there is no status line. */ 04333 ts->running_known = 0; 04334 ts->stop_reason = trace_stop_reason_unknown; 04335 ts->traceframe_count = -1; 04336 ts->buffer_free = 0; 04337 ts->disconnected_tracing = 0; 04338 ts->circular_buffer = 0; 04339 04340 TRY_CATCH (ex, RETURN_MASK_ALL) 04341 { 04342 /* Read through a section of newline-terminated lines that 04343 define things like tracepoints. */ 04344 i = 0; 04345 while (1) 04346 { 04347 tfile_read (&byte, 1); 04348 04349 ++bytes; 04350 if (byte == '\n') 04351 { 04352 /* Empty line marks end of the definition section. */ 04353 if (i == 0) 04354 break; 04355 linebuf[i] = '\0'; 04356 i = 0; 04357 tfile_interp_line (linebuf, &uploaded_tps, &uploaded_tsvs); 04358 } 04359 else 04360 linebuf[i++] = byte; 04361 if (i >= 1000) 04362 error (_("Excessively long lines in trace file")); 04363 } 04364 04365 /* Record the starting offset of the binary trace data. */ 04366 trace_frames_offset = bytes; 04367 04368 /* If we don't have a blocksize, we can't interpret the 04369 traceframes. */ 04370 if (trace_regblock_size == 0) 04371 error (_("No register block size recorded in trace file")); 04372 } 04373 if (ex.reason < 0) 04374 { 04375 /* Remove the partially set up target. */ 04376 unpush_target (&tfile_ops); 04377 throw_exception (ex); 04378 } 04379 04380 if (ts->traceframe_count <= 0) 04381 warning (_("No traceframes present in this file.")); 04382 04383 /* Add the file's tracepoints and variables into the current mix. */ 04384 04385 /* Get trace state variables first, they may be checked when parsing 04386 uploaded commands. */ 04387 merge_uploaded_trace_state_variables (&uploaded_tsvs); 04388 04389 merge_uploaded_tracepoints (&uploaded_tps); 04390 } 04391 04392 /* Interpret the given line from the definitions part of the trace 04393 file. */ 04394 04395 static void 04396 tfile_interp_line (char *line, struct uploaded_tp **utpp, 04397 struct uploaded_tsv **utsvp) 04398 { 04399 char *p = line; 04400 04401 if (strncmp (p, "R ", strlen ("R ")) == 0) 04402 { 04403 p += strlen ("R "); 04404 trace_regblock_size = strtol (p, &p, 16); 04405 } 04406 else if (strncmp (p, "status ", strlen ("status ")) == 0) 04407 { 04408 p += strlen ("status "); 04409 parse_trace_status (p, current_trace_status ()); 04410 } 04411 else if (strncmp (p, "tp ", strlen ("tp ")) == 0) 04412 { 04413 p += strlen ("tp "); 04414 parse_tracepoint_definition (p, utpp); 04415 } 04416 else if (strncmp (p, "tsv ", strlen ("tsv ")) == 0) 04417 { 04418 p += strlen ("tsv "); 04419 parse_tsv_definition (p, utsvp); 04420 } 04421 else 04422 warning (_("Ignoring trace file definition \"%s\""), line); 04423 } 04424 04425 /* Parse the part of trace status syntax that is shared between 04426 the remote protocol and the trace file reader. */ 04427 04428 void 04429 parse_trace_status (char *line, struct trace_status *ts) 04430 { 04431 char *p = line, *p1, *p2, *p3, *p_temp; 04432 int end; 04433 ULONGEST val; 04434 04435 ts->running_known = 1; 04436 ts->running = (*p++ == '1'); 04437 ts->stop_reason = trace_stop_reason_unknown; 04438 xfree (ts->stop_desc); 04439 ts->stop_desc = NULL; 04440 ts->traceframe_count = -1; 04441 ts->traceframes_created = -1; 04442 ts->buffer_free = -1; 04443 ts->buffer_size = -1; 04444 ts->disconnected_tracing = 0; 04445 ts->circular_buffer = 0; 04446 xfree (ts->user_name); 04447 ts->user_name = NULL; 04448 xfree (ts->notes); 04449 ts->notes = NULL; 04450 ts->start_time = ts->stop_time = 0; 04451 04452 while (*p++) 04453 { 04454 p1 = strchr (p, ':'); 04455 if (p1 == NULL) 04456 error (_("Malformed trace status, at %s\n\ 04457 Status line: '%s'\n"), p, line); 04458 p3 = strchr (p, ';'); 04459 if (p3 == NULL) 04460 p3 = p + strlen (p); 04461 if (strncmp (p, stop_reason_names[trace_buffer_full], p1 - p) == 0) 04462 { 04463 p = unpack_varlen_hex (++p1, &val); 04464 ts->stop_reason = trace_buffer_full; 04465 } 04466 else if (strncmp (p, stop_reason_names[trace_never_run], p1 - p) == 0) 04467 { 04468 p = unpack_varlen_hex (++p1, &val); 04469 ts->stop_reason = trace_never_run; 04470 } 04471 else if (strncmp (p, stop_reason_names[tracepoint_passcount], 04472 p1 - p) == 0) 04473 { 04474 p = unpack_varlen_hex (++p1, &val); 04475 ts->stop_reason = tracepoint_passcount; 04476 ts->stopping_tracepoint = val; 04477 } 04478 else if (strncmp (p, stop_reason_names[tstop_command], p1 - p) == 0) 04479 { 04480 p2 = strchr (++p1, ':'); 04481 if (!p2 || p2 > p3) 04482 { 04483 /*older style*/ 04484 p2 = p1; 04485 } 04486 else if (p2 != p1) 04487 { 04488 ts->stop_desc = xmalloc (strlen (line)); 04489 end = hex2bin (p1, (gdb_byte *) ts->stop_desc, (p2 - p1) / 2); 04490 ts->stop_desc[end] = '\0'; 04491 } 04492 else 04493 ts->stop_desc = xstrdup (""); 04494 04495 p = unpack_varlen_hex (++p2, &val); 04496 ts->stop_reason = tstop_command; 04497 } 04498 else if (strncmp (p, stop_reason_names[trace_disconnected], p1 - p) == 0) 04499 { 04500 p = unpack_varlen_hex (++p1, &val); 04501 ts->stop_reason = trace_disconnected; 04502 } 04503 else if (strncmp (p, stop_reason_names[tracepoint_error], p1 - p) == 0) 04504 { 04505 p2 = strchr (++p1, ':'); 04506 if (p2 != p1) 04507 { 04508 ts->stop_desc = xmalloc ((p2 - p1) / 2 + 1); 04509 end = hex2bin (p1, (gdb_byte *) ts->stop_desc, (p2 - p1) / 2); 04510 ts->stop_desc[end] = '\0'; 04511 } 04512 else 04513 ts->stop_desc = xstrdup (""); 04514 04515 p = unpack_varlen_hex (++p2, &val); 04516 ts->stopping_tracepoint = val; 04517 ts->stop_reason = tracepoint_error; 04518 } 04519 else if (strncmp (p, "tframes", p1 - p) == 0) 04520 { 04521 p = unpack_varlen_hex (++p1, &val); 04522 ts->traceframe_count = val; 04523 } 04524 else if (strncmp (p, "tcreated", p1 - p) == 0) 04525 { 04526 p = unpack_varlen_hex (++p1, &val); 04527 ts->traceframes_created = val; 04528 } 04529 else if (strncmp (p, "tfree", p1 - p) == 0) 04530 { 04531 p = unpack_varlen_hex (++p1, &val); 04532 ts->buffer_free = val; 04533 } 04534 else if (strncmp (p, "tsize", p1 - p) == 0) 04535 { 04536 p = unpack_varlen_hex (++p1, &val); 04537 ts->buffer_size = val; 04538 } 04539 else if (strncmp (p, "disconn", p1 - p) == 0) 04540 { 04541 p = unpack_varlen_hex (++p1, &val); 04542 ts->disconnected_tracing = val; 04543 } 04544 else if (strncmp (p, "circular", p1 - p) == 0) 04545 { 04546 p = unpack_varlen_hex (++p1, &val); 04547 ts->circular_buffer = val; 04548 } 04549 else if (strncmp (p, "starttime", p1 - p) == 0) 04550 { 04551 p = unpack_varlen_hex (++p1, &val); 04552 ts->start_time = val; 04553 } 04554 else if (strncmp (p, "stoptime", p1 - p) == 0) 04555 { 04556 p = unpack_varlen_hex (++p1, &val); 04557 ts->stop_time = val; 04558 } 04559 else if (strncmp (p, "username", p1 - p) == 0) 04560 { 04561 ++p1; 04562 ts->user_name = xmalloc (strlen (p) / 2); 04563 end = hex2bin (p1, (gdb_byte *) ts->user_name, (p3 - p1) / 2); 04564 ts->user_name[end] = '\0'; 04565 p = p3; 04566 } 04567 else if (strncmp (p, "notes", p1 - p) == 0) 04568 { 04569 ++p1; 04570 ts->notes = xmalloc (strlen (p) / 2); 04571 end = hex2bin (p1, (gdb_byte *) ts->notes, (p3 - p1) / 2); 04572 ts->notes[end] = '\0'; 04573 p = p3; 04574 } 04575 else 04576 { 04577 /* Silently skip unknown optional info. */ 04578 p_temp = strchr (p1 + 1, ';'); 04579 if (p_temp) 04580 p = p_temp; 04581 else 04582 /* Must be at the end. */ 04583 break; 04584 } 04585 } 04586 } 04587 04588 void 04589 parse_tracepoint_status (char *p, struct breakpoint *bp, 04590 struct uploaded_tp *utp) 04591 { 04592 ULONGEST uval; 04593 struct tracepoint *tp = (struct tracepoint *) bp; 04594 04595 p = unpack_varlen_hex (p, &uval); 04596 if (tp) 04597 tp->base.hit_count += uval; 04598 else 04599 utp->hit_count += uval; 04600 p = unpack_varlen_hex (p + 1, &uval); 04601 if (tp) 04602 tp->traceframe_usage += uval; 04603 else 04604 utp->traceframe_usage += uval; 04605 /* Ignore any extra, allowing for future extensions. */ 04606 } 04607 04608 /* Given a line of text defining a part of a tracepoint, parse it into 04609 an "uploaded tracepoint". */ 04610 04611 void 04612 parse_tracepoint_definition (char *line, struct uploaded_tp **utpp) 04613 { 04614 char *p; 04615 char piece; 04616 ULONGEST num, addr, step, pass, orig_size, xlen, start; 04617 int enabled, end; 04618 enum bptype type; 04619 char *cond, *srctype, *buf; 04620 struct uploaded_tp *utp = NULL; 04621 04622 p = line; 04623 /* Both tracepoint and action definitions start with the same number 04624 and address sequence. */ 04625 piece = *p++; 04626 p = unpack_varlen_hex (p, &num); 04627 p++; /* skip a colon */ 04628 p = unpack_varlen_hex (p, &addr); 04629 p++; /* skip a colon */ 04630 if (piece == 'T') 04631 { 04632 enabled = (*p++ == 'E'); 04633 p++; /* skip a colon */ 04634 p = unpack_varlen_hex (p, &step); 04635 p++; /* skip a colon */ 04636 p = unpack_varlen_hex (p, &pass); 04637 type = bp_tracepoint; 04638 cond = NULL; 04639 /* Thumb through optional fields. */ 04640 while (*p == ':') 04641 { 04642 p++; /* skip a colon */ 04643 if (*p == 'F') 04644 { 04645 type = bp_fast_tracepoint; 04646 p++; 04647 p = unpack_varlen_hex (p, &orig_size); 04648 } 04649 else if (*p == 'S') 04650 { 04651 type = bp_static_tracepoint; 04652 p++; 04653 } 04654 else if (*p == 'X') 04655 { 04656 p++; 04657 p = unpack_varlen_hex (p, &xlen); 04658 p++; /* skip a comma */ 04659 cond = (char *) xmalloc (2 * xlen + 1); 04660 strncpy (cond, p, 2 * xlen); 04661 cond[2 * xlen] = '\0'; 04662 p += 2 * xlen; 04663 } 04664 else 04665 warning (_("Unrecognized char '%c' in tracepoint " 04666 "definition, skipping rest"), *p); 04667 } 04668 utp = get_uploaded_tp (num, addr, utpp); 04669 utp->type = type; 04670 utp->enabled = enabled; 04671 utp->step = step; 04672 utp->pass = pass; 04673 utp->cond = cond; 04674 } 04675 else if (piece == 'A') 04676 { 04677 utp = get_uploaded_tp (num, addr, utpp); 04678 VEC_safe_push (char_ptr, utp->actions, xstrdup (p)); 04679 } 04680 else if (piece == 'S') 04681 { 04682 utp = get_uploaded_tp (num, addr, utpp); 04683 VEC_safe_push (char_ptr, utp->step_actions, xstrdup (p)); 04684 } 04685 else if (piece == 'Z') 04686 { 04687 /* Parse a chunk of source form definition. */ 04688 utp = get_uploaded_tp (num, addr, utpp); 04689 srctype = p; 04690 p = strchr (p, ':'); 04691 p++; /* skip a colon */ 04692 p = unpack_varlen_hex (p, &start); 04693 p++; /* skip a colon */ 04694 p = unpack_varlen_hex (p, &xlen); 04695 p++; /* skip a colon */ 04696 04697 buf = alloca (strlen (line)); 04698 04699 end = hex2bin (p, (gdb_byte *) buf, strlen (p) / 2); 04700 buf[end] = '\0'; 04701 04702 if (strncmp (srctype, "at:", strlen ("at:")) == 0) 04703 utp->at_string = xstrdup (buf); 04704 else if (strncmp (srctype, "cond:", strlen ("cond:")) == 0) 04705 utp->cond_string = xstrdup (buf); 04706 else if (strncmp (srctype, "cmd:", strlen ("cmd:")) == 0) 04707 VEC_safe_push (char_ptr, utp->cmd_strings, xstrdup (buf)); 04708 } 04709 else if (piece == 'V') 04710 { 04711 utp = get_uploaded_tp (num, addr, utpp); 04712 04713 parse_tracepoint_status (p, NULL, utp); 04714 } 04715 else 04716 { 04717 /* Don't error out, the target might be sending us optional 04718 info that we don't care about. */ 04719 warning (_("Unrecognized tracepoint piece '%c', ignoring"), piece); 04720 } 04721 } 04722 04723 /* Convert a textual description of a trace state variable into an 04724 uploaded object. */ 04725 04726 void 04727 parse_tsv_definition (char *line, struct uploaded_tsv **utsvp) 04728 { 04729 char *p, *buf; 04730 ULONGEST num, initval, builtin; 04731 int end; 04732 struct uploaded_tsv *utsv = NULL; 04733 04734 buf = alloca (strlen (line)); 04735 04736 p = line; 04737 p = unpack_varlen_hex (p, &num); 04738 p++; /* skip a colon */ 04739 p = unpack_varlen_hex (p, &initval); 04740 p++; /* skip a colon */ 04741 p = unpack_varlen_hex (p, &builtin); 04742 p++; /* skip a colon */ 04743 end = hex2bin (p, (gdb_byte *) buf, strlen (p) / 2); 04744 buf[end] = '\0'; 04745 04746 utsv = get_uploaded_tsv (num, utsvp); 04747 utsv->initial_value = initval; 04748 utsv->builtin = builtin; 04749 utsv->name = xstrdup (buf); 04750 } 04751 04752 /* Close the trace file and generally clean up. */ 04753 04754 static void 04755 tfile_close (void) 04756 { 04757 int pid; 04758 04759 if (trace_fd < 0) 04760 return; 04761 04762 close (trace_fd); 04763 trace_fd = -1; 04764 xfree (trace_filename); 04765 trace_filename = NULL; 04766 04767 trace_reset_local_state (); 04768 } 04769 04770 static void 04771 tfile_files_info (struct target_ops *t) 04772 { 04773 printf_filtered ("\t`%s'\n", trace_filename); 04774 } 04775 04776 /* The trace status for a file is that tracing can never be run. */ 04777 04778 static int 04779 tfile_get_trace_status (struct trace_status *ts) 04780 { 04781 /* Other bits of trace status were collected as part of opening the 04782 trace files, so nothing to do here. */ 04783 04784 return -1; 04785 } 04786 04787 static void 04788 tfile_get_tracepoint_status (struct breakpoint *tp, struct uploaded_tp *utp) 04789 { 04790 /* Other bits of trace status were collected as part of opening the 04791 trace files, so nothing to do here. */ 04792 } 04793 04794 /* Given the position of a traceframe in the file, figure out what 04795 address the frame was collected at. This would normally be the 04796 value of a collected PC register, but if not available, we 04797 improvise. */ 04798 04799 static CORE_ADDR 04800 tfile_get_traceframe_address (off_t tframe_offset) 04801 { 04802 CORE_ADDR addr = 0; 04803 short tpnum; 04804 struct tracepoint *tp; 04805 off_t saved_offset = cur_offset; 04806 04807 /* FIXME dig pc out of collected registers. */ 04808 04809 /* Fall back to using tracepoint address. */ 04810 lseek (trace_fd, tframe_offset, SEEK_SET); 04811 tfile_read ((gdb_byte *) &tpnum, 2); 04812 tpnum = (short) extract_signed_integer ((gdb_byte *) &tpnum, 2, 04813 gdbarch_byte_order 04814 (target_gdbarch ())); 04815 04816 tp = get_tracepoint_by_number_on_target (tpnum); 04817 /* FIXME this is a poor heuristic if multiple locations. */ 04818 if (tp && tp->base.loc) 04819 addr = tp->base.loc->address; 04820 04821 /* Restore our seek position. */ 04822 cur_offset = saved_offset; 04823 lseek (trace_fd, cur_offset, SEEK_SET); 04824 return addr; 04825 } 04826 04827 /* Given a type of search and some parameters, scan the collection of 04828 traceframes in the file looking for a match. When found, return 04829 both the traceframe and tracepoint number, otherwise -1 for 04830 each. */ 04831 04832 static int 04833 tfile_trace_find (enum trace_find_type type, int num, 04834 CORE_ADDR addr1, CORE_ADDR addr2, int *tpp) 04835 { 04836 short tpnum; 04837 int tfnum = 0, found = 0; 04838 unsigned int data_size; 04839 struct tracepoint *tp; 04840 off_t offset, tframe_offset; 04841 CORE_ADDR tfaddr; 04842 04843 if (num == -1) 04844 { 04845 if (tpp) 04846 *tpp = -1; 04847 return -1; 04848 } 04849 04850 lseek (trace_fd, trace_frames_offset, SEEK_SET); 04851 offset = trace_frames_offset; 04852 while (1) 04853 { 04854 tframe_offset = offset; 04855 tfile_read ((gdb_byte *) &tpnum, 2); 04856 tpnum = (short) extract_signed_integer ((gdb_byte *) &tpnum, 2, 04857 gdbarch_byte_order 04858 (target_gdbarch ())); 04859 offset += 2; 04860 if (tpnum == 0) 04861 break; 04862 tfile_read ((gdb_byte *) &data_size, 4); 04863 data_size = (unsigned int) extract_unsigned_integer 04864 ((gdb_byte *) &data_size, 4, 04865 gdbarch_byte_order (target_gdbarch ())); 04866 offset += 4; 04867 04868 if (type == tfind_number) 04869 { 04870 /* Looking for a specific trace frame. */ 04871 if (tfnum == num) 04872 found = 1; 04873 } 04874 else 04875 { 04876 /* Start from the _next_ trace frame. */ 04877 if (tfnum > traceframe_number) 04878 { 04879 switch (type) 04880 { 04881 case tfind_pc: 04882 tfaddr = tfile_get_traceframe_address (tframe_offset); 04883 if (tfaddr == addr1) 04884 found = 1; 04885 break; 04886 case tfind_tp: 04887 tp = get_tracepoint (num); 04888 if (tp && tpnum == tp->number_on_target) 04889 found = 1; 04890 break; 04891 case tfind_range: 04892 tfaddr = tfile_get_traceframe_address (tframe_offset); 04893 if (addr1 <= tfaddr && tfaddr <= addr2) 04894 found = 1; 04895 break; 04896 case tfind_outside: 04897 tfaddr = tfile_get_traceframe_address (tframe_offset); 04898 if (!(addr1 <= tfaddr && tfaddr <= addr2)) 04899 found = 1; 04900 break; 04901 default: 04902 internal_error (__FILE__, __LINE__, _("unknown tfind type")); 04903 } 04904 } 04905 } 04906 04907 if (found) 04908 { 04909 if (tpp) 04910 *tpp = tpnum; 04911 cur_offset = offset; 04912 cur_data_size = data_size; 04913 04914 return tfnum; 04915 } 04916 /* Skip past the traceframe's data. */ 04917 lseek (trace_fd, data_size, SEEK_CUR); 04918 offset += data_size; 04919 /* Update our own count of traceframes. */ 04920 ++tfnum; 04921 } 04922 /* Did not find what we were looking for. */ 04923 if (tpp) 04924 *tpp = -1; 04925 return -1; 04926 } 04927 04928 /* Prototype of the callback passed to tframe_walk_blocks. */ 04929 typedef int (*walk_blocks_callback_func) (char blocktype, void *data); 04930 04931 /* Callback for traceframe_walk_blocks, used to find a given block 04932 type in a traceframe. */ 04933 04934 static int 04935 match_blocktype (char blocktype, void *data) 04936 { 04937 char *wantedp = data; 04938 04939 if (*wantedp == blocktype) 04940 return 1; 04941 04942 return 0; 04943 } 04944 04945 /* Walk over all traceframe block starting at POS offset from 04946 CUR_OFFSET, and call CALLBACK for each block found, passing in DATA 04947 unmodified. If CALLBACK returns true, this returns the position in 04948 the traceframe where the block is found, relative to the start of 04949 the traceframe (cur_offset). Returns -1 if no callback call 04950 returned true, indicating that all blocks have been walked. */ 04951 04952 static int 04953 traceframe_walk_blocks (walk_blocks_callback_func callback, 04954 int pos, void *data) 04955 { 04956 /* Iterate through a traceframe's blocks, looking for a block of the 04957 requested type. */ 04958 04959 lseek (trace_fd, cur_offset + pos, SEEK_SET); 04960 while (pos < cur_data_size) 04961 { 04962 unsigned short mlen; 04963 char block_type; 04964 04965 tfile_read ((gdb_byte *) &block_type, 1); 04966 04967 ++pos; 04968 04969 if ((*callback) (block_type, data)) 04970 return pos; 04971 04972 switch (block_type) 04973 { 04974 case 'R': 04975 lseek (trace_fd, cur_offset + pos + trace_regblock_size, SEEK_SET); 04976 pos += trace_regblock_size; 04977 break; 04978 case 'M': 04979 lseek (trace_fd, cur_offset + pos + 8, SEEK_SET); 04980 tfile_read ((gdb_byte *) &mlen, 2); 04981 mlen = (unsigned short) 04982 extract_unsigned_integer ((gdb_byte *) &mlen, 2, 04983 gdbarch_byte_order 04984 (target_gdbarch ())); 04985 lseek (trace_fd, mlen, SEEK_CUR); 04986 pos += (8 + 2 + mlen); 04987 break; 04988 case 'V': 04989 lseek (trace_fd, cur_offset + pos + 4 + 8, SEEK_SET); 04990 pos += (4 + 8); 04991 break; 04992 default: 04993 error (_("Unknown block type '%c' (0x%x) in trace frame"), 04994 block_type, block_type); 04995 break; 04996 } 04997 } 04998 04999 return -1; 05000 } 05001 05002 /* Convenience wrapper around traceframe_walk_blocks. Looks for the 05003 position offset of a block of type TYPE_WANTED in the current trace 05004 frame, starting at POS. Returns -1 if no such block was found. */ 05005 05006 static int 05007 traceframe_find_block_type (char type_wanted, int pos) 05008 { 05009 return traceframe_walk_blocks (match_blocktype, pos, &type_wanted); 05010 } 05011 05012 /* Look for a block of saved registers in the traceframe, and get the 05013 requested register from it. */ 05014 05015 static void 05016 tfile_fetch_registers (struct target_ops *ops, 05017 struct regcache *regcache, int regno) 05018 { 05019 struct gdbarch *gdbarch = get_regcache_arch (regcache); 05020 int offset, regn, regsize, pc_regno; 05021 gdb_byte *regs; 05022 05023 /* An uninitialized reg size says we're not going to be 05024 successful at getting register blocks. */ 05025 if (!trace_regblock_size) 05026 return; 05027 05028 regs = alloca (trace_regblock_size); 05029 05030 if (traceframe_find_block_type ('R', 0) >= 0) 05031 { 05032 tfile_read (regs, trace_regblock_size); 05033 05034 /* Assume the block is laid out in GDB register number order, 05035 each register with the size that it has in GDB. */ 05036 offset = 0; 05037 for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++) 05038 { 05039 regsize = register_size (gdbarch, regn); 05040 /* Make sure we stay within block bounds. */ 05041 if (offset + regsize >= trace_regblock_size) 05042 break; 05043 if (regcache_register_status (regcache, regn) == REG_UNKNOWN) 05044 { 05045 if (regno == regn) 05046 { 05047 regcache_raw_supply (regcache, regno, regs + offset); 05048 break; 05049 } 05050 else if (regno == -1) 05051 { 05052 regcache_raw_supply (regcache, regn, regs + offset); 05053 } 05054 } 05055 offset += regsize; 05056 } 05057 return; 05058 } 05059 05060 /* We get here if no register data has been found. Mark registers 05061 as unavailable. */ 05062 for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++) 05063 regcache_raw_supply (regcache, regn, NULL); 05064 05065 /* We can often usefully guess that the PC is going to be the same 05066 as the address of the tracepoint. */ 05067 pc_regno = gdbarch_pc_regnum (gdbarch); 05068 if (pc_regno >= 0 && (regno == -1 || regno == pc_regno)) 05069 { 05070 struct tracepoint *tp = get_tracepoint (tracepoint_number); 05071 05072 if (tp && tp->base.loc) 05073 { 05074 /* But don't try to guess if tracepoint is multi-location... */ 05075 if (tp->base.loc->next) 05076 { 05077 warning (_("Tracepoint %d has multiple " 05078 "locations, cannot infer $pc"), 05079 tp->base.number); 05080 return; 05081 } 05082 /* ... or does while-stepping. */ 05083 if (tp->step_count > 0) 05084 { 05085 warning (_("Tracepoint %d does while-stepping, " 05086 "cannot infer $pc"), 05087 tp->base.number); 05088 return; 05089 } 05090 05091 store_unsigned_integer (regs, register_size (gdbarch, pc_regno), 05092 gdbarch_byte_order (gdbarch), 05093 tp->base.loc->address); 05094 regcache_raw_supply (regcache, pc_regno, regs); 05095 } 05096 } 05097 } 05098 05099 static LONGEST 05100 tfile_xfer_partial (struct target_ops *ops, enum target_object object, 05101 const char *annex, gdb_byte *readbuf, 05102 const gdb_byte *writebuf, ULONGEST offset, LONGEST len) 05103 { 05104 /* We're only doing regular memory for now. */ 05105 if (object != TARGET_OBJECT_MEMORY) 05106 return -1; 05107 05108 if (readbuf == NULL) 05109 error (_("tfile_xfer_partial: trace file is read-only")); 05110 05111 if (traceframe_number != -1) 05112 { 05113 int pos = 0; 05114 05115 /* Iterate through the traceframe's blocks, looking for 05116 memory. */ 05117 while ((pos = traceframe_find_block_type ('M', pos)) >= 0) 05118 { 05119 ULONGEST maddr, amt; 05120 unsigned short mlen; 05121 enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); 05122 05123 tfile_read ((gdb_byte *) &maddr, 8); 05124 maddr = extract_unsigned_integer ((gdb_byte *) &maddr, 8, 05125 byte_order); 05126 tfile_read ((gdb_byte *) &mlen, 2); 05127 mlen = (unsigned short) 05128 extract_unsigned_integer ((gdb_byte *) &mlen, 2, byte_order); 05129 05130 /* If the block includes the first part of the desired 05131 range, return as much it has; GDB will re-request the 05132 remainder, which might be in a different block of this 05133 trace frame. */ 05134 if (maddr <= offset && offset < (maddr + mlen)) 05135 { 05136 amt = (maddr + mlen) - offset; 05137 if (amt > len) 05138 amt = len; 05139 05140 if (maddr != offset) 05141 lseek (trace_fd, offset - maddr, SEEK_CUR); 05142 tfile_read (readbuf, amt); 05143 return amt; 05144 } 05145 05146 /* Skip over this block. */ 05147 pos += (8 + 2 + mlen); 05148 } 05149 } 05150 05151 /* It's unduly pedantic to refuse to look at the executable for 05152 read-only pieces; so do the equivalent of readonly regions aka 05153 QTro packet. */ 05154 /* FIXME account for relocation at some point. */ 05155 if (exec_bfd) 05156 { 05157 asection *s; 05158 bfd_size_type size; 05159 bfd_vma vma; 05160 05161 for (s = exec_bfd->sections; s; s = s->next) 05162 { 05163 if ((s->flags & SEC_LOAD) == 0 05164 || (s->flags & SEC_READONLY) == 0) 05165 continue; 05166 05167 vma = s->vma; 05168 size = bfd_get_section_size (s); 05169 if (vma <= offset && offset < (vma + size)) 05170 { 05171 ULONGEST amt; 05172 05173 amt = (vma + size) - offset; 05174 if (amt > len) 05175 amt = len; 05176 05177 amt = bfd_get_section_contents (exec_bfd, s, 05178 readbuf, offset - vma, amt); 05179 return amt; 05180 } 05181 } 05182 } 05183 05184 /* Indicate failure to find the requested memory block. */ 05185 return -1; 05186 } 05187 05188 /* Iterate through the blocks of a trace frame, looking for a 'V' 05189 block with a matching tsv number. */ 05190 05191 static int 05192 tfile_get_trace_state_variable_value (int tsvnum, LONGEST *val) 05193 { 05194 int pos; 05195 int found = 0; 05196 05197 /* Iterate over blocks in current frame and find the last 'V' 05198 block in which tsv number is TSVNUM. In one trace frame, there 05199 may be multiple 'V' blocks created for a given trace variable, 05200 and the last matched 'V' block contains the updated value. */ 05201 pos = 0; 05202 while ((pos = traceframe_find_block_type ('V', pos)) >= 0) 05203 { 05204 int vnum; 05205 05206 tfile_read ((gdb_byte *) &vnum, 4); 05207 vnum = (int) extract_signed_integer ((gdb_byte *) &vnum, 4, 05208 gdbarch_byte_order 05209 (target_gdbarch ())); 05210 if (tsvnum == vnum) 05211 { 05212 tfile_read ((gdb_byte *) val, 8); 05213 *val = extract_signed_integer ((gdb_byte *) val, 8, 05214 gdbarch_byte_order 05215 (target_gdbarch ())); 05216 found = 1; 05217 } 05218 pos += (4 + 8); 05219 } 05220 05221 return found; 05222 } 05223 05224 static int 05225 tfile_has_all_memory (struct target_ops *ops) 05226 { 05227 return 1; 05228 } 05229 05230 static int 05231 tfile_has_memory (struct target_ops *ops) 05232 { 05233 return 1; 05234 } 05235 05236 static int 05237 tfile_has_stack (struct target_ops *ops) 05238 { 05239 return traceframe_number != -1; 05240 } 05241 05242 static int 05243 tfile_has_registers (struct target_ops *ops) 05244 { 05245 return traceframe_number != -1; 05246 } 05247 05248 /* Callback for traceframe_walk_blocks. Builds a traceframe_info 05249 object for the tfile target's current traceframe. */ 05250 05251 static int 05252 build_traceframe_info (char blocktype, void *data) 05253 { 05254 struct traceframe_info *info = data; 05255 05256 switch (blocktype) 05257 { 05258 case 'M': 05259 { 05260 struct mem_range *r; 05261 ULONGEST maddr; 05262 unsigned short mlen; 05263 05264 tfile_read ((gdb_byte *) &maddr, 8); 05265 maddr = extract_unsigned_integer ((gdb_byte *) &maddr, 8, 05266 gdbarch_byte_order 05267 (target_gdbarch ())); 05268 tfile_read ((gdb_byte *) &mlen, 2); 05269 mlen = (unsigned short) 05270 extract_unsigned_integer ((gdb_byte *) &mlen, 05271 2, gdbarch_byte_order 05272 (target_gdbarch ())); 05273 05274 r = VEC_safe_push (mem_range_s, info->memory, NULL); 05275 05276 r->start = maddr; 05277 r->length = mlen; 05278 break; 05279 } 05280 case 'V': 05281 { 05282 int vnum; 05283 05284 tfile_read ((gdb_byte *) &vnum, 4); 05285 VEC_safe_push (int, info->tvars, vnum); 05286 } 05287 case 'R': 05288 case 'S': 05289 { 05290 break; 05291 } 05292 default: 05293 warning (_("Unhandled trace block type (%d) '%c ' " 05294 "while building trace frame info."), 05295 blocktype, blocktype); 05296 break; 05297 } 05298 05299 return 0; 05300 } 05301 05302 static struct traceframe_info * 05303 tfile_traceframe_info (void) 05304 { 05305 struct traceframe_info *info = XCNEW (struct traceframe_info); 05306 05307 traceframe_walk_blocks (build_traceframe_info, 0, info); 05308 return info; 05309 } 05310 05311 static void 05312 init_tfile_ops (void) 05313 { 05314 tfile_ops.to_shortname = "tfile"; 05315 tfile_ops.to_longname = "Local trace dump file"; 05316 tfile_ops.to_doc 05317 = "Use a trace file as a target. Specify the filename of the trace file."; 05318 tfile_ops.to_open = tfile_open; 05319 tfile_ops.to_close = tfile_close; 05320 tfile_ops.to_fetch_registers = tfile_fetch_registers; 05321 tfile_ops.to_xfer_partial = tfile_xfer_partial; 05322 tfile_ops.to_files_info = tfile_files_info; 05323 tfile_ops.to_get_trace_status = tfile_get_trace_status; 05324 tfile_ops.to_get_tracepoint_status = tfile_get_tracepoint_status; 05325 tfile_ops.to_trace_find = tfile_trace_find; 05326 tfile_ops.to_get_trace_state_variable_value 05327 = tfile_get_trace_state_variable_value; 05328 tfile_ops.to_stratum = process_stratum; 05329 tfile_ops.to_has_all_memory = tfile_has_all_memory; 05330 tfile_ops.to_has_memory = tfile_has_memory; 05331 tfile_ops.to_has_stack = tfile_has_stack; 05332 tfile_ops.to_has_registers = tfile_has_registers; 05333 tfile_ops.to_traceframe_info = tfile_traceframe_info; 05334 tfile_ops.to_magic = OPS_MAGIC; 05335 } 05336 05337 void 05338 free_current_marker (void *arg) 05339 { 05340 struct static_tracepoint_marker **marker_p = arg; 05341 05342 if (*marker_p != NULL) 05343 { 05344 release_static_tracepoint_marker (*marker_p); 05345 xfree (*marker_p); 05346 } 05347 else 05348 *marker_p = NULL; 05349 } 05350 05351 /* Given a line of text defining a static tracepoint marker, parse it 05352 into a "static tracepoint marker" object. Throws an error is 05353 parsing fails. If PP is non-null, it points to one past the end of 05354 the parsed marker definition. */ 05355 05356 void 05357 parse_static_tracepoint_marker_definition (char *line, char **pp, 05358 struct static_tracepoint_marker *marker) 05359 { 05360 char *p, *endp; 05361 ULONGEST addr; 05362 int end; 05363 05364 p = line; 05365 p = unpack_varlen_hex (p, &addr); 05366 p++; /* skip a colon */ 05367 05368 marker->gdbarch = target_gdbarch (); 05369 marker->address = (CORE_ADDR) addr; 05370 05371 endp = strchr (p, ':'); 05372 if (endp == NULL) 05373 error (_("bad marker definition: %s"), line); 05374 05375 marker->str_id = xmalloc (endp - p + 1); 05376 end = hex2bin (p, (gdb_byte *) marker->str_id, (endp - p + 1) / 2); 05377 marker->str_id[end] = '\0'; 05378 05379 p += 2 * end; 05380 p++; /* skip a colon */ 05381 05382 marker->extra = xmalloc (strlen (p) + 1); 05383 end = hex2bin (p, (gdb_byte *) marker->extra, strlen (p) / 2); 05384 marker->extra[end] = '\0'; 05385 05386 if (pp) 05387 *pp = p; 05388 } 05389 05390 /* Release a static tracepoint marker's contents. Note that the 05391 object itself isn't released here. There objects are usually on 05392 the stack. */ 05393 05394 void 05395 release_static_tracepoint_marker (struct static_tracepoint_marker *marker) 05396 { 05397 xfree (marker->str_id); 05398 marker->str_id = NULL; 05399 } 05400 05401 /* Print MARKER to gdb_stdout. */ 05402 05403 static void 05404 print_one_static_tracepoint_marker (int count, 05405 struct static_tracepoint_marker *marker) 05406 { 05407 struct command_line *l; 05408 struct symbol *sym; 05409 05410 char wrap_indent[80]; 05411 char extra_field_indent[80]; 05412 struct ui_out *uiout = current_uiout; 05413 struct cleanup *bkpt_chain; 05414 VEC(breakpoint_p) *tracepoints; 05415 05416 struct symtab_and_line sal; 05417 05418 init_sal (&sal); 05419 05420 sal.pc = marker->address; 05421 05422 tracepoints = static_tracepoints_here (marker->address); 05423 05424 bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "marker"); 05425 05426 /* A counter field to help readability. This is not a stable 05427 identifier! */ 05428 ui_out_field_int (uiout, "count", count); 05429 05430 ui_out_field_string (uiout, "marker-id", marker->str_id); 05431 05432 ui_out_field_fmt (uiout, "enabled", "%c", 05433 !VEC_empty (breakpoint_p, tracepoints) ? 'y' : 'n'); 05434 ui_out_spaces (uiout, 2); 05435 05436 strcpy (wrap_indent, " "); 05437 05438 if (gdbarch_addr_bit (marker->gdbarch) <= 32) 05439 strcat (wrap_indent, " "); 05440 else 05441 strcat (wrap_indent, " "); 05442 05443 strcpy (extra_field_indent, " "); 05444 05445 ui_out_field_core_addr (uiout, "addr", marker->gdbarch, marker->address); 05446 05447 sal = find_pc_line (marker->address, 0); 05448 sym = find_pc_sect_function (marker->address, NULL); 05449 if (sym) 05450 { 05451 ui_out_text (uiout, "in "); 05452 ui_out_field_string (uiout, "func", 05453 SYMBOL_PRINT_NAME (sym)); 05454 ui_out_wrap_hint (uiout, wrap_indent); 05455 ui_out_text (uiout, " at "); 05456 } 05457 else 05458 ui_out_field_skip (uiout, "func"); 05459 05460 if (sal.symtab != NULL) 05461 { 05462 ui_out_field_string (uiout, "file", 05463 symtab_to_filename_for_display (sal.symtab)); 05464 ui_out_text (uiout, ":"); 05465 05466 if (ui_out_is_mi_like_p (uiout)) 05467 { 05468 const char *fullname = symtab_to_fullname (sal.symtab); 05469 05470 ui_out_field_string (uiout, "fullname", fullname); 05471 } 05472 else 05473 ui_out_field_skip (uiout, "fullname"); 05474 05475 ui_out_field_int (uiout, "line", sal.line); 05476 } 05477 else 05478 { 05479 ui_out_field_skip (uiout, "fullname"); 05480 ui_out_field_skip (uiout, "line"); 05481 } 05482 05483 ui_out_text (uiout, "\n"); 05484 ui_out_text (uiout, extra_field_indent); 05485 ui_out_text (uiout, _("Data: \"")); 05486 ui_out_field_string (uiout, "extra-data", marker->extra); 05487 ui_out_text (uiout, "\"\n"); 05488 05489 if (!VEC_empty (breakpoint_p, tracepoints)) 05490 { 05491 struct cleanup *cleanup_chain; 05492 int ix; 05493 struct breakpoint *b; 05494 05495 cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout, 05496 "tracepoints-at"); 05497 05498 ui_out_text (uiout, extra_field_indent); 05499 ui_out_text (uiout, _("Probed by static tracepoints: ")); 05500 for (ix = 0; VEC_iterate(breakpoint_p, tracepoints, ix, b); ix++) 05501 { 05502 if (ix > 0) 05503 ui_out_text (uiout, ", "); 05504 ui_out_text (uiout, "#"); 05505 ui_out_field_int (uiout, "tracepoint-id", b->number); 05506 } 05507 05508 do_cleanups (cleanup_chain); 05509 05510 if (ui_out_is_mi_like_p (uiout)) 05511 ui_out_field_int (uiout, "number-of-tracepoints", 05512 VEC_length(breakpoint_p, tracepoints)); 05513 else 05514 ui_out_text (uiout, "\n"); 05515 } 05516 VEC_free (breakpoint_p, tracepoints); 05517 05518 do_cleanups (bkpt_chain); 05519 } 05520 05521 static void 05522 info_static_tracepoint_markers_command (char *arg, int from_tty) 05523 { 05524 VEC(static_tracepoint_marker_p) *markers; 05525 struct cleanup *old_chain; 05526 struct static_tracepoint_marker *marker; 05527 struct ui_out *uiout = current_uiout; 05528 int i; 05529 05530 /* We don't have to check target_can_use_agent and agent's capability on 05531 static tracepoint here, in order to be compatible with older GDBserver. 05532 We don't check USE_AGENT is true or not, because static tracepoints 05533 don't work without in-process agent, so we don't bother users to type 05534 `set agent on' when to use static tracepoint. */ 05535 05536 old_chain 05537 = make_cleanup_ui_out_table_begin_end (uiout, 5, -1, 05538 "StaticTracepointMarkersTable"); 05539 05540 ui_out_table_header (uiout, 7, ui_left, "counter", "Cnt"); 05541 05542 ui_out_table_header (uiout, 40, ui_left, "marker-id", "ID"); 05543 05544 ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb"); 05545 if (gdbarch_addr_bit (target_gdbarch ()) <= 32) 05546 ui_out_table_header (uiout, 10, ui_left, "addr", "Address"); 05547 else 05548 ui_out_table_header (uiout, 18, ui_left, "addr", "Address"); 05549 ui_out_table_header (uiout, 40, ui_noalign, "what", "What"); 05550 05551 ui_out_table_body (uiout); 05552 05553 markers = target_static_tracepoint_markers_by_strid (NULL); 05554 make_cleanup (VEC_cleanup (static_tracepoint_marker_p), &markers); 05555 05556 for (i = 0; 05557 VEC_iterate (static_tracepoint_marker_p, 05558 markers, i, marker); 05559 i++) 05560 { 05561 print_one_static_tracepoint_marker (i + 1, marker); 05562 release_static_tracepoint_marker (marker); 05563 } 05564 05565 do_cleanups (old_chain); 05566 } 05567 05568 /* The $_sdata convenience variable is a bit special. We don't know 05569 for sure type of the value until we actually have a chance to fetch 05570 the data --- the size of the object depends on what has been 05571 collected. We solve this by making $_sdata be an internalvar that 05572 creates a new value on access. */ 05573 05574 /* Return a new value with the correct type for the sdata object of 05575 the current trace frame. Return a void value if there's no object 05576 available. */ 05577 05578 static struct value * 05579 sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var, 05580 void *ignore) 05581 { 05582 LONGEST size; 05583 gdb_byte *buf; 05584 05585 /* We need to read the whole object before we know its size. */ 05586 size = target_read_alloc (¤t_target, 05587 TARGET_OBJECT_STATIC_TRACE_DATA, 05588 NULL, &buf); 05589 if (size >= 0) 05590 { 05591 struct value *v; 05592 struct type *type; 05593 05594 type = init_vector_type (builtin_type (gdbarch)->builtin_true_char, 05595 size); 05596 v = allocate_value (type); 05597 memcpy (value_contents_raw (v), buf, size); 05598 xfree (buf); 05599 return v; 05600 } 05601 else 05602 return allocate_value (builtin_type (gdbarch)->builtin_void); 05603 } 05604 05605 #if !defined(HAVE_LIBEXPAT) 05606 05607 struct traceframe_info * 05608 parse_traceframe_info (const char *tframe_info) 05609 { 05610 static int have_warned; 05611 05612 if (!have_warned) 05613 { 05614 have_warned = 1; 05615 warning (_("Can not parse XML trace frame info; XML support " 05616 "was disabled at compile time")); 05617 } 05618 05619 return NULL; 05620 } 05621 05622 #else /* HAVE_LIBEXPAT */ 05623 05624 #include "xml-support.h" 05625 05626 /* Handle the start of a <memory> element. */ 05627 05628 static void 05629 traceframe_info_start_memory (struct gdb_xml_parser *parser, 05630 const struct gdb_xml_element *element, 05631 void *user_data, VEC(gdb_xml_value_s) *attributes) 05632 { 05633 struct traceframe_info *info = user_data; 05634 struct mem_range *r = VEC_safe_push (mem_range_s, info->memory, NULL); 05635 ULONGEST *start_p, *length_p; 05636 05637 start_p = xml_find_attribute (attributes, "start")->value; 05638 length_p = xml_find_attribute (attributes, "length")->value; 05639 05640 r->start = *start_p; 05641 r->length = *length_p; 05642 } 05643 05644 /* Handle the start of a <tvar> element. */ 05645 05646 static void 05647 traceframe_info_start_tvar (struct gdb_xml_parser *parser, 05648 const struct gdb_xml_element *element, 05649 void *user_data, 05650 VEC(gdb_xml_value_s) *attributes) 05651 { 05652 struct traceframe_info *info = user_data; 05653 const char *id_attrib = xml_find_attribute (attributes, "id")->value; 05654 int id = gdb_xml_parse_ulongest (parser, id_attrib); 05655 05656 VEC_safe_push (int, info->tvars, id); 05657 } 05658 05659 /* Discard the constructed trace frame info (if an error occurs). */ 05660 05661 static void 05662 free_result (void *p) 05663 { 05664 struct traceframe_info *result = p; 05665 05666 free_traceframe_info (result); 05667 } 05668 05669 /* The allowed elements and attributes for an XML memory map. */ 05670 05671 static const struct gdb_xml_attribute memory_attributes[] = { 05672 { "start", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, 05673 { "length", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, 05674 { NULL, GDB_XML_AF_NONE, NULL, NULL } 05675 }; 05676 05677 static const struct gdb_xml_attribute tvar_attributes[] = { 05678 { "id", GDB_XML_AF_NONE, NULL, NULL }, 05679 { NULL, GDB_XML_AF_NONE, NULL, NULL } 05680 }; 05681 05682 static const struct gdb_xml_element traceframe_info_children[] = { 05683 { "memory", memory_attributes, NULL, 05684 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, 05685 traceframe_info_start_memory, NULL }, 05686 { "tvar", tvar_attributes, NULL, 05687 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, 05688 traceframe_info_start_tvar, NULL }, 05689 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 05690 }; 05691 05692 static const struct gdb_xml_element traceframe_info_elements[] = { 05693 { "traceframe-info", NULL, traceframe_info_children, GDB_XML_EF_NONE, 05694 NULL, NULL }, 05695 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 05696 }; 05697 05698 /* Parse a traceframe-info XML document. */ 05699 05700 struct traceframe_info * 05701 parse_traceframe_info (const char *tframe_info) 05702 { 05703 struct traceframe_info *result; 05704 struct cleanup *back_to; 05705 05706 result = XCNEW (struct traceframe_info); 05707 back_to = make_cleanup (free_result, result); 05708 05709 if (gdb_xml_parse_quick (_("trace frame info"), 05710 "traceframe-info.dtd", traceframe_info_elements, 05711 tframe_info, result) == 0) 05712 { 05713 /* Parsed successfully, keep the result. */ 05714 discard_cleanups (back_to); 05715 05716 return result; 05717 } 05718 05719 do_cleanups (back_to); 05720 return NULL; 05721 } 05722 05723 #endif /* HAVE_LIBEXPAT */ 05724 05725 /* Returns the traceframe_info object for the current traceframe. 05726 This is where we avoid re-fetching the object from the target if we 05727 already have it cached. */ 05728 05729 struct traceframe_info * 05730 get_traceframe_info (void) 05731 { 05732 if (traceframe_info == NULL) 05733 traceframe_info = target_traceframe_info (); 05734 05735 return traceframe_info; 05736 } 05737 05738 /* If the target supports the query, return in RESULT the set of 05739 collected memory in the current traceframe, found within the LEN 05740 bytes range starting at MEMADDR. Returns true if the target 05741 supports the query, otherwise returns false, and RESULT is left 05742 undefined. */ 05743 05744 int 05745 traceframe_available_memory (VEC(mem_range_s) **result, 05746 CORE_ADDR memaddr, ULONGEST len) 05747 { 05748 struct traceframe_info *info = get_traceframe_info (); 05749 05750 if (info != NULL) 05751 { 05752 struct mem_range *r; 05753 int i; 05754 05755 *result = NULL; 05756 05757 for (i = 0; VEC_iterate (mem_range_s, info->memory, i, r); i++) 05758 if (mem_ranges_overlap (r->start, r->length, memaddr, len)) 05759 { 05760 ULONGEST lo1, hi1, lo2, hi2; 05761 struct mem_range *nr; 05762 05763 lo1 = memaddr; 05764 hi1 = memaddr + len; 05765 05766 lo2 = r->start; 05767 hi2 = r->start + r->length; 05768 05769 nr = VEC_safe_push (mem_range_s, *result, NULL); 05770 05771 nr->start = max (lo1, lo2); 05772 nr->length = min (hi1, hi2) - nr->start; 05773 } 05774 05775 normalize_mem_ranges (*result); 05776 return 1; 05777 } 05778 05779 return 0; 05780 } 05781 05782 /* Implementation of `sdata' variable. */ 05783 05784 static const struct internalvar_funcs sdata_funcs = 05785 { 05786 sdata_make_value, 05787 NULL, 05788 NULL 05789 }; 05790 05791 /* module initialization */ 05792 void 05793 _initialize_tracepoint (void) 05794 { 05795 struct cmd_list_element *c; 05796 05797 /* Explicitly create without lookup, since that tries to create a 05798 value with a void typed value, and when we get here, gdbarch 05799 isn't initialized yet. At this point, we're quite sure there 05800 isn't another convenience variable of the same name. */ 05801 create_internalvar_type_lazy ("_sdata", &sdata_funcs, NULL); 05802 05803 traceframe_number = -1; 05804 tracepoint_number = -1; 05805 05806 add_info ("scope", scope_info, 05807 _("List the variables local to a scope")); 05808 05809 add_cmd ("tracepoints", class_trace, NULL, 05810 _("Tracing of program execution without stopping the program."), 05811 &cmdlist); 05812 05813 add_com ("tdump", class_trace, trace_dump_command, 05814 _("Print everything collected at the current tracepoint.")); 05815 05816 add_com ("tsave", class_trace, trace_save_command, _("\ 05817 Save the trace data to a file.\n\ 05818 Use the '-ctf' option to save the data to CTF format.\n\ 05819 Use the '-r' option to direct the target to save directly to the file,\n\ 05820 using its own filesystem.")); 05821 05822 c = add_com ("tvariable", class_trace, trace_variable_command,_("\ 05823 Define a trace state variable.\n\ 05824 Argument is a $-prefixed name, optionally followed\n\ 05825 by '=' and an expression that sets the initial value\n\ 05826 at the start of tracing.")); 05827 set_cmd_completer (c, expression_completer); 05828 05829 add_cmd ("tvariable", class_trace, delete_trace_variable_command, _("\ 05830 Delete one or more trace state variables.\n\ 05831 Arguments are the names of the variables to delete.\n\ 05832 If no arguments are supplied, delete all variables."), &deletelist); 05833 /* FIXME add a trace variable completer. */ 05834 05835 add_info ("tvariables", tvariables_info, _("\ 05836 Status of trace state variables and their values.\n\ 05837 ")); 05838 05839 add_info ("static-tracepoint-markers", 05840 info_static_tracepoint_markers_command, _("\ 05841 List target static tracepoints markers.\n\ 05842 ")); 05843 05844 add_prefix_cmd ("tfind", class_trace, trace_find_command, _("\ 05845 Select a trace frame;\n\ 05846 No argument means forward by one frame; '-' means backward by one frame."), 05847 &tfindlist, "tfind ", 1, &cmdlist); 05848 05849 add_cmd ("outside", class_trace, trace_find_outside_command, _("\ 05850 Select a trace frame whose PC is outside the given range (exclusive).\n\ 05851 Usage: tfind outside addr1, addr2"), 05852 &tfindlist); 05853 05854 add_cmd ("range", class_trace, trace_find_range_command, _("\ 05855 Select a trace frame whose PC is in the given range (inclusive).\n\ 05856 Usage: tfind range addr1,addr2"), 05857 &tfindlist); 05858 05859 add_cmd ("line", class_trace, trace_find_line_command, _("\ 05860 Select a trace frame by source line.\n\ 05861 Argument can be a line number (with optional source file),\n\ 05862 a function name, or '*' followed by an address.\n\ 05863 Default argument is 'the next source line that was traced'."), 05864 &tfindlist); 05865 05866 add_cmd ("tracepoint", class_trace, trace_find_tracepoint_command, _("\ 05867 Select a trace frame by tracepoint number.\n\ 05868 Default is the tracepoint for the current trace frame."), 05869 &tfindlist); 05870 05871 add_cmd ("pc", class_trace, trace_find_pc_command, _("\ 05872 Select a trace frame by PC.\n\ 05873 Default is the current PC, or the PC of the current trace frame."), 05874 &tfindlist); 05875 05876 add_cmd ("end", class_trace, trace_find_end_command, _("\ 05877 De-select any trace frame and resume 'live' debugging."), 05878 &tfindlist); 05879 05880 add_alias_cmd ("none", "end", class_trace, 0, &tfindlist); 05881 05882 add_cmd ("start", class_trace, trace_find_start_command, 05883 _("Select the first trace frame in the trace buffer."), 05884 &tfindlist); 05885 05886 add_com ("tstatus", class_trace, trace_status_command, 05887 _("Display the status of the current trace data collection.")); 05888 05889 add_com ("tstop", class_trace, trace_stop_command, _("\ 05890 Stop trace data collection.\n\ 05891 Usage: tstop [ <notes> ... ]\n\ 05892 Any arguments supplied are recorded with the trace as a stop reason and\n\ 05893 reported by tstatus (if the target supports trace notes).")); 05894 05895 add_com ("tstart", class_trace, trace_start_command, _("\ 05896 Start trace data collection.\n\ 05897 Usage: tstart [ <notes> ... ]\n\ 05898 Any arguments supplied are recorded with the trace as a note and\n\ 05899 reported by tstatus (if the target supports trace notes).")); 05900 05901 add_com ("end", class_trace, end_actions_pseudocommand, _("\ 05902 Ends a list of commands or actions.\n\ 05903 Several GDB commands allow you to enter a list of commands or actions.\n\ 05904 Entering \"end\" on a line by itself is the normal way to terminate\n\ 05905 such a list.\n\n\ 05906 Note: the \"end\" command cannot be used at the gdb prompt.")); 05907 05908 add_com ("while-stepping", class_trace, while_stepping_pseudocommand, _("\ 05909 Specify single-stepping behavior at a tracepoint.\n\ 05910 Argument is number of instructions to trace in single-step mode\n\ 05911 following the tracepoint. This command is normally followed by\n\ 05912 one or more \"collect\" commands, to specify what to collect\n\ 05913 while single-stepping.\n\n\ 05914 Note: this command can only be used in a tracepoint \"actions\" list.")); 05915 05916 add_com_alias ("ws", "while-stepping", class_alias, 0); 05917 add_com_alias ("stepping", "while-stepping", class_alias, 0); 05918 05919 add_com ("collect", class_trace, collect_pseudocommand, _("\ 05920 Specify one or more data items to be collected at a tracepoint.\n\ 05921 Accepts a comma-separated list of (one or more) expressions. GDB will\n\ 05922 collect all data (variables, registers) referenced by that expression.\n\ 05923 Also accepts the following special arguments:\n\ 05924 $regs -- all registers.\n\ 05925 $args -- all function arguments.\n\ 05926 $locals -- all variables local to the block/function scope.\n\ 05927 $_sdata -- static tracepoint data (ignored for non-static tracepoints).\n\ 05928 Note: this command can only be used in a tracepoint \"actions\" list.")); 05929 05930 add_com ("teval", class_trace, teval_pseudocommand, _("\ 05931 Specify one or more expressions to be evaluated at a tracepoint.\n\ 05932 Accepts a comma-separated list of (one or more) expressions.\n\ 05933 The result of each evaluation will be discarded.\n\ 05934 Note: this command can only be used in a tracepoint \"actions\" list.")); 05935 05936 add_com ("actions", class_trace, trace_actions_command, _("\ 05937 Specify the actions to be taken at a tracepoint.\n\ 05938 Tracepoint actions may include collecting of specified data,\n\ 05939 single-stepping, or enabling/disabling other tracepoints,\n\ 05940 depending on target's capabilities.")); 05941 05942 default_collect = xstrdup (""); 05943 add_setshow_string_cmd ("default-collect", class_trace, 05944 &default_collect, _("\ 05945 Set the list of expressions to collect by default"), _("\ 05946 Show the list of expressions to collect by default"), NULL, 05947 NULL, NULL, 05948 &setlist, &showlist); 05949 05950 add_setshow_boolean_cmd ("disconnected-tracing", no_class, 05951 &disconnected_tracing, _("\ 05952 Set whether tracing continues after GDB disconnects."), _("\ 05953 Show whether tracing continues after GDB disconnects."), _("\ 05954 Use this to continue a tracing run even if GDB disconnects\n\ 05955 or detaches from the target. You can reconnect later and look at\n\ 05956 trace data collected in the meantime."), 05957 set_disconnected_tracing, 05958 NULL, 05959 &setlist, 05960 &showlist); 05961 05962 add_setshow_boolean_cmd ("circular-trace-buffer", no_class, 05963 &circular_trace_buffer, _("\ 05964 Set target's use of circular trace buffer."), _("\ 05965 Show target's use of circular trace buffer."), _("\ 05966 Use this to make the trace buffer into a circular buffer,\n\ 05967 which will discard traceframes (oldest first) instead of filling\n\ 05968 up and stopping the trace run."), 05969 set_circular_trace_buffer, 05970 NULL, 05971 &setlist, 05972 &showlist); 05973 05974 add_setshow_zuinteger_unlimited_cmd ("trace-buffer-size", no_class, 05975 &trace_buffer_size, _("\ 05976 Set requested size of trace buffer."), _("\ 05977 Show requested size of trace buffer."), _("\ 05978 Use this to choose a size for the trace buffer. Some targets\n\ 05979 may have fixed or limited buffer sizes. Specifying \"unlimited\" or -1\n\ 05980 disables any attempt to set the buffer size and lets the target choose."), 05981 set_trace_buffer_size, NULL, 05982 &setlist, &showlist); 05983 05984 add_setshow_string_cmd ("trace-user", class_trace, 05985 &trace_user, _("\ 05986 Set the user name to use for current and future trace runs"), _("\ 05987 Show the user name to use for current and future trace runs"), NULL, 05988 set_trace_user, NULL, 05989 &setlist, &showlist); 05990 05991 add_setshow_string_cmd ("trace-notes", class_trace, 05992 &trace_notes, _("\ 05993 Set notes string to use for current and future trace runs"), _("\ 05994 Show the notes string to use for current and future trace runs"), NULL, 05995 set_trace_notes, NULL, 05996 &setlist, &showlist); 05997 05998 add_setshow_string_cmd ("trace-stop-notes", class_trace, 05999 &trace_stop_notes, _("\ 06000 Set notes string to use for future tstop commands"), _("\ 06001 Show the notes string to use for future tstop commands"), NULL, 06002 set_trace_stop_notes, NULL, 06003 &setlist, &showlist); 06004 06005 init_tfile_ops (); 06006 06007 add_target_with_completer (&tfile_ops, filename_completer); 06008 }