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
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)