xref: /netbsd-src/external/gpl3/gdb/dist/gdbserver/debug.cc (revision f1c2b495c8d0ed769f039187bdd4f963026e012b)
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