Avoid undefined behavior in Guile exception handling
[external/binutils.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-2019 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 "gdb_select.h"
26 #include "top.h"
27 #include "target.h"
28 #include "guile-internal.h"
29 #include "common/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 = ui_file_read (gdb_stdin, (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 }