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