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