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