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
) {
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
));
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 /* Do not allow to close OpenOCD's own standard streams */
230 if (fd
== 0 || fd
== 1 || fd
== 2) {
231 LOG_DEBUG("ignoring semihosting attempt to close %s",
232 (fd
== 0) ? "stdin" :
233 (fd
== 1) ? "stdout" : "stderr");
234 /* Just pretend success */
235 if (semihosting
->is_fileio
) {
236 semihosting
->result
= 0;
238 semihosting
->result
= 0;
239 semihosting
->sys_errno
= 0;
243 /* Close the descriptor */
244 if (semihosting
->is_fileio
) {
245 semihosting
->hit_fileio
= true;
246 fileio_info
->identifier
= "close";
247 fileio_info
->param_1
= fd
;
249 semihosting
->result
= close(fd
);
250 semihosting
->sys_errno
= errno
;
251 LOG_DEBUG("close(%d)=%d", fd
, (int)semihosting
->result
);
256 case SEMIHOSTING_SYS_ERRNO
: /* 0x13 */
258 * Returns the value of the C library errno variable that is
259 * associated with the semihosting implementation. The errno
260 * variable can be set by a number of C library semihosted
261 * functions, including:
269 * Whether errno is set or not, and to what value, is entirely
270 * host-specific, except where the ISO C standard defines the
274 * There are no parameters. The PARAMETER REGISTER must be 0.
277 * On exit, the RETURN REGISTER contains the value of the C
278 * library errno variable.
280 semihosting
->result
= semihosting
->sys_errno
;
283 case SEMIHOSTING_SYS_EXIT
: /* 0x18 */
285 * Note: SYS_EXIT was called angel_SWIreason_ReportException in
286 * previous versions of the documentation.
288 * An application calls this operation to report an exception
289 * to the debugger directly. The most common use is to report
290 * that execution has completed, using ADP_Stopped_ApplicationExit.
292 * Note: This semihosting operation provides no means for 32-bit
293 * callers to indicate an application exit with a specified exit
294 * code. Semihosting callers may prefer to check for the presence
295 * of the SH_EXT_EXTENDED_REPORT_EXCEPTION extension and use
296 * the SYS_REPORT_EXCEPTION_EXTENDED operation instead, if it
300 * On entry, the PARAMETER register is set to a reason code
301 * describing the cause of the trap. Not all semihosting client
302 * implementations will necessarily trap every corresponding
303 * event. Important reason codes are:
305 * - ADP_Stopped_ApplicationExit 0x20026
306 * - ADP_Stopped_RunTimeErrorUnknown 0x20023
309 * On entry, the PARAMETER REGISTER contains a pointer to a
310 * two-field argument block:
311 * - field 1 The exception type, which is one of the set of
312 * reason codes in the above tables.
313 * - field 2 A subcode, whose meaning depends on the reason
315 * In particular, if field 1 is ADP_Stopped_ApplicationExit
316 * then field 2 is an exit status code, as passed to the C
317 * standard library exit() function. A simulator receiving
318 * this request must notify a connected debugger, if present,
319 * and then exit with the specified status.
322 * No return is expected from these calls. However, it is
323 * possible for the debugger to request that the application
324 * continues by performing an RDI_Execute request or equivalent.
325 * In this case, execution continues with the registers as they
326 * were on entry to the operation, or as subsequently modified
329 if (semihosting
->word_size_bytes
== 8) {
330 retval
= semihosting_read_fields(target
, 2, fields
);
331 if (retval
!= ERROR_OK
)
334 int type
= semihosting_get_field(target
, 0, fields
);
335 int code
= semihosting_get_field(target
, 1, fields
);
337 if (type
== ADP_STOPPED_APPLICATION_EXIT
) {
338 if (!gdb_actual_connections
)
342 "semihosting: *** application exited with %d ***\n",
347 "semihosting: application exception %#x\n",
352 if (semihosting
->param
== ADP_STOPPED_APPLICATION_EXIT
) {
353 if (!gdb_actual_connections
)
357 "semihosting: *** application exited normally ***\n");
359 } else if (semihosting
->param
== ADP_STOPPED_RUN_TIME_ERROR
) {
360 /* Chosen more or less arbitrarily to have a nicer message,
361 * otherwise all other return the same exit code 1. */
362 if (!gdb_actual_connections
)
366 "semihosting: *** application exited with error ***\n");
369 if (!gdb_actual_connections
)
373 "semihosting: application exception %#x\n",
374 (unsigned) semihosting
->param
);
378 if (!semihosting
->has_resumable_exit
) {
379 semihosting
->is_resumable
= false;
380 return target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
384 case SEMIHOSTING_SYS_EXIT_EXTENDED
: /* 0x20 */
386 * This operation is only supported if the semihosting extension
387 * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is
388 * reported using feature byte 0, bit 0. If this extension is
389 * supported, then the implementation provides a means to
390 * report a normal exit with a nonzero exit status in both 32-bit
391 * and 64-bit semihosting APIs.
393 * The implementation must provide the semihosting call
394 * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs.
396 * SYS_EXIT_EXTENDED is used by an application to report an
397 * exception or exit to the debugger directly. The most common
398 * use is to report that execution has completed, using
399 * ADP_Stopped_ApplicationExit.
402 * On entry, the PARAMETER REGISTER contains a pointer to a
403 * two-field argument block:
404 * - field 1 The exception type, which should be one of the set
405 * of reason codes that are documented for the SYS_EXIT
406 * (0x18) call. For example, ADP_Stopped_ApplicationExit.
407 * - field 2 A subcode, whose meaning depends on the reason
408 * code in field 1. In particular, if field 1 is
409 * ADP_Stopped_ApplicationExit then field 2 is an exit status
410 * code, as passed to the C standard library exit() function.
411 * A simulator receiving this request must notify a connected
412 * debugger, if present, and then exit with the specified status.
415 * No return is expected from these calls.
417 * For the A64 API, this call is identical to the behavior of
418 * the mandatory SYS_EXIT (0x18) call. If this extension is
419 * supported, then both calls must be implemented.
421 retval
= semihosting_read_fields(target
, 2, fields
);
422 if (retval
!= ERROR_OK
)
425 int type
= semihosting_get_field(target
, 0, fields
);
426 int code
= semihosting_get_field(target
, 1, fields
);
428 if (type
== ADP_STOPPED_APPLICATION_EXIT
) {
429 if (!gdb_actual_connections
)
433 "semihosting: *** application exited with %d ***\n",
437 fprintf(stderr
, "semihosting: exception %#x\n",
441 if (!semihosting
->has_resumable_exit
) {
442 semihosting
->is_resumable
= false;
443 return target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
447 case SEMIHOSTING_SYS_FLEN
: /* 0x0C */
449 * Returns the length of a specified file.
452 * On entry, the PARAMETER REGISTER contains a pointer to a
453 * one-field argument block:
454 * - field 1 A handle for a previously opened, seekable file
458 * On exit, the RETURN REGISTER contains:
459 * - The current length of the file object, if the call is
461 * - –1 if an error occurs.
463 if (semihosting
->is_fileio
) {
464 semihosting
->result
= -1;
465 semihosting
->sys_errno
= EINVAL
;
467 retval
= semihosting_read_fields(target
, 1, fields
);
468 if (retval
!= ERROR_OK
)
471 int fd
= semihosting_get_field(target
, 0, fields
);
473 semihosting
->result
= fstat(fd
, &buf
);
474 if (semihosting
->result
== -1) {
475 semihosting
->sys_errno
= errno
;
476 LOG_DEBUG("fstat(%d)=%d", fd
, (int)semihosting
->result
);
479 LOG_DEBUG("fstat(%d)=%d", fd
, (int)semihosting
->result
);
480 semihosting
->result
= buf
.st_size
;
484 case SEMIHOSTING_SYS_GET_CMDLINE
: /* 0x15 */
486 * Returns the command line that is used for the call to the
487 * executable, that is, argc and argv.
490 * On entry, the PARAMETER REGISTER points to a two-field data
491 * block to be used for returning the command string and its length:
492 * - field 1 A pointer to a buffer of at least the size that is
493 * specified in field 2.
494 * - field 2 The length of the buffer in bytes.
498 * If the call is successful, then the RETURN REGISTER contains 0,
499 * the PARAMETER REGISTER is unchanged, and the data block is
500 * updated as follows:
501 * - field 1 A pointer to a null-terminated string of the command
503 * - field 2 The length of the string in bytes.
504 * If the call is not successful, then the RETURN REGISTER
507 * Note: The semihosting implementation might impose limits on
508 * the maximum length of the string that can be transferred.
509 * However, the implementation must be able to support a
510 * command-line length of at least 80 bytes.
512 retval
= semihosting_read_fields(target
, 2, fields
);
513 if (retval
!= ERROR_OK
)
516 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
517 size_t size
= semihosting_get_field(target
, 1, fields
);
519 char *arg
= semihosting
->cmdline
?
520 semihosting
->cmdline
: "";
521 uint32_t len
= strlen(arg
) + 1;
523 semihosting
->result
= -1;
525 semihosting_set_field(target
, len
, 1, fields
);
526 retval
= target_write_buffer(target
, addr
, len
,
528 if (retval
!= ERROR_OK
)
530 semihosting
->result
= 0;
532 retval
= semihosting_write_fields(target
, 2, fields
);
533 if (retval
!= ERROR_OK
)
536 LOG_DEBUG("SYS_GET_CMDLINE=[%s],%d", arg
,
537 (int)semihosting
->result
);
541 case SEMIHOSTING_SYS_HEAPINFO
: /* 0x16 */
543 * Returns the system stack and heap parameters.
546 * On entry, the PARAMETER REGISTER contains the address of a
547 * pointer to a four-field data block. The contents of the data
548 * block are filled by the function. The following C-like
549 * pseudocode describes the layout of the block:
558 * On exit, the PARAMETER REGISTER is unchanged and the data
559 * block has been updated.
561 retval
= semihosting_read_fields(target
, 1, fields
);
562 if (retval
!= ERROR_OK
)
565 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
566 /* tell the remote we have no idea */
567 memset(fields
, 0, 4 * semihosting
->word_size_bytes
);
568 retval
= target_write_memory(target
, addr
, 4,
569 semihosting
->word_size_bytes
,
571 if (retval
!= ERROR_OK
)
573 semihosting
->result
= 0;
577 case SEMIHOSTING_SYS_ISERROR
: /* 0x08 */
579 * Determines whether the return code from another semihosting
580 * call is an error status or not.
582 * This call is passed a parameter block containing the error
586 * On entry, the PARAMETER REGISTER contains a pointer to a
587 * one-field data block:
588 * - field 1 The required status word to check.
591 * On exit, the RETURN REGISTER contains:
592 * - 0 if the status field is not an error indication
593 * - A nonzero value if the status field is an error indication.
595 retval
= semihosting_read_fields(target
, 1, fields
);
596 if (retval
!= ERROR_OK
)
599 uint64_t code
= semihosting_get_field(target
, 0, fields
);
600 semihosting
->result
= (code
!= 0);
603 case SEMIHOSTING_SYS_ISTTY
: /* 0x09 */
605 * Checks whether a file is connected to an interactive device.
608 * On entry, the PARAMETER REGISTER contains a pointer to a
609 * one-field argument block:
610 * field 1 A handle for a previously opened file object.
613 * On exit, the RETURN REGISTER contains:
614 * - 1 if the handle identifies an interactive device.
615 * - 0 if the handle identifies a file.
616 * - A value other than 1 or 0 if an error occurs.
618 if (semihosting
->is_fileio
) {
619 semihosting
->hit_fileio
= true;
620 fileio_info
->identifier
= "isatty";
621 fileio_info
->param_1
= semihosting
->param
;
623 retval
= semihosting_read_fields(target
, 1, fields
);
624 if (retval
!= ERROR_OK
)
626 int fd
= semihosting_get_field(target
, 0, fields
);
627 semihosting
->result
= isatty(fd
);
628 semihosting
->sys_errno
= errno
;
629 LOG_DEBUG("isatty(%d)=%d", fd
, (int)semihosting
->result
);
633 case SEMIHOSTING_SYS_OPEN
: /* 0x01 */
635 * Opens a file on the host system.
637 * The file path is specified either as relative to the current
638 * directory of the host process, or absolute, using the path
639 * conventions of the host operating system.
641 * Semihosting implementations must support opening the special
642 * path name :semihosting-features as part of the semihosting
643 * extensions reporting mechanism.
645 * ARM targets interpret the special path name :tt as meaning
646 * the console input stream, for an open-read or the console
647 * output stream, for an open-write. Opening these streams is
648 * performed as part of the standard startup code for those
649 * applications that reference the C stdio streams. The
650 * semihosting extension SH_EXT_STDOUT_STDERR allows the
651 * semihosting caller to open separate output streams
652 * corresponding to stdout and stderr. This extension is
653 * reported using feature byte 0, bit 1. Use SYS_OPEN with
654 * the special path name :semihosting-features to access the
657 * If this extension is supported, the implementation must
658 * support the following additional semantics to SYS_OPEN:
659 * - If the special path name :tt is opened with an fopen
660 * mode requesting write access (w, wb, w+, or w+b), then
661 * this is a request to open stdout.
662 * - If the special path name :tt is opened with a mode
663 * requesting append access (a, ab, a+, or a+b), then this is
664 * a request to open stderr.
667 * On entry, the PARAMETER REGISTER contains a pointer to a
668 * three-field argument block:
669 * - field 1 A pointer to a null-terminated string containing
670 * a file or device name.
671 * - field 2 An integer that specifies the file opening mode.
672 * - field 3 An integer that gives the length of the string
673 * pointed to by field 1.
675 * The length does not include the terminating null character
676 * that must be present.
679 * On exit, the RETURN REGISTER contains:
680 * - A nonzero handle if the call is successful.
681 * - –1 if the call is not successful.
683 retval
= semihosting_read_fields(target
, 3, fields
);
684 if (retval
!= ERROR_OK
)
687 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
688 uint32_t mode
= semihosting_get_field(target
, 1, fields
);
689 size_t len
= semihosting_get_field(target
, 2, fields
);
692 semihosting
->result
= -1;
693 semihosting
->sys_errno
= EINVAL
;
696 uint8_t *fn
= malloc(len
+1);
698 semihosting
->result
= -1;
699 semihosting
->sys_errno
= ENOMEM
;
701 retval
= target_read_memory(target
, addr
, 1, len
, fn
);
702 if (retval
!= ERROR_OK
) {
707 /* TODO: implement the :semihosting-features special file.
709 if (semihosting
->is_fileio
) {
710 if (strcmp((char *)fn
, ":semihosting-features") == 0) {
711 semihosting
->result
= -1;
712 semihosting
->sys_errno
= EINVAL
;
713 } else if (strcmp((char *)fn
, ":tt") == 0) {
715 semihosting
->result
= 0;
717 semihosting
->result
= 1;
719 semihosting
->result
= 2;
721 semihosting
->result
= -1;
723 semihosting
->hit_fileio
= true;
724 fileio_info
->identifier
= "open";
725 fileio_info
->param_1
= addr
;
726 fileio_info
->param_2
= len
;
727 fileio_info
->param_3
= open_modeflags
[mode
];
728 fileio_info
->param_4
= 0644;
731 if (strcmp((char *)fn
, ":tt") == 0) {
733 * - 0-3 ("r") for stdin,
734 * - 4-7 ("w") for stdout,
735 * - 8-11 ("a") for stderr */
737 semihosting
->result
= dup(
739 semihosting
->sys_errno
= errno
;
740 LOG_DEBUG("dup(STDIN)=%d",
741 (int)semihosting
->result
);
742 } else if (mode
< 8) {
743 semihosting
->result
= dup(
745 semihosting
->sys_errno
= errno
;
746 LOG_DEBUG("dup(STDOUT)=%d",
747 (int)semihosting
->result
);
749 semihosting
->result
= dup(
751 semihosting
->sys_errno
= errno
;
752 LOG_DEBUG("dup(STDERR)=%d",
753 (int)semihosting
->result
);
756 /* cygwin requires the permission setting
757 * otherwise it will fail to reopen a previously
759 semihosting
->result
= open((char *)fn
,
760 open_modeflags
[mode
],
762 semihosting
->sys_errno
= errno
;
763 LOG_DEBUG("open('%s')=%d", fn
,
764 (int)semihosting
->result
);
772 case SEMIHOSTING_SYS_READ
: /* 0x06 */
774 * Reads the contents of a file into a buffer. The file position
775 * is specified either:
776 * - Explicitly by a SYS_SEEK.
777 * - Implicitly one byte beyond the previous SYS_READ or
780 * The file position is at the start of the file when it is
781 * opened, and is lost when the file is closed. Perform the
782 * file operation as a single action whenever possible. For
783 * example, do not split a read of 16KB into four 4KB chunks
784 * unless there is no alternative.
787 * On entry, the PARAMETER REGISTER contains a pointer to a
788 * three-field data block:
789 * - field 1 Contains a handle for a file previously opened
791 * - field 2 Points to a buffer.
792 * - field 3 Contains the number of bytes to read to the buffer
796 * On exit, the RETURN REGISTER contains the number of bytes not
797 * filled in the buffer (buffer_length - bytes_read) as follows:
798 * - If the RETURN REGISTER is 0, the entire buffer was
799 * successfully filled.
800 * - If the RETURN REGISTER is the same as field 3, no bytes
801 * were read (EOF can be assumed).
802 * - If the RETURN REGISTER contains a value smaller than
803 * field 3, the read succeeded but the buffer was only partly
804 * filled. For interactive devices, this is the most common
807 retval
= semihosting_read_fields(target
, 3, fields
);
808 if (retval
!= ERROR_OK
)
811 int fd
= semihosting_get_field(target
, 0, fields
);
812 uint64_t addr
= semihosting_get_field(target
, 1, fields
);
813 size_t len
= semihosting_get_field(target
, 2, fields
);
814 if (semihosting
->is_fileio
) {
815 semihosting
->hit_fileio
= true;
816 fileio_info
->identifier
= "read";
817 fileio_info
->param_1
= fd
;
818 fileio_info
->param_2
= addr
;
819 fileio_info
->param_3
= len
;
821 uint8_t *buf
= malloc(len
);
823 semihosting
->result
= -1;
824 semihosting
->sys_errno
= ENOMEM
;
826 semihosting
->result
= read(fd
, buf
, len
);
827 semihosting
->sys_errno
= errno
;
828 LOG_DEBUG("read(%d, 0x%" PRIx64
", %zu)=%d",
832 (int)semihosting
->result
);
833 if (semihosting
->result
>= 0) {
834 retval
= target_write_buffer(target
, addr
,
837 if (retval
!= ERROR_OK
) {
841 /* the number of bytes NOT filled in */
842 semihosting
->result
= len
-
851 case SEMIHOSTING_SYS_READC
: /* 0x07 */
853 * Reads a byte from the console.
856 * The PARAMETER REGISTER must contain 0. There are no other
857 * parameters or values possible.
860 * On exit, the RETURN REGISTER contains the byte read from
863 if (semihosting
->is_fileio
) {
864 LOG_ERROR("SYS_READC not supported by semihosting fileio");
867 semihosting
->result
= getchar();
868 LOG_DEBUG("getchar()=%d", (int)semihosting
->result
);
871 case SEMIHOSTING_SYS_REMOVE
: /* 0x0E */
873 * Deletes a specified file on the host filing system.
876 * On entry, the PARAMETER REGISTER contains a pointer to a
877 * two-field argument block:
878 * - field 1 Points to a null-terminated string that gives the
879 * path name of the file to be deleted.
880 * - field 2 The length of the string.
883 * On exit, the RETURN REGISTER contains:
884 * - 0 if the delete is successful
885 * - A nonzero, host-specific error code if the delete fails.
887 retval
= semihosting_read_fields(target
, 2, fields
);
888 if (retval
!= ERROR_OK
)
891 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
892 size_t len
= semihosting_get_field(target
, 1, fields
);
893 if (semihosting
->is_fileio
) {
894 semihosting
->hit_fileio
= true;
895 fileio_info
->identifier
= "unlink";
896 fileio_info
->param_1
= addr
;
897 fileio_info
->param_2
= len
;
899 uint8_t *fn
= malloc(len
+1);
901 semihosting
->result
= -1;
902 semihosting
->sys_errno
= ENOMEM
;
905 target_read_memory(target
, addr
, 1, len
,
907 if (retval
!= ERROR_OK
) {
912 semihosting
->result
= remove((char *)fn
);
913 semihosting
->sys_errno
= errno
;
914 LOG_DEBUG("remove('%s')=%d", fn
,
915 (int)semihosting
->result
);
923 case SEMIHOSTING_SYS_RENAME
: /* 0x0F */
925 * Renames a specified file.
928 * On entry, the PARAMETER REGISTER contains a pointer to a
929 * four-field data block:
930 * - field 1 A pointer to the name of the old file.
931 * - field 2 The length of the old filename.
932 * - field 3 A pointer to the new filename.
933 * - field 4 The length of the new filename. Both strings are
937 * On exit, the RETURN REGISTER contains:
938 * - 0 if the rename is successful.
939 * - A nonzero, host-specific error code if the rename fails.
941 retval
= semihosting_read_fields(target
, 4, fields
);
942 if (retval
!= ERROR_OK
)
945 uint64_t addr1
= semihosting_get_field(target
, 0, fields
);
946 size_t len1
= semihosting_get_field(target
, 1, fields
);
947 uint64_t addr2
= semihosting_get_field(target
, 2, fields
);
948 size_t len2
= semihosting_get_field(target
, 3, fields
);
949 if (semihosting
->is_fileio
) {
950 semihosting
->hit_fileio
= true;
951 fileio_info
->identifier
= "rename";
952 fileio_info
->param_1
= addr1
;
953 fileio_info
->param_2
= len1
;
954 fileio_info
->param_3
= addr2
;
955 fileio_info
->param_4
= len2
;
957 uint8_t *fn1
= malloc(len1
+1);
958 uint8_t *fn2
= malloc(len2
+1);
962 semihosting
->result
= -1;
963 semihosting
->sys_errno
= ENOMEM
;
965 retval
= target_read_memory(target
, addr1
, 1, len1
,
967 if (retval
!= ERROR_OK
) {
972 retval
= target_read_memory(target
, addr2
, 1, len2
,
974 if (retval
!= ERROR_OK
) {
981 semihosting
->result
= rename((char *)fn1
,
983 semihosting
->sys_errno
= errno
;
984 LOG_DEBUG("rename('%s', '%s')=%d", fn1
, fn2
,
985 (int)semihosting
->result
);
994 case SEMIHOSTING_SYS_SEEK
: /* 0x0A */
996 * Seeks to a specified position in a file using an offset
997 * specified from the start of the file. The file is assumed
998 * to be a byte array and the offset is given in bytes.
1001 * On entry, the PARAMETER REGISTER contains a pointer to a
1002 * two-field data block:
1003 * - field 1 A handle for a seekable file object.
1004 * - field 2 The absolute byte position to seek to.
1007 * On exit, the RETURN REGISTER contains:
1008 * - 0 if the request is successful.
1009 * - A negative value if the request is not successful.
1010 * Use SYS_ERRNO to read the value of the host errno variable
1011 * describing the error.
1013 * Note: The effect of seeking outside the current extent of
1014 * the file object is undefined.
1016 retval
= semihosting_read_fields(target
, 2, fields
);
1017 if (retval
!= ERROR_OK
)
1020 int fd
= semihosting_get_field(target
, 0, fields
);
1021 off_t pos
= semihosting_get_field(target
, 1, fields
);
1022 if (semihosting
->is_fileio
) {
1023 semihosting
->hit_fileio
= true;
1024 fileio_info
->identifier
= "lseek";
1025 fileio_info
->param_1
= fd
;
1026 fileio_info
->param_2
= pos
;
1027 fileio_info
->param_3
= SEEK_SET
;
1029 semihosting
->result
= lseek(fd
, pos
, SEEK_SET
);
1030 semihosting
->sys_errno
= errno
;
1031 LOG_DEBUG("lseek(%d, %d)=%d", fd
, (int)pos
,
1032 (int)semihosting
->result
);
1033 if (semihosting
->result
== pos
)
1034 semihosting
->result
= 0;
1039 case SEMIHOSTING_SYS_SYSTEM
: /* 0x12 */
1041 * Passes a command to the host command-line interpreter.
1042 * This enables you to execute a system command such as dir,
1043 * ls, or pwd. The terminal I/O is on the host, and is not
1044 * visible to the target.
1047 * On entry, the PARAMETER REGISTER contains a pointer to a
1048 * two-field argument block:
1049 * - field 1 Points to a string to be passed to the host
1050 * command-line interpreter.
1051 * - field 2 The length of the string.
1054 * On exit, the RETURN REGISTER contains the return status.
1057 /* Provide SYS_SYSTEM functionality. Uses the
1058 * libc system command, there may be a reason *NOT*
1059 * to use this, but as I can't think of one, I
1060 * implemented it this way.
1062 retval
= semihosting_read_fields(target
, 2, fields
);
1063 if (retval
!= ERROR_OK
)
1066 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
1067 size_t len
= semihosting_get_field(target
, 1, fields
);
1068 if (semihosting
->is_fileio
) {
1069 semihosting
->hit_fileio
= true;
1070 fileio_info
->identifier
= "system";
1071 fileio_info
->param_1
= addr
;
1072 fileio_info
->param_2
= len
;
1074 uint8_t *cmd
= malloc(len
+1);
1076 semihosting
->result
= -1;
1077 semihosting
->sys_errno
= ENOMEM
;
1079 retval
= target_read_memory(target
,
1084 if (retval
!= ERROR_OK
) {
1089 semihosting
->result
= system(
1091 LOG_DEBUG("system('%s')=%d",
1093 (int)semihosting
->result
);
1102 case SEMIHOSTING_SYS_TIME
: /* 0x11 */
1104 * Returns the number of seconds since 00:00 January 1, 1970.
1105 * This value is real-world time, regardless of any debug agent
1109 * There are no parameters.
1112 * On exit, the RETURN REGISTER contains the number of seconds.
1114 semihosting
->result
= time(NULL
);
1117 case SEMIHOSTING_SYS_WRITE
: /* 0x05 */
1119 * Writes the contents of a buffer to a specified file at the
1120 * current file position. The file position is specified either:
1121 * - Explicitly, by a SYS_SEEK.
1122 * - Implicitly as one byte beyond the previous SYS_READ or
1123 * SYS_WRITE request.
1125 * The file position is at the start of the file when the file
1126 * is opened, and is lost when the file is closed.
1128 * Perform the file operation as a single action whenever
1129 * possible. For example, do not split a write of 16KB into
1130 * four 4KB chunks unless there is no alternative.
1133 * On entry, the PARAMETER REGISTER contains a pointer to a
1134 * three-field data block:
1135 * - field 1 Contains a handle for a file previously opened
1137 * - field 2 Points to the memory containing the data to be written.
1138 * - field 3 Contains the number of bytes to be written from
1139 * the buffer to the file.
1142 * On exit, the RETURN REGISTER contains:
1143 * - 0 if the call is successful.
1144 * - The number of bytes that are not written, if there is an error.
1146 retval
= semihosting_read_fields(target
, 3, fields
);
1147 if (retval
!= ERROR_OK
)
1150 int fd
= semihosting_get_field(target
, 0, fields
);
1151 uint64_t addr
= semihosting_get_field(target
, 1, fields
);
1152 size_t len
= semihosting_get_field(target
, 2, fields
);
1153 if (semihosting
->is_fileio
) {
1154 semihosting
->hit_fileio
= true;
1155 fileio_info
->identifier
= "write";
1156 fileio_info
->param_1
= fd
;
1157 fileio_info
->param_2
= addr
;
1158 fileio_info
->param_3
= len
;
1160 uint8_t *buf
= malloc(len
);
1162 semihosting
->result
= -1;
1163 semihosting
->sys_errno
= ENOMEM
;
1165 retval
= target_read_buffer(target
, addr
, len
, buf
);
1166 if (retval
!= ERROR_OK
) {
1170 semihosting
->result
= write(fd
, buf
, len
);
1171 semihosting
->sys_errno
= errno
;
1172 LOG_DEBUG("write(%d, 0x%" PRIx64
", %zu)=%d",
1176 (int)semihosting
->result
);
1177 if (semihosting
->result
>= 0) {
1178 /* The number of bytes that are NOT written.
1180 semihosting
->result
= len
-
1181 semihosting
->result
;
1190 case SEMIHOSTING_SYS_WRITEC
: /* 0x03 */
1192 * Writes a character byte, pointed to by the PARAMETER REGISTER,
1193 * to the debug channel. When executed under a semihosting
1194 * debugger, the character appears on the host debugger console.
1197 * On entry, the PARAMETER REGISTER contains a pointer to the
1201 * None. The RETURN REGISTER is corrupted.
1203 if (semihosting
->is_fileio
) {
1204 semihosting
->hit_fileio
= true;
1205 fileio_info
->identifier
= "write";
1206 fileio_info
->param_1
= 1;
1207 fileio_info
->param_2
= semihosting
->param
;
1208 fileio_info
->param_3
= 1;
1210 uint64_t addr
= semihosting
->param
;
1212 retval
= target_read_memory(target
, addr
, 1, 1, &c
);
1213 if (retval
!= ERROR_OK
)
1216 semihosting
->result
= 0;
1220 case SEMIHOSTING_SYS_WRITE0
: /* 0x04 */
1222 * Writes a null-terminated string to the debug channel.
1223 * When executed under a semihosting debugger, the characters
1224 * appear on the host debugger console.
1227 * On entry, the PARAMETER REGISTER contains a pointer to the
1228 * first byte of the string.
1231 * None. The RETURN REGISTER is corrupted.
1233 if (semihosting
->is_fileio
) {
1235 uint64_t addr
= semihosting
->param
;
1238 retval
= target_read_memory(target
, addr
, 1, 1, &c
);
1239 if (retval
!= ERROR_OK
)
1245 semihosting
->hit_fileio
= true;
1246 fileio_info
->identifier
= "write";
1247 fileio_info
->param_1
= 1;
1248 fileio_info
->param_2
= semihosting
->param
;
1249 fileio_info
->param_3
= count
;
1251 uint64_t addr
= semihosting
->param
;
1254 retval
= target_read_memory(target
, addr
++, 1, 1, &c
);
1255 if (retval
!= ERROR_OK
)
1261 semihosting
->result
= 0;
1265 case SEMIHOSTING_SYS_ELAPSED
: /* 0x30 */
1267 * Returns the number of elapsed target ticks since execution
1269 * Use SYS_TICKFREQ to determine the tick frequency.
1272 * On entry, the PARAMETER REGISTER points to a two-field data
1273 * block to be used for returning the number of elapsed ticks:
1274 * - field 1 The least significant field and is at the low address.
1275 * - field 2 The most significant field and is at the high address.
1278 * On entry the PARAMETER REGISTER points to a one-field data
1279 * block to be used for returning the number of elapsed ticks:
1280 * - field 1 The number of elapsed ticks as a 64-bit value.
1284 * - On success, the RETURN REGISTER contains 0, the PARAMETER
1285 * REGISTER is unchanged, and the data block pointed to by the
1286 * PARAMETER REGISTER is filled in with the number of elapsed
1288 * - On failure, the RETURN REGISTER contains -1, and the
1289 * PARAMETER REGISTER contains -1.
1291 * Note: Some semihosting implementations might not support this
1292 * semihosting operation, and they always return -1 in the
1296 case SEMIHOSTING_SYS_TICKFREQ
: /* 0x31 */
1298 * Returns the tick frequency.
1301 * The PARAMETER REGISTER must contain 0 on entry to this routine.
1304 * On exit, the RETURN REGISTER contains either:
1305 * - The number of ticks per second.
1306 * - –1 if the target does not know the value of one tick.
1308 * Note: Some semihosting implementations might not support
1309 * this semihosting operation, and they always return -1 in the
1313 case SEMIHOSTING_SYS_TMPNAM
: /* 0x0D */
1315 * Returns a temporary name for a file identified by a system
1319 * On entry, the PARAMETER REGISTER contains a pointer to a
1320 * three-word argument block:
1321 * - field 1 A pointer to a buffer.
1322 * - field 2 A target identifier for this filename. Its value
1323 * must be an integer in the range 0-255.
1324 * - field 3 Contains the length of the buffer. The length must
1325 * be at least the value of L_tmpnam on the host system.
1328 * On exit, the RETURN REGISTER contains:
1329 * - 0 if the call is successful.
1330 * - –1 if an error occurs.
1332 * The buffer pointed to by the PARAMETER REGISTER contains
1333 * the filename, prefixed with a suitable directory name.
1334 * If you use the same target identifier again, the same
1335 * filename is returned.
1337 * Note: The returned string must be null-terminated.
1341 fprintf(stderr
, "semihosting: unsupported call %#x\n",
1342 (unsigned) semihosting
->op
);
1343 semihosting
->result
= -1;
1344 semihosting
->sys_errno
= ENOTSUP
;
1347 if (!semihosting
->hit_fileio
) {
1348 retval
= semihosting
->post_result(target
);
1349 if (retval
!= ERROR_OK
) {
1350 LOG_ERROR("Failed to post semihosting result");
1358 /* -------------------------------------------------------------------------
1359 * Local functions. */
1361 static int semihosting_common_fileio_info(struct target
*target
,
1362 struct gdb_fileio_info
*fileio_info
)
1364 struct semihosting
*semihosting
= target
->semihosting
;
1369 * To avoid unnecessary duplication, semihosting prepares the
1370 * fileio_info structure out-of-band when the target halts. See
1371 * do_semihosting for more detail.
1373 if (!semihosting
->is_fileio
|| !semihosting
->hit_fileio
)
1379 static int semihosting_common_fileio_end(struct target
*target
, int result
,
1380 int fileio_errno
, bool ctrl_c
)
1382 struct gdb_fileio_info
*fileio_info
= target
->fileio_info
;
1383 struct semihosting
*semihosting
= target
->semihosting
;
1387 /* clear pending status */
1388 semihosting
->hit_fileio
= false;
1390 semihosting
->result
= result
;
1391 semihosting
->sys_errno
= fileio_errno
;
1394 * Some fileio results do not match up with what the semihosting
1395 * operation expects; for these operations, we munge the results
1398 switch (semihosting
->op
) {
1399 case SEMIHOSTING_SYS_WRITE
: /* 0x05 */
1401 semihosting
->result
= fileio_info
->param_3
;
1403 semihosting
->result
= 0;
1406 case SEMIHOSTING_SYS_READ
: /* 0x06 */
1407 if (result
== (int)fileio_info
->param_3
)
1408 semihosting
->result
= 0;
1410 semihosting
->result
= fileio_info
->param_3
;
1413 case SEMIHOSTING_SYS_SEEK
: /* 0x0a */
1415 semihosting
->result
= 0;
1419 return semihosting
->post_result(target
);
1423 * Read all fields of a command from target to buffer.
1425 static int semihosting_read_fields(struct target
*target
, size_t number
,
1428 struct semihosting
*semihosting
= target
->semihosting
;
1429 /* Use 4-byte multiples to trigger fast memory access. */
1430 return target_read_memory(target
, semihosting
->param
, 4,
1431 number
* (semihosting
->word_size_bytes
/ 4), fields
);
1435 * Write all fields of a command from buffer to target.
1437 static int semihosting_write_fields(struct target
*target
, size_t number
,
1440 struct semihosting
*semihosting
= target
->semihosting
;
1441 /* Use 4-byte multiples to trigger fast memory access. */
1442 return target_write_memory(target
, semihosting
->param
, 4,
1443 number
* (semihosting
->word_size_bytes
/ 4), fields
);
1447 * Extract a field from the buffer, considering register size and endianness.
1449 static uint64_t semihosting_get_field(struct target
*target
, size_t index
,
1452 struct semihosting
*semihosting
= target
->semihosting
;
1453 if (semihosting
->word_size_bytes
== 8)
1454 return target_buffer_get_u64(target
, fields
+ (index
* 8));
1456 return target_buffer_get_u32(target
, fields
+ (index
* 4));
1460 * Store a field in the buffer, considering register size and endianness.
1462 static void semihosting_set_field(struct target
*target
, uint64_t value
,
1466 struct semihosting
*semihosting
= target
->semihosting
;
1467 if (semihosting
->word_size_bytes
== 8)
1468 target_buffer_set_u64(target
, fields
+ (index
* 8), value
);
1470 target_buffer_set_u32(target
, fields
+ (index
* 4), value
);
1474 /* -------------------------------------------------------------------------
1475 * Common semihosting commands handlers. */
1477 static __COMMAND_HANDLER(handle_common_semihosting_command
)
1479 struct target
*target
= get_current_target(CMD_CTX
);
1482 LOG_ERROR("No target selected");
1486 struct semihosting
*semihosting
= target
->semihosting
;
1488 command_print(CMD
, "semihosting not supported for current target");
1495 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], is_active
);
1497 if (!target_was_examined(target
)) {
1498 LOG_ERROR("Target not examined yet");
1502 if (semihosting
&& semihosting
->setup(target
, is_active
) != ERROR_OK
) {
1503 LOG_ERROR("Failed to Configure semihosting");
1507 /* FIXME never let that "catch" be dropped! (???) */
1508 semihosting
->is_active
= is_active
;
1511 command_print(CMD
, "semihosting is %s",
1512 semihosting
->is_active
1513 ? "enabled" : "disabled");
1518 static __COMMAND_HANDLER(handle_common_semihosting_fileio_command
)
1520 struct target
*target
= get_current_target(CMD_CTX
);
1523 LOG_ERROR("No target selected");
1527 struct semihosting
*semihosting
= target
->semihosting
;
1529 command_print(CMD
, "semihosting not supported for current target");
1533 if (!semihosting
->is_active
) {
1534 command_print(CMD
, "semihosting not yet enabled for current target");
1539 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], semihosting
->is_fileio
);
1541 command_print(CMD
, "semihosting fileio is %s",
1542 semihosting
->is_fileio
1543 ? "enabled" : "disabled");
1548 static __COMMAND_HANDLER(handle_common_semihosting_cmdline
)
1550 struct target
*target
= get_current_target(CMD_CTX
);
1554 LOG_ERROR("No target selected");
1558 struct semihosting
*semihosting
= target
->semihosting
;
1560 command_print(CMD
, "semihosting not supported for current target");
1564 free(semihosting
->cmdline
);
1565 semihosting
->cmdline
= CMD_ARGC
> 0 ? strdup(CMD_ARGV
[0]) : NULL
;
1567 for (i
= 1; i
< CMD_ARGC
; i
++) {
1568 char *cmdline
= alloc_printf("%s %s", semihosting
->cmdline
, CMD_ARGV
[i
]);
1571 free(semihosting
->cmdline
);
1572 semihosting
->cmdline
= cmdline
;
1575 command_print(CMD
, "semihosting command line is [%s]",
1576 semihosting
->cmdline
);
1581 static __COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command
)
1583 struct target
*target
= get_current_target(CMD_CTX
);
1586 LOG_ERROR("No target selected");
1590 struct semihosting
*semihosting
= target
->semihosting
;
1592 command_print(CMD
, "semihosting not supported for current target");
1596 if (!semihosting
->is_active
) {
1597 command_print(CMD
, "semihosting not yet enabled for current target");
1602 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], semihosting
->has_resumable_exit
);
1604 command_print(CMD
, "semihosting resumable exit is %s",
1605 semihosting
->has_resumable_exit
1606 ? "enabled" : "disabled");
1611 const struct command_registration semihosting_common_handlers
[] = {
1614 .handler
= handle_common_semihosting_command
,
1615 .mode
= COMMAND_EXEC
,
1616 .usage
= "['enable'|'disable']",
1617 .help
= "activate support for semihosting operations",
1620 "semihosting_cmdline",
1621 .handler
= handle_common_semihosting_cmdline
,
1622 .mode
= COMMAND_EXEC
,
1623 .usage
= "arguments",
1624 .help
= "command line arguments to be passed to program",
1627 "semihosting_fileio",
1628 .handler
= handle_common_semihosting_fileio_command
,
1629 .mode
= COMMAND_EXEC
,
1630 .usage
= "['enable'|'disable']",
1631 .help
= "activate support for semihosting fileio operations",
1634 "semihosting_resexit",
1635 .handler
= handle_common_semihosting_resumable_exit_command
,
1636 .mode
= COMMAND_EXEC
,
1637 .usage
= "['enable'|'disable']",
1638 .help
= "activate support for semihosting resumable exit",
1640 COMMAND_REGISTRATION_DONE