1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2018 by Liviu Ionescu *
7 * Copyright (C) 2018 by Marvell Technology Group Ltd. *
8 * Written by Nicolas Pitre <nico@marvell.com> *
10 * Copyright (C) 2010 by Spencer Oliver *
11 * spen@spen-soft.co.uk *
13 * Copyright (C) 2016 by Square, Inc. *
14 * Steven Stallion <stallion@squareup.com> *
15 ***************************************************************************/
19 * Common ARM semihosting support.
21 * Semihosting enables code running on a target to use some of the I/O
22 * facilities on the host computer. The target application must be linked
23 * against a library that forwards operation requests by using an
24 * instruction trapped by the debugger.
26 * Details can be found in
27 * "Semihosting for AArch32 and AArch64, Release 2.0"
28 * https://static.docs.arm.com/100863/0200/semihosting.pdf
37 #include "target_type.h"
38 #include "semihosting_common.h"
40 #include <helper/binarybuffer.h>
41 #include <helper/log.h>
42 #include <server/gdb_server.h>
46 * It is not possible to use O_... flags defined in sys/stat.h because they
47 * are not guaranteed to match the values defined by the GDB Remote Protocol.
48 * See https://sourceware.org/gdb/onlinedocs/gdb/Open-Flags.html#Open-Flags
51 TARGET_O_RDONLY
= 0x000,
52 TARGET_O_WRONLY
= 0x001,
53 TARGET_O_RDWR
= 0x002,
54 TARGET_O_APPEND
= 0x008,
55 TARGET_O_CREAT
= 0x200,
56 TARGET_O_TRUNC
= 0x400,
57 /* O_EXCL=0x800 is not required in this implementation. */
60 /* GDB remote protocol does not differentiate between text and binary open modes. */
61 static const int open_gdb_modeflags
[12] = {
66 TARGET_O_WRONLY
| TARGET_O_CREAT
| TARGET_O_TRUNC
,
67 TARGET_O_WRONLY
| TARGET_O_CREAT
| TARGET_O_TRUNC
,
68 TARGET_O_RDWR
| TARGET_O_CREAT
| TARGET_O_TRUNC
,
69 TARGET_O_RDWR
| TARGET_O_CREAT
| TARGET_O_TRUNC
,
70 TARGET_O_WRONLY
| TARGET_O_CREAT
| TARGET_O_APPEND
,
71 TARGET_O_WRONLY
| TARGET_O_CREAT
| TARGET_O_APPEND
,
72 TARGET_O_RDWR
| TARGET_O_CREAT
| TARGET_O_APPEND
,
73 TARGET_O_RDWR
| TARGET_O_CREAT
| TARGET_O_APPEND
76 static const int open_host_modeflags
[12] = {
81 O_WRONLY
| O_CREAT
| O_TRUNC
,
82 O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
,
83 O_RDWR
| O_CREAT
| O_TRUNC
,
84 O_RDWR
| O_CREAT
| O_TRUNC
| O_BINARY
,
85 O_WRONLY
| O_CREAT
| O_APPEND
,
86 O_WRONLY
| O_CREAT
| O_APPEND
| O_BINARY
,
87 O_RDWR
| O_CREAT
| O_APPEND
,
88 O_RDWR
| O_CREAT
| O_APPEND
| O_BINARY
91 static int semihosting_common_fileio_info(struct target
*target
,
92 struct gdb_fileio_info
*fileio_info
);
93 static int semihosting_common_fileio_end(struct target
*target
, int result
,
94 int fileio_errno
, bool ctrl_c
);
97 * Initialize common semihosting support.
99 * @param target Pointer to the target to initialize.
102 * @return An error status if there is a problem during initialization.
104 int semihosting_common_init(struct target
*target
, void *setup
,
109 target
->fileio_info
= malloc(sizeof(*target
->fileio_info
));
110 if (!target
->fileio_info
) {
111 LOG_ERROR("out of memory");
114 memset(target
->fileio_info
, 0, sizeof(*target
->fileio_info
));
116 struct semihosting
*semihosting
;
117 semihosting
= malloc(sizeof(*target
->semihosting
));
119 LOG_ERROR("out of memory");
123 semihosting
->is_active
= false;
124 semihosting
->redirect_cfg
= SEMIHOSTING_REDIRECT_CFG_NONE
;
125 semihosting
->tcp_connection
= NULL
;
126 semihosting
->stdin_fd
= -1;
127 semihosting
->stdout_fd
= -1;
128 semihosting
->stderr_fd
= -1;
129 semihosting
->is_fileio
= false;
130 semihosting
->hit_fileio
= false;
131 semihosting
->is_resumable
= false;
132 semihosting
->has_resumable_exit
= false;
133 semihosting
->word_size_bytes
= 0;
134 semihosting
->op
= -1;
135 semihosting
->param
= 0;
136 semihosting
->result
= -1;
137 semihosting
->sys_errno
= -1;
138 semihosting
->cmdline
= NULL
;
139 semihosting
->basedir
= NULL
;
141 /* If possible, update it in setup(). */
142 semihosting
->setup_time
= clock();
144 semihosting
->setup
= setup
;
145 semihosting
->post_result
= post_result
;
146 semihosting
->user_command_extension
= NULL
;
148 target
->semihosting
= semihosting
;
150 target
->type
->get_gdb_fileio_info
= semihosting_common_fileio_info
;
151 target
->type
->gdb_fileio_end
= semihosting_common_fileio_end
;
156 struct semihosting_tcp_service
{
157 struct semihosting
*semihosting
;
162 static bool semihosting_is_redirected(struct semihosting
*semihosting
, int fd
)
164 if (semihosting
->redirect_cfg
== SEMIHOSTING_REDIRECT_CFG_NONE
)
167 bool is_read_op
= false;
169 switch (semihosting
->op
) {
170 /* check debug semihosting operations: READC, WRITEC and WRITE0 */
171 case SEMIHOSTING_SYS_READC
:
174 case SEMIHOSTING_SYS_WRITEC
:
175 case SEMIHOSTING_SYS_WRITE0
:
176 /* debug operations are redirected when CFG is either DEBUG or ALL */
177 if (semihosting
->redirect_cfg
== SEMIHOSTING_REDIRECT_CFG_STDIO
)
181 /* check stdio semihosting operations: READ and WRITE */
182 case SEMIHOSTING_SYS_READ
:
185 case SEMIHOSTING_SYS_WRITE
:
186 /* stdio operations are redirected when CFG is either STDIO or ALL */
187 if (semihosting
->redirect_cfg
== SEMIHOSTING_REDIRECT_CFG_DEBUG
)
196 return fd
== semihosting
->stdin_fd
;
198 /* write operation */
199 return fd
== semihosting
->stdout_fd
|| fd
== semihosting
->stderr_fd
;
202 static ssize_t
semihosting_redirect_write(struct semihosting
*semihosting
, void *buf
, int size
)
204 if (!semihosting
->tcp_connection
) {
205 LOG_ERROR("No connected TCP client for semihosting");
206 semihosting
->sys_errno
= EBADF
; /* Bad file number */
210 struct semihosting_tcp_service
*service
= semihosting
->tcp_connection
->service
->priv
;
212 int retval
= connection_write(semihosting
->tcp_connection
, buf
, size
);
215 log_socket_error(service
->name
);
220 static ssize_t
semihosting_write(struct semihosting
*semihosting
, int fd
, void *buf
, int size
)
222 if (semihosting_is_redirected(semihosting
, fd
))
223 return semihosting_redirect_write(semihosting
, buf
, size
);
226 return write(fd
, buf
, size
);
229 static ssize_t
semihosting_redirect_read(struct semihosting
*semihosting
, void *buf
, int size
)
231 if (!semihosting
->tcp_connection
) {
232 LOG_ERROR("No connected TCP client for semihosting");
233 semihosting
->sys_errno
= EBADF
; /* Bad file number */
237 struct semihosting_tcp_service
*service
= semihosting
->tcp_connection
->service
->priv
;
239 service
->error
= ERROR_OK
;
240 semihosting
->tcp_connection
->input_pending
= true;
242 int retval
= connection_read(semihosting
->tcp_connection
, buf
, size
);
245 service
->error
= ERROR_SERVER_REMOTE_CLOSED
;
248 log_socket_error(service
->name
);
250 semihosting
->tcp_connection
->input_pending
= false;
255 static inline int semihosting_putchar(struct semihosting
*semihosting
, int fd
, int c
)
257 if (semihosting_is_redirected(semihosting
, fd
))
258 return semihosting_redirect_write(semihosting
, &c
, 1);
260 /* default putchar */
264 static inline ssize_t
semihosting_read(struct semihosting
*semihosting
, int fd
, void *buf
, int size
)
266 if (semihosting_is_redirected(semihosting
, fd
))
267 return semihosting_redirect_read(semihosting
, buf
, size
);
270 ssize_t result
= read(fd
, buf
, size
);
271 semihosting
->sys_errno
= errno
;
276 static inline int semihosting_getchar(struct semihosting
*semihosting
, int fd
)
278 if (semihosting_is_redirected(semihosting
, fd
)) {
281 if (semihosting_redirect_read(semihosting
, &c
, 1) > 0)
287 /* default getchar */
292 * User operation parameter string storage buffer. Contains valid data when the
293 * TARGET_EVENT_SEMIHOSTING_USER_CMD_xxxxx event callbacks are running.
295 static char *semihosting_user_op_params
;
298 * Portable implementation of ARM semihosting calls.
299 * Performs the currently pending semihosting operation
300 * encoded in target->semihosting.
302 int semihosting_common(struct target
*target
)
304 struct semihosting
*semihosting
= target
->semihosting
;
306 /* Silently ignore if the semihosting field was not set. */
310 struct gdb_fileio_info
*fileio_info
= target
->fileio_info
;
313 * By default return an error.
314 * The actual result must be set by each function
316 semihosting
->result
= -1;
318 /* Most operations are resumable, except the two exit calls. */
319 semihosting
->is_resumable
= true;
323 /* Enough space to hold 4 long words. */
326 LOG_DEBUG("op=0x%x, param=0x%" PRIx64
, semihosting
->op
,
329 switch (semihosting
->op
) {
331 case SEMIHOSTING_SYS_CLOCK
: /* 0x10 */
333 * Returns the number of centiseconds (hundredths of a second)
334 * since the execution started.
336 * Values returned can be of limited use for some benchmarking
337 * purposes because of communication overhead or other
338 * agent-specific factors. For example, with a debug hardware
339 * unit the request is passed back to the host for execution.
340 * This can lead to unpredictable delays in transmission and
341 * process scheduling.
343 * Use this function to calculate time intervals, by calculating
344 * differences between intervals with and without the code
345 * sequence to be timed.
348 * The PARAMETER REGISTER must contain 0. There are no other
352 * On exit, the RETURN REGISTER contains:
353 * - The number of centiseconds since some arbitrary start
354 * point, if the call is successful.
355 * - –1 if the call is not successful. For example, because
356 * of a communications error.
359 clock_t delta
= clock() - semihosting
->setup_time
;
361 semihosting
->result
= delta
/ (CLOCKS_PER_SEC
/ 100);
365 case SEMIHOSTING_SYS_CLOSE
: /* 0x02 */
367 * Closes a file on the host system. The handle must reference
368 * a file that was opened with SYS_OPEN.
371 * On entry, the PARAMETER REGISTER contains a pointer to a
372 * one-field argument block:
373 * - field 1 Contains a handle for an open file.
376 * On exit, the RETURN REGISTER contains:
377 * - 0 if the call is successful
378 * - –1 if the call is not successful.
380 retval
= semihosting_read_fields(target
, 1, fields
);
381 if (retval
!= ERROR_OK
)
384 int fd
= semihosting_get_field(target
, 0, fields
);
385 /* Do not allow to close OpenOCD's own standard streams */
386 if (fd
== 0 || fd
== 1 || fd
== 2) {
387 LOG_DEBUG("ignoring semihosting attempt to close %s",
388 (fd
== 0) ? "stdin" :
389 (fd
== 1) ? "stdout" : "stderr");
390 /* Just pretend success */
391 if (semihosting
->is_fileio
) {
392 semihosting
->result
= 0;
394 semihosting
->result
= 0;
395 semihosting
->sys_errno
= 0;
399 /* Close the descriptor */
400 if (semihosting
->is_fileio
) {
401 semihosting
->hit_fileio
= true;
402 fileio_info
->identifier
= "close";
403 fileio_info
->param_1
= fd
;
405 semihosting
->result
= close(fd
);
406 semihosting
->sys_errno
= errno
;
407 LOG_DEBUG("close(%d)=%" PRId64
, fd
, semihosting
->result
);
412 case SEMIHOSTING_SYS_ERRNO
: /* 0x13 */
414 * Returns the value of the C library errno variable that is
415 * associated with the semihosting implementation. The errno
416 * variable can be set by a number of C library semihosted
417 * functions, including:
425 * Whether errno is set or not, and to what value, is entirely
426 * host-specific, except where the ISO C standard defines the
430 * There are no parameters. The PARAMETER REGISTER must be 0.
433 * On exit, the RETURN REGISTER contains the value of the C
434 * library errno variable.
436 semihosting
->result
= semihosting
->sys_errno
;
439 case SEMIHOSTING_SYS_EXIT
: /* 0x18 */
441 * Note: SYS_EXIT was called angel_SWIreason_ReportException in
442 * previous versions of the documentation.
444 * An application calls this operation to report an exception
445 * to the debugger directly. The most common use is to report
446 * that execution has completed, using ADP_Stopped_ApplicationExit.
448 * Note: This semihosting operation provides no means for 32-bit
449 * callers to indicate an application exit with a specified exit
450 * code. Semihosting callers may prefer to check for the presence
451 * of the SH_EXT_EXTENDED_REPORT_EXCEPTION extension and use
452 * the SYS_REPORT_EXCEPTION_EXTENDED operation instead, if it
456 * On entry, the PARAMETER register is set to a reason code
457 * describing the cause of the trap. Not all semihosting client
458 * implementations will necessarily trap every corresponding
459 * event. Important reason codes are:
461 * - ADP_Stopped_ApplicationExit 0x20026
462 * - ADP_Stopped_RunTimeErrorUnknown 0x20023
465 * On entry, the PARAMETER REGISTER contains a pointer to a
466 * two-field argument block:
467 * - field 1 The exception type, which is one of the set of
468 * reason codes in the above tables.
469 * - field 2 A subcode, whose meaning depends on the reason
471 * In particular, if field 1 is ADP_Stopped_ApplicationExit
472 * then field 2 is an exit status code, as passed to the C
473 * standard library exit() function. A simulator receiving
474 * this request must notify a connected debugger, if present,
475 * and then exit with the specified status.
478 * No return is expected from these calls. However, it is
479 * possible for the debugger to request that the application
480 * continues by performing an RDI_Execute request or equivalent.
481 * In this case, execution continues with the registers as they
482 * were on entry to the operation, or as subsequently modified
485 if (semihosting
->word_size_bytes
== 8) {
486 retval
= semihosting_read_fields(target
, 2, fields
);
487 if (retval
!= ERROR_OK
)
490 int type
= semihosting_get_field(target
, 0, fields
);
491 int code
= semihosting_get_field(target
, 1, fields
);
493 if (type
== ADP_STOPPED_APPLICATION_EXIT
) {
494 if (!gdb_get_actual_connections())
498 "semihosting: *** application exited with %d ***\n",
503 "semihosting: application exception %#x\n",
508 if (semihosting
->param
== ADP_STOPPED_APPLICATION_EXIT
) {
509 if (!gdb_get_actual_connections())
513 "semihosting: *** application exited normally ***\n");
515 } else if (semihosting
->param
== ADP_STOPPED_RUN_TIME_ERROR
) {
516 /* Chosen more or less arbitrarily to have a nicer message,
517 * otherwise all other return the same exit code 1. */
518 if (!gdb_get_actual_connections())
522 "semihosting: *** application exited with error ***\n");
525 if (!gdb_get_actual_connections())
529 "semihosting: application exception %#x\n",
530 (unsigned) semihosting
->param
);
534 if (!semihosting
->has_resumable_exit
) {
535 semihosting
->is_resumable
= false;
536 return target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
540 case SEMIHOSTING_SYS_EXIT_EXTENDED
: /* 0x20 */
542 * This operation is only supported if the semihosting extension
543 * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is
544 * reported using feature byte 0, bit 0. If this extension is
545 * supported, then the implementation provides a means to
546 * report a normal exit with a nonzero exit status in both 32-bit
547 * and 64-bit semihosting APIs.
549 * The implementation must provide the semihosting call
550 * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs.
552 * SYS_EXIT_EXTENDED is used by an application to report an
553 * exception or exit to the debugger directly. The most common
554 * use is to report that execution has completed, using
555 * ADP_Stopped_ApplicationExit.
558 * On entry, the PARAMETER REGISTER contains a pointer to a
559 * two-field argument block:
560 * - field 1 The exception type, which should be one of the set
561 * of reason codes that are documented for the SYS_EXIT
562 * (0x18) call. For example, ADP_Stopped_ApplicationExit.
563 * - field 2 A subcode, whose meaning depends on the reason
564 * code in field 1. In particular, if field 1 is
565 * ADP_Stopped_ApplicationExit then field 2 is an exit status
566 * code, as passed to the C standard library exit() function.
567 * A simulator receiving this request must notify a connected
568 * debugger, if present, and then exit with the specified status.
571 * No return is expected from these calls.
573 * For the A64 API, this call is identical to the behavior of
574 * the mandatory SYS_EXIT (0x18) call. If this extension is
575 * supported, then both calls must be implemented.
577 retval
= semihosting_read_fields(target
, 2, fields
);
578 if (retval
!= ERROR_OK
)
581 int type
= semihosting_get_field(target
, 0, fields
);
582 int code
= semihosting_get_field(target
, 1, fields
);
584 if (type
== ADP_STOPPED_APPLICATION_EXIT
) {
585 if (!gdb_get_actual_connections())
589 "semihosting: *** application exited with %d ***\n",
593 fprintf(stderr
, "semihosting: exception %#x\n",
597 if (!semihosting
->has_resumable_exit
) {
598 semihosting
->is_resumable
= false;
599 return target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
603 case SEMIHOSTING_SYS_FLEN
: /* 0x0C */
605 * Returns the length of a specified file.
608 * On entry, the PARAMETER REGISTER contains a pointer to a
609 * one-field argument block:
610 * - field 1 A handle for a previously opened, seekable file
614 * On exit, the RETURN REGISTER contains:
615 * - The current length of the file object, if the call is
617 * - –1 if an error occurs.
619 if (semihosting
->is_fileio
) {
620 semihosting
->result
= -1;
621 semihosting
->sys_errno
= EINVAL
;
623 retval
= semihosting_read_fields(target
, 1, fields
);
624 if (retval
!= ERROR_OK
)
627 int fd
= semihosting_get_field(target
, 0, fields
);
629 semihosting
->result
= fstat(fd
, &buf
);
630 if (semihosting
->result
== -1) {
631 semihosting
->sys_errno
= errno
;
632 LOG_DEBUG("fstat(%d)=%" PRId64
, fd
, semihosting
->result
);
635 LOG_DEBUG("fstat(%d)=%" PRId64
, fd
, semihosting
->result
);
636 semihosting
->result
= buf
.st_size
;
640 case SEMIHOSTING_SYS_GET_CMDLINE
: /* 0x15 */
642 * Returns the command line that is used for the call to the
643 * executable, that is, argc and argv.
646 * On entry, the PARAMETER REGISTER points to a two-field data
647 * block to be used for returning the command string and its length:
648 * - field 1 A pointer to a buffer of at least the size that is
649 * specified in field 2.
650 * - field 2 The length of the buffer in bytes.
654 * If the call is successful, then the RETURN REGISTER contains 0,
655 * the PARAMETER REGISTER is unchanged, and the data block is
656 * updated as follows:
657 * - field 1 A pointer to a null-terminated string of the command
659 * - field 2 The length of the string in bytes.
660 * If the call is not successful, then the RETURN REGISTER
663 * Note: The semihosting implementation might impose limits on
664 * the maximum length of the string that can be transferred.
665 * However, the implementation must be able to support a
666 * command-line length of at least 80 bytes.
668 retval
= semihosting_read_fields(target
, 2, fields
);
669 if (retval
!= ERROR_OK
)
672 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
673 size_t size
= semihosting_get_field(target
, 1, fields
);
675 char *arg
= semihosting
->cmdline
?
676 semihosting
->cmdline
: "";
677 uint32_t len
= strlen(arg
) + 1;
679 semihosting
->result
= -1;
681 semihosting_set_field(target
, len
, 1, fields
);
682 retval
= target_write_buffer(target
, addr
, len
,
684 if (retval
!= ERROR_OK
)
686 semihosting
->result
= 0;
688 retval
= semihosting_write_fields(target
, 2, fields
);
689 if (retval
!= ERROR_OK
)
692 LOG_DEBUG("SYS_GET_CMDLINE=[%s], %" PRId64
, arg
, semihosting
->result
);
696 case SEMIHOSTING_SYS_HEAPINFO
: /* 0x16 */
698 * Returns the system stack and heap parameters.
701 * On entry, the PARAMETER REGISTER contains the address of a
702 * pointer to a four-field data block. The contents of the data
703 * block are filled by the function. The following C-like
704 * pseudocode describes the layout of the block:
713 * On exit, the PARAMETER REGISTER is unchanged and the data
714 * block has been updated.
716 retval
= semihosting_read_fields(target
, 1, fields
);
717 if (retval
!= ERROR_OK
)
720 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
721 /* tell the remote we have no idea */
722 memset(fields
, 0, 4 * semihosting
->word_size_bytes
);
723 retval
= target_write_memory(target
, addr
, 4,
724 semihosting
->word_size_bytes
,
726 if (retval
!= ERROR_OK
)
728 semihosting
->result
= 0;
732 case SEMIHOSTING_SYS_ISERROR
: /* 0x08 */
734 * Determines whether the return code from another semihosting
735 * call is an error status or not.
737 * This call is passed a parameter block containing the error
741 * On entry, the PARAMETER REGISTER contains a pointer to a
742 * one-field data block:
743 * - field 1 The required status word to check.
746 * On exit, the RETURN REGISTER contains:
747 * - 0 if the status field is not an error indication
748 * - A nonzero value if the status field is an error indication.
750 retval
= semihosting_read_fields(target
, 1, fields
);
751 if (retval
!= ERROR_OK
)
754 uint64_t code
= semihosting_get_field(target
, 0, fields
);
755 semihosting
->result
= (code
!= 0);
758 case SEMIHOSTING_SYS_ISTTY
: /* 0x09 */
760 * Checks whether a file is connected to an interactive device.
763 * On entry, the PARAMETER REGISTER contains a pointer to a
764 * one-field argument block:
765 * field 1 A handle for a previously opened file object.
768 * On exit, the RETURN REGISTER contains:
769 * - 1 if the handle identifies an interactive device.
770 * - 0 if the handle identifies a file.
771 * - A value other than 1 or 0 if an error occurs.
773 if (semihosting
->is_fileio
) {
774 semihosting
->hit_fileio
= true;
775 fileio_info
->identifier
= "isatty";
776 fileio_info
->param_1
= semihosting
->param
;
778 retval
= semihosting_read_fields(target
, 1, fields
);
779 if (retval
!= ERROR_OK
)
781 int fd
= semihosting_get_field(target
, 0, fields
);
782 semihosting
->result
= isatty(fd
);
783 semihosting
->sys_errno
= errno
;
784 LOG_DEBUG("isatty(%d)=%" PRId64
, fd
, semihosting
->result
);
788 case SEMIHOSTING_SYS_OPEN
: /* 0x01 */
790 * Opens a file on the host system.
792 * The file path is specified either as relative to the current
793 * directory of the host process, or absolute, using the path
794 * conventions of the host operating system.
796 * Semihosting implementations must support opening the special
797 * path name :semihosting-features as part of the semihosting
798 * extensions reporting mechanism.
800 * ARM targets interpret the special path name :tt as meaning
801 * the console input stream, for an open-read or the console
802 * output stream, for an open-write. Opening these streams is
803 * performed as part of the standard startup code for those
804 * applications that reference the C stdio streams. The
805 * semihosting extension SH_EXT_STDOUT_STDERR allows the
806 * semihosting caller to open separate output streams
807 * corresponding to stdout and stderr. This extension is
808 * reported using feature byte 0, bit 1. Use SYS_OPEN with
809 * the special path name :semihosting-features to access the
812 * If this extension is supported, the implementation must
813 * support the following additional semantics to SYS_OPEN:
814 * - If the special path name :tt is opened with an fopen
815 * mode requesting write access (w, wb, w+, or w+b), then
816 * this is a request to open stdout.
817 * - If the special path name :tt is opened with a mode
818 * requesting append access (a, ab, a+, or a+b), then this is
819 * a request to open stderr.
822 * On entry, the PARAMETER REGISTER contains a pointer to a
823 * three-field argument block:
824 * - field 1 A pointer to a null-terminated string containing
825 * a file or device name.
826 * - field 2 An integer that specifies the file opening mode.
827 * - field 3 An integer that gives the length of the string
828 * pointed to by field 1.
830 * The length does not include the terminating null character
831 * that must be present.
834 * On exit, the RETURN REGISTER contains:
835 * - A nonzero handle if the call is successful.
836 * - –1 if the call is not successful.
838 retval
= semihosting_read_fields(target
, 3, fields
);
839 if (retval
!= ERROR_OK
)
842 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
843 uint32_t mode
= semihosting_get_field(target
, 1, fields
);
844 size_t len
= semihosting_get_field(target
, 2, fields
);
847 semihosting
->result
= -1;
848 semihosting
->sys_errno
= EINVAL
;
851 size_t basedir_len
= semihosting
->basedir
? strlen(semihosting
->basedir
) : 0;
852 uint8_t *fn
= malloc(basedir_len
+ len
+ 2);
854 semihosting
->result
= -1;
855 semihosting
->sys_errno
= ENOMEM
;
857 if (basedir_len
> 0) {
858 strcpy((char *)fn
, semihosting
->basedir
);
859 if (fn
[basedir_len
- 1] != '/')
860 fn
[basedir_len
++] = '/';
862 retval
= target_read_memory(target
, addr
, 1, len
, fn
+ basedir_len
);
863 if (retval
!= ERROR_OK
) {
867 fn
[basedir_len
+ len
] = 0;
868 /* TODO: implement the :semihosting-features special file.
870 if (semihosting
->is_fileio
) {
871 if (strcmp((char *)fn
, ":semihosting-features") == 0) {
872 semihosting
->result
= -1;
873 semihosting
->sys_errno
= EINVAL
;
874 } else if (strcmp((char *)fn
, ":tt") == 0) {
876 semihosting
->result
= 0;
878 semihosting
->result
= 1;
880 semihosting
->result
= 2;
882 semihosting
->result
= -1;
884 semihosting
->hit_fileio
= true;
885 fileio_info
->identifier
= "open";
886 fileio_info
->param_1
= addr
;
887 fileio_info
->param_2
= len
;
888 fileio_info
->param_3
= open_gdb_modeflags
[mode
];
889 fileio_info
->param_4
= 0644;
892 if (strcmp((char *)fn
, ":tt") == 0) {
894 * - 0-3 ("r") for stdin,
895 * - 4-7 ("w") for stdout,
896 * - 8-11 ("a") for stderr */
898 int fd
= dup(STDIN_FILENO
);
899 semihosting
->result
= fd
;
900 semihosting
->stdin_fd
= fd
;
901 semihosting
->sys_errno
= errno
;
902 LOG_DEBUG("dup(STDIN)=%" PRId64
, semihosting
->result
);
903 } else if (mode
< 8) {
904 int fd
= dup(STDOUT_FILENO
);
905 semihosting
->result
= fd
;
906 semihosting
->stdout_fd
= fd
;
907 semihosting
->sys_errno
= errno
;
908 LOG_DEBUG("dup(STDOUT)=%" PRId64
, semihosting
->result
);
910 int fd
= dup(STDERR_FILENO
);
911 semihosting
->result
= fd
;
912 semihosting
->stderr_fd
= fd
;
913 semihosting
->sys_errno
= errno
;
914 LOG_DEBUG("dup(STDERR)=%" PRId64
, semihosting
->result
);
917 /* cygwin requires the permission setting
918 * otherwise it will fail to reopen a previously
920 semihosting
->result
= open((char *)fn
,
921 open_host_modeflags
[mode
],
923 semihosting
->sys_errno
= errno
;
924 LOG_DEBUG("open('%s')=%" PRId64
, fn
, semihosting
->result
);
932 case SEMIHOSTING_SYS_READ
: /* 0x06 */
934 * Reads the contents of a file into a buffer. The file position
935 * is specified either:
936 * - Explicitly by a SYS_SEEK.
937 * - Implicitly one byte beyond the previous SYS_READ or
940 * The file position is at the start of the file when it is
941 * opened, and is lost when the file is closed. Perform the
942 * file operation as a single action whenever possible. For
943 * example, do not split a read of 16KB into four 4KB chunks
944 * unless there is no alternative.
947 * On entry, the PARAMETER REGISTER contains a pointer to a
948 * three-field data block:
949 * - field 1 Contains a handle for a file previously opened
951 * - field 2 Points to a buffer.
952 * - field 3 Contains the number of bytes to read to the buffer
956 * On exit, the RETURN REGISTER contains the number of bytes not
957 * filled in the buffer (buffer_length - bytes_read) as follows:
958 * - If the RETURN REGISTER is 0, the entire buffer was
959 * successfully filled.
960 * - If the RETURN REGISTER is the same as field 3, no bytes
961 * were read (EOF can be assumed).
962 * - If the RETURN REGISTER contains a value smaller than
963 * field 3, the read succeeded but the buffer was only partly
964 * filled. For interactive devices, this is the most common
967 retval
= semihosting_read_fields(target
, 3, fields
);
968 if (retval
!= ERROR_OK
)
971 int fd
= semihosting_get_field(target
, 0, fields
);
972 uint64_t addr
= semihosting_get_field(target
, 1, fields
);
973 size_t len
= semihosting_get_field(target
, 2, fields
);
974 if (semihosting
->is_fileio
) {
975 semihosting
->hit_fileio
= true;
976 fileio_info
->identifier
= "read";
977 fileio_info
->param_1
= fd
;
978 fileio_info
->param_2
= addr
;
979 fileio_info
->param_3
= len
;
981 uint8_t *buf
= malloc(len
);
983 semihosting
->result
= -1;
984 semihosting
->sys_errno
= ENOMEM
;
986 semihosting
->result
= semihosting_read(semihosting
, fd
, buf
, len
);
987 LOG_DEBUG("read(%d, 0x%" PRIx64
", %zu)=%" PRId64
,
991 semihosting
->result
);
992 if (semihosting
->result
>= 0) {
993 retval
= target_write_buffer(target
, addr
,
996 if (retval
!= ERROR_OK
) {
1000 /* the number of bytes NOT filled in */
1001 semihosting
->result
= len
-
1002 semihosting
->result
;
1010 case SEMIHOSTING_SYS_READC
: /* 0x07 */
1012 * Reads a byte from the console.
1015 * The PARAMETER REGISTER must contain 0. There are no other
1016 * parameters or values possible.
1019 * On exit, the RETURN REGISTER contains the byte read from
1022 if (semihosting
->is_fileio
) {
1023 LOG_ERROR("SYS_READC not supported by semihosting fileio");
1026 semihosting
->result
= semihosting_getchar(semihosting
, semihosting
->stdin_fd
);
1027 LOG_DEBUG("getchar()=%" PRId64
, semihosting
->result
);
1030 case SEMIHOSTING_SYS_REMOVE
: /* 0x0E */
1032 * Deletes a specified file on the host filing system.
1035 * On entry, the PARAMETER REGISTER contains a pointer to a
1036 * two-field argument block:
1037 * - field 1 Points to a null-terminated string that gives the
1038 * path name of the file to be deleted.
1039 * - field 2 The length of the string.
1042 * On exit, the RETURN REGISTER contains:
1043 * - 0 if the delete is successful
1044 * - A nonzero, host-specific error code if the delete fails.
1046 retval
= semihosting_read_fields(target
, 2, fields
);
1047 if (retval
!= ERROR_OK
)
1050 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
1051 size_t len
= semihosting_get_field(target
, 1, fields
);
1052 if (semihosting
->is_fileio
) {
1053 semihosting
->hit_fileio
= true;
1054 fileio_info
->identifier
= "unlink";
1055 fileio_info
->param_1
= addr
;
1056 fileio_info
->param_2
= len
;
1058 uint8_t *fn
= malloc(len
+1);
1060 semihosting
->result
= -1;
1061 semihosting
->sys_errno
= ENOMEM
;
1064 target_read_memory(target
, addr
, 1, len
,
1066 if (retval
!= ERROR_OK
) {
1071 semihosting
->result
= remove((char *)fn
);
1072 semihosting
->sys_errno
= errno
;
1073 LOG_DEBUG("remove('%s')=%" PRId64
, fn
, semihosting
->result
);
1081 case SEMIHOSTING_SYS_RENAME
: /* 0x0F */
1083 * Renames a specified file.
1086 * On entry, the PARAMETER REGISTER contains a pointer to a
1087 * four-field data block:
1088 * - field 1 A pointer to the name of the old file.
1089 * - field 2 The length of the old filename.
1090 * - field 3 A pointer to the new filename.
1091 * - field 4 The length of the new filename. Both strings are
1095 * On exit, the RETURN REGISTER contains:
1096 * - 0 if the rename is successful.
1097 * - A nonzero, host-specific error code if the rename fails.
1099 retval
= semihosting_read_fields(target
, 4, fields
);
1100 if (retval
!= ERROR_OK
)
1103 uint64_t addr1
= semihosting_get_field(target
, 0, fields
);
1104 size_t len1
= semihosting_get_field(target
, 1, fields
);
1105 uint64_t addr2
= semihosting_get_field(target
, 2, fields
);
1106 size_t len2
= semihosting_get_field(target
, 3, fields
);
1107 if (semihosting
->is_fileio
) {
1108 semihosting
->hit_fileio
= true;
1109 fileio_info
->identifier
= "rename";
1110 fileio_info
->param_1
= addr1
;
1111 fileio_info
->param_2
= len1
;
1112 fileio_info
->param_3
= addr2
;
1113 fileio_info
->param_4
= len2
;
1115 uint8_t *fn1
= malloc(len1
+1);
1116 uint8_t *fn2
= malloc(len2
+1);
1120 semihosting
->result
= -1;
1121 semihosting
->sys_errno
= ENOMEM
;
1123 retval
= target_read_memory(target
, addr1
, 1, len1
,
1125 if (retval
!= ERROR_OK
) {
1130 retval
= target_read_memory(target
, addr2
, 1, len2
,
1132 if (retval
!= ERROR_OK
) {
1139 semihosting
->result
= rename((char *)fn1
,
1141 semihosting
->sys_errno
= errno
;
1142 LOG_DEBUG("rename('%s', '%s')=%" PRId64
" %d", fn1
, fn2
, semihosting
->result
, errno
);
1150 case SEMIHOSTING_SYS_SEEK
: /* 0x0A */
1152 * Seeks to a specified position in a file using an offset
1153 * specified from the start of the file. The file is assumed
1154 * to be a byte array and the offset is given in bytes.
1157 * On entry, the PARAMETER REGISTER contains a pointer to a
1158 * two-field data block:
1159 * - field 1 A handle for a seekable file object.
1160 * - field 2 The absolute byte position to seek to.
1163 * On exit, the RETURN REGISTER contains:
1164 * - 0 if the request is successful.
1165 * - A negative value if the request is not successful.
1166 * Use SYS_ERRNO to read the value of the host errno variable
1167 * describing the error.
1169 * Note: The effect of seeking outside the current extent of
1170 * the file object is undefined.
1172 retval
= semihosting_read_fields(target
, 2, fields
);
1173 if (retval
!= ERROR_OK
)
1176 int fd
= semihosting_get_field(target
, 0, fields
);
1177 off_t pos
= semihosting_get_field(target
, 1, fields
);
1178 if (semihosting
->is_fileio
) {
1179 semihosting
->hit_fileio
= true;
1180 fileio_info
->identifier
= "lseek";
1181 fileio_info
->param_1
= fd
;
1182 fileio_info
->param_2
= pos
;
1183 fileio_info
->param_3
= SEEK_SET
;
1185 semihosting
->result
= lseek(fd
, pos
, SEEK_SET
);
1186 semihosting
->sys_errno
= errno
;
1187 LOG_DEBUG("lseek(%d, %d)=%" PRId64
, fd
, (int)pos
, semihosting
->result
);
1188 if (semihosting
->result
== pos
)
1189 semihosting
->result
= 0;
1194 case SEMIHOSTING_SYS_SYSTEM
: /* 0x12 */
1196 * Passes a command to the host command-line interpreter.
1197 * This enables you to execute a system command such as dir,
1198 * ls, or pwd. The terminal I/O is on the host, and is not
1199 * visible to the target.
1202 * On entry, the PARAMETER REGISTER contains a pointer to a
1203 * two-field argument block:
1204 * - field 1 Points to a string to be passed to the host
1205 * command-line interpreter.
1206 * - field 2 The length of the string.
1209 * On exit, the RETURN REGISTER contains the return status.
1212 /* Provide SYS_SYSTEM functionality. Uses the
1213 * libc system command, there may be a reason *NOT*
1214 * to use this, but as I can't think of one, I
1215 * implemented it this way.
1217 retval
= semihosting_read_fields(target
, 2, fields
);
1218 if (retval
!= ERROR_OK
)
1221 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
1222 size_t len
= semihosting_get_field(target
, 1, fields
);
1223 if (semihosting
->is_fileio
) {
1224 semihosting
->hit_fileio
= true;
1225 fileio_info
->identifier
= "system";
1226 fileio_info
->param_1
= addr
;
1227 fileio_info
->param_2
= len
;
1229 uint8_t *cmd
= malloc(len
+1);
1231 semihosting
->result
= -1;
1232 semihosting
->sys_errno
= ENOMEM
;
1234 retval
= target_read_memory(target
,
1239 if (retval
!= ERROR_OK
) {
1244 semihosting
->result
= system(
1246 LOG_DEBUG("system('%s')=%" PRId64
, cmd
, semihosting
->result
);
1255 case SEMIHOSTING_SYS_TIME
: /* 0x11 */
1257 * Returns the number of seconds since 00:00 January 1, 1970.
1258 * This value is real-world time, regardless of any debug agent
1262 * There are no parameters.
1265 * On exit, the RETURN REGISTER contains the number of seconds.
1267 semihosting
->result
= time(NULL
);
1270 case SEMIHOSTING_SYS_WRITE
: /* 0x05 */
1272 * Writes the contents of a buffer to a specified file at the
1273 * current file position. The file position is specified either:
1274 * - Explicitly, by a SYS_SEEK.
1275 * - Implicitly as one byte beyond the previous SYS_READ or
1276 * SYS_WRITE request.
1278 * The file position is at the start of the file when the file
1279 * is opened, and is lost when the file is closed.
1281 * Perform the file operation as a single action whenever
1282 * possible. For example, do not split a write of 16KB into
1283 * four 4KB chunks unless there is no alternative.
1286 * On entry, the PARAMETER REGISTER contains a pointer to a
1287 * three-field data block:
1288 * - field 1 Contains a handle for a file previously opened
1290 * - field 2 Points to the memory containing the data to be written.
1291 * - field 3 Contains the number of bytes to be written from
1292 * the buffer to the file.
1295 * On exit, the RETURN REGISTER contains:
1296 * - 0 if the call is successful.
1297 * - The number of bytes that are not written, if there is an error.
1299 retval
= semihosting_read_fields(target
, 3, fields
);
1300 if (retval
!= ERROR_OK
)
1303 int fd
= semihosting_get_field(target
, 0, fields
);
1304 uint64_t addr
= semihosting_get_field(target
, 1, fields
);
1305 size_t len
= semihosting_get_field(target
, 2, fields
);
1306 if (semihosting
->is_fileio
) {
1307 semihosting
->hit_fileio
= true;
1308 fileio_info
->identifier
= "write";
1309 fileio_info
->param_1
= fd
;
1310 fileio_info
->param_2
= addr
;
1311 fileio_info
->param_3
= len
;
1313 uint8_t *buf
= malloc(len
);
1315 semihosting
->result
= -1;
1316 semihosting
->sys_errno
= ENOMEM
;
1318 retval
= target_read_buffer(target
, addr
, len
, buf
);
1319 if (retval
!= ERROR_OK
) {
1323 semihosting
->result
= semihosting_write(semihosting
, fd
, buf
, len
);
1324 semihosting
->sys_errno
= errno
;
1325 LOG_DEBUG("write(%d, 0x%" PRIx64
", %zu)=%" PRId64
,
1329 semihosting
->result
);
1330 if (semihosting
->result
>= 0) {
1331 /* The number of bytes that are NOT written.
1333 semihosting
->result
= len
-
1334 semihosting
->result
;
1343 case SEMIHOSTING_SYS_WRITEC
: /* 0x03 */
1345 * Writes a character byte, pointed to by the PARAMETER REGISTER,
1346 * to the debug channel. When executed under a semihosting
1347 * debugger, the character appears on the host debugger console.
1350 * On entry, the PARAMETER REGISTER contains a pointer to the
1354 * None. The RETURN REGISTER is corrupted.
1356 if (semihosting
->is_fileio
) {
1357 semihosting
->hit_fileio
= true;
1358 fileio_info
->identifier
= "write";
1359 fileio_info
->param_1
= 1;
1360 fileio_info
->param_2
= semihosting
->param
;
1361 fileio_info
->param_3
= 1;
1363 uint64_t addr
= semihosting
->param
;
1365 retval
= target_read_memory(target
, addr
, 1, 1, &c
);
1366 if (retval
!= ERROR_OK
)
1368 semihosting_putchar(semihosting
, semihosting
->stdout_fd
, c
);
1369 semihosting
->result
= 0;
1373 case SEMIHOSTING_SYS_WRITE0
: /* 0x04 */
1375 * Writes a null-terminated string to the debug channel.
1376 * When executed under a semihosting debugger, the characters
1377 * appear on the host debugger console.
1380 * On entry, the PARAMETER REGISTER contains a pointer to the
1381 * first byte of the string.
1384 * None. The RETURN REGISTER is corrupted.
1386 if (semihosting
->is_fileio
) {
1388 uint64_t addr
= semihosting
->param
;
1391 retval
= target_read_memory(target
, addr
, 1, 1, &c
);
1392 if (retval
!= ERROR_OK
)
1398 semihosting
->hit_fileio
= true;
1399 fileio_info
->identifier
= "write";
1400 fileio_info
->param_1
= 1;
1401 fileio_info
->param_2
= semihosting
->param
;
1402 fileio_info
->param_3
= count
;
1404 uint64_t addr
= semihosting
->param
;
1407 retval
= target_read_memory(target
, addr
++, 1, 1, &c
);
1408 if (retval
!= ERROR_OK
)
1412 semihosting_putchar(semihosting
, semihosting
->stdout_fd
, c
);
1414 semihosting
->result
= 0;
1418 case SEMIHOSTING_USER_CMD_0X100
... SEMIHOSTING_USER_CMD_0X107
:
1420 * This is a user defined operation (while user cmds 0x100-0x1ff
1421 * are possible, only 0x100-0x107 are currently implemented).
1423 * Reads the user operation parameters from target, then fires the
1424 * corresponding target event. When the target callbacks returned,
1425 * cleans up the command parameter buffer.
1428 * On entry, the PARAMETER REGISTER contains a pointer to a
1429 * two-field data block:
1430 * - field 1 Contains a pointer to the bound command parameter
1432 * - field 2 Contains the command parameter string length
1435 * On exit, the RETURN REGISTER contains the return status.
1437 if (semihosting
->user_command_extension
) {
1438 retval
= semihosting
->user_command_extension(target
);
1439 if (retval
!= ERROR_NOT_IMPLEMENTED
)
1441 /* If custom user command not handled, we are looking for the TCL handler */
1444 assert(!semihosting_user_op_params
);
1445 retval
= semihosting_read_fields(target
, 2, fields
);
1446 if (retval
!= ERROR_OK
) {
1447 LOG_ERROR("Failed to read fields for user defined command"
1448 " op=0x%x", semihosting
->op
);
1452 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
1454 size_t len
= semihosting_get_field(target
, 1, fields
);
1455 if (len
> SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH
) {
1456 LOG_ERROR("The maximum length for user defined command "
1457 "parameter is %u, received length is %zu (op=0x%x)",
1458 SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH
,
1464 semihosting_user_op_params
= malloc(len
+ 1);
1465 if (!semihosting_user_op_params
)
1467 semihosting_user_op_params
[len
] = 0;
1469 retval
= target_read_buffer(target
, addr
, len
,
1470 (uint8_t *)(semihosting_user_op_params
));
1471 if (retval
!= ERROR_OK
) {
1472 LOG_ERROR("Failed to read from target, semihosting op=0x%x",
1474 free(semihosting_user_op_params
);
1475 semihosting_user_op_params
= NULL
;
1479 target_handle_event(target
, semihosting
->op
);
1480 free(semihosting_user_op_params
);
1481 semihosting_user_op_params
= NULL
;
1482 semihosting
->result
= 0;
1485 case SEMIHOSTING_SYS_ELAPSED
: /* 0x30 */
1487 * Returns the number of elapsed target ticks since execution
1489 * Use SYS_TICKFREQ to determine the tick frequency.
1492 * On entry, the PARAMETER REGISTER points to a two-field data
1493 * block to be used for returning the number of elapsed ticks:
1494 * - field 1 The least significant field and is at the low address.
1495 * - field 2 The most significant field and is at the high address.
1498 * On entry the PARAMETER REGISTER points to a one-field data
1499 * block to be used for returning the number of elapsed ticks:
1500 * - field 1 The number of elapsed ticks as a 64-bit value.
1504 * - On success, the RETURN REGISTER contains 0, the PARAMETER
1505 * REGISTER is unchanged, and the data block pointed to by the
1506 * PARAMETER REGISTER is filled in with the number of elapsed
1508 * - On failure, the RETURN REGISTER contains -1, and the
1509 * PARAMETER REGISTER contains -1.
1511 * Note: Some semihosting implementations might not support this
1512 * semihosting operation, and they always return -1 in the
1516 case SEMIHOSTING_SYS_TICKFREQ
: /* 0x31 */
1518 * Returns the tick frequency.
1521 * The PARAMETER REGISTER must contain 0 on entry to this routine.
1524 * On exit, the RETURN REGISTER contains either:
1525 * - The number of ticks per second.
1526 * - –1 if the target does not know the value of one tick.
1528 * Note: Some semihosting implementations might not support
1529 * this semihosting operation, and they always return -1 in the
1533 case SEMIHOSTING_SYS_TMPNAM
: /* 0x0D */
1535 * Returns a temporary name for a file identified by a system
1539 * On entry, the PARAMETER REGISTER contains a pointer to a
1540 * three-word argument block:
1541 * - field 1 A pointer to a buffer.
1542 * - field 2 A target identifier for this filename. Its value
1543 * must be an integer in the range 0-255.
1544 * - field 3 Contains the length of the buffer. The length must
1545 * be at least the value of L_tmpnam on the host system.
1548 * On exit, the RETURN REGISTER contains:
1549 * - 0 if the call is successful.
1550 * - –1 if an error occurs.
1552 * The buffer pointed to by the PARAMETER REGISTER contains
1553 * the filename, prefixed with a suitable directory name.
1554 * If you use the same target identifier again, the same
1555 * filename is returned.
1557 * Note: The returned string must be null-terminated.
1561 fprintf(stderr
, "semihosting: unsupported call %#x\n",
1562 (unsigned) semihosting
->op
);
1563 semihosting
->result
= -1;
1564 semihosting
->sys_errno
= ENOTSUP
;
1567 if (!semihosting
->hit_fileio
) {
1568 retval
= semihosting
->post_result(target
);
1569 if (retval
!= ERROR_OK
) {
1570 LOG_ERROR("Failed to post semihosting result");
1578 /* -------------------------------------------------------------------------
1579 * Local functions. */
1581 static int semihosting_common_fileio_info(struct target
*target
,
1582 struct gdb_fileio_info
*fileio_info
)
1584 struct semihosting
*semihosting
= target
->semihosting
;
1589 * To avoid unnecessary duplication, semihosting prepares the
1590 * fileio_info structure out-of-band when the target halts. See
1591 * do_semihosting for more detail.
1593 if (!semihosting
->is_fileio
|| !semihosting
->hit_fileio
)
1599 static int semihosting_common_fileio_end(struct target
*target
, int result
,
1600 int fileio_errno
, bool ctrl_c
)
1602 struct gdb_fileio_info
*fileio_info
= target
->fileio_info
;
1603 struct semihosting
*semihosting
= target
->semihosting
;
1607 /* clear pending status */
1608 semihosting
->hit_fileio
= false;
1610 semihosting
->result
= result
;
1611 semihosting
->sys_errno
= fileio_errno
;
1614 * Some fileio results do not match up with what the semihosting
1615 * operation expects; for these operations, we munge the results
1618 switch (semihosting
->op
) {
1619 case SEMIHOSTING_SYS_WRITE
: /* 0x05 */
1620 case SEMIHOSTING_SYS_READ
: /* 0x06 */
1622 semihosting
->result
= fileio_info
->param_3
; /* Zero bytes read/written. */
1624 semihosting
->result
= (int64_t)fileio_info
->param_3
- result
;
1627 case SEMIHOSTING_SYS_SEEK
: /* 0x0a */
1629 semihosting
->result
= 0;
1633 return semihosting
->post_result(target
);
1636 /* -------------------------------------------------------------------------
1637 * Utility functions. */
1640 * Read all fields of a command from target to buffer.
1642 int semihosting_read_fields(struct target
*target
, size_t number
,
1645 struct semihosting
*semihosting
= target
->semihosting
;
1646 /* Use 4-byte multiples to trigger fast memory access. */
1647 return target_read_memory(target
, semihosting
->param
, 4,
1648 number
* (semihosting
->word_size_bytes
/ 4), fields
);
1652 * Write all fields of a command from buffer to target.
1654 int semihosting_write_fields(struct target
*target
, size_t number
,
1657 struct semihosting
*semihosting
= target
->semihosting
;
1658 /* Use 4-byte multiples to trigger fast memory access. */
1659 return target_write_memory(target
, semihosting
->param
, 4,
1660 number
* (semihosting
->word_size_bytes
/ 4), fields
);
1664 * Extract a field from the buffer, considering register size and endianness.
1666 uint64_t semihosting_get_field(struct target
*target
, size_t index
,
1669 struct semihosting
*semihosting
= target
->semihosting
;
1670 if (semihosting
->word_size_bytes
== 8)
1671 return target_buffer_get_u64(target
, fields
+ (index
* 8));
1673 return target_buffer_get_u32(target
, fields
+ (index
* 4));
1677 * Store a field in the buffer, considering register size and endianness.
1679 void semihosting_set_field(struct target
*target
, uint64_t value
,
1683 struct semihosting
*semihosting
= target
->semihosting
;
1684 if (semihosting
->word_size_bytes
== 8)
1685 target_buffer_set_u64(target
, fields
+ (index
* 8), value
);
1687 target_buffer_set_u32(target
, fields
+ (index
* 4), value
);
1690 /* -------------------------------------------------------------------------
1691 * Semihosting redirect over TCP structs and functions */
1693 static int semihosting_service_new_connection_handler(struct connection
*connection
)
1695 struct semihosting_tcp_service
*service
= connection
->service
->priv
;
1696 service
->semihosting
->tcp_connection
= connection
;
1701 static int semihosting_service_input_handler(struct connection
*connection
)
1703 struct semihosting_tcp_service
*service
= connection
->service
->priv
;
1705 if (!connection
->input_pending
) {
1706 /* consume received data, not for semihosting IO */
1707 const int buf_len
= 100;
1709 int bytes_read
= connection_read(connection
, buf
, buf_len
);
1711 if (bytes_read
== 0) {
1712 return ERROR_SERVER_REMOTE_CLOSED
;
1713 } else if (bytes_read
== -1) {
1714 LOG_ERROR("error during read: %s", strerror(errno
));
1715 return ERROR_SERVER_REMOTE_CLOSED
;
1717 } else if (service
->error
!= ERROR_OK
) {
1718 return ERROR_SERVER_REMOTE_CLOSED
;
1724 static int semihosting_service_connection_closed_handler(struct connection
*connection
)
1726 struct semihosting_tcp_service
*service
= connection
->service
->priv
;
1728 free(service
->name
);
1735 static void semihosting_tcp_close_cnx(struct semihosting
*semihosting
)
1737 if (!semihosting
->tcp_connection
)
1740 struct service
*service
= semihosting
->tcp_connection
->service
;
1741 remove_service(service
->name
, service
->port
);
1742 semihosting
->tcp_connection
= NULL
;
1746 static const struct service_driver semihosting_service_driver
= {
1747 .name
= "semihosting",
1748 .new_connection_during_keep_alive_handler
= NULL
,
1749 .new_connection_handler
= semihosting_service_new_connection_handler
,
1750 .input_handler
= semihosting_service_input_handler
,
1751 .connection_closed_handler
= semihosting_service_connection_closed_handler
,
1752 .keep_client_alive_handler
= NULL
,
1755 /* -------------------------------------------------------------------------
1756 * Common semihosting commands handlers. */
1758 COMMAND_HANDLER(handle_common_semihosting_command
)
1760 struct target
*target
= get_current_target(CMD_CTX
);
1763 LOG_ERROR("No target selected");
1767 struct semihosting
*semihosting
= target
->semihosting
;
1769 command_print(CMD
, "semihosting not supported for current target");
1776 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], is_active
);
1778 if (!target_was_examined(target
)) {
1779 LOG_ERROR("Target not examined yet");
1783 if (semihosting
&& semihosting
->setup(target
, is_active
) != ERROR_OK
) {
1784 LOG_ERROR("Failed to Configure semihosting");
1788 /* FIXME never let that "catch" be dropped! (???) */
1789 semihosting
->is_active
= is_active
;
1792 command_print(CMD
, "semihosting is %s",
1793 semihosting
->is_active
1794 ? "enabled" : "disabled");
1799 COMMAND_HANDLER(handle_common_semihosting_redirect_command
)
1801 struct target
*target
= get_current_target(CMD_CTX
);
1804 LOG_ERROR("No target selected");
1808 struct semihosting
*semihosting
= target
->semihosting
;
1810 command_print(CMD
, "semihosting not supported for current target");
1814 if (!semihosting
->is_active
) {
1815 command_print(CMD
, "semihosting not yet enabled for current target");
1819 enum semihosting_redirect_config cfg
;
1823 return ERROR_COMMAND_SYNTAX_ERROR
;
1825 if (strcmp(CMD_ARGV
[0], "disable") == 0) {
1826 cfg
= SEMIHOSTING_REDIRECT_CFG_NONE
;
1828 return ERROR_COMMAND_SYNTAX_ERROR
;
1829 } else if (strcmp(CMD_ARGV
[0], "tcp") == 0) {
1830 if (CMD_ARGC
< 2 || CMD_ARGC
> 3)
1831 return ERROR_COMMAND_SYNTAX_ERROR
;
1835 cfg
= SEMIHOSTING_REDIRECT_CFG_ALL
;
1836 if (CMD_ARGC
== 3) {
1837 if (strcmp(CMD_ARGV
[2], "debug") == 0)
1838 cfg
= SEMIHOSTING_REDIRECT_CFG_DEBUG
;
1839 else if (strcmp(CMD_ARGV
[2], "stdio") == 0)
1840 cfg
= SEMIHOSTING_REDIRECT_CFG_STDIO
;
1841 else if (strcmp(CMD_ARGV
[2], "all") != 0)
1842 return ERROR_COMMAND_SYNTAX_ERROR
;
1845 return ERROR_COMMAND_SYNTAX_ERROR
;
1848 semihosting_tcp_close_cnx(semihosting
);
1849 semihosting
->redirect_cfg
= SEMIHOSTING_REDIRECT_CFG_NONE
;
1851 if (cfg
!= SEMIHOSTING_REDIRECT_CFG_NONE
) {
1852 struct semihosting_tcp_service
*service
=
1853 calloc(1, sizeof(struct semihosting_tcp_service
));
1855 LOG_ERROR("Failed to allocate semihosting TCP service.");
1859 service
->semihosting
= semihosting
;
1861 service
->name
= alloc_printf("%s semihosting service", target_name(target
));
1862 if (!service
->name
) {
1863 LOG_ERROR("Out of memory");
1868 int ret
= add_service(&semihosting_service_driver
,
1871 if (ret
!= ERROR_OK
) {
1872 LOG_ERROR("failed to initialize %s", service
->name
);
1873 free(service
->name
);
1879 semihosting
->redirect_cfg
= cfg
;
1884 COMMAND_HANDLER(handle_common_semihosting_fileio_command
)
1886 struct target
*target
= get_current_target(CMD_CTX
);
1889 LOG_ERROR("No target selected");
1893 struct semihosting
*semihosting
= target
->semihosting
;
1895 command_print(CMD
, "semihosting not supported for current target");
1899 if (!semihosting
->is_active
) {
1900 command_print(CMD
, "semihosting not yet enabled for current target");
1905 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], semihosting
->is_fileio
);
1907 command_print(CMD
, "semihosting fileio is %s",
1908 semihosting
->is_fileio
1909 ? "enabled" : "disabled");
1914 COMMAND_HANDLER(handle_common_semihosting_cmdline
)
1916 struct target
*target
= get_current_target(CMD_CTX
);
1920 LOG_ERROR("No target selected");
1924 struct semihosting
*semihosting
= target
->semihosting
;
1926 command_print(CMD
, "semihosting not supported for current target");
1930 free(semihosting
->cmdline
);
1931 semihosting
->cmdline
= CMD_ARGC
> 0 ? strdup(CMD_ARGV
[0]) : NULL
;
1933 for (i
= 1; i
< CMD_ARGC
; i
++) {
1934 char *cmdline
= alloc_printf("%s %s", semihosting
->cmdline
, CMD_ARGV
[i
]);
1937 free(semihosting
->cmdline
);
1938 semihosting
->cmdline
= cmdline
;
1941 command_print(CMD
, "semihosting command line is [%s]",
1942 semihosting
->cmdline
);
1947 COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command
)
1949 struct target
*target
= get_current_target(CMD_CTX
);
1952 LOG_ERROR("No target selected");
1956 struct semihosting
*semihosting
= target
->semihosting
;
1958 command_print(CMD
, "semihosting not supported for current target");
1962 if (!semihosting
->is_active
) {
1963 command_print(CMD
, "semihosting not yet enabled for current target");
1968 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], semihosting
->has_resumable_exit
);
1970 command_print(CMD
, "semihosting resumable exit is %s",
1971 semihosting
->has_resumable_exit
1972 ? "enabled" : "disabled");
1977 COMMAND_HANDLER(handle_common_semihosting_read_user_param_command
)
1979 struct target
*target
= get_current_target(CMD_CTX
);
1980 struct semihosting
*semihosting
= target
->semihosting
;
1983 return ERROR_COMMAND_SYNTAX_ERROR
;
1985 if (!semihosting
->is_active
) {
1986 LOG_ERROR("semihosting not yet enabled for current target");
1990 if (!semihosting_user_op_params
) {
1991 LOG_ERROR("This command is usable only from a registered user "
1992 "semihosting event callback.");
1996 command_print_sameline(CMD
, "%s", semihosting_user_op_params
);
2001 COMMAND_HANDLER(handle_common_semihosting_basedir_command
)
2003 struct target
*target
= get_current_target(CMD_CTX
);
2006 return ERROR_COMMAND_SYNTAX_ERROR
;
2009 LOG_ERROR("No target selected");
2013 struct semihosting
*semihosting
= target
->semihosting
;
2015 command_print(CMD
, "semihosting not supported for current target");
2019 if (!semihosting
->is_active
) {
2020 command_print(CMD
, "semihosting not yet enabled for current target");
2025 free(semihosting
->basedir
);
2026 semihosting
->basedir
= strdup(CMD_ARGV
[0]);
2027 if (!semihosting
->basedir
) {
2028 command_print(CMD
, "semihosting failed to allocate memory for basedir!");
2033 command_print(CMD
, "semihosting base dir: %s",
2034 semihosting
->basedir
? semihosting
->basedir
: "");
2039 const struct command_registration semihosting_common_handlers
[] = {
2041 .name
= "semihosting",
2042 .handler
= handle_common_semihosting_command
,
2043 .mode
= COMMAND_EXEC
,
2044 .usage
= "['enable'|'disable']",
2045 .help
= "activate support for semihosting operations",
2048 .name
= "semihosting_redirect",
2049 .handler
= handle_common_semihosting_redirect_command
,
2050 .mode
= COMMAND_EXEC
,
2051 .usage
= "(disable | tcp <port> ['debug'|'stdio'|'all'])",
2052 .help
= "redirect semihosting IO",
2055 .name
= "semihosting_cmdline",
2056 .handler
= handle_common_semihosting_cmdline
,
2057 .mode
= COMMAND_EXEC
,
2058 .usage
= "arguments",
2059 .help
= "command line arguments to be passed to program",
2062 .name
= "semihosting_fileio",
2063 .handler
= handle_common_semihosting_fileio_command
,
2064 .mode
= COMMAND_EXEC
,
2065 .usage
= "['enable'|'disable']",
2066 .help
= "activate support for semihosting fileio operations",
2069 .name
= "semihosting_resexit",
2070 .handler
= handle_common_semihosting_resumable_exit_command
,
2071 .mode
= COMMAND_EXEC
,
2072 .usage
= "['enable'|'disable']",
2073 .help
= "activate support for semihosting resumable exit",
2076 .name
= "semihosting_read_user_param",
2077 .handler
= handle_common_semihosting_read_user_param_command
,
2078 .mode
= COMMAND_EXEC
,
2080 .help
= "read parameters in semihosting-user-cmd-0x10X callbacks",
2083 .name
= "semihosting_basedir",
2084 .handler
= handle_common_semihosting_basedir_command
,
2085 .mode
= COMMAND_EXEC
,
2087 .help
= "set the base directory for semihosting I/O operations",
2089 COMMAND_REGISTRATION_DONE