Remove path name from test case
[binutils-gdb.git] / gdb / mingw-hdep.c
1 /* Host support routines for MinGW, for GDB, the GNU debugger.
2
3 Copyright (C) 2006-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 "main.h"
22 #include "serial.h"
23 #include "gdbsupport/event-loop.h"
24 #include "gdbsupport/gdb_select.h"
25 #include "inferior.h"
26
27 #include <windows.h>
28 #include <signal.h>
29
30 /* Return an absolute file name of the running GDB, if possible, or
31 ARGV0 if not. The return value is in malloc'ed storage. */
32
33 char *
34 windows_get_absolute_argv0 (const char *argv0)
35 {
36 char full_name[PATH_MAX];
37
38 if (GetModuleFileName (NULL, full_name, PATH_MAX))
39 return xstrdup (full_name);
40 return xstrdup (argv0);
41 }
42
43 /* Wrapper for select. On Windows systems, where the select interface
44 only works for sockets, this uses the GDB serial abstraction to
45 handle sockets, consoles, pipes, and serial ports.
46
47 The arguments to this function are the same as the traditional
48 arguments to select on POSIX platforms. */
49
50 int
51 gdb_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
52 struct timeval *timeout)
53 {
54 static HANDLE never_handle;
55 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
56 HANDLE h;
57 DWORD event;
58 DWORD num_handles;
59 /* SCBS contains serial control objects corresponding to file
60 descriptors in READFDS and WRITEFDS. */
61 struct serial *scbs[MAXIMUM_WAIT_OBJECTS];
62 /* The number of valid entries in SCBS. */
63 size_t num_scbs;
64 int fd;
65 int num_ready;
66 size_t indx;
67
68 if (n == 0)
69 {
70 /* The MS API says that the first argument to
71 WaitForMultipleObjects cannot be zero. That's why we just
72 use a regular Sleep here. */
73 if (timeout != NULL)
74 Sleep (timeout->tv_sec * 1000 + timeout->tv_usec / 1000);
75
76 return 0;
77 }
78
79 num_ready = 0;
80 num_handles = 0;
81 num_scbs = 0;
82 for (fd = 0; fd < n; ++fd)
83 {
84 HANDLE read = NULL, except = NULL;
85 struct serial *scb;
86
87 /* There is no support yet for WRITEFDS. At present, this isn't
88 used by GDB -- but we do not want to silently ignore WRITEFDS
89 if something starts using it. */
90 gdb_assert (!writefds || !FD_ISSET (fd, writefds));
91
92 if ((!readfds || !FD_ISSET (fd, readfds))
93 && (!exceptfds || !FD_ISSET (fd, exceptfds)))
94 continue;
95
96 scb = serial_for_fd (fd);
97 if (scb)
98 {
99 serial_wait_handle (scb, &read, &except);
100 scbs[num_scbs++] = scb;
101 }
102
103 if (read == NULL)
104 read = (HANDLE) _get_osfhandle (fd);
105 if (except == NULL)
106 {
107 if (!never_handle)
108 never_handle = CreateEvent (0, FALSE, FALSE, 0);
109
110 except = never_handle;
111 }
112
113 if (readfds && FD_ISSET (fd, readfds))
114 {
115 gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
116 handles[num_handles++] = read;
117 }
118
119 if (exceptfds && FD_ISSET (fd, exceptfds))
120 {
121 gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
122 handles[num_handles++] = except;
123 }
124 }
125
126 gdb_assert (num_handles <= MAXIMUM_WAIT_OBJECTS);
127
128 event = WaitForMultipleObjects (num_handles,
129 handles,
130 FALSE,
131 timeout
132 ? (timeout->tv_sec * 1000
133 + timeout->tv_usec / 1000)
134 : INFINITE);
135 /* EVENT can only be a value in the WAIT_ABANDONED_0 range if the
136 HANDLES included an abandoned mutex. Since GDB doesn't use
137 mutexes, that should never occur. */
138 gdb_assert (!(WAIT_ABANDONED_0 <= event
139 && event < WAIT_ABANDONED_0 + num_handles));
140 /* We no longer need the helper threads to check for activity. */
141 for (indx = 0; indx < num_scbs; ++indx)
142 serial_done_wait_handle (scbs[indx]);
143 if (event == WAIT_FAILED)
144 return -1;
145 if (event == WAIT_TIMEOUT)
146 return 0;
147 /* Run through the READFDS, clearing bits corresponding to descriptors
148 for which input is unavailable. */
149 h = handles[event - WAIT_OBJECT_0];
150 for (fd = 0, indx = 0; fd < n; ++fd)
151 {
152 HANDLE fd_h;
153
154 if ((!readfds || !FD_ISSET (fd, readfds))
155 && (!exceptfds || !FD_ISSET (fd, exceptfds)))
156 continue;
157
158 if (readfds && FD_ISSET (fd, readfds))
159 {
160 fd_h = handles[indx++];
161 /* This handle might be ready, even though it wasn't the handle
162 returned by WaitForMultipleObjects. */
163 if (fd_h != h && WaitForSingleObject (fd_h, 0) != WAIT_OBJECT_0)
164 FD_CLR (fd, readfds);
165 else
166 num_ready++;
167 }
168
169 if (exceptfds && FD_ISSET (fd, exceptfds))
170 {
171 fd_h = handles[indx++];
172 /* This handle might be ready, even though it wasn't the handle
173 returned by WaitForMultipleObjects. */
174 if (fd_h != h && WaitForSingleObject (fd_h, 0) != WAIT_OBJECT_0)
175 FD_CLR (fd, exceptfds);
176 else
177 num_ready++;
178 }
179 }
180
181 return num_ready;
182 }
183
184 /* Map COLOR's RGB triplet, with 8 bits per component, into 16 Windows
185 console colors, where each component has just 1 bit, plus a single
186 intensity bit which affects all 3 components. */
187 static int
188 rgb_to_16colors (const ui_file_style::color &color)
189 {
190 uint8_t rgb[3];
191 color.get_rgb (rgb);
192
193 int retval = 0;
194 for (int i = 0; i < 3; i++)
195 {
196 /* Subdivide 256 possible values of each RGB component into 3
197 regions: no color, normal color, bright color. 256 / 3 = 85,
198 but ui-style.c follows xterm and uses 92 for R and G
199 components of the bright-blue color, so we bias the divisor a
200 bit to have the bright colors between 9 and 15 identical to
201 what ui-style.c expects. */
202 int bits = rgb[i] / 93;
203 retval |= ((bits > 0) << (2 - i)) | ((bits > 1) << 3);
204 }
205
206 return retval;
207 }
208
209 /* Zero if not yet initialized, 1 if stdout is a console device, else -1. */
210 static int mingw_console_initialized;
211
212 /* Handle to stdout . */
213 static HANDLE hstdout = INVALID_HANDLE_VALUE;
214
215 /* Text attribute to use for normal text (the "none" pseudo-color). */
216 static SHORT norm_attr;
217
218 /* The most recently applied style. */
219 static ui_file_style last_style;
220
221 /* Alternative for the libc 'fputs' which handles embedded SGR
222 sequences in support of styling. */
223
224 int
225 gdb_console_fputs (const char *linebuf, FILE *fstream)
226 {
227 if (!mingw_console_initialized)
228 {
229 hstdout = (HANDLE)_get_osfhandle (fileno (fstream));
230 DWORD cmode;
231 CONSOLE_SCREEN_BUFFER_INFO csbi;
232
233 if (hstdout != INVALID_HANDLE_VALUE
234 && GetConsoleMode (hstdout, &cmode) != 0
235 && GetConsoleScreenBufferInfo (hstdout, &csbi))
236 {
237 norm_attr = csbi.wAttributes;
238 mingw_console_initialized = 1;
239 }
240 else if (hstdout != INVALID_HANDLE_VALUE)
241 mingw_console_initialized = -1; /* valid, but not a console device */
242 }
243 /* If our stdout is not a console device, let the default 'fputs'
244 handle the task. */
245 if (mingw_console_initialized <= 0)
246 return 0;
247
248 /* Mapping between 8 ANSI colors and Windows console attributes. */
249 static int fg_color[] = {
250 0, /* black */
251 FOREGROUND_RED, /* red */
252 FOREGROUND_GREEN, /* green */
253 FOREGROUND_GREEN | FOREGROUND_RED, /* yellow */
254 FOREGROUND_BLUE, /* blue */
255 FOREGROUND_BLUE | FOREGROUND_RED, /* magenta */
256 FOREGROUND_BLUE | FOREGROUND_GREEN, /* cyan */
257 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE /* gray */
258 };
259 static int bg_color[] = {
260 0, /* black */
261 BACKGROUND_RED, /* red */
262 BACKGROUND_GREEN, /* green */
263 BACKGROUND_GREEN | BACKGROUND_RED, /* yellow */
264 BACKGROUND_BLUE, /* blue */
265 BACKGROUND_BLUE | BACKGROUND_RED, /* magenta */
266 BACKGROUND_BLUE | BACKGROUND_GREEN, /* cyan */
267 BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE /* gray */
268 };
269
270 ui_file_style style = last_style;
271 unsigned char c;
272 size_t n_read;
273
274 for ( ; (c = *linebuf) != 0; linebuf += n_read)
275 {
276 if (c == '\033')
277 {
278 fflush (fstream);
279 bool parsed = style.parse (linebuf, &n_read);
280 if (n_read <= 0) /* should never happen */
281 n_read = 1;
282 if (!parsed)
283 {
284 /* This means we silently swallow SGR sequences we
285 cannot parse. */
286 continue;
287 }
288 /* Colors. */
289 const ui_file_style::color &fg = style.get_foreground ();
290 const ui_file_style::color &bg = style.get_background ();
291 int fgcolor, bgcolor, bright, inverse;
292 if (fg.is_none ())
293 fgcolor = norm_attr & 15;
294 else if (fg.is_basic ())
295 fgcolor = fg_color[fg.get_value () & 15];
296 else
297 fgcolor = rgb_to_16colors (fg);
298 if (bg.is_none ())
299 bgcolor = norm_attr & (15 << 4);
300 else if (bg.is_basic ())
301 bgcolor = bg_color[bg.get_value () & 15];
302 else
303 bgcolor = rgb_to_16colors (bg) << 4;
304
305 /* Intensity. */
306 switch (style.get_intensity ())
307 {
308 case ui_file_style::NORMAL:
309 case ui_file_style::DIM:
310 bright = 0;
311 break;
312 case ui_file_style::BOLD:
313 bright = 1;
314 break;
315 default:
316 gdb_assert_not_reached ("invalid intensity");
317 }
318
319 /* Inverse video. */
320 if (style.is_reverse ())
321 inverse = 1;
322 else
323 inverse = 0;
324
325 /* Construct the attribute. */
326 if (inverse)
327 {
328 int t = fgcolor;
329 fgcolor = (bgcolor >> 4);
330 bgcolor = (t << 4);
331 }
332 if (bright)
333 fgcolor |= FOREGROUND_INTENSITY;
334
335 SHORT attr = (bgcolor & (15 << 4)) | (fgcolor & 15);
336
337 /* Apply the attribute. */
338 SetConsoleTextAttribute (hstdout, attr);
339 }
340 else
341 {
342 /* When we are about to write newline, we need to clear to
343 EOL with the normal attribute, to avoid spilling the
344 colors to the next screen line. We assume here that no
345 non-default attribute extends beyond the newline. */
346 if (c == '\n')
347 {
348 DWORD nchars;
349 COORD start_pos;
350 DWORD written;
351 CONSOLE_SCREEN_BUFFER_INFO csbi;
352
353 fflush (fstream);
354 GetConsoleScreenBufferInfo (hstdout, &csbi);
355
356 if (csbi.wAttributes != norm_attr)
357 {
358 start_pos = csbi.dwCursorPosition;
359 nchars = csbi.dwSize.X - start_pos.X;
360
361 FillConsoleOutputAttribute (hstdout, norm_attr, nchars,
362 start_pos, &written);
363 FillConsoleOutputCharacter (hstdout, ' ', nchars,
364 start_pos, &written);
365 }
366 }
367 fputc (c, fstream);
368 n_read = 1;
369 }
370 }
371
372 last_style = style;
373 return 1;
374 }
375
376 /* See inferior.h. */
377
378 tribool
379 sharing_input_terminal (int pid)
380 {
381 std::vector<DWORD> results (10);
382 DWORD len = 0;
383 while (true)
384 {
385 len = GetConsoleProcessList (results.data (), results.size ());
386 /* Note that LEN == 0 is a failure, but we can treat it the same
387 as a "no". */
388 if (len <= results.size ())
389 break;
390
391 results.resize (len);
392 }
393 /* In case the vector was too big. */
394 results.resize (len);
395 if (std::find (results.begin (), results.end (), pid) != results.end ())
396 {
397 /* The pid is in the list sharing the console, so don't
398 interrupt the inferior -- it will get the signal itself. */
399 return TRIBOOL_TRUE;
400 }
401
402 return TRIBOOL_FALSE;
403 }
404
405 /* Current C-c handler. */
406 static c_c_handler_ftype *current_handler;
407
408 /* The Windows callback that forwards requests to the C-c handler. */
409 static BOOL WINAPI
410 ctrl_c_handler (DWORD event_type)
411 {
412 if (event_type == CTRL_BREAK_EVENT || event_type == CTRL_C_EVENT)
413 {
414 if (current_handler != SIG_IGN)
415 current_handler (SIGINT);
416 }
417 else
418 return FALSE;
419 return TRUE;
420 }
421
422 /* See inferior.h. */
423
424 c_c_handler_ftype *
425 install_sigint_handler (c_c_handler_ftype *fn)
426 {
427 /* We want to make sure the gdb handler always comes first, so that
428 gdb gets to handle the C-c. This is why the handler is always
429 removed and reinstalled here. Note that trying to remove the
430 function without installing it first will cause a crash. */
431 static bool installed = false;
432 if (installed)
433 SetConsoleCtrlHandler (ctrl_c_handler, FALSE);
434 SetConsoleCtrlHandler (ctrl_c_handler, TRUE);
435 installed = true;
436
437 c_c_handler_ftype *result = current_handler;
438 current_handler = fn;
439 return result;
440 }