1 /* Trace file support in GDB. 2 3 Copyright (C) 1997-2023 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "defs.h" 21 #include "tracefile.h" 22 #include "tracectf.h" 23 #include "exec.h" 24 #include "regcache.h" 25 #include "gdbsupport/byte-vector.h" 26 #include "gdbarch.h" 27 #include "gdbsupport/buildargv.h" 28 29 /* Helper macros. */ 30 31 #define TRACE_WRITE_R_BLOCK(writer, buf, size) \ 32 writer->ops->frame_ops->write_r_block ((writer), (buf), (size)) 33 #define TRACE_WRITE_M_BLOCK_HEADER(writer, addr, size) \ 34 writer->ops->frame_ops->write_m_block_header ((writer), (addr), \ 35 (size)) 36 #define TRACE_WRITE_M_BLOCK_MEMORY(writer, buf, size) \ 37 writer->ops->frame_ops->write_m_block_memory ((writer), (buf), \ 38 (size)) 39 #define TRACE_WRITE_V_BLOCK(writer, num, val) \ 40 writer->ops->frame_ops->write_v_block ((writer), (num), (val)) 41 42 /* A unique pointer policy class for trace_file_writer. */ 43 44 struct trace_file_writer_deleter 45 { 46 void operator() (struct trace_file_writer *writer) 47 { 48 writer->ops->dtor (writer); 49 xfree (writer); 50 } 51 }; 52 53 /* A unique_ptr specialization for trace_file_writer. */ 54 55 typedef std::unique_ptr<trace_file_writer, trace_file_writer_deleter> 56 trace_file_writer_up; 57 58 /* Save tracepoint data to file named FILENAME through WRITER. WRITER 59 determines the trace file format. If TARGET_DOES_SAVE is non-zero, 60 the save is performed on the target, otherwise GDB obtains all trace 61 data and saves it locally. */ 62 63 static void 64 trace_save (const char *filename, struct trace_file_writer *writer, 65 int target_does_save) 66 { 67 struct trace_status *ts = current_trace_status (); 68 struct uploaded_tp *uploaded_tps = NULL, *utp; 69 struct uploaded_tsv *uploaded_tsvs = NULL, *utsv; 70 71 ULONGEST offset = 0; 72 #define MAX_TRACE_UPLOAD 2000 73 gdb::byte_vector buf (std::max (MAX_TRACE_UPLOAD, trace_regblock_size)); 74 enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); 75 76 /* If the target is to save the data to a file on its own, then just 77 send the command and be done with it. */ 78 if (target_does_save) 79 { 80 if (!writer->ops->target_save (writer, filename)) 81 error (_("Target failed to save trace data to '%s'."), 82 filename); 83 return; 84 } 85 86 /* Get the trace status first before opening the file, so if the 87 target is losing, we can get out without touching files. Since 88 we're just calling this for side effects, we ignore the 89 result. */ 90 target_get_trace_status (ts); 91 92 writer->ops->start (writer, filename); 93 94 writer->ops->write_header (writer); 95 96 /* Write descriptive info. */ 97 98 /* Write out the size of a register block. */ 99 writer->ops->write_regblock_type (writer, trace_regblock_size); 100 101 /* Write out the target description info. */ 102 writer->ops->write_tdesc (writer); 103 104 /* Write out status of the tracing run (aka "tstatus" info). */ 105 writer->ops->write_status (writer, ts); 106 107 /* Note that we want to upload tracepoints and save those, rather 108 than simply writing out the local ones, because the user may have 109 changed tracepoints in GDB in preparation for a future tracing 110 run, or maybe just mass-deleted all types of breakpoints as part 111 of cleaning up. So as not to contaminate the session, leave the 112 data in its uploaded form, don't make into real tracepoints. */ 113 114 /* Get trace state variables first, they may be checked when parsing 115 uploaded commands. */ 116 117 target_upload_trace_state_variables (&uploaded_tsvs); 118 119 for (utsv = uploaded_tsvs; utsv; utsv = utsv->next) 120 writer->ops->write_uploaded_tsv (writer, utsv); 121 122 free_uploaded_tsvs (&uploaded_tsvs); 123 124 target_upload_tracepoints (&uploaded_tps); 125 126 for (utp = uploaded_tps; utp; utp = utp->next) 127 target_get_tracepoint_status (NULL, utp); 128 129 for (utp = uploaded_tps; utp; utp = utp->next) 130 writer->ops->write_uploaded_tp (writer, utp); 131 132 free_uploaded_tps (&uploaded_tps); 133 134 /* Mark the end of the definition section. */ 135 writer->ops->write_definition_end (writer); 136 137 /* Get and write the trace data proper. */ 138 while (1) 139 { 140 LONGEST gotten = 0; 141 142 /* The writer supports writing the contents of trace buffer 143 directly to trace file. Don't parse the contents of trace 144 buffer. */ 145 if (writer->ops->write_trace_buffer != NULL) 146 { 147 /* We ask for big blocks, in the hopes of efficiency, but 148 will take less if the target has packet size limitations 149 or some such. */ 150 gotten = target_get_raw_trace_data (buf.data (), offset, 151 MAX_TRACE_UPLOAD); 152 if (gotten < 0) 153 error (_("Failure to get requested trace buffer data")); 154 /* No more data is forthcoming, we're done. */ 155 if (gotten == 0) 156 break; 157 158 writer->ops->write_trace_buffer (writer, buf.data (), gotten); 159 160 offset += gotten; 161 } 162 else 163 { 164 uint16_t tp_num; 165 uint32_t tf_size; 166 /* Parse the trace buffers according to how data are stored 167 in trace buffer in GDBserver. */ 168 169 gotten = target_get_raw_trace_data (buf.data (), offset, 6); 170 171 if (gotten == 0) 172 break; 173 174 /* Read the first six bytes in, which is the tracepoint 175 number and trace frame size. */ 176 tp_num = (uint16_t) 177 extract_unsigned_integer (&((buf.data ())[0]), 2, byte_order); 178 179 tf_size = (uint32_t) 180 extract_unsigned_integer (&((buf.data ())[2]), 4, byte_order); 181 182 writer->ops->frame_ops->start (writer, tp_num); 183 gotten = 6; 184 185 if (tf_size > 0) 186 { 187 unsigned int block; 188 189 offset += 6; 190 191 for (block = 0; block < tf_size; ) 192 { 193 gdb_byte block_type; 194 195 /* We'll fetch one block each time, in order to 196 handle the extremely large 'M' block. We first 197 fetch one byte to get the type of the block. */ 198 gotten = target_get_raw_trace_data (buf.data (), 199 offset, 1); 200 if (gotten < 1) 201 error (_("Failure to get requested trace buffer data")); 202 203 gotten = 1; 204 block += 1; 205 offset += 1; 206 207 block_type = buf[0]; 208 switch (block_type) 209 { 210 case 'R': 211 gotten 212 = target_get_raw_trace_data (buf.data (), offset, 213 trace_regblock_size); 214 if (gotten < trace_regblock_size) 215 error (_("Failure to get requested trace" 216 " buffer data")); 217 218 TRACE_WRITE_R_BLOCK (writer, buf.data (), 219 trace_regblock_size); 220 break; 221 case 'M': 222 { 223 unsigned short mlen; 224 ULONGEST addr; 225 LONGEST t; 226 int j; 227 228 t = target_get_raw_trace_data (buf.data (), 229 offset, 10); 230 if (t < 10) 231 error (_("Failure to get requested trace" 232 " buffer data")); 233 234 offset += 10; 235 block += 10; 236 237 gotten = 0; 238 addr = (ULONGEST) 239 extract_unsigned_integer (buf.data (), 8, 240 byte_order); 241 mlen = (unsigned short) 242 extract_unsigned_integer (&((buf.data ())[8]), 2, 243 byte_order); 244 245 TRACE_WRITE_M_BLOCK_HEADER (writer, addr, 246 mlen); 247 248 /* The memory contents in 'M' block may be 249 very large. Fetch the data from the target 250 and write them into file one by one. */ 251 for (j = 0; j < mlen; ) 252 { 253 unsigned int read_length; 254 255 if (mlen - j > MAX_TRACE_UPLOAD) 256 read_length = MAX_TRACE_UPLOAD; 257 else 258 read_length = mlen - j; 259 260 t = target_get_raw_trace_data (buf.data (), 261 offset + j, 262 read_length); 263 if (t < read_length) 264 error (_("Failure to get requested" 265 " trace buffer data")); 266 267 TRACE_WRITE_M_BLOCK_MEMORY (writer, 268 buf.data (), 269 read_length); 270 271 j += read_length; 272 gotten += read_length; 273 } 274 275 break; 276 } 277 case 'V': 278 { 279 int vnum; 280 LONGEST val; 281 282 gotten 283 = target_get_raw_trace_data (buf.data (), 284 offset, 12); 285 if (gotten < 12) 286 error (_("Failure to get requested" 287 " trace buffer data")); 288 289 vnum = (int) extract_signed_integer (buf.data (), 290 4, 291 byte_order); 292 val 293 = extract_signed_integer (&((buf.data ())[4]), 294 8, byte_order); 295 296 TRACE_WRITE_V_BLOCK (writer, vnum, val); 297 } 298 break; 299 default: 300 error (_("Unknown block type '%c' (0x%x) in" 301 " trace frame"), 302 block_type, block_type); 303 } 304 305 block += gotten; 306 offset += gotten; 307 } 308 } 309 else 310 offset += gotten; 311 312 writer->ops->frame_ops->end (writer); 313 } 314 } 315 316 writer->ops->end (writer); 317 } 318 319 static void 320 tsave_command (const char *args, int from_tty) 321 { 322 int target_does_save = 0; 323 char **argv; 324 char *filename = NULL; 325 int generate_ctf = 0; 326 327 if (args == NULL) 328 error_no_arg (_("file in which to save trace data")); 329 330 gdb_argv built_argv (args); 331 argv = built_argv.get (); 332 333 for (; *argv; ++argv) 334 { 335 if (strcmp (*argv, "-r") == 0) 336 target_does_save = 1; 337 else if (strcmp (*argv, "-ctf") == 0) 338 generate_ctf = 1; 339 else if (**argv == '-') 340 error (_("unknown option `%s'"), *argv); 341 else 342 filename = *argv; 343 } 344 345 if (!filename) 346 error_no_arg (_("file in which to save trace data")); 347 348 if (generate_ctf) 349 trace_save_ctf (filename, target_does_save); 350 else 351 trace_save_tfile (filename, target_does_save); 352 353 if (from_tty) 354 gdb_printf (_("Trace data saved to %s '%s'.\n"), 355 generate_ctf ? "directory" : "file", filename); 356 } 357 358 /* Save the trace data to file FILENAME of tfile format. */ 359 360 void 361 trace_save_tfile (const char *filename, int target_does_save) 362 { 363 trace_file_writer_up writer (tfile_trace_file_writer_new ()); 364 trace_save (filename, writer.get (), target_does_save); 365 } 366 367 /* Save the trace data to dir DIRNAME of ctf format. */ 368 369 void 370 trace_save_ctf (const char *dirname, int target_does_save) 371 { 372 trace_file_writer_up writer (ctf_trace_file_writer_new ()); 373 trace_save (dirname, writer.get (), target_does_save); 374 } 375 376 /* Fetch register data from tracefile, shared for both tfile and 377 ctf. */ 378 379 void 380 tracefile_fetch_registers (struct regcache *regcache, int regno) 381 { 382 struct gdbarch *gdbarch = regcache->arch (); 383 struct tracepoint *tp = get_tracepoint (get_tracepoint_number ()); 384 int regn; 385 386 /* We get here if no register data has been found. Mark registers 387 as unavailable. */ 388 for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++) 389 regcache->raw_supply (regn, NULL); 390 391 /* We can often usefully guess that the PC is going to be the same 392 as the address of the tracepoint. */ 393 if (tp == NULL || tp->loc == NULL) 394 return; 395 396 /* But don't try to guess if tracepoint is multi-location... */ 397 if (tp->loc->next) 398 { 399 warning (_("Tracepoint %d has multiple " 400 "locations, cannot infer $pc"), 401 tp->number); 402 return; 403 } 404 /* ... or does while-stepping. */ 405 else if (tp->step_count > 0) 406 { 407 warning (_("Tracepoint %d does while-stepping, " 408 "cannot infer $pc"), 409 tp->number); 410 return; 411 } 412 413 /* Guess what we can from the tracepoint location. */ 414 gdbarch_guess_tracepoint_registers (gdbarch, regcache, 415 tp->loc->address); 416 } 417 418 /* This is the implementation of target_ops method to_has_all_memory. */ 419 420 bool 421 tracefile_target::has_all_memory () 422 { 423 return true; 424 } 425 426 /* This is the implementation of target_ops method to_has_memory. */ 427 428 bool 429 tracefile_target::has_memory () 430 { 431 return true; 432 } 433 434 /* This is the implementation of target_ops method to_has_stack. 435 The target has a stack when GDB has already selected one trace 436 frame. */ 437 438 bool 439 tracefile_target::has_stack () 440 { 441 return get_traceframe_number () != -1; 442 } 443 444 /* This is the implementation of target_ops method to_has_registers. 445 The target has registers when GDB has already selected one trace 446 frame. */ 447 448 bool 449 tracefile_target::has_registers () 450 { 451 return get_traceframe_number () != -1; 452 } 453 454 /* This is the implementation of target_ops method to_thread_alive. 455 tracefile has one thread faked by GDB. */ 456 457 bool 458 tracefile_target::thread_alive (ptid_t ptid) 459 { 460 return true; 461 } 462 463 /* This is the implementation of target_ops method to_get_trace_status. 464 The trace status for a file is that tracing can never be run. */ 465 466 int 467 tracefile_target::get_trace_status (struct trace_status *ts) 468 { 469 /* Other bits of trace status were collected as part of opening the 470 trace files, so nothing to do here. */ 471 472 return -1; 473 } 474 475 void _initialize_tracefile (); 476 void 477 _initialize_tracefile () 478 { 479 add_com ("tsave", class_trace, tsave_command, _("\ 480 Save the trace data to a file.\n\ 481 Use the '-ctf' option to save the data to CTF format.\n\ 482 Use the '-r' option to direct the target to save directly to the file,\n\ 483 using its own filesystem.")); 484 } 485