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.
94 * @return An error status if there is a problem during initialization.
96 int semihosting_common_init(struct target
*target
, void *setup
,
101 target
->fileio_info
= malloc(sizeof(*target
->fileio_info
));
102 if (target
->fileio_info
== NULL
) {
103 LOG_ERROR("out of memory");
106 memset(target
->fileio_info
, 0, sizeof(*target
->fileio_info
));
108 struct semihosting
*semihosting
;
109 semihosting
= malloc(sizeof(*target
->semihosting
));
110 if (semihosting
== NULL
) {
111 LOG_ERROR("out of memory");
115 semihosting
->is_active
= false;
116 semihosting
->is_fileio
= false;
117 semihosting
->hit_fileio
= false;
118 semihosting
->is_resumable
= false;
119 semihosting
->has_resumable_exit
= false;
120 semihosting
->word_size_bytes
= 0;
121 semihosting
->op
= -1;
122 semihosting
->param
= 0;
123 semihosting
->result
= -1;
124 semihosting
->sys_errno
= -1;
125 semihosting
->cmdline
= NULL
;
127 /* If possible, update it in setup(). */
128 semihosting
->setup_time
= clock();
130 semihosting
->setup
= setup
;
131 semihosting
->post_result
= post_result
;
133 target
->semihosting
= semihosting
;
135 target
->type
->get_gdb_fileio_info
= semihosting_common_fileio_info
;
136 target
->type
->gdb_fileio_end
= semihosting_common_fileio_end
;
142 * Portable implementation of ARM semihosting calls.
143 * Performs the currently pending semihosting operation
144 * encoded in target->semihosting.
146 int semihosting_common(struct target
*target
)
148 struct semihosting
*semihosting
= target
->semihosting
;
150 /* Silently ignore if the semihosting field was not set. */
154 struct gdb_fileio_info
*fileio_info
= target
->fileio_info
;
157 * By default return an error.
158 * The actual result must be set by each function
160 semihosting
->result
= -1;
162 /* Most operations are resumable, except the two exit calls. */
163 semihosting
->is_resumable
= true;
167 /* Enough space to hold 4 long words. */
170 LOG_DEBUG("op=0x%x, param=0x%" PRIx64
, (int)semihosting
->op
,
173 switch (semihosting
->op
) {
175 case SEMIHOSTING_SYS_CLOCK
: /* 0x10 */
177 * Returns the number of centiseconds (hundredths of a second)
178 * since the execution started.
180 * Values returned can be of limited use for some benchmarking
181 * purposes because of communication overhead or other
182 * agent-specific factors. For example, with a debug hardware
183 * unit the request is passed back to the host for execution.
184 * This can lead to unpredictable delays in transmission and
185 * process scheduling.
187 * Use this function to calculate time intervals, by calculating
188 * differences between intervals with and without the code
189 * sequence to be timed.
192 * The PARAMETER REGISTER must contain 0. There are no other
196 * On exit, the RETURN REGISTER contains:
197 * - The number of centiseconds since some arbitrary start
198 * point, if the call is successful.
199 * - –1 if the call is not successful. For example, because
200 * of a communications error.
203 clock_t delta
= clock() - semihosting
->setup_time
;
205 semihosting
->result
= delta
/ (CLOCKS_PER_SEC
/ 100);
209 case SEMIHOSTING_SYS_CLOSE
: /* 0x02 */
211 * Closes a file on the host system. The handle must reference
212 * a file that was opened with SYS_OPEN.
215 * On entry, the PARAMETER REGISTER contains a pointer to a
216 * one-field argument block:
217 * - field 1 Contains a handle for an open file.
220 * On exit, the RETURN REGISTER contains:
221 * - 0 if the call is successful
222 * - –1 if the call is not successful.
224 retval
= semihosting_read_fields(target
, 1, fields
);
225 if (retval
!= ERROR_OK
)
228 int fd
= semihosting_get_field(target
, 0, fields
);
229 if (semihosting
->is_fileio
) {
230 if (fd
== 0 || fd
== 1 || fd
== 2) {
231 semihosting
->result
= 0;
234 semihosting
->hit_fileio
= true;
235 fileio_info
->identifier
= "close";
236 fileio_info
->param_1
= fd
;
238 semihosting
->result
= close(fd
);
239 semihosting
->sys_errno
= errno
;
241 LOG_DEBUG("close(%d)=%d", fd
, (int)semihosting
->result
);
246 case SEMIHOSTING_SYS_ERRNO
: /* 0x13 */
248 * Returns the value of the C library errno variable that is
249 * associated with the semihosting implementation. The errno
250 * variable can be set by a number of C library semihosted
251 * functions, including:
259 * Whether errno is set or not, and to what value, is entirely
260 * host-specific, except where the ISO C standard defines the
264 * There are no parameters. The PARAMETER REGISTER must be 0.
267 * On exit, the RETURN REGISTER contains the value of the C
268 * library errno variable.
270 semihosting
->result
= semihosting
->sys_errno
;
273 case SEMIHOSTING_SYS_EXIT
: /* 0x18 */
275 * Note: SYS_EXIT was called angel_SWIreason_ReportException in
276 * previous versions of the documentation.
278 * An application calls this operation to report an exception
279 * to the debugger directly. The most common use is to report
280 * that execution has completed, using ADP_Stopped_ApplicationExit.
282 * Note: This semihosting operation provides no means for 32-bit
283 * callers to indicate an application exit with a specified exit
284 * code. Semihosting callers may prefer to check for the presence
285 * of the SH_EXT_EXTENDED_REPORT_EXCEPTION extension and use
286 * the SYS_REPORT_EXCEPTION_EXTENDED operation instead, if it
290 * On entry, the PARAMETER register is set to a reason code
291 * describing the cause of the trap. Not all semihosting client
292 * implementations will necessarily trap every corresponding
293 * event. Important reason codes are:
295 * - ADP_Stopped_ApplicationExit 0x20026
296 * - ADP_Stopped_RunTimeErrorUnknown 0x20023
299 * On entry, the PARAMETER REGISTER contains a pointer to a
300 * two-field argument block:
301 * - field 1 The exception type, which is one of the set of
302 * reason codes in the above tables.
303 * - field 2 A subcode, whose meaning depends on the reason
305 * In particular, if field 1 is ADP_Stopped_ApplicationExit
306 * then field 2 is an exit status code, as passed to the C
307 * standard library exit() function. A simulator receiving
308 * this request must notify a connected debugger, if present,
309 * and then exit with the specified status.
312 * No return is expected from these calls. However, it is
313 * possible for the debugger to request that the application
314 * continues by performing an RDI_Execute request or equivalent.
315 * In this case, execution continues with the registers as they
316 * were on entry to the operation, or as subsequently modified
319 if (semihosting
->word_size_bytes
== 8) {
320 retval
= semihosting_read_fields(target
, 2, fields
);
321 if (retval
!= ERROR_OK
)
324 int type
= semihosting_get_field(target
, 0, fields
);
325 int code
= semihosting_get_field(target
, 1, fields
);
327 if (type
== ADP_STOPPED_APPLICATION_EXIT
) {
328 if (!gdb_actual_connections
)
332 "semihosting: *** application exited with %d ***\n",
337 "semihosting: application exception %#x\n",
342 if (semihosting
->param
== ADP_STOPPED_APPLICATION_EXIT
) {
343 if (!gdb_actual_connections
)
347 "semihosting: *** application exited normally ***\n");
349 } else if (semihosting
->param
== ADP_STOPPED_RUN_TIME_ERROR
) {
350 /* Chosen more or less arbitrarily to have a nicer message,
351 * otherwise all other return the same exit code 1. */
352 if (!gdb_actual_connections
)
356 "semihosting: *** application exited with error ***\n");
359 if (!gdb_actual_connections
)
363 "semihosting: application exception %#x\n",
364 (unsigned) semihosting
->param
);
368 if (!semihosting
->has_resumable_exit
) {
369 semihosting
->is_resumable
= false;
370 return target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
374 case SEMIHOSTING_SYS_EXIT_EXTENDED
: /* 0x20 */
376 * This operation is only supported if the semihosting extension
377 * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is
378 * reported using feature byte 0, bit 0. If this extension is
379 * supported, then the implementation provides a means to
380 * report a normal exit with a nonzero exit status in both 32-bit
381 * and 64-bit semihosting APIs.
383 * The implementation must provide the semihosting call
384 * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs.
386 * SYS_EXIT_EXTENDED is used by an application to report an
387 * exception or exit to the debugger directly. The most common
388 * use is to report that execution has completed, using
389 * ADP_Stopped_ApplicationExit.
392 * On entry, the PARAMETER REGISTER contains a pointer to a
393 * two-field argument block:
394 * - field 1 The exception type, which should be one of the set
395 * of reason codes that are documented for the SYS_EXIT
396 * (0x18) call. For example, ADP_Stopped_ApplicationExit.
397 * - field 2 A subcode, whose meaning depends on the reason
398 * code in field 1. In particular, if field 1 is
399 * ADP_Stopped_ApplicationExit then field 2 is an exit status
400 * code, as passed to the C standard library exit() function.
401 * A simulator receiving this request must notify a connected
402 * debugger, if present, and then exit with the specified status.
405 * No return is expected from these calls.
407 * For the A64 API, this call is identical to the behavior of
408 * the mandatory SYS_EXIT (0x18) call. If this extension is
409 * supported, then both calls must be implemented.
411 retval
= semihosting_read_fields(target
, 2, fields
);
412 if (retval
!= ERROR_OK
)
415 int type
= semihosting_get_field(target
, 0, fields
);
416 int code
= semihosting_get_field(target
, 1, fields
);
418 if (type
== ADP_STOPPED_APPLICATION_EXIT
) {
419 if (!gdb_actual_connections
)
423 "semihosting: *** application exited with %d ***\n",
427 fprintf(stderr
, "semihosting: exception %#x\n",
431 if (!semihosting
->has_resumable_exit
) {
432 semihosting
->is_resumable
= false;
433 return target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
437 case SEMIHOSTING_SYS_FLEN
: /* 0x0C */
439 * Returns the length of a specified file.
442 * On entry, the PARAMETER REGISTER contains a pointer to a
443 * one-field argument block:
444 * - field 1 A handle for a previously opened, seekable file
448 * On exit, the RETURN REGISTER contains:
449 * - The current length of the file object, if the call is
451 * - –1 if an error occurs.
453 if (semihosting
->is_fileio
) {
454 semihosting
->result
= -1;
455 semihosting
->sys_errno
= EINVAL
;
457 retval
= semihosting_read_fields(target
, 1, fields
);
458 if (retval
!= ERROR_OK
)
461 int fd
= semihosting_get_field(target
, 0, fields
);
463 semihosting
->result
= fstat(fd
, &buf
);
464 if (semihosting
->result
== -1) {
465 semihosting
->sys_errno
= errno
;
466 LOG_DEBUG("fstat(%d)=%d", fd
, (int)semihosting
->result
);
469 LOG_DEBUG("fstat(%d)=%d", fd
, (int)semihosting
->result
);
470 semihosting
->result
= buf
.st_size
;
474 case SEMIHOSTING_SYS_GET_CMDLINE
: /* 0x15 */
476 * Returns the command line that is used for the call to the
477 * executable, that is, argc and argv.
480 * On entry, the PARAMETER REGISTER points to a two-field data
481 * block to be used for returning the command string and its length:
482 * - field 1 A pointer to a buffer of at least the size that is
483 * specified in field 2.
484 * - field 2 The length of the buffer in bytes.
488 * If the call is successful, then the RETURN REGISTER contains 0,
489 * the PARAMETER REGISTER is unchanged, and the data block is
490 * updated as follows:
491 * - field 1 A pointer to a null-terminated string of the command
493 * - field 2 The length of the string in bytes.
494 * If the call is not successful, then the RETURN REGISTER
497 * Note: The semihosting implementation might impose limits on
498 * the maximum length of the string that can be transferred.
499 * However, the implementation must be able to support a
500 * command-line length of at least 80 bytes.
502 retval
= semihosting_read_fields(target
, 2, fields
);
503 if (retval
!= ERROR_OK
)
506 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
507 size_t size
= semihosting_get_field(target
, 1, fields
);
509 char *arg
= semihosting
->cmdline
!= NULL
?
510 semihosting
->cmdline
: "";
511 uint32_t len
= strlen(arg
) + 1;
513 semihosting
->result
= -1;
515 semihosting_set_field(target
, len
, 1, fields
);
516 retval
= target_write_buffer(target
, addr
, len
,
518 if (retval
!= ERROR_OK
)
520 semihosting
->result
= 0;
522 retval
= semihosting_write_fields(target
, 2, fields
);
523 if (retval
!= ERROR_OK
)
526 LOG_DEBUG("SYS_GET_CMDLINE=[%s],%d", arg
,
527 (int)semihosting
->result
);
531 case SEMIHOSTING_SYS_HEAPINFO
: /* 0x16 */
533 * Returns the system stack and heap parameters.
536 * On entry, the PARAMETER REGISTER contains the address of a
537 * pointer to a four-field data block. The contents of the data
538 * block are filled by the function. The following C-like
539 * pseudocode describes the layout of the block:
548 * On exit, the PARAMETER REGISTER is unchanged and the data
549 * block has been updated.
551 retval
= semihosting_read_fields(target
, 1, fields
);
552 if (retval
!= ERROR_OK
)
555 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
556 /* tell the remote we have no idea */
557 memset(fields
, 0, 4 * semihosting
->word_size_bytes
);
558 retval
= target_write_memory(target
, addr
, 4,
559 semihosting
->word_size_bytes
,
561 if (retval
!= ERROR_OK
)
563 semihosting
->result
= 0;
567 case SEMIHOSTING_SYS_ISERROR
: /* 0x08 */
569 * Determines whether the return code from another semihosting
570 * call is an error status or not.
572 * This call is passed a parameter block containing the error
576 * On entry, the PARAMETER REGISTER contains a pointer to a
577 * one-field data block:
578 * - field 1 The required status word to check.
581 * On exit, the RETURN REGISTER contains:
582 * - 0 if the status field is not an error indication
583 * - A nonzero value if the status field is an error indication.
585 retval
= semihosting_read_fields(target
, 1, fields
);
586 if (retval
!= ERROR_OK
)
589 uint64_t code
= semihosting_get_field(target
, 0, fields
);
590 semihosting
->result
= (code
!= 0);
593 case SEMIHOSTING_SYS_ISTTY
: /* 0x09 */
595 * Checks whether a file is connected to an interactive device.
598 * On entry, the PARAMETER REGISTER contains a pointer to a
599 * one-field argument block:
600 * field 1 A handle for a previously opened file object.
603 * On exit, the RETURN REGISTER contains:
604 * - 1 if the handle identifies an interactive device.
605 * - 0 if the handle identifies a file.
606 * - A value other than 1 or 0 if an error occurs.
608 if (semihosting
->is_fileio
) {
609 semihosting
->hit_fileio
= true;
610 fileio_info
->identifier
= "isatty";
611 fileio_info
->param_1
= semihosting
->param
;
613 retval
= semihosting_read_fields(target
, 1, fields
);
614 if (retval
!= ERROR_OK
)
616 int fd
= semihosting_get_field(target
, 0, fields
);
617 semihosting
->result
= isatty(fd
);
618 LOG_DEBUG("isatty(%d)=%d", fd
, (int)semihosting
->result
);
622 case SEMIHOSTING_SYS_OPEN
: /* 0x01 */
624 * Opens a file on the host system.
626 * The file path is specified either as relative to the current
627 * directory of the host process, or absolute, using the path
628 * conventions of the host operating system.
630 * Semihosting implementations must support opening the special
631 * path name :semihosting-features as part of the semihosting
632 * extensions reporting mechanism.
634 * ARM targets interpret the special path name :tt as meaning
635 * the console input stream, for an open-read or the console
636 * output stream, for an open-write. Opening these streams is
637 * performed as part of the standard startup code for those
638 * applications that reference the C stdio streams. The
639 * semihosting extension SH_EXT_STDOUT_STDERR allows the
640 * semihosting caller to open separate output streams
641 * corresponding to stdout and stderr. This extension is
642 * reported using feature byte 0, bit 1. Use SYS_OPEN with
643 * the special path name :semihosting-features to access the
646 * If this extension is supported, the implementation must
647 * support the following additional semantics to SYS_OPEN:
648 * - If the special path name :tt is opened with an fopen
649 * mode requesting write access (w, wb, w+, or w+b), then
650 * this is a request to open stdout.
651 * - If the special path name :tt is opened with a mode
652 * requesting append access (a, ab, a+, or a+b), then this is
653 * a request to open stderr.
656 * On entry, the PARAMETER REGISTER contains a pointer to a
657 * three-field argument block:
658 * - field 1 A pointer to a null-terminated string containing
659 * a file or device name.
660 * - field 2 An integer that specifies the file opening mode.
661 * - field 3 An integer that gives the length of the string
662 * pointed to by field 1.
664 * The length does not include the terminating null character
665 * that must be present.
668 * On exit, the RETURN REGISTER contains:
669 * - A nonzero handle if the call is successful.
670 * - –1 if the call is not successful.
672 retval
= semihosting_read_fields(target
, 3, fields
);
673 if (retval
!= ERROR_OK
)
676 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
677 uint32_t mode
= semihosting_get_field(target
, 1, fields
);
678 size_t len
= semihosting_get_field(target
, 2, fields
);
681 semihosting
->result
= -1;
682 semihosting
->sys_errno
= EINVAL
;
685 uint8_t *fn
= malloc(len
+1);
687 semihosting
->result
= -1;
688 semihosting
->sys_errno
= ENOMEM
;
690 retval
= target_read_memory(target
, addr
, 1, len
, fn
);
691 if (retval
!= ERROR_OK
) {
696 /* TODO: implement the :semihosting-features special file.
698 if (semihosting
->is_fileio
) {
699 if (strcmp((char *)fn
, ":semihosting-features") == 0) {
700 semihosting
->result
= -1;
701 semihosting
->sys_errno
= EINVAL
;
702 } else if (strcmp((char *)fn
, ":tt") == 0) {
704 semihosting
->result
= 0;
706 semihosting
->result
= 1;
708 semihosting
->result
= 2;
710 semihosting
->result
= -1;
712 semihosting
->hit_fileio
= true;
713 fileio_info
->identifier
= "open";
714 fileio_info
->param_1
= addr
;
715 fileio_info
->param_2
= len
;
716 fileio_info
->param_3
= open_modeflags
[mode
];
717 fileio_info
->param_4
= 0644;
720 if (strcmp((char *)fn
, ":tt") == 0) {
722 * - 0-3 ("r") for stdin,
723 * - 4-7 ("w") for stdout,
724 * - 8-11 ("a") for stderr */
726 semihosting
->result
= dup(
728 semihosting
->sys_errno
= errno
;
729 LOG_DEBUG("dup(STDIN)=%d",
730 (int)semihosting
->result
);
731 } else if (mode
< 8) {
732 semihosting
->result
= dup(
734 semihosting
->sys_errno
= errno
;
735 LOG_DEBUG("dup(STDOUT)=%d",
736 (int)semihosting
->result
);
738 semihosting
->result
= dup(
740 semihosting
->sys_errno
= errno
;
741 LOG_DEBUG("dup(STDERR)=%d",
742 (int)semihosting
->result
);
745 /* cygwin requires the permission setting
746 * otherwise it will fail to reopen a previously
748 semihosting
->result
= open((char *)fn
,
749 open_modeflags
[mode
],
751 semihosting
->sys_errno
= errno
;
752 LOG_DEBUG("open('%s')=%d", fn
,
753 (int)semihosting
->result
);
761 case SEMIHOSTING_SYS_READ
: /* 0x06 */
763 * Reads the contents of a file into a buffer. The file position
764 * is specified either:
765 * - Explicitly by a SYS_SEEK.
766 * - Implicitly one byte beyond the previous SYS_READ or
769 * The file position is at the start of the file when it is
770 * opened, and is lost when the file is closed. Perform the
771 * file operation as a single action whenever possible. For
772 * example, do not split a read of 16KB into four 4KB chunks
773 * unless there is no alternative.
776 * On entry, the PARAMETER REGISTER contains a pointer to a
777 * three-field data block:
778 * - field 1 Contains a handle for a file previously opened
780 * - field 2 Points to a buffer.
781 * - field 3 Contains the number of bytes to read to the buffer
785 * On exit, the RETURN REGISTER contains the number of bytes not
786 * filled in the buffer (buffer_length - bytes_read) as follows:
787 * - If the RETURN REGISTER is 0, the entire buffer was
788 * successfully filled.
789 * - If the RETURN REGISTER is the same as field 3, no bytes
790 * were read (EOF can be assumed).
791 * - If the RETURN REGISTER contains a value smaller than
792 * field 3, the read succeeded but the buffer was only partly
793 * filled. For interactive devices, this is the most common
796 retval
= semihosting_read_fields(target
, 3, fields
);
797 if (retval
!= ERROR_OK
)
800 int fd
= semihosting_get_field(target
, 0, fields
);
801 uint64_t addr
= semihosting_get_field(target
, 1, fields
);
802 size_t len
= semihosting_get_field(target
, 2, fields
);
803 if (semihosting
->is_fileio
) {
804 semihosting
->hit_fileio
= true;
805 fileio_info
->identifier
= "read";
806 fileio_info
->param_1
= fd
;
807 fileio_info
->param_2
= addr
;
808 fileio_info
->param_3
= len
;
810 uint8_t *buf
= malloc(len
);
812 semihosting
->result
= -1;
813 semihosting
->sys_errno
= ENOMEM
;
815 semihosting
->result
= read(fd
, buf
, len
);
816 semihosting
->sys_errno
= errno
;
817 LOG_DEBUG("read(%d, 0x%" PRIx64
", %zu)=%d",
821 (int)semihosting
->result
);
822 if (semihosting
->result
>= 0) {
823 retval
= target_write_buffer(target
, addr
,
826 if (retval
!= ERROR_OK
) {
830 /* the number of bytes NOT filled in */
831 semihosting
->result
= len
-
840 case SEMIHOSTING_SYS_READC
: /* 0x07 */
842 * Reads a byte from the console.
845 * The PARAMETER REGISTER must contain 0. There are no other
846 * parameters or values possible.
849 * On exit, the RETURN REGISTER contains the byte read from
852 if (semihosting
->is_fileio
) {
853 LOG_ERROR("SYS_READC not supported by semihosting fileio");
856 semihosting
->result
= getchar();
857 LOG_DEBUG("getchar()=%d", (int)semihosting
->result
);
860 case SEMIHOSTING_SYS_REMOVE
: /* 0x0E */
862 * Deletes a specified file on the host filing system.
865 * On entry, the PARAMETER REGISTER contains a pointer to a
866 * two-field argument block:
867 * - field 1 Points to a null-terminated string that gives the
868 * path name of the file to be deleted.
869 * - field 2 The length of the string.
872 * On exit, the RETURN REGISTER contains:
873 * - 0 if the delete is successful
874 * - A nonzero, host-specific error code if the delete fails.
876 retval
= semihosting_read_fields(target
, 2, fields
);
877 if (retval
!= ERROR_OK
)
880 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
881 size_t len
= semihosting_get_field(target
, 1, fields
);
882 if (semihosting
->is_fileio
) {
883 semihosting
->hit_fileio
= true;
884 fileio_info
->identifier
= "unlink";
885 fileio_info
->param_1
= addr
;
886 fileio_info
->param_2
= len
;
888 uint8_t *fn
= malloc(len
+1);
890 semihosting
->result
= -1;
891 semihosting
->sys_errno
= ENOMEM
;
894 target_read_memory(target
, addr
, 1, len
,
896 if (retval
!= ERROR_OK
) {
901 semihosting
->result
= remove((char *)fn
);
902 semihosting
->sys_errno
= errno
;
903 LOG_DEBUG("remove('%s')=%d", fn
,
904 (int)semihosting
->result
);
912 case SEMIHOSTING_SYS_RENAME
: /* 0x0F */
914 * Renames a specified file.
917 * On entry, the PARAMETER REGISTER contains a pointer to a
918 * four-field data block:
919 * - field 1 A pointer to the name of the old file.
920 * - field 2 The length of the old filename.
921 * - field 3 A pointer to the new filename.
922 * - field 4 The length of the new filename. Both strings are
926 * On exit, the RETURN REGISTER contains:
927 * - 0 if the rename is successful.
928 * - A nonzero, host-specific error code if the rename fails.
930 retval
= semihosting_read_fields(target
, 4, fields
);
931 if (retval
!= ERROR_OK
)
934 uint64_t addr1
= semihosting_get_field(target
, 0, fields
);
935 size_t len1
= semihosting_get_field(target
, 1, fields
);
936 uint64_t addr2
= semihosting_get_field(target
, 2, fields
);
937 size_t len2
= semihosting_get_field(target
, 3, fields
);
938 if (semihosting
->is_fileio
) {
939 semihosting
->hit_fileio
= true;
940 fileio_info
->identifier
= "rename";
941 fileio_info
->param_1
= addr1
;
942 fileio_info
->param_2
= len1
;
943 fileio_info
->param_3
= addr2
;
944 fileio_info
->param_4
= len2
;
946 uint8_t *fn1
= malloc(len1
+1);
947 uint8_t *fn2
= malloc(len2
+1);
951 semihosting
->result
= -1;
952 semihosting
->sys_errno
= ENOMEM
;
954 retval
= target_read_memory(target
, addr1
, 1, len1
,
956 if (retval
!= ERROR_OK
) {
961 retval
= target_read_memory(target
, addr2
, 1, len2
,
963 if (retval
!= ERROR_OK
) {
970 semihosting
->result
= rename((char *)fn1
,
972 semihosting
->sys_errno
= errno
;
973 LOG_DEBUG("rename('%s', '%s')=%d", fn1
, fn2
,
974 (int)semihosting
->result
);
983 case SEMIHOSTING_SYS_SEEK
: /* 0x0A */
985 * Seeks to a specified position in a file using an offset
986 * specified from the start of the file. The file is assumed
987 * to be a byte array and the offset is given in bytes.
990 * On entry, the PARAMETER REGISTER contains a pointer to a
991 * two-field data block:
992 * - field 1 A handle for a seekable file object.
993 * - field 2 The absolute byte position to seek to.
996 * On exit, the RETURN REGISTER contains:
997 * - 0 if the request is successful.
998 * - A negative value if the request is not successful.
999 * Use SYS_ERRNO to read the value of the host errno variable
1000 * describing the error.
1002 * Note: The effect of seeking outside the current extent of
1003 * the file object is undefined.
1005 retval
= semihosting_read_fields(target
, 2, fields
);
1006 if (retval
!= ERROR_OK
)
1009 int fd
= semihosting_get_field(target
, 0, fields
);
1010 off_t pos
= semihosting_get_field(target
, 1, fields
);
1011 if (semihosting
->is_fileio
) {
1012 semihosting
->hit_fileio
= true;
1013 fileio_info
->identifier
= "lseek";
1014 fileio_info
->param_1
= fd
;
1015 fileio_info
->param_2
= pos
;
1016 fileio_info
->param_3
= SEEK_SET
;
1018 semihosting
->result
= lseek(fd
, pos
, SEEK_SET
);
1019 semihosting
->sys_errno
= errno
;
1020 LOG_DEBUG("lseek(%d, %d)=%d", fd
, (int)pos
,
1021 (int)semihosting
->result
);
1022 if (semihosting
->result
== pos
)
1023 semihosting
->result
= 0;
1028 case SEMIHOSTING_SYS_SYSTEM
: /* 0x12 */
1030 * Passes a command to the host command-line interpreter.
1031 * This enables you to execute a system command such as dir,
1032 * ls, or pwd. The terminal I/O is on the host, and is not
1033 * visible to the target.
1036 * On entry, the PARAMETER REGISTER contains a pointer to a
1037 * two-field argument block:
1038 * - field 1 Points to a string to be passed to the host
1039 * command-line interpreter.
1040 * - field 2 The length of the string.
1043 * On exit, the RETURN REGISTER contains the return status.
1046 /* Provide SYS_SYSTEM functionality. Uses the
1047 * libc system command, there may be a reason *NOT*
1048 * to use this, but as I can't think of one, I
1049 * implemented it this way.
1051 retval
= semihosting_read_fields(target
, 2, fields
);
1052 if (retval
!= ERROR_OK
)
1055 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
1056 size_t len
= semihosting_get_field(target
, 1, fields
);
1057 if (semihosting
->is_fileio
) {
1058 semihosting
->hit_fileio
= true;
1059 fileio_info
->identifier
= "system";
1060 fileio_info
->param_1
= addr
;
1061 fileio_info
->param_2
= len
;
1063 uint8_t *cmd
= malloc(len
+1);
1065 semihosting
->result
= -1;
1066 semihosting
->sys_errno
= ENOMEM
;
1068 retval
= target_read_memory(target
,
1073 if (retval
!= ERROR_OK
) {
1078 semihosting
->result
= system(
1080 LOG_DEBUG("system('%s')=%d",
1082 (int)semihosting
->result
);
1091 case SEMIHOSTING_SYS_TIME
: /* 0x11 */
1093 * Returns the number of seconds since 00:00 January 1, 1970.
1094 * This value is real-world time, regardless of any debug agent
1098 * There are no parameters.
1101 * On exit, the RETURN REGISTER contains the number of seconds.
1103 semihosting
->result
= time(NULL
);
1106 case SEMIHOSTING_SYS_WRITE
: /* 0x05 */
1108 * Writes the contents of a buffer to a specified file at the
1109 * current file position. The file position is specified either:
1110 * - Explicitly, by a SYS_SEEK.
1111 * - Implicitly as one byte beyond the previous SYS_READ or
1112 * SYS_WRITE request.
1114 * The file position is at the start of the file when the file
1115 * is opened, and is lost when the file is closed.
1117 * Perform the file operation as a single action whenever
1118 * possible. For example, do not split a write of 16KB into
1119 * four 4KB chunks unless there is no alternative.
1122 * On entry, the PARAMETER REGISTER contains a pointer to a
1123 * three-field data block:
1124 * - field 1 Contains a handle for a file previously opened
1126 * - field 2 Points to the memory containing the data to be written.
1127 * - field 3 Contains the number of bytes to be written from
1128 * the buffer to the file.
1131 * On exit, the RETURN REGISTER contains:
1132 * - 0 if the call is successful.
1133 * - The number of bytes that are not written, if there is an error.
1135 retval
= semihosting_read_fields(target
, 3, fields
);
1136 if (retval
!= ERROR_OK
)
1139 int fd
= semihosting_get_field(target
, 0, fields
);
1140 uint64_t addr
= semihosting_get_field(target
, 1, fields
);
1141 size_t len
= semihosting_get_field(target
, 2, fields
);
1142 if (semihosting
->is_fileio
) {
1143 semihosting
->hit_fileio
= true;
1144 fileio_info
->identifier
= "write";
1145 fileio_info
->param_1
= fd
;
1146 fileio_info
->param_2
= addr
;
1147 fileio_info
->param_3
= len
;
1149 uint8_t *buf
= malloc(len
);
1151 semihosting
->result
= -1;
1152 semihosting
->sys_errno
= ENOMEM
;
1154 retval
= target_read_buffer(target
, addr
, len
, buf
);
1155 if (retval
!= ERROR_OK
) {
1159 semihosting
->result
= write(fd
, buf
, len
);
1160 semihosting
->sys_errno
= errno
;
1161 LOG_DEBUG("write(%d, 0x%" PRIx64
", %zu)=%d",
1165 (int)semihosting
->result
);
1166 if (semihosting
->result
>= 0) {
1167 /* The number of bytes that are NOT written.
1169 semihosting
->result
= len
-
1170 semihosting
->result
;
1179 case SEMIHOSTING_SYS_WRITEC
: /* 0x03 */
1181 * Writes a character byte, pointed to by the PARAMETER REGISTER,
1182 * to the debug channel. When executed under a semihosting
1183 * debugger, the character appears on the host debugger console.
1186 * On entry, the PARAMETER REGISTER contains a pointer to the
1190 * None. The RETURN REGISTER is corrupted.
1192 if (semihosting
->is_fileio
) {
1193 semihosting
->hit_fileio
= true;
1194 fileio_info
->identifier
= "write";
1195 fileio_info
->param_1
= 1;
1196 fileio_info
->param_2
= semihosting
->param
;
1197 fileio_info
->param_3
= 1;
1199 uint64_t addr
= semihosting
->param
;
1201 retval
= target_read_memory(target
, addr
, 1, 1, &c
);
1202 if (retval
!= ERROR_OK
)
1205 semihosting
->result
= 0;
1209 case SEMIHOSTING_SYS_WRITE0
: /* 0x04 */
1211 * Writes a null-terminated string to the debug channel.
1212 * When executed under a semihosting debugger, the characters
1213 * appear on the host debugger console.
1216 * On entry, the PARAMETER REGISTER contains a pointer to the
1217 * first byte of the string.
1220 * None. The RETURN REGISTER is corrupted.
1222 if (semihosting
->is_fileio
) {
1224 uint64_t addr
= semihosting
->param
;
1227 retval
= target_read_memory(target
, addr
, 1, 1, &c
);
1228 if (retval
!= ERROR_OK
)
1234 semihosting
->hit_fileio
= true;
1235 fileio_info
->identifier
= "write";
1236 fileio_info
->param_1
= 1;
1237 fileio_info
->param_2
= semihosting
->param
;
1238 fileio_info
->param_3
= count
;
1240 uint64_t addr
= semihosting
->param
;
1243 retval
= target_read_memory(target
, addr
++, 1, 1, &c
);
1244 if (retval
!= ERROR_OK
)
1250 semihosting
->result
= 0;
1254 case SEMIHOSTING_SYS_ELAPSED
: /* 0x30 */
1256 * Returns the number of elapsed target ticks since execution
1258 * Use SYS_TICKFREQ to determine the tick frequency.
1261 * On entry, the PARAMETER REGISTER points to a two-field data
1262 * block to be used for returning the number of elapsed ticks:
1263 * - field 1 The least significant field and is at the low address.
1264 * - field 2 The most significant field and is at the high address.
1267 * On entry the PARAMETER REGISTER points to a one-field data
1268 * block to be used for returning the number of elapsed ticks:
1269 * - field 1 The number of elapsed ticks as a 64-bit value.
1273 * - On success, the RETURN REGISTER contains 0, the PARAMETER
1274 * REGISTER is unchanged, and the data block pointed to by the
1275 * PARAMETER REGISTER is filled in with the number of elapsed
1277 * - On failure, the RETURN REGISTER contains -1, and the
1278 * PARAMETER REGISTER contains -1.
1280 * Note: Some semihosting implementations might not support this
1281 * semihosting operation, and they always return -1 in the
1285 case SEMIHOSTING_SYS_TICKFREQ
: /* 0x31 */
1287 * Returns the tick frequency.
1290 * The PARAMETER REGISTER must contain 0 on entry to this routine.
1293 * On exit, the RETURN REGISTER contains either:
1294 * - The number of ticks per second.
1295 * - –1 if the target does not know the value of one tick.
1297 * Note: Some semihosting implementations might not support
1298 * this semihosting operation, and they always return -1 in the
1302 case SEMIHOSTING_SYS_TMPNAM
: /* 0x0D */
1304 * Returns a temporary name for a file identified by a system
1308 * On entry, the PARAMETER REGISTER contains a pointer to a
1309 * three-word argument block:
1310 * - field 1 A pointer to a buffer.
1311 * - field 2 A target identifier for this filename. Its value
1312 * must be an integer in the range 0-255.
1313 * - field 3 Contains the length of the buffer. The length must
1314 * be at least the value of L_tmpnam on the host system.
1317 * On exit, the RETURN REGISTER contains:
1318 * - 0 if the call is successful.
1319 * - –1 if an error occurs.
1321 * The buffer pointed to by the PARAMETER REGISTER contains
1322 * the filename, prefixed with a suitable directory name.
1323 * If you use the same target identifier again, the same
1324 * filename is returned.
1326 * Note: The returned string must be null-terminated.
1330 fprintf(stderr
, "semihosting: unsupported call %#x\n",
1331 (unsigned) semihosting
->op
);
1332 semihosting
->result
= -1;
1333 semihosting
->sys_errno
= ENOTSUP
;
1336 if (!semihosting
->hit_fileio
) {
1337 retval
= semihosting
->post_result(target
);
1338 if (retval
!= ERROR_OK
) {
1339 LOG_ERROR("Failed to post semihosting result");
1347 /* -------------------------------------------------------------------------
1348 * Local functions. */
1350 static int semihosting_common_fileio_info(struct target
*target
,
1351 struct gdb_fileio_info
*fileio_info
)
1353 struct semihosting
*semihosting
= target
->semihosting
;
1358 * To avoid unnecessary duplication, semihosting prepares the
1359 * fileio_info structure out-of-band when the target halts. See
1360 * do_semihosting for more detail.
1362 if (!semihosting
->is_fileio
|| !semihosting
->hit_fileio
)
1368 static int semihosting_common_fileio_end(struct target
*target
, int result
,
1369 int fileio_errno
, bool ctrl_c
)
1371 struct gdb_fileio_info
*fileio_info
= target
->fileio_info
;
1372 struct semihosting
*semihosting
= target
->semihosting
;
1376 /* clear pending status */
1377 semihosting
->hit_fileio
= false;
1379 semihosting
->result
= result
;
1380 semihosting
->sys_errno
= fileio_errno
;
1383 * Some fileio results do not match up with what the semihosting
1384 * operation expects; for these operations, we munge the results
1387 switch (semihosting
->op
) {
1388 case SEMIHOSTING_SYS_WRITE
: /* 0x05 */
1390 semihosting
->result
= fileio_info
->param_3
;
1392 semihosting
->result
= 0;
1395 case SEMIHOSTING_SYS_READ
: /* 0x06 */
1396 if (result
== (int)fileio_info
->param_3
)
1397 semihosting
->result
= 0;
1399 semihosting
->result
= fileio_info
->param_3
;
1402 case SEMIHOSTING_SYS_SEEK
: /* 0x0a */
1404 semihosting
->result
= 0;
1408 return semihosting
->post_result(target
);
1412 * Read all fields of a command from target to buffer.
1414 static int semihosting_read_fields(struct target
*target
, size_t number
,
1417 struct semihosting
*semihosting
= target
->semihosting
;
1418 /* Use 4-byte multiples to trigger fast memory access. */
1419 return target_read_memory(target
, semihosting
->param
, 4,
1420 number
* (semihosting
->word_size_bytes
/ 4), fields
);
1424 * Write all fields of a command from buffer to target.
1426 static int semihosting_write_fields(struct target
*target
, size_t number
,
1429 struct semihosting
*semihosting
= target
->semihosting
;
1430 /* Use 4-byte multiples to trigger fast memory access. */
1431 return target_write_memory(target
, semihosting
->param
, 4,
1432 number
* (semihosting
->word_size_bytes
/ 4), fields
);
1436 * Extract a field from the buffer, considering register size and endianness.
1438 static uint64_t semihosting_get_field(struct target
*target
, size_t index
,
1441 struct semihosting
*semihosting
= target
->semihosting
;
1442 if (semihosting
->word_size_bytes
== 8)
1443 return target_buffer_get_u64(target
, fields
+ (index
* 8));
1445 return target_buffer_get_u32(target
, fields
+ (index
* 4));
1449 * Store a field in the buffer, considering register size and endianness.
1451 static void semihosting_set_field(struct target
*target
, uint64_t value
,
1455 struct semihosting
*semihosting
= target
->semihosting
;
1456 if (semihosting
->word_size_bytes
== 8)
1457 target_buffer_set_u64(target
, fields
+ (index
* 8), value
);
1459 target_buffer_set_u32(target
, fields
+ (index
* 4), value
);
1463 /* -------------------------------------------------------------------------
1464 * Common semihosting commands handlers. */
1466 static __COMMAND_HANDLER(handle_common_semihosting_command
)
1468 struct target
*target
= get_current_target(CMD_CTX
);
1470 if (target
== NULL
) {
1471 LOG_ERROR("No target selected");
1475 struct semihosting
*semihosting
= target
->semihosting
;
1477 command_print(CMD
, "semihosting not supported for current target");
1484 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], is_active
);
1486 if (!target_was_examined(target
)) {
1487 LOG_ERROR("Target not examined yet");
1491 if (semihosting
&& semihosting
->setup(target
, is_active
) != ERROR_OK
) {
1492 LOG_ERROR("Failed to Configure semihosting");
1496 /* FIXME never let that "catch" be dropped! (???) */
1497 semihosting
->is_active
= is_active
;
1500 command_print(CMD
, "semihosting is %s",
1501 semihosting
->is_active
1502 ? "enabled" : "disabled");
1507 static __COMMAND_HANDLER(handle_common_semihosting_fileio_command
)
1509 struct target
*target
= get_current_target(CMD_CTX
);
1511 if (target
== NULL
) {
1512 LOG_ERROR("No target selected");
1516 struct semihosting
*semihosting
= target
->semihosting
;
1518 command_print(CMD
, "semihosting not supported for current target");
1522 if (!semihosting
->is_active
) {
1523 command_print(CMD
, "semihosting not yet enabled for current target");
1528 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], semihosting
->is_fileio
);
1530 command_print(CMD
, "semihosting fileio is %s",
1531 semihosting
->is_fileio
1532 ? "enabled" : "disabled");
1537 static __COMMAND_HANDLER(handle_common_semihosting_cmdline
)
1539 struct target
*target
= get_current_target(CMD_CTX
);
1542 if (target
== NULL
) {
1543 LOG_ERROR("No target selected");
1547 struct semihosting
*semihosting
= target
->semihosting
;
1549 command_print(CMD
, "semihosting not supported for current target");
1553 free(semihosting
->cmdline
);
1554 semihosting
->cmdline
= CMD_ARGC
> 0 ? strdup(CMD_ARGV
[0]) : NULL
;
1556 for (i
= 1; i
< CMD_ARGC
; i
++) {
1557 char *cmdline
= alloc_printf("%s %s", semihosting
->cmdline
, CMD_ARGV
[i
]);
1558 if (cmdline
== NULL
)
1560 free(semihosting
->cmdline
);
1561 semihosting
->cmdline
= cmdline
;
1564 command_print(CMD
, "semihosting command line is [%s]",
1565 semihosting
->cmdline
);
1570 static __COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command
)
1572 struct target
*target
= get_current_target(CMD_CTX
);
1574 if (target
== NULL
) {
1575 LOG_ERROR("No target selected");
1579 struct semihosting
*semihosting
= target
->semihosting
;
1581 command_print(CMD
, "semihosting not supported for current target");
1585 if (!semihosting
->is_active
) {
1586 command_print(CMD
, "semihosting not yet enabled for current target");
1591 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], semihosting
->has_resumable_exit
);
1593 command_print(CMD
, "semihosting resumable exit is %s",
1594 semihosting
->has_resumable_exit
1595 ? "enabled" : "disabled");
1600 const struct command_registration semihosting_common_handlers
[] = {
1603 .handler
= handle_common_semihosting_command
,
1604 .mode
= COMMAND_EXEC
,
1605 .usage
= "['enable'|'disable']",
1606 .help
= "activate support for semihosting operations",
1609 "semihosting_cmdline",
1610 .handler
= handle_common_semihosting_cmdline
,
1611 .mode
= COMMAND_EXEC
,
1612 .usage
= "arguments",
1613 .help
= "command line arguments to be passed to program",
1616 "semihosting_fileio",
1617 .handler
= handle_common_semihosting_fileio_command
,
1618 .mode
= COMMAND_EXEC
,
1619 .usage
= "['enable'|'disable']",
1620 .help
= "activate support for semihosting fileio operations",
1623 "semihosting_resexit",
1624 .handler
= handle_common_semihosting_resumable_exit_command
,
1625 .mode
= COMMAND_EXEC
,
1626 .usage
= "['enable'|'disable']",
1627 .help
= "activate support for semihosting resumable exit",
1629 COMMAND_REGISTRATION_DONE
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)