1 /***************************************************************************
2 * Copyright (C) 2018 by Liviu Ionescu *
5 * Copyright (C) 2018 by Marvell Technology Group Ltd. *
6 * Written by Nicolas Pitre <nico@marvell.com> *
8 * Copyright (C) 2010 by Spencer Oliver *
9 * spen@spen-soft.co.uk *
11 * Copyright (C) 2016 by Square, Inc. *
12 * Steven Stallion <stallion@squareup.com> *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
19 * This program is distributed in the hope that it will be useful, *
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22 * GNU General Public License for more details. *
24 * You should have received a copy of the GNU General Public License *
25 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
26 ***************************************************************************/
30 * Common ARM semihosting support.
32 * Semihosting enables code running on a target to use some of the I/O
33 * facilities on the host computer. The target application must be linked
34 * against a library that forwards operation requests by using an
35 * instruction trapped by the debugger.
37 * Details can be found in
38 * "Semihosting for AArch32 and AArch64, Release 2.0"
39 * https://static.docs.arm.com/100863/0200/semihosting.pdf
48 #include "target_type.h"
49 #include "semihosting_common.h"
51 #include <helper/binarybuffer.h>
52 #include <helper/log.h>
55 static const int open_modeflags
[12] = {
60 O_WRONLY
| O_CREAT
| O_TRUNC
,
61 O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
,
62 O_RDWR
| O_CREAT
| O_TRUNC
,
63 O_RDWR
| O_CREAT
| O_TRUNC
| O_BINARY
,
64 O_WRONLY
| O_CREAT
| O_APPEND
,
65 O_WRONLY
| O_CREAT
| O_APPEND
| O_BINARY
,
66 O_RDWR
| O_CREAT
| O_APPEND
,
67 O_RDWR
| O_CREAT
| O_APPEND
| O_BINARY
70 static int semihosting_common_fileio_info(struct target
*target
,
71 struct gdb_fileio_info
*fileio_info
);
72 static int semihosting_common_fileio_end(struct target
*target
, int result
,
73 int fileio_errno
, bool ctrl_c
);
75 static int semihosting_read_fields(struct target
*target
, size_t number
,
77 static int semihosting_write_fields(struct target
*target
, size_t number
,
79 static uint64_t semihosting_get_field(struct target
*target
, size_t index
,
81 static void semihosting_set_field(struct target
*target
, uint64_t value
,
85 /* Attempts to include gdb_server.h failed. */
86 extern int gdb_actual_connections
;
89 * Initialize common semihosting support.
91 * @param target Pointer to the target to initialize.
92 * @return An error status if there is a problem during initialization.
94 int semihosting_common_init(struct target
*target
, void *setup
,
99 target
->fileio_info
= malloc(sizeof(*target
->fileio_info
));
100 if (target
->fileio_info
== NULL
) {
101 LOG_ERROR("out of memory");
104 memset(target
->fileio_info
, 0, sizeof(*target
->fileio_info
));
106 struct semihosting
*semihosting
;
107 semihosting
= malloc(sizeof(*target
->semihosting
));
108 if (semihosting
== NULL
) {
109 LOG_ERROR("out of memory");
113 semihosting
->is_active
= false;
114 semihosting
->is_fileio
= false;
115 semihosting
->hit_fileio
= false;
116 semihosting
->is_resumable
= false;
117 semihosting
->has_resumable_exit
= false;
118 semihosting
->word_size_bytes
= 0;
119 semihosting
->op
= -1;
120 semihosting
->param
= 0;
121 semihosting
->result
= -1;
122 semihosting
->sys_errno
= -1;
123 semihosting
->cmdline
= NULL
;
125 /* If possible, update it in setup(). */
126 semihosting
->setup_time
= clock();
128 semihosting
->setup
= setup
;
129 semihosting
->post_result
= post_result
;
131 target
->semihosting
= semihosting
;
133 target
->type
->get_gdb_fileio_info
= semihosting_common_fileio_info
;
134 target
->type
->gdb_fileio_end
= semihosting_common_fileio_end
;
140 * Portable implementation of ARM semihosting calls.
141 * Performs the currently pending semihosting operation
142 * encoded in target->semihosting.
144 int semihosting_common(struct target
*target
)
146 struct semihosting
*semihosting
= target
->semihosting
;
148 /* Silently ignore if the semhosting field was not set. */
152 struct gdb_fileio_info
*fileio_info
= target
->fileio_info
;
155 * By default return an error.
156 * The actual result must be set by each function
158 semihosting
->result
= -1;
160 /* Most operations are resumable, except the two exit calls. */
161 semihosting
->is_resumable
= true;
165 /* Enough space to hold 4 long words. */
168 LOG_DEBUG("op=0x%x, param=0x%" PRIx64
, (int)semihosting
->op
,
171 switch (semihosting
->op
) {
173 case SEMIHOSTING_SYS_CLOCK
: /* 0x10 */
175 * Returns the number of centiseconds (hundredths of a second)
176 * since the execution started.
178 * Values returned can be of limited use for some benchmarking
179 * purposes because of communication overhead or other
180 * agent-specific factors. For example, with a debug hardware
181 * unit the request is passed back to the host for execution.
182 * This can lead to unpredictable delays in transmission and
183 * process scheduling.
185 * Use this function to calculate time intervals, by calculating
186 * differences between intervals with and without the code
187 * sequence to be timed.
190 * The PARAMETER REGISTER must contain 0. There are no other
194 * On exit, the RETURN REGISTER contains:
195 * - The number of centiseconds since some arbitrary start
196 * point, if the call is successful.
197 * - –1 if the call is not successful. For example, because
198 * of a communications error.
201 clock_t delta
= clock() - semihosting
->setup_time
;
203 semihosting
->result
= delta
/ (CLOCKS_PER_SEC
/ 100);
207 case SEMIHOSTING_SYS_CLOSE
: /* 0x02 */
209 * Closes a file on the host system. The handle must reference
210 * a file that was opened with SYS_OPEN.
213 * On entry, the PARAMETER REGISTER contains a pointer to a
214 * one-field argument block:
215 * - field 1 Contains a handle for an open file.
218 * On exit, the RETURN REGISTER contains:
219 * - 0 if the call is successful
220 * - –1 if the call is not successful.
222 retval
= semihosting_read_fields(target
, 1, fields
);
223 if (retval
!= ERROR_OK
)
226 int fd
= semihosting_get_field(target
, 0, fields
);
227 if (semihosting
->is_fileio
) {
228 if (fd
== 0 || fd
== 1 || fd
== 2) {
229 semihosting
->result
= 0;
232 semihosting
->hit_fileio
= true;
233 fileio_info
->identifier
= "close";
234 fileio_info
->param_1
= fd
;
236 semihosting
->result
= close(fd
);
237 semihosting
->sys_errno
= errno
;
239 LOG_DEBUG("close(%d)=%d", fd
, (int)semihosting
->result
);
244 case SEMIHOSTING_SYS_ERRNO
: /* 0x13 */
246 * Returns the value of the C library errno variable that is
247 * associated with the semihosting implementation. The errno
248 * variable can be set by a number of C library semihosted
249 * functions, including:
257 * Whether errno is set or not, and to what value, is entirely
258 * host-specific, except where the ISO C standard defines the
262 * There are no parameters. The PARAMETER REGISTER must be 0.
265 * On exit, the RETURN REGISTER contains the value of the C
266 * library errno variable.
268 semihosting
->result
= semihosting
->sys_errno
;
271 case SEMIHOSTING_SYS_EXIT
: /* 0x18 */
273 * Note: SYS_EXIT was called angel_SWIreason_ReportException in
274 * previous versions of the documentation.
276 * An application calls this operation to report an exception
277 * to the debugger directly. The most common use is to report
278 * that execution has completed, using ADP_Stopped_ApplicationExit.
280 * Note: This semihosting operation provides no means for 32-bit
281 * callers to indicate an application exit with a specified exit
282 * code. Semihosting callers may prefer to check for the presence
283 * of the SH_EXT_EXTENDED_REPORT_EXCEPTION extension and use
284 * the SYS_REPORT_EXCEPTION_EXTENDED operation instead, if it
288 * On entry, the PARAMETER register is set to a reason code
289 * describing the cause of the trap. Not all semihosting client
290 * implementations will necessarily trap every corresponding
291 * event. Important reason codes are:
293 * - ADP_Stopped_ApplicationExit 0x20026
294 * - ADP_Stopped_RunTimeErrorUnknown 0x20023
297 * On entry, the PARAMETER REGISTER contains a pointer to a
298 * two-field argument block:
299 * - field 1 The exception type, which is one of the set of
300 * reason codes in the above tables.
301 * - field 2 A subcode, whose meaning depends on the reason
303 * In particular, if field 1 is ADP_Stopped_ApplicationExit
304 * then field 2 is an exit status code, as passed to the C
305 * standard library exit() function. A simulator receiving
306 * this request must notify a connected debugger, if present,
307 * and then exit with the specified status.
310 * No return is expected from these calls. However, it is
311 * possible for the debugger to request that the application
312 * continues by performing an RDI_Execute request or equivalent.
313 * In this case, execution continues with the registers as they
314 * were on entry to the operation, or as subsequently modified
317 if (semihosting
->word_size_bytes
== 8) {
318 retval
= semihosting_read_fields(target
, 2, fields
);
319 if (retval
!= ERROR_OK
)
322 int type
= semihosting_get_field(target
, 0, fields
);
323 int code
= semihosting_get_field(target
, 1, fields
);
325 if (type
== ADP_STOPPED_APPLICATION_EXIT
) {
326 if (!gdb_actual_connections
)
330 "semihosting: *** application exited with %d ***\n",
335 "semihosting: application exception %#x\n",
340 if (semihosting
->param
== ADP_STOPPED_APPLICATION_EXIT
) {
341 if (!gdb_actual_connections
)
345 "semihosting: *** application exited normally ***\n");
347 } else if (semihosting
->param
== ADP_STOPPED_RUN_TIME_ERROR
) {
348 /* Chosen more or less arbitrarly to have a nicer message,
349 * otherwise all other return the same exit code 1. */
350 if (!gdb_actual_connections
)
354 "semihosting: *** application exited with error ***\n");
357 if (!gdb_actual_connections
)
361 "semihosting: application exception %#x\n",
362 (unsigned) semihosting
->param
);
366 if (!semihosting
->has_resumable_exit
) {
367 semihosting
->is_resumable
= false;
368 return target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
372 case SEMIHOSTING_SYS_EXIT_EXTENDED
: /* 0x20 */
374 * This operation is only supported if the semihosting extension
375 * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is
376 * reported using feature byte 0, bit 0. If this extension is
377 * supported, then the implementation provides a means to
378 * report a normal exit with a nonzero exit status in both 32-bit
379 * and 64-bit semihosting APIs.
381 * The implementation must provide the semihosting call
382 * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs.
384 * SYS_EXIT_EXTENDED is used by an application to report an
385 * exception or exit to the debugger directly. The most common
386 * use is to report that execution has completed, using
387 * ADP_Stopped_ApplicationExit.
390 * On entry, the PARAMETER REGISTER contains a pointer to a
391 * two-field argument block:
392 * - field 1 The exception type, which should be one of the set
393 * of reason codes that are documented for the SYS_EXIT
394 * (0x18) call. For example, ADP_Stopped_ApplicationExit.
395 * - field 2 A subcode, whose meaning depends on the reason
396 * code in field 1. In particular, if field 1 is
397 * ADP_Stopped_ApplicationExit then field 2 is an exit status
398 * code, as passed to the C standard library exit() function.
399 * A simulator receiving this request must notify a connected
400 * debugger, if present, and then exit with the specified status.
403 * No return is expected from these calls.
405 * For the A64 API, this call is identical to the behavior of
406 * the mandatory SYS_EXIT (0x18) call. If this extension is
407 * supported, then both calls must be implemented.
409 retval
= semihosting_read_fields(target
, 2, fields
);
410 if (retval
!= ERROR_OK
)
413 int type
= semihosting_get_field(target
, 0, fields
);
414 int code
= semihosting_get_field(target
, 1, fields
);
416 if (type
== ADP_STOPPED_APPLICATION_EXIT
) {
417 if (!gdb_actual_connections
)
421 "semihosting: *** application exited with %d ***\n",
425 fprintf(stderr
, "semihosting: exception %#x\n",
429 if (!semihosting
->has_resumable_exit
) {
430 semihosting
->is_resumable
= false;
431 return target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
435 case SEMIHOSTING_SYS_FLEN
: /* 0x0C */
437 * Returns the length of a specified file.
440 * On entry, the PARAMETER REGISTER contains a pointer to a
441 * one-field argument block:
442 * - field 1 A handle for a previously opened, seekable file
446 * On exit, the RETURN REGISTER contains:
447 * - The current length of the file object, if the call is
449 * - –1 if an error occurs.
451 if (semihosting
->is_fileio
) {
452 semihosting
->result
= -1;
453 semihosting
->sys_errno
= EINVAL
;
455 retval
= semihosting_read_fields(target
, 1, fields
);
456 if (retval
!= ERROR_OK
)
459 int fd
= semihosting_get_field(target
, 0, fields
);
461 semihosting
->result
= fstat(fd
, &buf
);
462 if (semihosting
->result
== -1) {
463 semihosting
->sys_errno
= errno
;
464 LOG_DEBUG("fstat(%d)=%d", fd
, (int)semihosting
->result
);
467 LOG_DEBUG("fstat(%d)=%d", fd
, (int)semihosting
->result
);
468 semihosting
->result
= buf
.st_size
;
472 case SEMIHOSTING_SYS_GET_CMDLINE
: /* 0x15 */
474 * Returns the command line that is used for the call to the
475 * executable, that is, argc and argv.
478 * On entry, the PARAMETER REGISTER points to a two-field data
479 * block to be used for returning the command string and its length:
480 * - field 1 A pointer to a buffer of at least the size that is
481 * specified in field 2.
482 * - field 2 The length of the buffer in bytes.
486 * If the call is successful, then the RETURN REGISTER contains 0,
487 * the PARAMETER REGISTER is unchanged, and the data block is
488 * updated as follows:
489 * - field 1 A pointer to a null-terminated string of the command
491 * - field 2 The length of the string in bytes.
492 * If the call is not successful, then the RETURN REGISTER
495 * Note: The semihosting implementation might impose limits on
496 * the maximum length of the string that can be transferred.
497 * However, the implementation must be able to support a
498 * command-line length of at least 80 bytes.
500 retval
= semihosting_read_fields(target
, 2, fields
);
501 if (retval
!= ERROR_OK
)
504 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
505 size_t size
= semihosting_get_field(target
, 1, fields
);
507 char *arg
= semihosting
->cmdline
!= NULL
?
508 semihosting
->cmdline
: "";
509 uint32_t len
= strlen(arg
) + 1;
511 semihosting
->result
= -1;
513 semihosting_set_field(target
, len
, 1, fields
);
514 retval
= target_write_buffer(target
, addr
, len
,
516 if (retval
!= ERROR_OK
)
518 semihosting
->result
= 0;
520 retval
= semihosting_write_fields(target
, 2, fields
);
521 if (retval
!= ERROR_OK
)
524 LOG_DEBUG("SYS_GET_CMDLINE=[%s],%d", arg
,
525 (int)semihosting
->result
);
529 case SEMIHOSTING_SYS_HEAPINFO
: /* 0x16 */
531 * Returns the system stack and heap parameters.
534 * On entry, the PARAMETER REGISTER contains the address of a
535 * pointer to a four-field data block. The contents of the data
536 * block are filled by the function. The following C-like
537 * pseudocode describes the layout of the block:
546 * On exit, the PARAMETER REGISTER is unchanged and the data
547 * block has been updated.
549 retval
= semihosting_read_fields(target
, 1, fields
);
550 if (retval
!= ERROR_OK
)
553 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
554 /* tell the remote we have no idea */
555 memset(fields
, 0, 4 * semihosting
->word_size_bytes
);
556 retval
= target_write_memory(target
, addr
, 4,
557 semihosting
->word_size_bytes
,
559 if (retval
!= ERROR_OK
)
561 semihosting
->result
= 0;
565 case SEMIHOSTING_SYS_ISERROR
: /* 0x08 */
567 * Determines whether the return code from another semihosting
568 * call is an error status or not.
570 * This call is passed a parameter block containing the error
574 * On entry, the PARAMETER REGISTER contains a pointer to a
575 * one-field data block:
576 * - field 1 The required status word to check.
579 * On exit, the RETURN REGISTER contains:
580 * - 0 if the status field is not an error indication
581 * - A nonzero value if the status field is an error indication.
583 retval
= semihosting_read_fields(target
, 1, fields
);
584 if (retval
!= ERROR_OK
)
587 uint64_t code
= semihosting_get_field(target
, 0, fields
);
588 semihosting
->result
= (code
!= 0);
591 case SEMIHOSTING_SYS_ISTTY
: /* 0x09 */
593 * Checks whether a file is connected to an interactive device.
596 * On entry, the PARAMETER REGISTER contains a pointer to a
597 * one-field argument block:
598 * field 1 A handle for a previously opened file object.
601 * On exit, the RETURN REGISTER contains:
602 * - 1 if the handle identifies an interactive device.
603 * - 0 if the handle identifies a file.
604 * - A value other than 1 or 0 if an error occurs.
606 if (semihosting
->is_fileio
) {
607 semihosting
->hit_fileio
= true;
608 fileio_info
->identifier
= "isatty";
609 fileio_info
->param_1
= semihosting
->param
;
611 retval
= semihosting_read_fields(target
, 1, fields
);
612 if (retval
!= ERROR_OK
)
614 int fd
= semihosting_get_field(target
, 0, fields
);
615 semihosting
->result
= isatty(fd
);
616 LOG_DEBUG("isatty(%d)=%d", fd
, (int)semihosting
->result
);
620 case SEMIHOSTING_SYS_OPEN
: /* 0x01 */
622 * Opens a file on the host system.
624 * The file path is specified either as relative to the current
625 * directory of the host process, or absolute, using the path
626 * conventions of the host operating system.
628 * Semihosting implementations must support opening the special
629 * path name :semihosting-features as part of the semihosting
630 * extensions reporting mechanism.
632 * ARM targets interpret the special path name :tt as meaning
633 * the console input stream, for an open-read or the console
634 * output stream, for an open-write. Opening these streams is
635 * performed as part of the standard startup code for those
636 * applications that reference the C stdio streams. The
637 * semihosting extension SH_EXT_STDOUT_STDERR allows the
638 * semihosting caller to open separate output streams
639 * corresponding to stdout and stderr. This extension is
640 * reported using feature byte 0, bit 1. Use SYS_OPEN with
641 * the special path name :semihosting-features to access the
644 * If this extension is supported, the implementation must
645 * support the following additional semantics to SYS_OPEN:
646 * - If the special path name :tt is opened with an fopen
647 * mode requesting write access (w, wb, w+, or w+b), then
648 * this is a request to open stdout.
649 * - If the special path name :tt is opened with a mode
650 * requesting append access (a, ab, a+, or a+b), then this is
651 * a request to open stderr.
654 * On entry, the PARAMETER REGISTER contains a pointer to a
655 * three-field argument block:
656 * - field 1 A pointer to a null-terminated string containing
657 * a file or device name.
658 * - field 2 An integer that specifies the file opening mode.
659 * - field 3 An integer that gives the length of the string
660 * pointed to by field 1.
662 * The length does not include the terminating null character
663 * that must be present.
666 * On exit, the RETURN REGISTER contains:
667 * - A nonzero handle if the call is successful.
668 * - –1 if the call is not successful.
670 retval
= semihosting_read_fields(target
, 3, fields
);
671 if (retval
!= ERROR_OK
)
674 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
675 uint32_t mode
= semihosting_get_field(target
, 1, fields
);
676 size_t len
= semihosting_get_field(target
, 2, fields
);
679 semihosting
->result
= -1;
680 semihosting
->sys_errno
= EINVAL
;
683 uint8_t *fn
= malloc(len
+1);
685 semihosting
->result
= -1;
686 semihosting
->sys_errno
= ENOMEM
;
688 retval
= target_read_memory(target
, addr
, 1, len
, fn
);
689 if (retval
!= ERROR_OK
) {
694 /* TODO: implement the :semihosting-features special file.
696 if (semihosting
->is_fileio
) {
697 if (strcmp((char *)fn
, ":semihosting-features") == 0) {
698 semihosting
->result
= -1;
699 semihosting
->sys_errno
= EINVAL
;
700 } else if (strcmp((char *)fn
, ":tt") == 0) {
702 semihosting
->result
= 0;
704 semihosting
->result
= 1;
706 semihosting
->result
= 2;
708 semihosting
->result
= -1;
710 semihosting
->hit_fileio
= true;
711 fileio_info
->identifier
= "open";
712 fileio_info
->param_1
= addr
;
713 fileio_info
->param_2
= len
;
714 fileio_info
->param_3
= open_modeflags
[mode
];
715 fileio_info
->param_4
= 0644;
718 if (strcmp((char *)fn
, ":tt") == 0) {
720 * - 0-3 ("r") for stdin,
721 * - 4-7 ("w") for stdout,
722 * - 8-11 ("a") for stderr */
724 semihosting
->result
= dup(
726 semihosting
->sys_errno
= errno
;
727 LOG_DEBUG("dup(STDIN)=%d",
728 (int)semihosting
->result
);
729 } else if (mode
< 8) {
730 semihosting
->result
= dup(
732 semihosting
->sys_errno
= errno
;
733 LOG_DEBUG("dup(STDOUT)=%d",
734 (int)semihosting
->result
);
736 semihosting
->result
= dup(
738 semihosting
->sys_errno
= errno
;
739 LOG_DEBUG("dup(STDERR)=%d",
740 (int)semihosting
->result
);
743 /* cygwin requires the permission setting
744 * otherwise it will fail to reopen a previously
746 semihosting
->result
= open((char *)fn
,
747 open_modeflags
[mode
],
749 semihosting
->sys_errno
= errno
;
750 LOG_DEBUG("open('%s')=%d", fn
,
751 (int)semihosting
->result
);
759 case SEMIHOSTING_SYS_READ
: /* 0x06 */
761 * Reads the contents of a file into a buffer. The file position
762 * is specified either:
763 * - Explicitly by a SYS_SEEK.
764 * - Implicitly one byte beyond the previous SYS_READ or
767 * The file position is at the start of the file when it is
768 * opened, and is lost when the file is closed. Perform the
769 * file operation as a single action whenever possible. For
770 * example, do not split a read of 16KB into four 4KB chunks
771 * unless there is no alternative.
774 * On entry, the PARAMETER REGISTER contains a pointer to a
775 * three-field data block:
776 * - field 1 Contains a handle for a file previously opened
778 * - field 2 Points to a buffer.
779 * - field 3 Contains the number of bytes to read to the buffer
783 * On exit, the RETURN REGISTER contains the number of bytes not
784 * filled in the buffer (buffer_length - bytes_read) as follows:
785 * - If the RETURN REGISTER is 0, the entire buffer was
786 * successfully filled.
787 * - If the RETURN REGISTER is the same as field 3, no bytes
788 * were read (EOF can be assumed).
789 * - If the RETURN REGISTER contains a value smaller than
790 * field 3, the read succeeded but the buffer was only partly
791 * filled. For interactive devices, this is the most common
794 retval
= semihosting_read_fields(target
, 3, fields
);
795 if (retval
!= ERROR_OK
)
798 int fd
= semihosting_get_field(target
, 0, fields
);
799 uint64_t addr
= semihosting_get_field(target
, 1, fields
);
800 size_t len
= semihosting_get_field(target
, 2, fields
);
801 if (semihosting
->is_fileio
) {
802 semihosting
->hit_fileio
= true;
803 fileio_info
->identifier
= "read";
804 fileio_info
->param_1
= fd
;
805 fileio_info
->param_2
= addr
;
806 fileio_info
->param_3
= len
;
808 uint8_t *buf
= malloc(len
);
810 semihosting
->result
= -1;
811 semihosting
->sys_errno
= ENOMEM
;
813 semihosting
->result
= read(fd
, buf
, len
);
814 semihosting
->sys_errno
= errno
;
815 LOG_DEBUG("read(%d, 0x%" PRIx64
", %zu)=%d",
819 (int)semihosting
->result
);
820 if (semihosting
->result
>= 0) {
821 retval
= target_write_buffer(target
, addr
,
824 if (retval
!= ERROR_OK
) {
828 /* the number of bytes NOT filled in */
829 semihosting
->result
= len
-
838 case SEMIHOSTING_SYS_READC
: /* 0x07 */
840 * Reads a byte from the console.
843 * The PARAMETER REGISTER must contain 0. There are no other
844 * parameters or values possible.
847 * On exit, the RETURN REGISTER contains the byte read from
850 if (semihosting
->is_fileio
) {
851 LOG_ERROR("SYS_READC not supported by semihosting fileio");
854 semihosting
->result
= getchar();
855 LOG_DEBUG("getchar()=%d", (int)semihosting
->result
);
858 case SEMIHOSTING_SYS_REMOVE
: /* 0x0E */
860 * Deletes a specified file on the host filing system.
863 * On entry, the PARAMETER REGISTER contains a pointer to a
864 * two-field argument block:
865 * - field 1 Points to a null-terminated string that gives the
866 * path name of the file to be deleted.
867 * - field 2 The length of the string.
870 * On exit, the RETURN REGISTER contains:
871 * - 0 if the delete is successful
872 * - A nonzero, host-specific error code if the delete fails.
874 retval
= semihosting_read_fields(target
, 2, fields
);
875 if (retval
!= ERROR_OK
)
878 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
879 size_t len
= semihosting_get_field(target
, 1, fields
);
880 if (semihosting
->is_fileio
) {
881 semihosting
->hit_fileio
= true;
882 fileio_info
->identifier
= "unlink";
883 fileio_info
->param_1
= addr
;
884 fileio_info
->param_2
= len
;
886 uint8_t *fn
= malloc(len
+1);
888 semihosting
->result
= -1;
889 semihosting
->sys_errno
= ENOMEM
;
892 target_read_memory(target
, addr
, 1, len
,
894 if (retval
!= ERROR_OK
) {
899 semihosting
->result
= remove((char *)fn
);
900 semihosting
->sys_errno
= errno
;
901 LOG_DEBUG("remove('%s')=%d", fn
,
902 (int)semihosting
->result
);
910 case SEMIHOSTING_SYS_RENAME
: /* 0x0F */
912 * Renames a specified file.
915 * On entry, the PARAMETER REGISTER contains a pointer to a
916 * four-field data block:
917 * - field 1 A pointer to the name of the old file.
918 * - field 2 The length of the old filename.
919 * - field 3 A pointer to the new filename.
920 * - field 4 The length of the new filename. Both strings are
924 * On exit, the RETURN REGISTER contains:
925 * - 0 if the rename is successful.
926 * - A nonzero, host-specific error code if the rename fails.
928 retval
= semihosting_read_fields(target
, 4, fields
);
929 if (retval
!= ERROR_OK
)
932 uint64_t addr1
= semihosting_get_field(target
, 0, fields
);
933 size_t len1
= semihosting_get_field(target
, 1, fields
);
934 uint64_t addr2
= semihosting_get_field(target
, 2, fields
);
935 size_t len2
= semihosting_get_field(target
, 3, fields
);
936 if (semihosting
->is_fileio
) {
937 semihosting
->hit_fileio
= true;
938 fileio_info
->identifier
= "rename";
939 fileio_info
->param_1
= addr1
;
940 fileio_info
->param_2
= len1
;
941 fileio_info
->param_3
= addr2
;
942 fileio_info
->param_4
= len2
;
944 uint8_t *fn1
= malloc(len1
+1);
945 uint8_t *fn2
= malloc(len2
+1);
947 semihosting
->result
= -1;
948 semihosting
->sys_errno
= ENOMEM
;
950 retval
= target_read_memory(target
, addr1
, 1, len1
,
952 if (retval
!= ERROR_OK
) {
957 retval
= target_read_memory(target
, addr2
, 1, len2
,
959 if (retval
!= ERROR_OK
) {
966 semihosting
->result
= rename((char *)fn1
,
968 semihosting
->sys_errno
= errno
;
969 LOG_DEBUG("rename('%s', '%s')=%d", fn1
, fn2
,
970 (int)semihosting
->result
);
979 case SEMIHOSTING_SYS_SEEK
: /* 0x0A */
981 * Seeks to a specified position in a file using an offset
982 * specified from the start of the file. The file is assumed
983 * to be a byte array and the offset is given in bytes.
986 * On entry, the PARAMETER REGISTER contains a pointer to a
987 * two-field data block:
988 * - field 1 A handle for a seekable file object.
989 * - field 2 The absolute byte position to seek to.
992 * On exit, the RETURN REGISTER contains:
993 * - 0 if the request is successful.
994 * - A negative value if the request is not successful.
995 * Use SYS_ERRNO to read the value of the host errno variable
996 * describing the error.
998 * Note: The effect of seeking outside the current extent of
999 * the file object is undefined.
1001 retval
= semihosting_read_fields(target
, 2, fields
);
1002 if (retval
!= ERROR_OK
)
1005 int fd
= semihosting_get_field(target
, 0, fields
);
1006 off_t pos
= semihosting_get_field(target
, 1, fields
);
1007 if (semihosting
->is_fileio
) {
1008 semihosting
->hit_fileio
= true;
1009 fileio_info
->identifier
= "lseek";
1010 fileio_info
->param_1
= fd
;
1011 fileio_info
->param_2
= pos
;
1012 fileio_info
->param_3
= SEEK_SET
;
1014 semihosting
->result
= lseek(fd
, pos
, SEEK_SET
);
1015 semihosting
->sys_errno
= errno
;
1016 LOG_DEBUG("lseek(%d, %d)=%d", fd
, (int)pos
,
1017 (int)semihosting
->result
);
1018 if (semihosting
->result
== pos
)
1019 semihosting
->result
= 0;
1024 case SEMIHOSTING_SYS_SYSTEM
: /* 0x12 */
1026 * Passes a command to the host command-line interpreter.
1027 * This enables you to execute a system command such as dir,
1028 * ls, or pwd. The terminal I/O is on the host, and is not
1029 * visible to the target.
1032 * On entry, the PARAMETER REGISTER contains a pointer to a
1033 * two-field argument block:
1034 * - field 1 Points to a string to be passed to the host
1035 * command-line interpreter.
1036 * - field 2 The length of the string.
1039 * On exit, the RETURN REGISTER contains the return status.
1042 /* Provide SYS_SYSTEM functionality. Uses the
1043 * libc system command, there may be a reason *NOT*
1044 * to use this, but as I can't think of one, I
1045 * implemented it this way.
1047 retval
= semihosting_read_fields(target
, 2, fields
);
1048 if (retval
!= ERROR_OK
)
1051 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
1052 size_t len
= semihosting_get_field(target
, 1, fields
);
1053 if (semihosting
->is_fileio
) {
1054 semihosting
->hit_fileio
= true;
1055 fileio_info
->identifier
= "system";
1056 fileio_info
->param_1
= addr
;
1057 fileio_info
->param_2
= len
;
1059 uint8_t *cmd
= malloc(len
+1);
1061 semihosting
->result
= -1;
1062 semihosting
->sys_errno
= ENOMEM
;
1064 retval
= target_read_memory(target
,
1069 if (retval
!= ERROR_OK
) {
1074 semihosting
->result
= system(
1076 LOG_DEBUG("system('%s')=%d",
1078 (int)semihosting
->result
);
1087 case SEMIHOSTING_SYS_TIME
: /* 0x11 */
1089 * Returns the number of seconds since 00:00 January 1, 1970.
1090 * This value is real-world time, regardless of any debug agent
1094 * There are no parameters.
1097 * On exit, the RETURN REGISTER contains the number of seconds.
1099 semihosting
->result
= time(NULL
);
1102 case SEMIHOSTING_SYS_WRITE
: /* 0x05 */
1104 * Writes the contents of a buffer to a specified file at the
1105 * current file position. The file position is specified either:
1106 * - Explicitly, by a SYS_SEEK.
1107 * - Implicitly as one byte beyond the previous SYS_READ or
1108 * SYS_WRITE request.
1110 * The file position is at the start of the file when the file
1111 * is opened, and is lost when the file is closed.
1113 * Perform the file operation as a single action whenever
1114 * possible. For example, do not split a write of 16KB into
1115 * four 4KB chunks unless there is no alternative.
1118 * On entry, the PARAMETER REGISTER contains a pointer to a
1119 * three-field data block:
1120 * - field 1 Contains a handle for a file previously opened
1122 * - field 2 Points to the memory containing the data to be written.
1123 * - field 3 Contains the number of bytes to be written from
1124 * the buffer to the file.
1127 * On exit, the RETURN REGISTER contains:
1128 * - 0 if the call is successful.
1129 * - The number of bytes that are not written, if there is an error.
1131 retval
= semihosting_read_fields(target
, 3, fields
);
1132 if (retval
!= ERROR_OK
)
1135 int fd
= semihosting_get_field(target
, 0, fields
);
1136 uint64_t addr
= semihosting_get_field(target
, 1, fields
);
1137 size_t len
= semihosting_get_field(target
, 2, fields
);
1138 if (semihosting
->is_fileio
) {
1139 semihosting
->hit_fileio
= true;
1140 fileio_info
->identifier
= "write";
1141 fileio_info
->param_1
= fd
;
1142 fileio_info
->param_2
= addr
;
1143 fileio_info
->param_3
= len
;
1145 uint8_t *buf
= malloc(len
);
1147 semihosting
->result
= -1;
1148 semihosting
->sys_errno
= ENOMEM
;
1150 retval
= target_read_buffer(target
, addr
, len
, buf
);
1151 if (retval
!= ERROR_OK
) {
1155 semihosting
->result
= write(fd
, buf
, len
);
1156 semihosting
->sys_errno
= errno
;
1157 LOG_DEBUG("write(%d, 0x%" PRIx64
", %zu)=%d",
1161 (int)semihosting
->result
);
1162 if (semihosting
->result
>= 0) {
1163 /* The number of bytes that are NOT written.
1165 semihosting
->result
= len
-
1166 semihosting
->result
;
1175 case SEMIHOSTING_SYS_WRITEC
: /* 0x03 */
1177 * Writes a character byte, pointed to by the PARAMETER REGISTER,
1178 * to the debug channel. When executed under a semihosting
1179 * debugger, the character appears on the host debugger console.
1182 * On entry, the PARAMETER REGISTER contains a pointer to the
1186 * None. The RETURN REGISTER is corrupted.
1188 if (semihosting
->is_fileio
) {
1189 semihosting
->hit_fileio
= true;
1190 fileio_info
->identifier
= "write";
1191 fileio_info
->param_1
= 1;
1192 fileio_info
->param_2
= semihosting
->param
;
1193 fileio_info
->param_3
= 1;
1195 uint64_t addr
= semihosting
->param
;
1197 retval
= target_read_memory(target
, addr
, 1, 1, &c
);
1198 if (retval
!= ERROR_OK
)
1201 semihosting
->result
= 0;
1205 case SEMIHOSTING_SYS_WRITE0
: /* 0x04 */
1207 * Writes a null-terminated string to the debug channel.
1208 * When executed under a semihosting debugger, the characters
1209 * appear on the host debugger console.
1212 * On entry, the PARAMETER REGISTER contains a pointer to the
1213 * first byte of the string.
1216 * None. The RETURN REGISTER is corrupted.
1218 if (semihosting
->is_fileio
) {
1220 uint64_t addr
= semihosting
->param
;
1223 retval
= target_read_memory(target
, addr
, 1, 1, &c
);
1224 if (retval
!= ERROR_OK
)
1230 semihosting
->hit_fileio
= true;
1231 fileio_info
->identifier
= "write";
1232 fileio_info
->param_1
= 1;
1233 fileio_info
->param_2
= semihosting
->param
;
1234 fileio_info
->param_3
= count
;
1236 uint64_t addr
= semihosting
->param
;
1239 retval
= target_read_memory(target
, addr
++, 1, 1, &c
);
1240 if (retval
!= ERROR_OK
)
1246 semihosting
->result
= 0;
1250 case SEMIHOSTING_SYS_ELAPSED
: /* 0x30 */
1252 * Returns the number of elapsed target ticks since execution
1254 * Use SYS_TICKFREQ to determine the tick frequency.
1257 * On entry, the PARAMETER REGISTER points to a two-field data
1258 * block to be used for returning the number of elapsed ticks:
1259 * - field 1 The least significant field and is at the low address.
1260 * - field 2 The most significant field and is at the high address.
1263 * On entry the PARAMETER REGISTER points to a one-field data
1264 * block to be used for returning the number of elapsed ticks:
1265 * - field 1 The number of elapsed ticks as a 64-bit value.
1269 * - On success, the RETURN REGISTER contains 0, the PARAMETER
1270 * REGISTER is unchanged, and the data block pointed to by the
1271 * PARAMETER REGISTER is filled in with the number of elapsed
1273 * - On failure, the RETURN REGISTER contains -1, and the
1274 * PARAMETER REGISTER contains -1.
1276 * Note: Some semihosting implementations might not support this
1277 * semihosting operation, and they always return -1 in the
1281 case SEMIHOSTING_SYS_TICKFREQ
: /* 0x31 */
1283 * Returns the tick frequency.
1286 * The PARAMETER REGISTER must contain 0 on entry to this routine.
1289 * On exit, the RETURN REGISTER contains either:
1290 * - The number of ticks per second.
1291 * - –1 if the target does not know the value of one tick.
1293 * Note: Some semihosting implementations might not support
1294 * this semihosting operation, and they always return -1 in the
1298 case SEMIHOSTING_SYS_TMPNAM
: /* 0x0D */
1300 * Returns a temporary name for a file identified by a system
1304 * On entry, the PARAMETER REGISTER contains a pointer to a
1305 * three-word argument block:
1306 * - field 1 A pointer to a buffer.
1307 * - field 2 A target identifier for this filename. Its value
1308 * must be an integer in the range 0-255.
1309 * - field 3 Contains the length of the buffer. The length must
1310 * be at least the value of L_tmpnam on the host system.
1313 * On exit, the RETURN REGISTER contains:
1314 * - 0 if the call is successful.
1315 * - –1 if an error occurs.
1317 * The buffer pointed to by the PARAMETER REGISTER contains
1318 * the filename, prefixed with a suitable directory name.
1319 * If you use the same target identifier again, the same
1320 * filename is returned.
1322 * Note: The returned string must be null-terminated.
1326 fprintf(stderr
, "semihosting: unsupported call %#x\n",
1327 (unsigned) semihosting
->op
);
1328 semihosting
->result
= -1;
1329 semihosting
->sys_errno
= ENOTSUP
;
1332 if (!semihosting
->hit_fileio
) {
1333 retval
= semihosting
->post_result(target
);
1334 if (retval
!= ERROR_OK
) {
1335 LOG_ERROR("Failed to post semihosting result");
1343 /* -------------------------------------------------------------------------
1344 * Local functions. */
1346 static int semihosting_common_fileio_info(struct target
*target
,
1347 struct gdb_fileio_info
*fileio_info
)
1349 struct semihosting
*semihosting
= target
->semihosting
;
1354 * To avoid unnecessary duplication, semihosting prepares the
1355 * fileio_info structure out-of-band when the target halts. See
1356 * do_semihosting for more detail.
1358 if (!semihosting
->is_fileio
|| !semihosting
->hit_fileio
)
1364 static int semihosting_common_fileio_end(struct target
*target
, int result
,
1365 int fileio_errno
, bool ctrl_c
)
1367 struct gdb_fileio_info
*fileio_info
= target
->fileio_info
;
1368 struct semihosting
*semihosting
= target
->semihosting
;
1372 /* clear pending status */
1373 semihosting
->hit_fileio
= false;
1375 semihosting
->result
= result
;
1376 semihosting
->sys_errno
= fileio_errno
;
1379 * Some fileio results do not match up with what the semihosting
1380 * operation expects; for these operations, we munge the results
1383 switch (semihosting
->op
) {
1384 case SEMIHOSTING_SYS_WRITE
: /* 0x05 */
1386 semihosting
->result
= fileio_info
->param_3
;
1388 semihosting
->result
= 0;
1391 case SEMIHOSTING_SYS_READ
: /* 0x06 */
1392 if (result
== (int)fileio_info
->param_3
)
1393 semihosting
->result
= 0;
1395 semihosting
->result
= fileio_info
->param_3
;
1398 case SEMIHOSTING_SYS_SEEK
: /* 0x0a */
1400 semihosting
->result
= 0;
1404 return semihosting
->post_result(target
);
1408 * Read all fields of a command from target to buffer.
1410 static int semihosting_read_fields(struct target
*target
, size_t number
,
1413 struct semihosting
*semihosting
= target
->semihosting
;
1414 /* Use 4-byte multiples to trigger fast memory access. */
1415 return target_read_memory(target
, semihosting
->param
, 4,
1416 number
* (semihosting
->word_size_bytes
/ 4), fields
);
1420 * Write all fields of a command from buffer to target.
1422 static int semihosting_write_fields(struct target
*target
, size_t number
,
1425 struct semihosting
*semihosting
= target
->semihosting
;
1426 /* Use 4-byte multiples to trigger fast memory access. */
1427 return target_write_memory(target
, semihosting
->param
, 4,
1428 number
* (semihosting
->word_size_bytes
/ 4), fields
);
1432 * Extract a field from the buffer, considering register size and endianness.
1434 static uint64_t semihosting_get_field(struct target
*target
, size_t index
,
1437 struct semihosting
*semihosting
= target
->semihosting
;
1438 if (semihosting
->word_size_bytes
== 8)
1439 return target_buffer_get_u64(target
, fields
+ (index
* 8));
1441 return target_buffer_get_u32(target
, fields
+ (index
* 4));
1445 * Store a field in the buffer, considering register size and endianness.
1447 static void semihosting_set_field(struct target
*target
, uint64_t value
,
1451 struct semihosting
*semihosting
= target
->semihosting
;
1452 if (semihosting
->word_size_bytes
== 8)
1453 target_buffer_set_u64(target
, fields
+ (index
* 8), value
);
1455 target_buffer_set_u32(target
, fields
+ (index
* 4), value
);
1459 /* -------------------------------------------------------------------------
1460 * Common semihosting commands handlers. */
1462 __COMMAND_HANDLER(handle_common_semihosting_command
)
1464 struct target
*target
= get_current_target(CMD_CTX
);
1466 if (target
== NULL
) {
1467 LOG_ERROR("No target selected");
1471 struct semihosting
*semihosting
= target
->semihosting
;
1473 command_print(CMD_CTX
, "semihosting not supported for current target");
1480 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], is_active
);
1482 if (!target_was_examined(target
)) {
1483 LOG_ERROR("Target not examined yet");
1487 if (semihosting
&& semihosting
->setup(target
, is_active
) != ERROR_OK
) {
1488 LOG_ERROR("Failed to Configure semihosting");
1492 /* FIXME never let that "catch" be dropped! (???) */
1493 semihosting
->is_active
= is_active
;
1496 command_print(CMD_CTX
, "semihosting is %s",
1497 semihosting
->is_active
1498 ? "enabled" : "disabled");
1504 __COMMAND_HANDLER(handle_common_semihosting_fileio_command
)
1506 struct target
*target
= get_current_target(CMD_CTX
);
1508 if (target
== NULL
) {
1509 LOG_ERROR("No target selected");
1513 struct semihosting
*semihosting
= target
->semihosting
;
1515 command_print(CMD_CTX
, "semihosting not supported for current target");
1519 if (!semihosting
->is_active
) {
1520 command_print(CMD_CTX
, "semihosting not yet enabled for current target");
1525 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], semihosting
->is_fileio
);
1527 command_print(CMD_CTX
, "semihosting fileio is %s",
1528 semihosting
->is_fileio
1529 ? "enabled" : "disabled");
1534 __COMMAND_HANDLER(handle_common_semihosting_cmdline
)
1536 struct target
*target
= get_current_target(CMD_CTX
);
1539 if (target
== NULL
) {
1540 LOG_ERROR("No target selected");
1544 struct semihosting
*semihosting
= target
->semihosting
;
1546 command_print(CMD_CTX
, "semihosting not supported for current target");
1550 free(semihosting
->cmdline
);
1551 semihosting
->cmdline
= CMD_ARGC
> 0 ? strdup(CMD_ARGV
[0]) : NULL
;
1553 for (i
= 1; i
< CMD_ARGC
; i
++) {
1554 char *cmdline
= alloc_printf("%s %s", semihosting
->cmdline
, CMD_ARGV
[i
]);
1555 if (cmdline
== NULL
)
1557 free(semihosting
->cmdline
);
1558 semihosting
->cmdline
= cmdline
;
1561 command_print(CMD_CTX
, "semihosting command line is [%s]",
1562 semihosting
->cmdline
);
1567 __COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command
)
1569 struct target
*target
= get_current_target(CMD_CTX
);
1571 if (target
== NULL
) {
1572 LOG_ERROR("No target selected");
1576 struct semihosting
*semihosting
= target
->semihosting
;
1578 command_print(CMD_CTX
, "semihosting not supported for current target");
1582 if (!semihosting
->is_active
) {
1583 command_print(CMD_CTX
, "semihosting not yet enabled for current target");
1588 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], semihosting
->has_resumable_exit
);
1590 command_print(CMD_CTX
, "semihosting resumable exit is %s",
1591 semihosting
->has_resumable_exit
1592 ? "enabled" : "disabled");