18dffb485Schristos /* Debugging routines for the remote server for GDB. 2*f1c2b495Schristos Copyright (C) 2014-2024 Free Software Foundation, Inc. 38dffb485Schristos 48dffb485Schristos This file is part of GDB. 58dffb485Schristos 68dffb485Schristos This program is free software; you can redistribute it and/or modify 78dffb485Schristos it under the terms of the GNU General Public License as published by 88dffb485Schristos the Free Software Foundation; either version 3 of the License, or 98dffb485Schristos (at your option) any later version. 108dffb485Schristos 118dffb485Schristos This program is distributed in the hope that it will be useful, 128dffb485Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 138dffb485Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 148dffb485Schristos GNU General Public License for more details. 158dffb485Schristos 168dffb485Schristos You should have received a copy of the GNU General Public License 178dffb485Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 188dffb485Schristos 198dffb485Schristos #include <chrono> 208dffb485Schristos 218dffb485Schristos #if !defined (IN_PROCESS_AGENT) 224b169a6bSchristos bool remote_debug = false; 238dffb485Schristos #endif 248dffb485Schristos 258dffb485Schristos /* Output file for debugging. Default to standard error. */ 264b169a6bSchristos static FILE *debug_file = stderr; 278dffb485Schristos 288dffb485Schristos /* See debug.h. */ 294b169a6bSchristos bool debug_threads; 308dffb485Schristos 318dffb485Schristos /* Include timestamps in debugging output. */ 328dffb485Schristos int debug_timestamp; 338dffb485Schristos 348dffb485Schristos #if !defined (IN_PROCESS_AGENT) 358dffb485Schristos 368dffb485Schristos /* See debug.h. */ 378dffb485Schristos 388dffb485Schristos void 398dffb485Schristos debug_set_output (const char *new_debug_file) 408dffb485Schristos { 418dffb485Schristos /* Close any existing file and reset to standard error. */ 428dffb485Schristos if (debug_file != stderr) 438dffb485Schristos { 448dffb485Schristos fclose (debug_file); 458dffb485Schristos } 468dffb485Schristos debug_file = stderr; 478dffb485Schristos 488dffb485Schristos /* Catch empty filenames. */ 498dffb485Schristos if (new_debug_file == nullptr || strlen (new_debug_file) == 0) 508dffb485Schristos return; 518dffb485Schristos 528dffb485Schristos FILE *fptr = fopen (new_debug_file, "w"); 538dffb485Schristos 548dffb485Schristos if (fptr == nullptr) 558dffb485Schristos { 568dffb485Schristos debug_printf ("Cannot open %s for writing. %s. Switching to stderr.\n", 578dffb485Schristos new_debug_file, safe_strerror (errno)); 588dffb485Schristos return; 598dffb485Schristos } 608dffb485Schristos 618dffb485Schristos debug_file = fptr; 628dffb485Schristos } 638dffb485Schristos 648dffb485Schristos #endif 658dffb485Schristos 664b169a6bSchristos /* See gdbsupport/common-debug.h. */ 674b169a6bSchristos 684b169a6bSchristos int debug_print_depth = 0; 694b169a6bSchristos 708dffb485Schristos /* Print a debugging message. 718dffb485Schristos If the text begins a new line it is preceded by a timestamp. 728dffb485Schristos We don't get fancy with newline checking, we just check whether the 738dffb485Schristos previous call ended with "\n". */ 748dffb485Schristos 758dffb485Schristos void 768dffb485Schristos debug_vprintf (const char *format, va_list ap) 778dffb485Schristos { 788dffb485Schristos #if !defined (IN_PROCESS_AGENT) 798dffb485Schristos /* N.B. Not thread safe, and can't be used, as is, with IPA. */ 808dffb485Schristos static int new_line = 1; 818dffb485Schristos 828dffb485Schristos if (debug_timestamp && new_line) 838dffb485Schristos { 848dffb485Schristos using namespace std::chrono; 858dffb485Schristos 868dffb485Schristos steady_clock::time_point now = steady_clock::now (); 878dffb485Schristos seconds s = duration_cast<seconds> (now.time_since_epoch ()); 888dffb485Schristos microseconds us = duration_cast<microseconds> (now.time_since_epoch ()) - s; 898dffb485Schristos 908dffb485Schristos fprintf (debug_file, "%ld.%06ld ", (long) s.count (), (long) us.count ()); 918dffb485Schristos } 928dffb485Schristos #endif 938dffb485Schristos 948dffb485Schristos vfprintf (debug_file, format, ap); 958dffb485Schristos 968dffb485Schristos #if !defined (IN_PROCESS_AGENT) 978dffb485Schristos if (*format) 988dffb485Schristos new_line = format[strlen (format) - 1] == '\n'; 998dffb485Schristos #endif 1008dffb485Schristos } 1018dffb485Schristos 1028dffb485Schristos /* Flush debugging output. 1038dffb485Schristos This is called, for example, when starting an inferior to ensure all debug 1048dffb485Schristos output thus far appears before any inferior output. */ 1058dffb485Schristos 1068dffb485Schristos void 1078dffb485Schristos debug_flush (void) 1088dffb485Schristos { 1098dffb485Schristos fflush (debug_file); 1108dffb485Schristos } 1118dffb485Schristos 1128dffb485Schristos /* See debug.h. */ 1138dffb485Schristos 1148dffb485Schristos ssize_t 1158dffb485Schristos debug_write (const void *buf, size_t nbyte) 1168dffb485Schristos { 1178dffb485Schristos int fd = fileno (debug_file); 1188dffb485Schristos return write (fd, buf, nbyte); 1198dffb485Schristos } 120