]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/mingw-hdep.c
[binutils, ARM, 4/16] BF insns infrastructure with array of relocs in struct arm_it
[thirdparty/binutils-gdb.git] / gdb / mingw-hdep.c
CommitLineData
121ce6e5
DJ
1/* Host support routines for MinGW, for GDB, the GNU debugger.
2
42a4f53d 3 Copyright (C) 2006-2019 Free Software Foundation, Inc.
121ce6e5
DJ
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
121ce6e5
DJ
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
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
121ce6e5
DJ
19
20#include "defs.h"
d9ac0664 21#include "main.h"
0ea3f30e 22#include "serial.h"
b803fb0f 23#include "event-loop.h"
121ce6e5 24
0ea3f30e 25#include "gdb_select.h"
b803fb0f 26#include "readline/readline.h"
121ce6e5
DJ
27
28#include <windows.h>
29
d9ac0664
EZ
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
33char *
34windows_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
0ea3f30e
DJ
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
50int
51gdb_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;
4577549b
DJ
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;
0ea3f30e
DJ
64 int fd;
65 int num_ready;
4577549b 66 size_t indx;
0ea3f30e
DJ
67
68 num_ready = 0;
69 num_handles = 0;
4577549b 70 num_scbs = 0;
0ea3f30e
DJ
71 for (fd = 0; fd < n; ++fd)
72 {
73 HANDLE read = NULL, except = NULL;
74 struct serial *scb;
75
76 /* There is no support yet for WRITEFDS. At present, this isn't
77 used by GDB -- but we do not want to silently ignore WRITEFDS
78 if something starts using it. */
79 gdb_assert (!writefds || !FD_ISSET (fd, writefds));
80
98739726
DJ
81 if ((!readfds || !FD_ISSET (fd, readfds))
82 && (!exceptfds || !FD_ISSET (fd, exceptfds)))
0ea3f30e 83 continue;
0ea3f30e
DJ
84
85 scb = serial_for_fd (fd);
86 if (scb)
4577549b
DJ
87 {
88 serial_wait_handle (scb, &read, &except);
89 scbs[num_scbs++] = scb;
90 }
0ea3f30e
DJ
91
92 if (read == NULL)
4577549b 93 read = (HANDLE) _get_osfhandle (fd);
0ea3f30e
DJ
94 if (except == NULL)
95 {
96 if (!never_handle)
97 never_handle = CreateEvent (0, FALSE, FALSE, 0);
98
99 except = never_handle;
100 }
101
98739726 102 if (readfds && FD_ISSET (fd, readfds))
0ea3f30e
DJ
103 {
104 gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
105 handles[num_handles++] = read;
106 }
107
98739726 108 if (exceptfds && FD_ISSET (fd, exceptfds))
0ea3f30e
DJ
109 {
110 gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
111 handles[num_handles++] = except;
112 }
113 }
0ea3f30e 114
585a46a2 115 gdb_assert (num_handles <= MAXIMUM_WAIT_OBJECTS);
0ea3f30e
DJ
116
117 event = WaitForMultipleObjects (num_handles,
118 handles,
119 FALSE,
120 timeout
121 ? (timeout->tv_sec * 1000
122 + timeout->tv_usec / 1000)
123 : INFINITE);
124 /* EVENT can only be a value in the WAIT_ABANDONED_0 range if the
125 HANDLES included an abandoned mutex. Since GDB doesn't use
126 mutexes, that should never occur. */
127 gdb_assert (!(WAIT_ABANDONED_0 <= event
128 && event < WAIT_ABANDONED_0 + num_handles));
4577549b
DJ
129 /* We no longer need the helper threads to check for activity. */
130 for (indx = 0; indx < num_scbs; ++indx)
131 serial_done_wait_handle (scbs[indx]);
0ea3f30e
DJ
132 if (event == WAIT_FAILED)
133 return -1;
134 if (event == WAIT_TIMEOUT)
135 return 0;
136 /* Run through the READFDS, clearing bits corresponding to descriptors
137 for which input is unavailable. */
138 h = handles[event - WAIT_OBJECT_0];
139 for (fd = 0, indx = 0; fd < n; ++fd)
140 {
141 HANDLE fd_h;
c3e2b812 142
98739726
DJ
143 if ((!readfds || !FD_ISSET (fd, readfds))
144 && (!exceptfds || !FD_ISSET (fd, exceptfds)))
c3e2b812 145 continue;
0ea3f30e 146
98739726 147 if (readfds && FD_ISSET (fd, readfds))
0ea3f30e
DJ
148 {
149 fd_h = handles[indx++];
150 /* This handle might be ready, even though it wasn't the handle
151 returned by WaitForMultipleObjects. */
152 if (fd_h != h && WaitForSingleObject (fd_h, 0) != WAIT_OBJECT_0)
153 FD_CLR (fd, readfds);
154 else
155 num_ready++;
156 }
157
98739726 158 if (exceptfds && FD_ISSET (fd, exceptfds))
0ea3f30e
DJ
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, exceptfds);
165 else
166 num_ready++;
167 }
168 }
169
b803fb0f
DJ
170 /* With multi-threaded SIGINT handling, there is a race between the
171 readline signal handler and GDB. It may still be in
172 rl_prep_terminal in another thread. Do not return until it is
173 done; we can check the state here because we never longjmp from
174 signal handlers on Windows. */
175 while (RL_ISSTATE (RL_STATE_SIGHANDLER))
176 Sleep (1);
177
0ea3f30e
DJ
178 return num_ready;
179}
e4adb939
EZ
180
181/* Map COLOR's RGB triplet, with 8 bits per component, into 16 Windows
182 console colors, where each component has just 1 bit, plus a single
183 intensity bit which affects all 3 components. */
184static int
185rgb_to_16colors (const ui_file_style::color &color)
186{
187 uint8_t rgb[3];
188 color.get_rgb (rgb);
189
190 int retval = 0;
191 for (int i = 0; i < 3; i++)
192 {
193 /* Subdivide 256 possible values of each RGB component into 3
194 regions: no color, normal color, bright color. 256 / 3 = 85,
195 but ui-style.c follows xterm and uses 92 for R and G
196 components of the bright-blue color, so we bias the divisor a
197 bit to have the bright colors between 9 and 15 identical to
198 what ui-style.c expects. */
199 int bits = rgb[i] / 93;
200 retval |= ((bits > 0) << (2 - i)) | ((bits > 1) << 3);
201 }
202
203 return retval;
204}
205
206/* Zero if not yet initialized, 1 if stdout is a console device, else -1. */
207static int mingw_console_initialized;
208
209/* Handle to stdout . */
210static HANDLE hstdout = INVALID_HANDLE_VALUE;
211
212/* Text attribute to use for normal text (the "none" pseudo-color). */
213static SHORT norm_attr;
214
215/* The most recently applied style. */
216static ui_file_style last_style;
217
218/* Alternative for the libc 'fputs' which handles embedded SGR
219 sequences in support of styling. */
220
221int
222gdb_console_fputs (const char *linebuf, FILE *fstream)
223{
224 if (!mingw_console_initialized)
225 {
226 hstdout = (HANDLE)_get_osfhandle (fileno (fstream));
227 DWORD cmode;
228 CONSOLE_SCREEN_BUFFER_INFO csbi;
229
230 if (hstdout != INVALID_HANDLE_VALUE
231 && GetConsoleMode (hstdout, &cmode) != 0
232 && GetConsoleScreenBufferInfo (hstdout, &csbi))
233 {
234 norm_attr = csbi.wAttributes;
235 mingw_console_initialized = 1;
236 }
237 else if (hstdout != INVALID_HANDLE_VALUE)
238 mingw_console_initialized = -1; /* valid, but not a console device */
239 }
240 /* If our stdout is not a console device, let the default 'fputs'
241 handle the task. */
242 if (mingw_console_initialized <= 0)
243 return 0;
244
245 /* Mapping between 8 ANSI colors and Windows console attributes. */
246 static int fg_color[] = {
247 0, /* black */
248 FOREGROUND_RED, /* red */
249 FOREGROUND_GREEN, /* green */
250 FOREGROUND_GREEN | FOREGROUND_RED, /* yellow */
251 FOREGROUND_BLUE, /* blue */
252 FOREGROUND_BLUE | FOREGROUND_RED, /* magenta */
253 FOREGROUND_BLUE | FOREGROUND_GREEN, /* cyan */
254 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE /* gray */
255 };
256 static int bg_color[] = {
257 0, /* black */
258 BACKGROUND_RED, /* red */
259 BACKGROUND_GREEN, /* green */
260 BACKGROUND_GREEN | BACKGROUND_RED, /* yellow */
261 BACKGROUND_BLUE, /* blue */
262 BACKGROUND_BLUE | BACKGROUND_RED, /* magenta */
263 BACKGROUND_BLUE | BACKGROUND_GREEN, /* cyan */
264 BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE /* gray */
265 };
266
267 ui_file_style style = last_style;
268 unsigned char c;
269 size_t n_read;
270
271 for ( ; (c = *linebuf) != 0; linebuf += n_read)
272 {
273 if (c == '\033')
274 {
275 fflush (fstream);
276 bool parsed = style.parse (linebuf, &n_read);
277 if (n_read <= 0) /* should never happen */
278 n_read = 1;
279 if (!parsed)
280 {
281 /* This means we silently swallow SGR sequences we
282 cannot parse. */
283 continue;
284 }
285 /* Colors. */
286 const ui_file_style::color &fg = style.get_foreground ();
287 const ui_file_style::color &bg = style.get_background ();
288 int fgcolor, bgcolor, bright, inverse;
289 if (fg.is_none ())
290 fgcolor = norm_attr & 15;
291 else if (fg.is_basic ())
292 fgcolor = fg_color[fg.get_value () & 15];
293 else
294 fgcolor = rgb_to_16colors (fg);
295 if (bg.is_none ())
296 bgcolor = norm_attr & (15 << 4);
297 else if (bg.is_basic ())
298 bgcolor = bg_color[bg.get_value () & 15];
299 else
300 bgcolor = rgb_to_16colors (bg) << 4;
301
302 /* Intensity. */
303 switch (style.get_intensity ())
304 {
305 case ui_file_style::NORMAL:
306 case ui_file_style::DIM:
307 bright = 0;
308 break;
309 case ui_file_style::BOLD:
310 bright = 1;
311 break;
312 default:
313 gdb_assert_not_reached ("invalid intensity");
314 }
315
316 /* Inverse video. */
317 if (style.is_reverse ())
318 inverse = 1;
319 else
320 inverse = 0;
321
322 /* Construct the attribute. */
323 if (inverse)
324 {
325 int t = fgcolor;
326 fgcolor = (bgcolor >> 4);
327 bgcolor = (t << 4);
328 }
329 if (bright)
330 fgcolor |= FOREGROUND_INTENSITY;
331
332 SHORT attr = (bgcolor & (15 << 4)) | (fgcolor & 15);
333
334 /* Apply the attribute. */
335 SetConsoleTextAttribute (hstdout, attr);
336 }
337 else
338 {
339 /* When we are about to write newline, we need to clear to
340 EOL with the normal attribute, to avoid spilling the
341 colors to the next screen line. We assume here that no
342 non-default attribute extends beyond the newline. */
343 if (c == '\n')
344 {
345 DWORD nchars;
346 COORD start_pos;
347 DWORD written;
348 CONSOLE_SCREEN_BUFFER_INFO csbi;
349
350 fflush (fstream);
351 GetConsoleScreenBufferInfo (hstdout, &csbi);
352
353 if (csbi.wAttributes != norm_attr)
354 {
355 start_pos = csbi.dwCursorPosition;
356 nchars = csbi.dwSize.X - start_pos.X;
357
358 FillConsoleOutputAttribute (hstdout, norm_attr, nchars,
359 start_pos, &written);
360 FillConsoleOutputCharacter (hstdout, ' ', nchars,
361 start_pos, &written);
362 }
363 }
364 fputc (c, fstream);
365 n_read = 1;
366 }
367 }
368
369 last_style = style;
370 return 1;
371}