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 semihosting
->hit_fileio
= true;
229 fileio_info
->identifier
= "close";
230 fileio_info
->param_1
= fd
;
232 semihosting
->result
= close(fd
);
233 semihosting
->sys_errno
= errno
;
235 LOG_DEBUG("close(%d)=%d", fd
, (int)semihosting
->result
);
240 case SEMIHOSTING_SYS_ERRNO
: /* 0x13 */
242 * Returns the value of the C library errno variable that is
243 * associated with the semihosting implementation. The errno
244 * variable can be set by a number of C library semihosted
245 * functions, including:
253 * Whether errno is set or not, and to what value, is entirely
254 * host-specific, except where the ISO C standard defines the
258 * There are no parameters. The PARAMETER REGISTER must be 0.
261 * On exit, the RETURN REGISTER contains the value of the C
262 * library errno variable.
264 semihosting
->result
= semihosting
->sys_errno
;
267 case SEMIHOSTING_SYS_EXIT
: /* 0x18 */
269 * Note: SYS_EXIT was called angel_SWIreason_ReportException in
270 * previous versions of the documentation.
272 * An application calls this operation to report an exception
273 * to the debugger directly. The most common use is to report
274 * that execution has completed, using ADP_Stopped_ApplicationExit.
276 * Note: This semihosting operation provides no means for 32-bit
277 * callers to indicate an application exit with a specified exit
278 * code. Semihosting callers may prefer to check for the presence
279 * of the SH_EXT_EXTENDED_REPORT_EXCEPTION extension and use
280 * the SYS_REPORT_EXCEPTION_EXTENDED operation instead, if it
284 * On entry, the PARAMETER register is set to a reason code
285 * describing the cause of the trap. Not all semihosting client
286 * implementations will necessarily trap every corresponding
287 * event. Important reason codes are:
289 * - ADP_Stopped_ApplicationExit 0x20026
290 * - ADP_Stopped_RunTimeErrorUnknown 0x20023
293 * On entry, the PARAMETER REGISTER contains a pointer to a
294 * two-field argument block:
295 * - field 1 The exception type, which is one of the set of
296 * reason codes in the above tables.
297 * - field 2 A subcode, whose meaning depends on the reason
299 * In particular, if field 1 is ADP_Stopped_ApplicationExit
300 * then field 2 is an exit status code, as passed to the C
301 * standard library exit() function. A simulator receiving
302 * this request must notify a connected debugger, if present,
303 * and then exit with the specified status.
306 * No return is expected from these calls. However, it is
307 * possible for the debugger to request that the application
308 * continues by performing an RDI_Execute request or equivalent.
309 * In this case, execution continues with the registers as they
310 * were on entry to the operation, or as subsequently modified
313 if (semihosting
->word_size_bytes
== 8) {
314 retval
= semihosting_read_fields(target
, 2, fields
);
315 if (retval
!= ERROR_OK
)
318 int type
= semihosting_get_field(target
, 0, fields
);
319 int code
= semihosting_get_field(target
, 1, fields
);
321 if (type
== ADP_STOPPED_APPLICATION_EXIT
) {
322 if (!gdb_actual_connections
)
326 "semihosting: *** application exited with %d ***\n",
331 "semihosting: application exception %#x\n",
336 if (semihosting
->param
== ADP_STOPPED_APPLICATION_EXIT
) {
337 if (!gdb_actual_connections
)
341 "semihosting: *** application exited normally ***\n");
343 } else if (semihosting
->param
== ADP_STOPPED_RUN_TIME_ERROR
) {
344 /* Chosen more or less arbitrarly to have a nicer message,
345 * otherwise all other return the same exit code 1. */
346 if (!gdb_actual_connections
)
350 "semihosting: *** application exited with error ***\n");
353 if (!gdb_actual_connections
)
357 "semihosting: application exception %#x\n",
358 (unsigned) semihosting
->param
);
362 if (!semihosting
->has_resumable_exit
) {
363 semihosting
->is_resumable
= false;
364 return target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
368 case SEMIHOSTING_SYS_EXIT_EXTENDED
: /* 0x20 */
370 * This operation is only supported if the semihosting extension
371 * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is
372 * reported using feature byte 0, bit 0. If this extension is
373 * supported, then the implementation provides a means to
374 * report a normal exit with a nonzero exit status in both 32-bit
375 * and 64-bit semihosting APIs.
377 * The implementation must provide the semihosting call
378 * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs.
380 * SYS_EXIT_EXTENDED is used by an application to report an
381 * exception or exit to the debugger directly. The most common
382 * use is to report that execution has completed, using
383 * ADP_Stopped_ApplicationExit.
386 * On entry, the PARAMETER REGISTER contains a pointer to a
387 * two-field argument block:
388 * - field 1 The exception type, which should be one of the set
389 * of reason codes that are documented for the SYS_EXIT
390 * (0x18) call. For example, ADP_Stopped_ApplicationExit.
391 * - field 2 A subcode, whose meaning depends on the reason
392 * code in field 1. In particular, if field 1 is
393 * ADP_Stopped_ApplicationExit then field 2 is an exit status
394 * code, as passed to the C standard library exit() function.
395 * A simulator receiving this request must notify a connected
396 * debugger, if present, and then exit with the specified status.
399 * No return is expected from these calls.
401 * For the A64 API, this call is identical to the behavior of
402 * the mandatory SYS_EXIT (0x18) call. If this extension is
403 * supported, then both calls must be implemented.
405 retval
= semihosting_read_fields(target
, 2, fields
);
406 if (retval
!= ERROR_OK
)
409 int type
= semihosting_get_field(target
, 0, fields
);
410 int code
= semihosting_get_field(target
, 1, fields
);
412 if (type
== ADP_STOPPED_APPLICATION_EXIT
) {
413 if (!gdb_actual_connections
)
417 "semihosting: *** application exited with %d ***\n",
421 fprintf(stderr
, "semihosting: exception %#x\n",
425 if (!semihosting
->has_resumable_exit
) {
426 semihosting
->is_resumable
= false;
427 return target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
431 case SEMIHOSTING_SYS_FLEN
: /* 0x0C */
433 * Returns the length of a specified file.
436 * On entry, the PARAMETER REGISTER contains a pointer to a
437 * one-field argument block:
438 * - field 1 A handle for a previously opened, seekable file
442 * On exit, the RETURN REGISTER contains:
443 * - The current length of the file object, if the call is
445 * - –1 if an error occurs.
447 if (semihosting
->is_fileio
) {
448 LOG_ERROR("SYS_FLEN not supported by semihosting fileio");
451 retval
= semihosting_read_fields(target
, 1, fields
);
452 if (retval
!= ERROR_OK
)
455 int fd
= semihosting_get_field(target
, 0, fields
);
457 semihosting
->result
= fstat(fd
, &buf
);
458 if (semihosting
->result
== -1) {
459 semihosting
->sys_errno
= errno
;
460 LOG_DEBUG("fstat(%d)=%d", fd
, (int)semihosting
->result
);
463 LOG_DEBUG("fstat(%d)=%d", fd
, (int)semihosting
->result
);
464 semihosting
->result
= buf
.st_size
;
468 case SEMIHOSTING_SYS_GET_CMDLINE
: /* 0x15 */
470 * Returns the command line that is used for the call to the
471 * executable, that is, argc and argv.
474 * On entry, the PARAMETER REGISTER points to a two-field data
475 * block to be used for returning the command string and its length:
476 * - field 1 A pointer to a buffer of at least the size that is
477 * specified in field 2.
478 * - field 2 The length of the buffer in bytes.
482 * If the call is successful, then the RETURN REGISTER contains 0,
483 * the PARAMETER REGISTER is unchanged, and the data block is
484 * updated as follows:
485 * - field 1 A pointer to a null-terminated string of the command
487 * - field 2 The length of the string in bytes.
488 * If the call is not successful, then the RETURN REGISTER
491 * Note: The semihosting implementation might impose limits on
492 * the maximum length of the string that can be transferred.
493 * However, the implementation must be able to support a
494 * command-line length of at least 80 bytes.
496 retval
= semihosting_read_fields(target
, 2, fields
);
497 if (retval
!= ERROR_OK
)
500 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
501 size_t size
= semihosting_get_field(target
, 1, fields
);
503 char *arg
= semihosting
->cmdline
!= NULL
?
504 semihosting
->cmdline
: "";
505 uint32_t len
= strlen(arg
) + 1;
507 semihosting
->result
= -1;
509 semihosting_set_field(target
, len
, 1, fields
);
510 retval
= target_write_buffer(target
, addr
, len
,
512 if (retval
!= ERROR_OK
)
514 semihosting
->result
= 0;
516 retval
= semihosting_write_fields(target
, 2, fields
);
517 if (retval
!= ERROR_OK
)
520 LOG_DEBUG("SYS_GET_CMDLINE=[%s],%d", arg
,
521 (int)semihosting
->result
);
525 case SEMIHOSTING_SYS_HEAPINFO
: /* 0x16 */
527 * Returns the system stack and heap parameters.
530 * On entry, the PARAMETER REGISTER contains the address of a
531 * pointer to a four-field data block. The contents of the data
532 * block are filled by the function. The following C-like
533 * pseudocode describes the layout of the block:
542 * On exit, the PARAMETER REGISTER is unchanged and the data
543 * block has been updated.
545 retval
= semihosting_read_fields(target
, 1, fields
);
546 if (retval
!= ERROR_OK
)
549 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
550 /* tell the remote we have no idea */
551 memset(fields
, 0, 4 * semihosting
->word_size_bytes
);
552 retval
= target_write_memory(target
, addr
, 4,
553 semihosting
->word_size_bytes
,
555 if (retval
!= ERROR_OK
)
557 semihosting
->result
= 0;
561 case SEMIHOSTING_SYS_ISERROR
: /* 0x08 */
563 * Determines whether the return code from another semihosting
564 * call is an error status or not.
566 * This call is passed a parameter block containing the error
570 * On entry, the PARAMETER REGISTER contains a pointer to a
571 * one-field data block:
572 * - field 1 The required status word to check.
575 * On exit, the RETURN REGISTER contains:
576 * - 0 if the status field is not an error indication
577 * - A nonzero value if the status field is an error indication.
579 retval
= semihosting_read_fields(target
, 1, fields
);
580 if (retval
!= ERROR_OK
)
583 uint64_t code
= semihosting_get_field(target
, 0, fields
);
584 semihosting
->result
= (code
!= 0);
587 case SEMIHOSTING_SYS_ISTTY
: /* 0x09 */
589 * Checks whether a file is connected to an interactive device.
592 * On entry, the PARAMETER REGISTER contains a pointer to a
593 * one-field argument block:
594 * field 1 A handle for a previously opened file object.
597 * On exit, the RETURN REGISTER contains:
598 * - 1 if the handle identifies an interactive device.
599 * - 0 if the handle identifies a file.
600 * - A value other than 1 or 0 if an error occurs.
602 if (semihosting
->is_fileio
) {
603 semihosting
->hit_fileio
= true;
604 fileio_info
->identifier
= "isatty";
605 fileio_info
->param_1
= semihosting
->param
;
607 retval
= semihosting_read_fields(target
, 1, fields
);
608 if (retval
!= ERROR_OK
)
610 int fd
= semihosting_get_field(target
, 0, fields
);
611 semihosting
->result
= isatty(fd
);
612 LOG_DEBUG("isatty(%d)=%d", fd
, (int)semihosting
->result
);
616 case SEMIHOSTING_SYS_OPEN
: /* 0x01 */
618 * Opens a file on the host system.
620 * The file path is specified either as relative to the current
621 * directory of the host process, or absolute, using the path
622 * conventions of the host operating system.
624 * Semihosting implementations must support opening the special
625 * path name :semihosting-features as part of the semihosting
626 * extensions reporting mechanism.
628 * ARM targets interpret the special path name :tt as meaning
629 * the console input stream, for an open-read or the console
630 * output stream, for an open-write. Opening these streams is
631 * performed as part of the standard startup code for those
632 * applications that reference the C stdio streams. The
633 * semihosting extension SH_EXT_STDOUT_STDERR allows the
634 * semihosting caller to open separate output streams
635 * corresponding to stdout and stderr. This extension is
636 * reported using feature byte 0, bit 1. Use SYS_OPEN with
637 * the special path name :semihosting-features to access the
640 * If this extension is supported, the implementation must
641 * support the following additional semantics to SYS_OPEN:
642 * - If the special path name :tt is opened with an fopen
643 * mode requesting write access (w, wb, w+, or w+b), then
644 * this is a request to open stdout.
645 * - If the special path name :tt is opened with a mode
646 * requesting append access (a, ab, a+, or a+b), then this is
647 * a request to open stderr.
650 * On entry, the PARAMETER REGISTER contains a pointer to a
651 * three-field argument block:
652 * - field 1 A pointer to a null-terminated string containing
653 * a file or device name.
654 * - field 2 An integer that specifies the file opening mode.
655 * - field 3 An integer that gives the length of the string
656 * pointed to by field 1.
658 * The length does not include the terminating null character
659 * that must be present.
662 * On exit, the RETURN REGISTER contains:
663 * - A nonzero handle if the call is successful.
664 * - –1 if the call is not successful.
666 retval
= semihosting_read_fields(target
, 3, fields
);
667 if (retval
!= ERROR_OK
)
670 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
671 uint32_t mode
= semihosting_get_field(target
, 1, fields
);
672 size_t len
= semihosting_get_field(target
, 2, fields
);
675 semihosting
->result
= -1;
676 semihosting
->sys_errno
= EINVAL
;
679 uint8_t *fn
= malloc(len
+1);
681 semihosting
->result
= -1;
682 semihosting
->sys_errno
= ENOMEM
;
684 retval
= target_read_memory(target
, addr
, 1, len
, fn
);
685 if (retval
!= ERROR_OK
) {
690 /* TODO: implement the :semihosting-features special file.
692 if (semihosting
->is_fileio
) {
693 if (strcmp((char *)fn
, ":tt") == 0)
694 semihosting
->result
= 0;
696 semihosting
->hit_fileio
= true;
697 fileio_info
->identifier
= "open";
698 fileio_info
->param_1
= addr
;
699 fileio_info
->param_2
= len
;
700 fileio_info
->param_3
= open_modeflags
[mode
];
701 fileio_info
->param_4
= 0644;
704 if (strcmp((char *)fn
, ":tt") == 0) {
706 * - 0-3 ("r") for stdin,
707 * - 4-7 ("w") for stdout,
708 * - 8-11 ("a") for stderr */
710 semihosting
->result
= dup(
712 semihosting
->sys_errno
= errno
;
713 LOG_DEBUG("dup(STDIN)=%d",
714 (int)semihosting
->result
);
715 } else if (mode
< 8) {
716 semihosting
->result
= dup(
718 semihosting
->sys_errno
= errno
;
719 LOG_DEBUG("dup(STDOUT)=%d",
720 (int)semihosting
->result
);
722 semihosting
->result
= dup(
724 semihosting
->sys_errno
= errno
;
725 LOG_DEBUG("dup(STDERR)=%d",
726 (int)semihosting
->result
);
729 /* cygwin requires the permission setting
730 * otherwise it will fail to reopen a previously
732 semihosting
->result
= open((char *)fn
,
733 open_modeflags
[mode
],
735 semihosting
->sys_errno
= errno
;
736 LOG_DEBUG("open('%s')=%d", fn
,
737 (int)semihosting
->result
);
745 case SEMIHOSTING_SYS_READ
: /* 0x06 */
747 * Reads the contents of a file into a buffer. The file position
748 * is specified either:
749 * - Explicitly by a SYS_SEEK.
750 * - Implicitly one byte beyond the previous SYS_READ or
753 * The file position is at the start of the file when it is
754 * opened, and is lost when the file is closed. Perform the
755 * file operation as a single action whenever possible. For
756 * example, do not split a read of 16KB into four 4KB chunks
757 * unless there is no alternative.
760 * On entry, the PARAMETER REGISTER contains a pointer to a
761 * three-field data block:
762 * - field 1 Contains a handle for a file previously opened
764 * - field 2 Points to a buffer.
765 * - field 3 Contains the number of bytes to read to the buffer
769 * On exit, the RETURN REGISTER contains the number of bytes not
770 * filled in the buffer (buffer_length - bytes_read) as follows:
771 * - If the RETURN REGISTER is 0, the entire buffer was
772 * successfully filled.
773 * - If the RETURN REGISTER is the same as field 3, no bytes
774 * were read (EOF can be assumed).
775 * - If the RETURN REGISTER contains a value smaller than
776 * field 3, the read succeeded but the buffer was only partly
777 * filled. For interactive devices, this is the most common
780 retval
= semihosting_read_fields(target
, 3, fields
);
781 if (retval
!= ERROR_OK
)
784 int fd
= semihosting_get_field(target
, 0, fields
);
785 uint64_t addr
= semihosting_get_field(target
, 1, fields
);
786 size_t len
= semihosting_get_field(target
, 2, fields
);
787 if (semihosting
->is_fileio
) {
788 semihosting
->hit_fileio
= true;
789 fileio_info
->identifier
= "read";
790 fileio_info
->param_1
= fd
;
791 fileio_info
->param_2
= addr
;
792 fileio_info
->param_3
= len
;
794 uint8_t *buf
= malloc(len
);
796 semihosting
->result
= -1;
797 semihosting
->sys_errno
= ENOMEM
;
799 semihosting
->result
= read(fd
, buf
, len
);
800 semihosting
->sys_errno
= errno
;
801 LOG_DEBUG("read(%d, 0x%" PRIx64
", %zu)=%d",
805 (int)semihosting
->result
);
806 if (semihosting
->result
>= 0) {
807 retval
= target_write_buffer(target
, addr
,
810 if (retval
!= ERROR_OK
) {
814 /* the number of bytes NOT filled in */
815 semihosting
->result
= len
-
824 case SEMIHOSTING_SYS_READC
: /* 0x07 */
826 * Reads a byte from the console.
829 * The PARAMETER REGISTER must contain 0. There are no other
830 * parameters or values possible.
833 * On exit, the RETURN REGISTER contains the byte read from
836 if (semihosting
->is_fileio
) {
837 LOG_ERROR("SYS_READC not supported by semihosting fileio");
840 semihosting
->result
= getchar();
841 LOG_DEBUG("getchar()=%d", (int)semihosting
->result
);
844 case SEMIHOSTING_SYS_REMOVE
: /* 0x0E */
846 * Deletes a specified file on the host filing system.
849 * On entry, the PARAMETER REGISTER contains a pointer to a
850 * two-field argument block:
851 * - field 1 Points to a null-terminated string that gives the
852 * path name of the file to be deleted.
853 * - field 2 The length of the string.
856 * On exit, the RETURN REGISTER contains:
857 * - 0 if the delete is successful
858 * - A nonzero, host-specific error code if the delete fails.
860 retval
= semihosting_read_fields(target
, 2, fields
);
861 if (retval
!= ERROR_OK
)
864 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
865 size_t len
= semihosting_get_field(target
, 1, fields
);
866 if (semihosting
->is_fileio
) {
867 semihosting
->hit_fileio
= true;
868 fileio_info
->identifier
= "unlink";
869 fileio_info
->param_1
= addr
;
870 fileio_info
->param_2
= len
;
872 uint8_t *fn
= malloc(len
+1);
874 semihosting
->result
= -1;
875 semihosting
->sys_errno
= ENOMEM
;
878 target_read_memory(target
, addr
, 1, len
,
880 if (retval
!= ERROR_OK
) {
885 semihosting
->result
= remove((char *)fn
);
886 semihosting
->sys_errno
= errno
;
887 LOG_DEBUG("remove('%s')=%d", fn
,
888 (int)semihosting
->result
);
896 case SEMIHOSTING_SYS_RENAME
: /* 0x0F */
898 * Renames a specified file.
901 * On entry, the PARAMETER REGISTER contains a pointer to a
902 * four-field data block:
903 * - field 1 A pointer to the name of the old file.
904 * - field 2 The length of the old filename.
905 * - field 3 A pointer to the new filename.
906 * - field 4 The length of the new filename. Both strings are
910 * On exit, the RETURN REGISTER contains:
911 * - 0 if the rename is successful.
912 * - A nonzero, host-specific error code if the rename fails.
914 retval
= semihosting_read_fields(target
, 4, fields
);
915 if (retval
!= ERROR_OK
)
918 uint64_t addr1
= semihosting_get_field(target
, 0, fields
);
919 size_t len1
= semihosting_get_field(target
, 1, fields
);
920 uint64_t addr2
= semihosting_get_field(target
, 2, fields
);
921 size_t len2
= semihosting_get_field(target
, 3, fields
);
922 if (semihosting
->is_fileio
) {
923 semihosting
->hit_fileio
= true;
924 fileio_info
->identifier
= "rename";
925 fileio_info
->param_1
= addr1
;
926 fileio_info
->param_2
= len1
;
927 fileio_info
->param_3
= addr2
;
928 fileio_info
->param_4
= len2
;
930 uint8_t *fn1
= malloc(len1
+1);
931 uint8_t *fn2
= malloc(len2
+1);
933 semihosting
->result
= -1;
934 semihosting
->sys_errno
= ENOMEM
;
936 retval
= target_read_memory(target
, addr1
, 1, len1
,
938 if (retval
!= ERROR_OK
) {
943 retval
= target_read_memory(target
, addr2
, 1, len2
,
945 if (retval
!= ERROR_OK
) {
952 semihosting
->result
= rename((char *)fn1
,
954 semihosting
->sys_errno
= errno
;
955 LOG_DEBUG("rename('%s', '%s')=%d", fn1
, fn2
,
956 (int)semihosting
->result
);
965 case SEMIHOSTING_SYS_SEEK
: /* 0x0A */
967 * Seeks to a specified position in a file using an offset
968 * specified from the start of the file. The file is assumed
969 * to be a byte array and the offset is given in bytes.
972 * On entry, the PARAMETER REGISTER contains a pointer to a
973 * two-field data block:
974 * - field 1 A handle for a seekable file object.
975 * - field 2 The absolute byte position to seek to.
978 * On exit, the RETURN REGISTER contains:
979 * - 0 if the request is successful.
980 * - A negative value if the request is not successful.
981 * Use SYS_ERRNO to read the value of the host errno variable
982 * describing the error.
984 * Note: The effect of seeking outside the current extent of
985 * the file object is undefined.
987 retval
= semihosting_read_fields(target
, 2, fields
);
988 if (retval
!= ERROR_OK
)
991 int fd
= semihosting_get_field(target
, 0, fields
);
992 off_t pos
= semihosting_get_field(target
, 1, fields
);
993 if (semihosting
->is_fileio
) {
994 semihosting
->hit_fileio
= true;
995 fileio_info
->identifier
= "lseek";
996 fileio_info
->param_1
= fd
;
997 fileio_info
->param_2
= pos
;
998 fileio_info
->param_3
= SEEK_SET
;
1000 semihosting
->result
= lseek(fd
, pos
, SEEK_SET
);
1001 semihosting
->sys_errno
= errno
;
1002 LOG_DEBUG("lseek(%d, %d)=%d", fd
, (int)pos
,
1003 (int)semihosting
->result
);
1004 if (semihosting
->result
== pos
)
1005 semihosting
->result
= 0;
1010 case SEMIHOSTING_SYS_SYSTEM
: /* 0x12 */
1012 * Passes a command to the host command-line interpreter.
1013 * This enables you to execute a system command such as dir,
1014 * ls, or pwd. The terminal I/O is on the host, and is not
1015 * visible to the target.
1018 * On entry, the PARAMETER REGISTER contains a pointer to a
1019 * two-field argument block:
1020 * - field 1 Points to a string to be passed to the host
1021 * command-line interpreter.
1022 * - field 2 The length of the string.
1025 * On exit, the RETURN REGISTER contains the return status.
1028 /* Provide SYS_SYSTEM functionality. Uses the
1029 * libc system command, there may be a reason *NOT*
1030 * to use this, but as I can't think of one, I
1031 * implemented it this way.
1033 retval
= semihosting_read_fields(target
, 2, fields
);
1034 if (retval
!= ERROR_OK
)
1037 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
1038 size_t len
= semihosting_get_field(target
, 1, fields
);
1039 if (semihosting
->is_fileio
) {
1040 semihosting
->hit_fileio
= true;
1041 fileio_info
->identifier
= "system";
1042 fileio_info
->param_1
= addr
;
1043 fileio_info
->param_2
= len
;
1045 uint8_t *cmd
= malloc(len
+1);
1047 semihosting
->result
= -1;
1048 semihosting
->sys_errno
= ENOMEM
;
1050 retval
= target_read_memory(target
,
1055 if (retval
!= ERROR_OK
) {
1060 semihosting
->result
= system(
1062 LOG_DEBUG("system('%s')=%d",
1064 (int)semihosting
->result
);
1073 case SEMIHOSTING_SYS_TIME
: /* 0x11 */
1075 * Returns the number of seconds since 00:00 January 1, 1970.
1076 * This value is real-world time, regardless of any debug agent
1080 * There are no parameters.
1083 * On exit, the RETURN REGISTER contains the number of seconds.
1085 semihosting
->result
= time(NULL
);
1088 case SEMIHOSTING_SYS_WRITE
: /* 0x05 */
1090 * Writes the contents of a buffer to a specified file at the
1091 * current file position. The file position is specified either:
1092 * - Explicitly, by a SYS_SEEK.
1093 * - Implicitly as one byte beyond the previous SYS_READ or
1094 * SYS_WRITE request.
1096 * The file position is at the start of the file when the file
1097 * is opened, and is lost when the file is closed.
1099 * Perform the file operation as a single action whenever
1100 * possible. For example, do not split a write of 16KB into
1101 * four 4KB chunks unless there is no alternative.
1104 * On entry, the PARAMETER REGISTER contains a pointer to a
1105 * three-field data block:
1106 * - field 1 Contains a handle for a file previously opened
1108 * - field 2 Points to the memory containing the data to be written.
1109 * - field 3 Contains the number of bytes to be written from
1110 * the buffer to the file.
1113 * On exit, the RETURN REGISTER contains:
1114 * - 0 if the call is successful.
1115 * - The number of bytes that are not written, if there is an error.
1117 retval
= semihosting_read_fields(target
, 3, fields
);
1118 if (retval
!= ERROR_OK
)
1121 int fd
= semihosting_get_field(target
, 0, fields
);
1122 uint64_t addr
= semihosting_get_field(target
, 1, fields
);
1123 size_t len
= semihosting_get_field(target
, 2, fields
);
1124 if (semihosting
->is_fileio
) {
1125 semihosting
->hit_fileio
= true;
1126 fileio_info
->identifier
= "write";
1127 fileio_info
->param_1
= fd
;
1128 fileio_info
->param_2
= addr
;
1129 fileio_info
->param_3
= len
;
1131 uint8_t *buf
= malloc(len
);
1133 semihosting
->result
= -1;
1134 semihosting
->sys_errno
= ENOMEM
;
1136 retval
= target_read_buffer(target
, addr
, len
, buf
);
1137 if (retval
!= ERROR_OK
) {
1141 semihosting
->result
= write(fd
, buf
, len
);
1142 semihosting
->sys_errno
= errno
;
1143 LOG_DEBUG("write(%d, 0x%" PRIx64
", %zu)=%d",
1147 (int)semihosting
->result
);
1148 if (semihosting
->result
>= 0) {
1149 /* The number of bytes that are NOT written.
1151 semihosting
->result
= len
-
1152 semihosting
->result
;
1161 case SEMIHOSTING_SYS_WRITEC
: /* 0x03 */
1163 * Writes a character byte, pointed to by the PARAMETER REGISTER,
1164 * to the debug channel. When executed under a semihosting
1165 * debugger, the character appears on the host debugger console.
1168 * On entry, the PARAMETER REGISTER contains a pointer to the
1172 * None. The RETURN REGISTER is corrupted.
1174 if (semihosting
->is_fileio
) {
1175 semihosting
->hit_fileio
= true;
1176 fileio_info
->identifier
= "write";
1177 fileio_info
->param_1
= 1;
1178 fileio_info
->param_2
= semihosting
->param
;
1179 fileio_info
->param_3
= 1;
1181 uint64_t addr
= semihosting
->param
;
1183 retval
= target_read_memory(target
, addr
, 1, 1, &c
);
1184 if (retval
!= ERROR_OK
)
1187 semihosting
->result
= 0;
1191 case SEMIHOSTING_SYS_WRITE0
: /* 0x04 */
1193 * Writes a null-terminated string to the debug channel.
1194 * When executed under a semihosting debugger, the characters
1195 * appear on the host debugger console.
1198 * On entry, the PARAMETER REGISTER contains a pointer to the
1199 * first byte of the string.
1202 * None. The RETURN REGISTER is corrupted.
1204 if (semihosting
->is_fileio
) {
1206 uint64_t addr
= semihosting
->param
;
1209 retval
= target_read_memory(target
, addr
, 1, 1, &c
);
1210 if (retval
!= ERROR_OK
)
1216 semihosting
->hit_fileio
= true;
1217 fileio_info
->identifier
= "write";
1218 fileio_info
->param_1
= 1;
1219 fileio_info
->param_2
= semihosting
->param
;
1220 fileio_info
->param_3
= count
;
1222 uint64_t addr
= semihosting
->param
;
1225 retval
= target_read_memory(target
, addr
++, 1, 1, &c
);
1226 if (retval
!= ERROR_OK
)
1232 semihosting
->result
= 0;
1236 case SEMIHOSTING_SYS_ELAPSED
: /* 0x30 */
1238 * Returns the number of elapsed target ticks since execution
1240 * Use SYS_TICKFREQ to determine the tick frequency.
1243 * On entry, the PARAMETER REGISTER points to a two-field data
1244 * block to be used for returning the number of elapsed ticks:
1245 * - field 1 The least significant field and is at the low address.
1246 * - field 2 The most significant field and is at the high address.
1249 * On entry the PARAMETER REGISTER points to a one-field data
1250 * block to be used for returning the number of elapsed ticks:
1251 * - field 1 The number of elapsed ticks as a 64-bit value.
1255 * - On success, the RETURN REGISTER contains 0, the PARAMETER
1256 * REGISTER is unchanged, and the data block pointed to by the
1257 * PARAMETER REGISTER is filled in with the number of elapsed
1259 * - On failure, the RETURN REGISTER contains -1, and the
1260 * PARAMETER REGISTER contains -1.
1262 * Note: Some semihosting implementations might not support this
1263 * semihosting operation, and they always return -1 in the
1267 case SEMIHOSTING_SYS_TICKFREQ
: /* 0x31 */
1269 * Returns the tick frequency.
1272 * The PARAMETER REGISTER must contain 0 on entry to this routine.
1275 * On exit, the RETURN REGISTER contains either:
1276 * - The number of ticks per second.
1277 * - –1 if the target does not know the value of one tick.
1279 * Note: Some semihosting implementations might not support
1280 * this semihosting operation, and they always return -1 in the
1284 case SEMIHOSTING_SYS_TMPNAM
: /* 0x0D */
1286 * Returns a temporary name for a file identified by a system
1290 * On entry, the PARAMETER REGISTER contains a pointer to a
1291 * three-word argument block:
1292 * - field 1 A pointer to a buffer.
1293 * - field 2 A target identifier for this filename. Its value
1294 * must be an integer in the range 0-255.
1295 * - field 3 Contains the length of the buffer. The length must
1296 * be at least the value of L_tmpnam on the host system.
1299 * On exit, the RETURN REGISTER contains:
1300 * - 0 if the call is successful.
1301 * - –1 if an error occurs.
1303 * The buffer pointed to by the PARAMETER REGISTER contains
1304 * the filename, prefixed with a suitable directory name.
1305 * If you use the same target identifier again, the same
1306 * filename is returned.
1308 * Note: The returned string must be null-terminated.
1312 fprintf(stderr
, "semihosting: unsupported call %#x\n",
1313 (unsigned) semihosting
->op
);
1314 semihosting
->result
= -1;
1315 semihosting
->sys_errno
= ENOTSUP
;
1318 if (!semihosting
->hit_fileio
) {
1319 retval
= semihosting
->post_result(target
);
1320 if (retval
!= ERROR_OK
) {
1321 LOG_ERROR("Failed to post semihosting result");
1329 /* -------------------------------------------------------------------------
1330 * Local functions. */
1332 static int semihosting_common_fileio_info(struct target
*target
,
1333 struct gdb_fileio_info
*fileio_info
)
1335 struct semihosting
*semihosting
= target
->semihosting
;
1340 * To avoid unnecessary duplication, semihosting prepares the
1341 * fileio_info structure out-of-band when the target halts. See
1342 * do_semihosting for more detail.
1344 if (!semihosting
->is_fileio
|| !semihosting
->hit_fileio
)
1350 static int semihosting_common_fileio_end(struct target
*target
, int result
,
1351 int fileio_errno
, bool ctrl_c
)
1353 struct gdb_fileio_info
*fileio_info
= target
->fileio_info
;
1354 struct semihosting
*semihosting
= target
->semihosting
;
1358 /* clear pending status */
1359 semihosting
->hit_fileio
= false;
1361 semihosting
->result
= result
;
1362 semihosting
->sys_errno
= fileio_errno
;
1365 * Some fileio results do not match up with what the semihosting
1366 * operation expects; for these operations, we munge the results
1369 switch (semihosting
->op
) {
1370 case SEMIHOSTING_SYS_WRITE
: /* 0x05 */
1372 semihosting
->result
= fileio_info
->param_3
;
1374 semihosting
->result
= 0;
1377 case SEMIHOSTING_SYS_READ
: /* 0x06 */
1378 if (result
== (int)fileio_info
->param_3
)
1379 semihosting
->result
= 0;
1381 semihosting
->result
= fileio_info
->param_3
;
1384 case SEMIHOSTING_SYS_SEEK
: /* 0x0a */
1386 semihosting
->result
= 0;
1390 return semihosting
->post_result(target
);
1394 * Read all fields of a command from target to buffer.
1396 static int semihosting_read_fields(struct target
*target
, size_t number
,
1399 struct semihosting
*semihosting
= target
->semihosting
;
1400 /* Use 4-byte multiples to trigger fast memory access. */
1401 return target_read_memory(target
, semihosting
->param
, 4,
1402 number
* (semihosting
->word_size_bytes
/ 4), fields
);
1406 * Write all fields of a command from buffer to target.
1408 static int semihosting_write_fields(struct target
*target
, size_t number
,
1411 struct semihosting
*semihosting
= target
->semihosting
;
1412 /* Use 4-byte multiples to trigger fast memory access. */
1413 return target_write_memory(target
, semihosting
->param
, 4,
1414 number
* (semihosting
->word_size_bytes
/ 4), fields
);
1418 * Extract a field from the buffer, considering register size and endianness.
1420 static uint64_t semihosting_get_field(struct target
*target
, size_t index
,
1423 struct semihosting
*semihosting
= target
->semihosting
;
1424 if (semihosting
->word_size_bytes
== 8)
1425 return target_buffer_get_u64(target
, fields
+ (index
* 8));
1427 return target_buffer_get_u32(target
, fields
+ (index
* 4));
1431 * Store a field in the buffer, considering register size and endianness.
1433 static void semihosting_set_field(struct target
*target
, uint64_t value
,
1437 struct semihosting
*semihosting
= target
->semihosting
;
1438 if (semihosting
->word_size_bytes
== 8)
1439 target_buffer_set_u64(target
, fields
+ (index
* 8), value
);
1441 target_buffer_set_u32(target
, fields
+ (index
* 4), value
);
1445 /* -------------------------------------------------------------------------
1446 * Common semihosting commands handlers. */
1448 __COMMAND_HANDLER(handle_common_semihosting_command
)
1450 struct target
*target
= get_current_target(CMD_CTX
);
1452 if (target
== NULL
) {
1453 LOG_ERROR("No target selected");
1457 struct semihosting
*semihosting
= target
->semihosting
;
1459 command_print(CMD_CTX
, "semihosting not supported for current target");
1466 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], is_active
);
1468 if (!target_was_examined(target
)) {
1469 LOG_ERROR("Target not examined yet");
1473 if (semihosting
&& semihosting
->setup(target
, is_active
) != ERROR_OK
) {
1474 LOG_ERROR("Failed to Configure semihosting");
1478 /* FIXME never let that "catch" be dropped! (???) */
1479 semihosting
->is_active
= is_active
;
1482 command_print(CMD_CTX
, "semihosting is %s",
1483 semihosting
->is_active
1484 ? "enabled" : "disabled");
1490 __COMMAND_HANDLER(handle_common_semihosting_fileio_command
)
1492 struct target
*target
= get_current_target(CMD_CTX
);
1494 if (target
== NULL
) {
1495 LOG_ERROR("No target selected");
1499 struct semihosting
*semihosting
= target
->semihosting
;
1501 command_print(CMD_CTX
, "semihosting not supported for current target");
1505 if (!semihosting
->is_active
) {
1506 command_print(CMD_CTX
, "semihosting not yet enabled for current target");
1511 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], semihosting
->is_fileio
);
1513 command_print(CMD_CTX
, "semihosting fileio is %s",
1514 semihosting
->is_fileio
1515 ? "enabled" : "disabled");
1520 __COMMAND_HANDLER(handle_common_semihosting_cmdline
)
1522 struct target
*target
= get_current_target(CMD_CTX
);
1525 if (target
== NULL
) {
1526 LOG_ERROR("No target selected");
1530 struct semihosting
*semihosting
= target
->semihosting
;
1532 command_print(CMD_CTX
, "semihosting not supported for current target");
1536 free(semihosting
->cmdline
);
1537 semihosting
->cmdline
= CMD_ARGC
> 0 ? strdup(CMD_ARGV
[0]) : NULL
;
1539 for (i
= 1; i
< CMD_ARGC
; i
++) {
1540 char *cmdline
= alloc_printf("%s %s", semihosting
->cmdline
, CMD_ARGV
[i
]);
1541 if (cmdline
== NULL
)
1543 free(semihosting
->cmdline
);
1544 semihosting
->cmdline
= cmdline
;
1547 command_print(CMD_CTX
, "semihosting command line is [%s]",
1548 semihosting
->cmdline
);
1553 __COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command
)
1555 struct target
*target
= get_current_target(CMD_CTX
);
1557 if (target
== NULL
) {
1558 LOG_ERROR("No target selected");
1562 struct semihosting
*semihosting
= target
->semihosting
;
1564 command_print(CMD_CTX
, "semihosting not supported for current target");
1568 if (!semihosting
->is_active
) {
1569 command_print(CMD_CTX
, "semihosting not yet enabled for current target");
1574 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], semihosting
->has_resumable_exit
);
1576 command_print(CMD_CTX
, "semihosting resumable exit is %s",
1577 semihosting
->has_resumable_exit
1578 ? "enabled" : "disabled");
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)