Move gdb_select.h to gdbsupport/
[deliverable/binutils-gdb.git] / gdb / guile / scm-ports.c
1 /* Support for connecting Guile's stdio to GDB's.
2 as well as r/w memory via ports.
3
4 Copyright (C) 2014-2020 Free Software Foundation, Inc.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21 /* See README file in this directory for implementation notes, coding
22 conventions, et.al. */
23
24 #include "defs.h"
25 #include "gdbsupport/gdb_select.h"
26 #include "top.h"
27 #include "target.h"
28 #include "guile-internal.h"
29 #include "gdbsupport/gdb_optional.h"
30
31 #ifdef HAVE_POLL
32 #if defined (HAVE_POLL_H)
33 #include <poll.h>
34 #elif defined (HAVE_SYS_POLL_H)
35 #include <sys/poll.h>
36 #endif
37 #endif
38
39 /* A ui-file for sending output to Guile. */
40
41 class ioscm_file_port : public ui_file
42 {
43 public:
44 /* Return a ui_file that writes to PORT. */
45 explicit ioscm_file_port (SCM port);
46
47 void flush () override;
48 void write (const char *buf, long length_buf) override;
49
50 private:
51 SCM m_port;
52 };
53
54 /* Data for a memory port. */
55
56 typedef struct
57 {
58 /* Bounds of memory range this port is allowed to access: [start, end).
59 This means that 0xff..ff is not accessible. I can live with that. */
60 CORE_ADDR start, end;
61
62 /* (end - start), recorded for convenience. */
63 ULONGEST size;
64
65 /* Think of this as the lseek value maintained by the kernel.
66 This value is always in the range [0, size]. */
67 ULONGEST current;
68
69 /* The size of the internal r/w buffers.
70 Scheme ports aren't a straightforward mapping to memory r/w.
71 Generally the user specifies how much to r/w and all access is
72 unbuffered. We don't try to provide equivalent access, but we allow
73 the user to specify these values to help get something similar. */
74 unsigned read_buf_size, write_buf_size;
75 } ioscm_memory_port;
76
77 /* Copies of the original system input/output/error ports.
78 These are recorded for debugging purposes. */
79 static SCM orig_input_port_scm;
80 static SCM orig_output_port_scm;
81 static SCM orig_error_port_scm;
82
83 /* This is the stdio port descriptor, scm_ptob_descriptor. */
84 static scm_t_bits stdio_port_desc;
85
86 /* Note: scm_make_port_type takes a char * instead of a const char *. */
87 static /*const*/ char stdio_port_desc_name[] = "gdb:stdio-port";
88
89 /* Names of each gdb port. */
90 static const char input_port_name[] = "gdb:stdin";
91 static const char output_port_name[] = "gdb:stdout";
92 static const char error_port_name[] = "gdb:stderr";
93
94 /* This is the actual port used from Guile.
95 We don't expose these to the user though, to ensure they're not
96 overwritten. */
97 static SCM input_port_scm;
98 static SCM output_port_scm;
99 static SCM error_port_scm;
100
101 /* Internal enum for specifying output port. */
102 enum oport { GDB_STDOUT, GDB_STDERR };
103
104 /* This is the memory port descriptor, scm_ptob_descriptor. */
105 static scm_t_bits memory_port_desc;
106
107 /* Note: scm_make_port_type takes a char * instead of a const char *. */
108 static /*const*/ char memory_port_desc_name[] = "gdb:memory-port";
109
110 /* The default amount of memory to fetch for each read/write request.
111 Scheme ports don't provide a way to specify the size of a read,
112 which is important to us to minimize the number of inferior interactions,
113 which over a remote link can be important. To compensate we augment the
114 port API with a new function that let's the user specify how much the next
115 read request should fetch. This is the initial value for each new port. */
116 static const unsigned default_read_buf_size = 16;
117 static const unsigned default_write_buf_size = 16;
118
119 /* Arbitrarily limit memory port buffers to 1 byte to 4K. */
120 static const unsigned min_memory_port_buf_size = 1;
121 static const unsigned max_memory_port_buf_size = 4096;
122
123 /* "out of range" error message for buf sizes. */
124 static char *out_of_range_buf_size;
125
126 /* Keywords used by open-memory. */
127 static SCM mode_keyword;
128 static SCM start_keyword;
129 static SCM size_keyword;
130 \f
131 /* Helper to do the low level work of opening a port.
132 Newer versions of Guile (2.1.x) have scm_c_make_port. */
133
134 static SCM
135 ioscm_open_port (scm_t_bits port_type, long mode_bits)
136 {
137 SCM port;
138
139 #if 0 /* TODO: Guile doesn't export this. What to do? */
140 scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
141 #endif
142
143 port = scm_new_port_table_entry (port_type);
144
145 SCM_SET_CELL_TYPE (port, port_type | mode_bits);
146
147 #if 0 /* TODO: Guile doesn't export this. What to do? */
148 scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
149 #endif
150
151 return port;
152 }
153 \f
154 /* Support for connecting Guile's stdio ports to GDB's stdio ports. */
155
156 /* The scm_t_ptob_descriptor.input_waiting "method".
157 Return a lower bound on the number of bytes available for input. */
158
159 static int
160 ioscm_input_waiting (SCM port)
161 {
162 int fdes = 0;
163
164 if (! scm_is_eq (port, input_port_scm))
165 return 0;
166
167 #ifdef HAVE_POLL
168 {
169 /* This is copied from libguile/fports.c. */
170 struct pollfd pollfd = { fdes, POLLIN, 0 };
171 static int use_poll = -1;
172
173 if (use_poll < 0)
174 {
175 /* This is copied from event-loop.c: poll cannot be used for stdin on
176 m68k-motorola-sysv. */
177 struct pollfd test_pollfd = { fdes, POLLIN, 0 };
178
179 if (poll (&test_pollfd, 1, 0) == 1 && (test_pollfd.revents & POLLNVAL))
180 use_poll = 0;
181 else
182 use_poll = 1;
183 }
184
185 if (use_poll)
186 {
187 /* Guile doesn't export SIGINT hooks like Python does.
188 For now pass EINTR to scm_syserror, that's what fports.c does. */
189 if (poll (&pollfd, 1, 0) < 0)
190 scm_syserror (FUNC_NAME);
191
192 return pollfd.revents & POLLIN ? 1 : 0;
193 }
194 }
195 /* Fall through. */
196 #endif
197
198 {
199 struct timeval timeout;
200 fd_set input_fds;
201 int num_fds = fdes + 1;
202 int num_found;
203
204 memset (&timeout, 0, sizeof (timeout));
205 FD_ZERO (&input_fds);
206 FD_SET (fdes, &input_fds);
207
208 num_found = interruptible_select (num_fds,
209 &input_fds, NULL, NULL,
210 &timeout);
211 if (num_found < 0)
212 {
213 /* Guile doesn't export SIGINT hooks like Python does.
214 For now pass EINTR to scm_syserror, that's what fports.c does. */
215 scm_syserror (FUNC_NAME);
216 }
217 return num_found > 0 && FD_ISSET (fdes, &input_fds);
218 }
219 }
220
221 /* The scm_t_ptob_descriptor.fill_input "method". */
222
223 static int
224 ioscm_fill_input (SCM port)
225 {
226 /* Borrowed from libguile/fports.c. */
227 long count;
228 scm_t_port *pt = SCM_PTAB_ENTRY (port);
229
230 /* If we're called on stdout,stderr, punt. */
231 if (! scm_is_eq (port, input_port_scm))
232 return (scm_t_wchar) EOF; /* Set errno and return -1? */
233
234 gdb_flush (gdb_stdout);
235 gdb_flush (gdb_stderr);
236
237 count = gdb_stdin->read ((char *) pt->read_buf, pt->read_buf_size);
238 if (count == -1)
239 scm_syserror (FUNC_NAME);
240 if (count == 0)
241 return (scm_t_wchar) EOF;
242
243 pt->read_pos = pt->read_buf;
244 pt->read_end = pt->read_buf + count;
245 return *pt->read_buf;
246 }
247
248 /* Like fputstrn_filtered, but don't escape characters, except nul.
249 Also like fputs_filtered, but a length is specified. */
250
251 static void
252 fputsn_filtered (const char *s, size_t size, struct ui_file *stream)
253 {
254 size_t i;
255
256 for (i = 0; i < size; ++i)
257 {
258 if (s[i] == '\0')
259 fputs_filtered ("\\000", stream);
260 else
261 fputc_filtered (s[i], stream);
262 }
263 }
264
265 /* Write to gdb's stdout or stderr. */
266
267 static void
268 ioscm_write (SCM port, const void *data, size_t size)
269 {
270
271 /* If we're called on stdin, punt. */
272 if (scm_is_eq (port, input_port_scm))
273 return;
274
275 gdbscm_gdb_exception exc {};
276 try
277 {
278 if (scm_is_eq (port, error_port_scm))
279 fputsn_filtered ((const char *) data, size, gdb_stderr);
280 else
281 fputsn_filtered ((const char *) data, size, gdb_stdout);
282 }
283 catch (const gdb_exception &except)
284 {
285 exc = unpack (except);
286 }
287 GDBSCM_HANDLE_GDB_EXCEPTION (exc);
288 }
289
290 /* Flush gdb's stdout or stderr. */
291
292 static void
293 ioscm_flush (SCM port)
294 {
295 /* If we're called on stdin, punt. */
296 if (scm_is_eq (port, input_port_scm))
297 return;
298
299 if (scm_is_eq (port, error_port_scm))
300 gdb_flush (gdb_stderr);
301 else
302 gdb_flush (gdb_stdout);
303 }
304
305 /* Initialize the gdb stdio port type.
306
307 N.B. isatty? will fail on these ports, it is only supported for file
308 ports. IWBN if we could "subclass" file ports. */
309
310 static void
311 ioscm_init_gdb_stdio_port (void)
312 {
313 stdio_port_desc = scm_make_port_type (stdio_port_desc_name,
314 ioscm_fill_input, ioscm_write);
315
316 scm_set_port_input_waiting (stdio_port_desc, ioscm_input_waiting);
317 scm_set_port_flush (stdio_port_desc, ioscm_flush);
318 }
319
320 /* Subroutine of ioscm_make_gdb_stdio_port to simplify it.
321 Set up the buffers of port PORT.
322 MODE_BITS are the mode bits of PORT. */
323
324 static void
325 ioscm_init_stdio_buffers (SCM port, long mode_bits)
326 {
327 scm_t_port *pt = SCM_PTAB_ENTRY (port);
328 #define GDB_STDIO_BUFFER_DEFAULT_SIZE 1024
329 int size = mode_bits & SCM_BUF0 ? 0 : GDB_STDIO_BUFFER_DEFAULT_SIZE;
330 int writing = (mode_bits & SCM_WRTNG) != 0;
331
332 /* This is heavily copied from scm_fport_buffer_add. */
333
334 if (!writing && size > 0)
335 {
336 pt->read_buf
337 = (unsigned char *) scm_gc_malloc_pointerless (size, "port buffer");
338 pt->read_pos = pt->read_end = pt->read_buf;
339 pt->read_buf_size = size;
340 }
341 else
342 {
343 pt->read_pos = pt->read_buf = pt->read_end = &pt->shortbuf;
344 pt->read_buf_size = 1;
345 }
346
347 if (writing && size > 0)
348 {
349 pt->write_buf
350 = (unsigned char *) scm_gc_malloc_pointerless (size, "port buffer");
351 pt->write_pos = pt->write_buf;
352 pt->write_buf_size = size;
353 }
354 else
355 {
356 pt->write_buf = pt->write_pos = &pt->shortbuf;
357 pt->write_buf_size = 1;
358 }
359 pt->write_end = pt->write_buf + pt->write_buf_size;
360 }
361
362 /* Create a gdb stdio port. */
363
364 static SCM
365 ioscm_make_gdb_stdio_port (int fd)
366 {
367 int is_a_tty = isatty (fd);
368 const char *name;
369 const char *mode_str;
370 long mode_bits;
371 SCM port;
372
373 switch (fd)
374 {
375 case 0:
376 name = input_port_name;
377 mode_str = is_a_tty ? "r0" : "r";
378 break;
379 case 1:
380 name = output_port_name;
381 mode_str = is_a_tty ? "w0" : "w";
382 break;
383 case 2:
384 name = error_port_name;
385 mode_str = is_a_tty ? "w0" : "w";
386 break;
387 default:
388 gdb_assert_not_reached ("bad stdio file descriptor");
389 }
390
391 mode_bits = scm_mode_bits ((char *) mode_str);
392 port = ioscm_open_port (stdio_port_desc, mode_bits);
393
394 scm_set_port_filename_x (port, gdbscm_scm_from_c_string (name));
395
396 ioscm_init_stdio_buffers (port, mode_bits);
397
398 return port;
399 }
400
401 /* (stdio-port? object) -> boolean */
402
403 static SCM
404 gdbscm_stdio_port_p (SCM scm)
405 {
406 /* This is copied from SCM_FPORTP. */
407 return scm_from_bool (!SCM_IMP (scm)
408 && (SCM_TYP16 (scm) == stdio_port_desc));
409 }
410 \f
411 /* GDB's ports are accessed via functions to keep them read-only. */
412
413 /* (input-port) -> port */
414
415 static SCM
416 gdbscm_input_port (void)
417 {
418 return input_port_scm;
419 }
420
421 /* (output-port) -> port */
422
423 static SCM
424 gdbscm_output_port (void)
425 {
426 return output_port_scm;
427 }
428
429 /* (error-port) -> port */
430
431 static SCM
432 gdbscm_error_port (void)
433 {
434 return error_port_scm;
435 }
436 \f
437 /* Support for sending GDB I/O to Guile ports. */
438
439 ioscm_file_port::ioscm_file_port (SCM port)
440 : m_port (port)
441 {}
442
443 void
444 ioscm_file_port::flush ()
445 {
446 }
447
448 void
449 ioscm_file_port::write (const char *buffer, long length_buffer)
450 {
451 scm_c_write (m_port, buffer, length_buffer);
452 }
453
454 \f
455 /* Helper routine for with-{output,error}-to-port. */
456
457 static SCM
458 ioscm_with_output_to_port_worker (SCM port, SCM thunk, enum oport oport,
459 const char *func_name)
460 {
461 SCM result;
462
463 SCM_ASSERT_TYPE (gdbscm_is_true (scm_output_port_p (port)), port,
464 SCM_ARG1, func_name, _("output port"));
465 SCM_ASSERT_TYPE (gdbscm_is_true (scm_thunk_p (thunk)), thunk,
466 SCM_ARG2, func_name, _("thunk"));
467
468 set_batch_flag_and_restore_page_info save_page_info;
469
470 scoped_restore restore_async = make_scoped_restore (&current_ui->async, 0);
471
472 ui_file_up port_file (new ioscm_file_port (port));
473
474 scoped_restore save_file = make_scoped_restore (oport == GDB_STDERR
475 ? &gdb_stderr : &gdb_stdout);
476
477 {
478 gdb::optional<ui_out_redirect_pop> redirect_popper;
479 if (oport == GDB_STDERR)
480 gdb_stderr = port_file.get ();
481 else
482 {
483 current_uiout->redirect (port_file.get ());
484 redirect_popper.emplace (current_uiout);
485
486 gdb_stdout = port_file.get ();
487 }
488
489 result = gdbscm_safe_call_0 (thunk, NULL);
490 }
491
492 if (gdbscm_is_exception (result))
493 gdbscm_throw (result);
494
495 return result;
496 }
497
498 /* (%with-gdb-output-to-port port thunk) -> object
499 This function is experimental.
500 IWBN to not include "gdb" in the name, but it would collide with a standard
501 procedure, and it's common to import the gdb module without a prefix.
502 There are ways around this, but they're more cumbersome.
503
504 This has % in the name because it's experimental, and we want the
505 user-visible version to come from module (gdb experimental). */
506
507 static SCM
508 gdbscm_percent_with_gdb_output_to_port (SCM port, SCM thunk)
509 {
510 return ioscm_with_output_to_port_worker (port, thunk, GDB_STDOUT, FUNC_NAME);
511 }
512
513 /* (%with-gdb-error-to-port port thunk) -> object
514 This function is experimental.
515 IWBN to not include "gdb" in the name, but it would collide with a standard
516 procedure, and it's common to import the gdb module without a prefix.
517 There are ways around this, but they're more cumbersome.
518
519 This has % in the name because it's experimental, and we want the
520 user-visible version to come from module (gdb experimental). */
521
522 static SCM
523 gdbscm_percent_with_gdb_error_to_port (SCM port, SCM thunk)
524 {
525 return ioscm_with_output_to_port_worker (port, thunk, GDB_STDERR, FUNC_NAME);
526 }
527 \f
528 /* Support for r/w memory via ports. */
529
530 /* Perform an "lseek" to OFFSET,WHENCE on memory port IOMEM.
531 OFFSET must be in the range [0,size].
532 The result is non-zero for success, zero for failure. */
533
534 static int
535 ioscm_lseek_address (ioscm_memory_port *iomem, LONGEST offset, int whence)
536 {
537 CORE_ADDR new_current;
538
539 gdb_assert (iomem->current <= iomem->size);
540
541 switch (whence)
542 {
543 case SEEK_CUR:
544 /* Catch over/underflow. */
545 if ((offset < 0 && iomem->current + offset > iomem->current)
546 || (offset > 0 && iomem->current + offset < iomem->current))
547 return 0;
548 new_current = iomem->current + offset;
549 break;
550 case SEEK_SET:
551 new_current = offset;
552 break;
553 case SEEK_END:
554 if (offset == 0)
555 {
556 new_current = iomem->size;
557 break;
558 }
559 /* TODO: Not supported yet. */
560 return 0;
561 default:
562 return 0;
563 }
564
565 if (new_current > iomem->size)
566 return 0;
567 iomem->current = new_current;
568 return 1;
569 }
570
571 /* "fill_input" method for memory ports. */
572
573 static int
574 gdbscm_memory_port_fill_input (SCM port)
575 {
576 scm_t_port *pt = SCM_PTAB_ENTRY (port);
577 ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
578 size_t to_read;
579
580 /* "current" is the offset of the first byte we want to read. */
581 gdb_assert (iomem->current <= iomem->size);
582 if (iomem->current == iomem->size)
583 return EOF;
584
585 /* Don't read outside the allowed memory range. */
586 to_read = pt->read_buf_size;
587 if (to_read > iomem->size - iomem->current)
588 to_read = iomem->size - iomem->current;
589
590 if (target_read_memory (iomem->start + iomem->current, pt->read_buf,
591 to_read) != 0)
592 gdbscm_memory_error (FUNC_NAME, _("error reading memory"), SCM_EOL);
593
594 iomem->current += to_read;
595 pt->read_pos = pt->read_buf;
596 pt->read_end = pt->read_buf + to_read;
597 return *pt->read_buf;
598 }
599
600 /* "end_input" method for memory ports.
601 Clear the read buffer and adjust the file position for unread bytes. */
602
603 static void
604 gdbscm_memory_port_end_input (SCM port, int offset)
605 {
606 scm_t_port *pt = SCM_PTAB_ENTRY (port);
607 ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
608 size_t remaining = pt->read_end - pt->read_pos;
609
610 /* Note: Use of "int offset" is specified by Guile ports API. */
611 if ((offset < 0 && remaining + offset > remaining)
612 || (offset > 0 && remaining + offset < remaining))
613 {
614 gdbscm_out_of_range_error (FUNC_NAME, 0, scm_from_int (offset),
615 _("overflow in offset calculation"));
616 }
617 offset += remaining;
618
619 if (offset > 0)
620 {
621 pt->read_pos = pt->read_end;
622 /* Throw error if unread-char used at beginning of file
623 then attempting to write. Seems correct. */
624 if (!ioscm_lseek_address (iomem, -offset, SEEK_CUR))
625 {
626 gdbscm_out_of_range_error (FUNC_NAME, 0, scm_from_int (offset),
627 _("bad offset"));
628 }
629 }
630
631 pt->rw_active = SCM_PORT_NEITHER;
632 }
633
634 /* "flush" method for memory ports. */
635
636 static void
637 gdbscm_memory_port_flush (SCM port)
638 {
639 scm_t_port *pt = SCM_PTAB_ENTRY (port);
640 ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
641 size_t to_write = pt->write_pos - pt->write_buf;
642
643 if (to_write == 0)
644 return;
645
646 /* There's no way to indicate a short write, so if the request goes past
647 the end of the port's memory range, flag an error. */
648 if (to_write > iomem->size - iomem->current)
649 {
650 gdbscm_out_of_range_error (FUNC_NAME, 0,
651 gdbscm_scm_from_ulongest (to_write),
652 _("writing beyond end of memory range"));
653 }
654
655 if (target_write_memory (iomem->start + iomem->current, pt->write_buf,
656 to_write) != 0)
657 gdbscm_memory_error (FUNC_NAME, _("error writing memory"), SCM_EOL);
658
659 iomem->current += to_write;
660 pt->write_pos = pt->write_buf;
661 pt->rw_active = SCM_PORT_NEITHER;
662 }
663
664 /* "write" method for memory ports. */
665
666 static void
667 gdbscm_memory_port_write (SCM port, const void *void_data, size_t size)
668 {
669 scm_t_port *pt = SCM_PTAB_ENTRY (port);
670 ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
671 const gdb_byte *data = (const gdb_byte *) void_data;
672
673 /* There's no way to indicate a short write, so if the request goes past
674 the end of the port's memory range, flag an error. */
675 if (size > iomem->size - iomem->current)
676 {
677 gdbscm_out_of_range_error (FUNC_NAME, 0, gdbscm_scm_from_ulongest (size),
678 _("writing beyond end of memory range"));
679 }
680
681 if (pt->write_buf == &pt->shortbuf)
682 {
683 /* Unbuffered port. */
684 if (target_write_memory (iomem->start + iomem->current, data, size) != 0)
685 gdbscm_memory_error (FUNC_NAME, _("error writing memory"), SCM_EOL);
686 iomem->current += size;
687 return;
688 }
689
690 /* Note: The edge case of what to do when the buffer exactly fills is
691 debatable. Guile flushes when the buffer exactly fills up, so we
692 do too. It's counter-intuitive to my mind, but in case there's a
693 subtlety somewhere that depends on this, we do the same. */
694
695 {
696 size_t space = pt->write_end - pt->write_pos;
697
698 if (size < space)
699 {
700 /* Data fits in buffer, and does not fill it. */
701 memcpy (pt->write_pos, data, size);
702 pt->write_pos += size;
703 }
704 else
705 {
706 memcpy (pt->write_pos, data, space);
707 pt->write_pos = pt->write_end;
708 gdbscm_memory_port_flush (port);
709 {
710 const gdb_byte *ptr = data + space;
711 size_t remaining = size - space;
712
713 if (remaining >= pt->write_buf_size)
714 {
715 if (target_write_memory (iomem->start + iomem->current, ptr,
716 remaining) != 0)
717 gdbscm_memory_error (FUNC_NAME, _("error writing memory"),
718 SCM_EOL);
719 iomem->current += remaining;
720 }
721 else
722 {
723 memcpy (pt->write_pos, ptr, remaining);
724 pt->write_pos += remaining;
725 }
726 }
727 }
728 }
729 }
730
731 /* "seek" method for memory ports. */
732
733 static scm_t_off
734 gdbscm_memory_port_seek (SCM port, scm_t_off offset, int whence)
735 {
736 scm_t_port *pt = SCM_PTAB_ENTRY (port);
737 ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
738 CORE_ADDR result;
739 int rc;
740
741 if (pt->rw_active == SCM_PORT_WRITE)
742 {
743 if (offset != 0 || whence != SEEK_CUR)
744 {
745 gdbscm_memory_port_flush (port);
746 rc = ioscm_lseek_address (iomem, offset, whence);
747 result = iomem->current;
748 }
749 else
750 {
751 /* Read current position without disturbing the buffer,
752 but flag an error if what's in the buffer goes outside the
753 allowed range. */
754 CORE_ADDR current = iomem->current;
755 size_t delta = pt->write_pos - pt->write_buf;
756
757 if (current + delta < current
758 || current + delta > iomem->size)
759 rc = 0;
760 else
761 {
762 result = current + delta;
763 rc = 1;
764 }
765 }
766 }
767 else if (pt->rw_active == SCM_PORT_READ)
768 {
769 if (offset != 0 || whence != SEEK_CUR)
770 {
771 scm_end_input (port);
772 rc = ioscm_lseek_address (iomem, offset, whence);
773 result = iomem->current;
774 }
775 else
776 {
777 /* Read current position without disturbing the buffer
778 (particularly the unread-char buffer). */
779 CORE_ADDR current = iomem->current;
780 size_t remaining = pt->read_end - pt->read_pos;
781
782 if (current - remaining > current
783 || current - remaining < iomem->start)
784 rc = 0;
785 else
786 {
787 result = current - remaining;
788 rc = 1;
789 }
790
791 if (rc != 0 && pt->read_buf == pt->putback_buf)
792 {
793 size_t saved_remaining = pt->saved_read_end - pt->saved_read_pos;
794
795 if (result - saved_remaining > result
796 || result - saved_remaining < iomem->start)
797 rc = 0;
798 else
799 result -= saved_remaining;
800 }
801 }
802 }
803 else /* SCM_PORT_NEITHER */
804 {
805 rc = ioscm_lseek_address (iomem, offset, whence);
806 result = iomem->current;
807 }
808
809 if (rc == 0)
810 {
811 gdbscm_out_of_range_error (FUNC_NAME, 0,
812 gdbscm_scm_from_longest (offset),
813 _("bad seek"));
814 }
815
816 /* TODO: The Guile API doesn't support 32x64. We can't fix that here,
817 and there's no need to throw an error if the new address can't be
818 represented in a scm_t_off. But we could return something less
819 clumsy. */
820 return result;
821 }
822
823 /* "close" method for memory ports. */
824
825 static int
826 gdbscm_memory_port_close (SCM port)
827 {
828 scm_t_port *pt = SCM_PTAB_ENTRY (port);
829 ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
830
831 gdbscm_memory_port_flush (port);
832
833 if (pt->read_buf == pt->putback_buf)
834 pt->read_buf = pt->saved_read_buf;
835 if (pt->read_buf != &pt->shortbuf)
836 xfree (pt->read_buf);
837 if (pt->write_buf != &pt->shortbuf)
838 xfree (pt->write_buf);
839 scm_gc_free (iomem, sizeof (*iomem), "memory port");
840
841 return 0;
842 }
843
844 /* "free" method for memory ports. */
845
846 static size_t
847 gdbscm_memory_port_free (SCM port)
848 {
849 gdbscm_memory_port_close (port);
850
851 return 0;
852 }
853
854 /* "print" method for memory ports. */
855
856 static int
857 gdbscm_memory_port_print (SCM exp, SCM port, scm_print_state *pstate)
858 {
859 ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (exp);
860 char *type = SCM_PTOBNAME (SCM_PTOBNUM (exp));
861
862 scm_puts ("#<", port);
863 scm_print_port_mode (exp, port);
864 /* scm_print_port_mode includes a trailing space. */
865 gdbscm_printf (port, "%s %s-%s", type,
866 hex_string (iomem->start), hex_string (iomem->end));
867 scm_putc ('>', port);
868 return 1;
869 }
870
871 /* Create the port type used for memory. */
872
873 static void
874 ioscm_init_memory_port_type (void)
875 {
876 memory_port_desc = scm_make_port_type (memory_port_desc_name,
877 gdbscm_memory_port_fill_input,
878 gdbscm_memory_port_write);
879
880 scm_set_port_end_input (memory_port_desc, gdbscm_memory_port_end_input);
881 scm_set_port_flush (memory_port_desc, gdbscm_memory_port_flush);
882 scm_set_port_seek (memory_port_desc, gdbscm_memory_port_seek);
883 scm_set_port_close (memory_port_desc, gdbscm_memory_port_close);
884 scm_set_port_free (memory_port_desc, gdbscm_memory_port_free);
885 scm_set_port_print (memory_port_desc, gdbscm_memory_port_print);
886 }
887
888 /* Helper for gdbscm_open_memory to parse the mode bits.
889 An exception is thrown if MODE is invalid. */
890
891 static long
892 ioscm_parse_mode_bits (const char *func_name, const char *mode)
893 {
894 const char *p;
895 long mode_bits;
896
897 if (*mode != 'r' && *mode != 'w')
898 {
899 gdbscm_out_of_range_error (func_name, 0,
900 gdbscm_scm_from_c_string (mode),
901 _("bad mode string"));
902 }
903 for (p = mode + 1; *p != '\0'; ++p)
904 {
905 switch (*p)
906 {
907 case '0':
908 case 'b':
909 case '+':
910 break;
911 default:
912 gdbscm_out_of_range_error (func_name, 0,
913 gdbscm_scm_from_c_string (mode),
914 _("bad mode string"));
915 }
916 }
917
918 /* Kinda awkward to convert the mode from SCM -> string only to have Guile
919 convert it back to SCM, but that's the API we have to work with. */
920 mode_bits = scm_mode_bits ((char *) mode);
921
922 return mode_bits;
923 }
924
925 /* Helper for gdbscm_open_memory to finish initializing the port.
926 The port has address range [start,end).
927 This means that address of 0xff..ff is not accessible.
928 I can live with that. */
929
930 static void
931 ioscm_init_memory_port (SCM port, CORE_ADDR start, CORE_ADDR end)
932 {
933 scm_t_port *pt;
934 ioscm_memory_port *iomem;
935 int buffered = (SCM_CELL_WORD_0 (port) & SCM_BUF0) == 0;
936
937 gdb_assert (start <= end);
938
939 iomem = (ioscm_memory_port *) scm_gc_malloc_pointerless (sizeof (*iomem),
940 "memory port");
941
942 iomem->start = start;
943 iomem->end = end;
944 iomem->size = end - start;
945 iomem->current = 0;
946 if (buffered)
947 {
948 iomem->read_buf_size = default_read_buf_size;
949 iomem->write_buf_size = default_write_buf_size;
950 }
951 else
952 {
953 iomem->read_buf_size = 1;
954 iomem->write_buf_size = 1;
955 }
956
957 pt = SCM_PTAB_ENTRY (port);
958 /* Match the expectation of `binary-port?'. */
959 pt->encoding = NULL;
960 pt->rw_random = 1;
961 pt->read_buf_size = iomem->read_buf_size;
962 pt->write_buf_size = iomem->write_buf_size;
963 if (buffered)
964 {
965 pt->read_buf = (unsigned char *) xmalloc (pt->read_buf_size);
966 pt->write_buf = (unsigned char *) xmalloc (pt->write_buf_size);
967 }
968 else
969 {
970 pt->read_buf = &pt->shortbuf;
971 pt->write_buf = &pt->shortbuf;
972 }
973 pt->read_pos = pt->read_end = pt->read_buf;
974 pt->write_pos = pt->write_buf;
975 pt->write_end = pt->write_buf + pt->write_buf_size;
976
977 SCM_SETSTREAM (port, iomem);
978 }
979
980 /* Re-initialize a memory port, updating its read/write buffer sizes.
981 An exception is thrown if the port is unbuffered.
982 TODO: Allow switching buffered/unbuffered.
983 An exception is also thrown if data is still buffered, except in the case
984 where the buffer size isn't changing (since that's just a nop). */
985
986 static void
987 ioscm_reinit_memory_port (SCM port, size_t read_buf_size,
988 size_t write_buf_size, const char *func_name)
989 {
990 scm_t_port *pt = SCM_PTAB_ENTRY (port);
991 ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port);
992
993 gdb_assert (read_buf_size >= min_memory_port_buf_size
994 && read_buf_size <= max_memory_port_buf_size);
995 gdb_assert (write_buf_size >= min_memory_port_buf_size
996 && write_buf_size <= max_memory_port_buf_size);
997
998 /* First check if the port is unbuffered. */
999
1000 if (pt->read_buf == &pt->shortbuf)
1001 {
1002 gdb_assert (pt->write_buf == &pt->shortbuf);
1003 scm_misc_error (func_name, _("port is unbuffered: ~a"),
1004 scm_list_1 (port));
1005 }
1006
1007 /* Next check if anything is buffered. */
1008
1009 if (read_buf_size != pt->read_buf_size
1010 && pt->read_end != pt->read_buf)
1011 {
1012 scm_misc_error (func_name, _("read buffer not empty: ~a"),
1013 scm_list_1 (port));
1014 }
1015
1016 if (write_buf_size != pt->write_buf_size
1017 && pt->write_pos != pt->write_buf)
1018 {
1019 scm_misc_error (func_name, _("write buffer not empty: ~a"),
1020 scm_list_1 (port));
1021 }
1022
1023 /* Now we can update the buffer sizes, but only if the size has changed. */
1024
1025 if (read_buf_size != pt->read_buf_size)
1026 {
1027 iomem->read_buf_size = read_buf_size;
1028 pt->read_buf_size = read_buf_size;
1029 xfree (pt->read_buf);
1030 pt->read_buf = (unsigned char *) xmalloc (pt->read_buf_size);
1031 pt->read_pos = pt->read_end = pt->read_buf;
1032 }
1033
1034 if (write_buf_size != pt->write_buf_size)
1035 {
1036 iomem->write_buf_size = write_buf_size;
1037 pt->write_buf_size = write_buf_size;
1038 xfree (pt->write_buf);
1039 pt->write_buf = (unsigned char *) xmalloc (pt->write_buf_size);
1040 pt->write_pos = pt->write_buf;
1041 pt->write_end = pt->write_buf + pt->write_buf_size;
1042 }
1043 }
1044
1045 /* (open-memory [#:mode string] [#:start address] [#:size integer]) -> port
1046 Return a port that can be used for reading and writing memory.
1047 MODE is a string, and must be one of "r", "w", or "r+".
1048 "0" may be appended to MODE to mark the port as unbuffered.
1049 For compatibility "b" (binary) may also be appended, but we ignore it:
1050 memory ports are binary only.
1051
1052 The chunk of memory that can be accessed can be bounded.
1053 If both START,SIZE are unspecified, all of memory can be accessed
1054 (except 0xff..ff). If only START is specified, all of memory from that
1055 point on can be accessed (except 0xff..ff). If only SIZE if specified,
1056 all memory in [0,SIZE) can be accessed. If both are specified, all memory
1057 in [START,START+SIZE) can be accessed.
1058
1059 Note: If it becomes useful enough we can later add #:end as an alternative
1060 to #:size. For now it is left out.
1061
1062 The result is a Scheme port, and its semantics are a bit odd for accessing
1063 memory (e.g., unget), but we don't try to hide this. It's a port.
1064
1065 N.B. Seeks on the port must be in the range [0,size].
1066 This is for similarity with bytevector ports, and so that one can seek
1067 to the first byte. */
1068
1069 static SCM
1070 gdbscm_open_memory (SCM rest)
1071 {
1072 const SCM keywords[] = {
1073 mode_keyword, start_keyword, size_keyword, SCM_BOOL_F
1074 };
1075 char *mode = NULL;
1076 CORE_ADDR start = 0;
1077 CORE_ADDR end;
1078 int mode_arg_pos = -1, start_arg_pos = -1, size_arg_pos = -1;
1079 ULONGEST size;
1080 SCM port;
1081 long mode_bits;
1082
1083 gdbscm_parse_function_args (FUNC_NAME, SCM_ARG1, keywords, "#sUU", rest,
1084 &mode_arg_pos, &mode,
1085 &start_arg_pos, &start,
1086 &size_arg_pos, &size);
1087
1088 scm_dynwind_begin ((scm_t_dynwind_flags) 0);
1089
1090 if (mode == NULL)
1091 mode = xstrdup ("r");
1092 scm_dynwind_free (mode);
1093
1094 if (size_arg_pos > 0)
1095 {
1096 /* For now be strict about start+size overflowing. If it becomes
1097 a nuisance we can relax things later. */
1098 if (start + size < start)
1099 {
1100 gdbscm_out_of_range_error (FUNC_NAME, 0,
1101 scm_list_2 (gdbscm_scm_from_ulongest (start),
1102 gdbscm_scm_from_ulongest (size)),
1103 _("start+size overflows"));
1104 }
1105 end = start + size;
1106 }
1107 else
1108 end = ~(CORE_ADDR) 0;
1109
1110 mode_bits = ioscm_parse_mode_bits (FUNC_NAME, mode);
1111
1112 port = ioscm_open_port (memory_port_desc, mode_bits);
1113
1114 ioscm_init_memory_port (port, start, end);
1115
1116 scm_dynwind_end ();
1117
1118 /* TODO: Set the file name as "memory-start-end"? */
1119 return port;
1120 }
1121
1122 /* Return non-zero if OBJ is a memory port. */
1123
1124 static int
1125 gdbscm_is_memory_port (SCM obj)
1126 {
1127 return !SCM_IMP (obj) && (SCM_TYP16 (obj) == memory_port_desc);
1128 }
1129
1130 /* (memory-port? obj) -> boolean */
1131
1132 static SCM
1133 gdbscm_memory_port_p (SCM obj)
1134 {
1135 return scm_from_bool (gdbscm_is_memory_port (obj));
1136 }
1137
1138 /* (memory-port-range port) -> (start end) */
1139
1140 static SCM
1141 gdbscm_memory_port_range (SCM port)
1142 {
1143 ioscm_memory_port *iomem;
1144
1145 SCM_ASSERT_TYPE (gdbscm_is_memory_port (port), port, SCM_ARG1, FUNC_NAME,
1146 memory_port_desc_name);
1147
1148 iomem = (ioscm_memory_port *) SCM_STREAM (port);
1149 return scm_list_2 (gdbscm_scm_from_ulongest (iomem->start),
1150 gdbscm_scm_from_ulongest (iomem->end));
1151 }
1152
1153 /* (memory-port-read-buffer-size port) -> integer */
1154
1155 static SCM
1156 gdbscm_memory_port_read_buffer_size (SCM port)
1157 {
1158 ioscm_memory_port *iomem;
1159
1160 SCM_ASSERT_TYPE (gdbscm_is_memory_port (port), port, SCM_ARG1, FUNC_NAME,
1161 memory_port_desc_name);
1162
1163 iomem = (ioscm_memory_port *) SCM_STREAM (port);
1164 return scm_from_uint (iomem->read_buf_size);
1165 }
1166
1167 /* (set-memory-port-read-buffer-size! port size) -> unspecified
1168 An exception is thrown if read data is still buffered or if the port
1169 is unbuffered. */
1170
1171 static SCM
1172 gdbscm_set_memory_port_read_buffer_size_x (SCM port, SCM size)
1173 {
1174 ioscm_memory_port *iomem;
1175
1176 SCM_ASSERT_TYPE (gdbscm_is_memory_port (port), port, SCM_ARG1, FUNC_NAME,
1177 memory_port_desc_name);
1178 SCM_ASSERT_TYPE (scm_is_integer (size), size, SCM_ARG2, FUNC_NAME,
1179 _("integer"));
1180
1181 if (!scm_is_unsigned_integer (size, min_memory_port_buf_size,
1182 max_memory_port_buf_size))
1183 {
1184 gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG2, size,
1185 out_of_range_buf_size);
1186 }
1187
1188 iomem = (ioscm_memory_port *) SCM_STREAM (port);
1189 ioscm_reinit_memory_port (port, scm_to_uint (size), iomem->write_buf_size,
1190 FUNC_NAME);
1191
1192 return SCM_UNSPECIFIED;
1193 }
1194
1195 /* (memory-port-write-buffer-size port) -> integer */
1196
1197 static SCM
1198 gdbscm_memory_port_write_buffer_size (SCM port)
1199 {
1200 ioscm_memory_port *iomem;
1201
1202 SCM_ASSERT_TYPE (gdbscm_is_memory_port (port), port, SCM_ARG1, FUNC_NAME,
1203 memory_port_desc_name);
1204
1205 iomem = (ioscm_memory_port *) SCM_STREAM (port);
1206 return scm_from_uint (iomem->write_buf_size);
1207 }
1208
1209 /* (set-memory-port-write-buffer-size! port size) -> unspecified
1210 An exception is thrown if write data is still buffered or if the port
1211 is unbuffered. */
1212
1213 static SCM
1214 gdbscm_set_memory_port_write_buffer_size_x (SCM port, SCM size)
1215 {
1216 ioscm_memory_port *iomem;
1217
1218 SCM_ASSERT_TYPE (gdbscm_is_memory_port (port), port, SCM_ARG1, FUNC_NAME,
1219 memory_port_desc_name);
1220 SCM_ASSERT_TYPE (scm_is_integer (size), size, SCM_ARG2, FUNC_NAME,
1221 _("integer"));
1222
1223 if (!scm_is_unsigned_integer (size, min_memory_port_buf_size,
1224 max_memory_port_buf_size))
1225 {
1226 gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG2, size,
1227 out_of_range_buf_size);
1228 }
1229
1230 iomem = (ioscm_memory_port *) SCM_STREAM (port);
1231 ioscm_reinit_memory_port (port, iomem->read_buf_size, scm_to_uint (size),
1232 FUNC_NAME);
1233
1234 return SCM_UNSPECIFIED;
1235 }
1236 \f
1237 /* Initialize gdb ports. */
1238
1239 static const scheme_function port_functions[] =
1240 {
1241 { "input-port", 0, 0, 0, as_a_scm_t_subr (gdbscm_input_port),
1242 "\
1243 Return gdb's input port." },
1244
1245 { "output-port", 0, 0, 0, as_a_scm_t_subr (gdbscm_output_port),
1246 "\
1247 Return gdb's output port." },
1248
1249 { "error-port", 0, 0, 0, as_a_scm_t_subr (gdbscm_error_port),
1250 "\
1251 Return gdb's error port." },
1252
1253 { "stdio-port?", 1, 0, 0, as_a_scm_t_subr (gdbscm_stdio_port_p),
1254 "\
1255 Return #t if the object is a gdb:stdio-port." },
1256
1257 { "open-memory", 0, 0, 1, as_a_scm_t_subr (gdbscm_open_memory),
1258 "\
1259 Return a port that can be used for reading/writing inferior memory.\n\
1260 \n\
1261 Arguments: [#:mode string] [#:start address] [#:size integer]\n\
1262 Returns: A port object." },
1263
1264 { "memory-port?", 1, 0, 0, as_a_scm_t_subr (gdbscm_memory_port_p),
1265 "\
1266 Return #t if the object is a memory port." },
1267
1268 { "memory-port-range", 1, 0, 0, as_a_scm_t_subr (gdbscm_memory_port_range),
1269 "\
1270 Return the memory range of the port as (start end)." },
1271
1272 { "memory-port-read-buffer-size", 1, 0, 0,
1273 as_a_scm_t_subr (gdbscm_memory_port_read_buffer_size),
1274 "\
1275 Return the size of the read buffer for the memory port." },
1276
1277 { "set-memory-port-read-buffer-size!", 2, 0, 0,
1278 as_a_scm_t_subr (gdbscm_set_memory_port_read_buffer_size_x),
1279 "\
1280 Set the size of the read buffer for the memory port.\n\
1281 \n\
1282 Arguments: port integer\n\
1283 Returns: unspecified." },
1284
1285 { "memory-port-write-buffer-size", 1, 0, 0,
1286 as_a_scm_t_subr (gdbscm_memory_port_write_buffer_size),
1287 "\
1288 Return the size of the write buffer for the memory port." },
1289
1290 { "set-memory-port-write-buffer-size!", 2, 0, 0,
1291 as_a_scm_t_subr (gdbscm_set_memory_port_write_buffer_size_x),
1292 "\
1293 Set the size of the write buffer for the memory port.\n\
1294 \n\
1295 Arguments: port integer\n\
1296 Returns: unspecified." },
1297
1298 END_FUNCTIONS
1299 };
1300
1301 static const scheme_function private_port_functions[] =
1302 {
1303 #if 0 /* TODO */
1304 { "%with-gdb-input-from-port", 2, 0, 0,
1305 as_a_scm_t_subr (gdbscm_percent_with_gdb_input_from_port),
1306 "\
1307 Temporarily set GDB's input port to PORT and then invoke THUNK.\n\
1308 \n\
1309 Arguments: port thunk\n\
1310 Returns: The result of calling THUNK.\n\
1311 \n\
1312 This procedure is experimental." },
1313 #endif
1314
1315 { "%with-gdb-output-to-port", 2, 0, 0,
1316 as_a_scm_t_subr (gdbscm_percent_with_gdb_output_to_port),
1317 "\
1318 Temporarily set GDB's output port to PORT and then invoke THUNK.\n\
1319 \n\
1320 Arguments: port thunk\n\
1321 Returns: The result of calling THUNK.\n\
1322 \n\
1323 This procedure is experimental." },
1324
1325 { "%with-gdb-error-to-port", 2, 0, 0,
1326 as_a_scm_t_subr (gdbscm_percent_with_gdb_error_to_port),
1327 "\
1328 Temporarily set GDB's error port to PORT and then invoke THUNK.\n\
1329 \n\
1330 Arguments: port thunk\n\
1331 Returns: The result of calling THUNK.\n\
1332 \n\
1333 This procedure is experimental." },
1334
1335 END_FUNCTIONS
1336 };
1337
1338 void
1339 gdbscm_initialize_ports (void)
1340 {
1341 /* Save the original stdio ports for debugging purposes. */
1342
1343 orig_input_port_scm = scm_current_input_port ();
1344 orig_output_port_scm = scm_current_output_port ();
1345 orig_error_port_scm = scm_current_error_port ();
1346
1347 /* Set up the stdio ports. */
1348
1349 ioscm_init_gdb_stdio_port ();
1350 input_port_scm = ioscm_make_gdb_stdio_port (0);
1351 output_port_scm = ioscm_make_gdb_stdio_port (1);
1352 error_port_scm = ioscm_make_gdb_stdio_port (2);
1353
1354 /* Set up memory ports. */
1355
1356 ioscm_init_memory_port_type ();
1357
1358 /* Install the accessor functions. */
1359
1360 gdbscm_define_functions (port_functions, 1);
1361 gdbscm_define_functions (private_port_functions, 0);
1362
1363 /* Keyword args for open-memory. */
1364
1365 mode_keyword = scm_from_latin1_keyword ("mode");
1366 start_keyword = scm_from_latin1_keyword ("start");
1367 size_keyword = scm_from_latin1_keyword ("size");
1368
1369 /* Error message text for "out of range" memory port buffer sizes. */
1370
1371 out_of_range_buf_size = xstrprintf ("size not between %u - %u",
1372 min_memory_port_buf_size,
1373 max_memory_port_buf_size);
1374 }
This page took 0.088914 seconds and 4 git commands to generate.