OpenOCD
semihosting_common.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2018 by Liviu Ionescu *
5  * <ilg@livius.net> *
6  * *
7  * Copyright (C) 2018 by Marvell Technology Group Ltd. *
8  * Written by Nicolas Pitre <nico@marvell.com> *
9  * *
10  * Copyright (C) 2010 by Spencer Oliver *
11  * spen@spen-soft.co.uk *
12  * *
13  * Copyright (C) 2016 by Square, Inc. *
14  * Steven Stallion <stallion@squareup.com> *
15  ***************************************************************************/
16 
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35 
36 #include "target.h"
37 #include "target_type.h"
38 #include "semihosting_common.h"
39 
40 #include <helper/binarybuffer.h>
41 #include <helper/log.h>
42 #include <server/gdb_server.h>
43 #include <sys/stat.h>
44 
50 enum {
51  TARGET_O_RDONLY = 0x000,
52  TARGET_O_WRONLY = 0x001,
53  TARGET_O_RDWR = 0x002,
54  TARGET_O_APPEND = 0x008,
55  TARGET_O_CREAT = 0x200,
56  TARGET_O_TRUNC = 0x400,
57  /* O_EXCL=0x800 is not required in this implementation. */
58 };
59 
60 /* GDB remote protocol does not differentiate between text and binary open modes. */
61 static const int open_gdb_modeflags[12] = {
74 };
75 
76 static const int open_host_modeflags[12] = {
77  O_RDONLY,
78  O_RDONLY | O_BINARY,
79  O_RDWR,
80  O_RDWR | O_BINARY,
81  O_WRONLY | O_CREAT | O_TRUNC,
82  O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
83  O_RDWR | O_CREAT | O_TRUNC,
84  O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
85  O_WRONLY | O_CREAT | O_APPEND,
86  O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
87  O_RDWR | O_CREAT | O_APPEND,
88  O_RDWR | O_CREAT | O_APPEND | O_BINARY
89 };
90 
92  struct gdb_fileio_info *fileio_info);
93 static int semihosting_common_fileio_end(struct target *target, int result,
94  int fileio_errno, bool ctrl_c);
95 
104 int semihosting_common_init(struct target *target, void *setup,
105  void *post_result)
106 {
107  LOG_DEBUG(" ");
108 
109  target->fileio_info = malloc(sizeof(*target->fileio_info));
110  if (!target->fileio_info) {
111  LOG_ERROR("out of memory");
112  return ERROR_FAIL;
113  }
114  memset(target->fileio_info, 0, sizeof(*target->fileio_info));
115 
116  struct semihosting *semihosting;
117  semihosting = malloc(sizeof(*target->semihosting));
118  if (!semihosting) {
119  LOG_ERROR("out of memory");
120  return ERROR_FAIL;
121  }
122 
123  semihosting->is_active = false;
126  semihosting->stdin_fd = -1;
127  semihosting->stdout_fd = -1;
128  semihosting->stderr_fd = -1;
129  semihosting->is_fileio = false;
130  semihosting->hit_fileio = false;
131  semihosting->is_resumable = false;
134  semihosting->op = -1;
135  semihosting->param = 0;
136  semihosting->result = -1;
137  semihosting->sys_errno = -1;
140 
141  /* If possible, update it in setup(). */
142  semihosting->setup_time = clock();
143 
147 
149 
152 
153  return ERROR_OK;
154 }
155 
158  char *name;
159  int error;
160 };
161 
163 {
165  return false;
166 
167  bool is_read_op = false;
168 
169  switch (semihosting->op) {
170  /* check debug semihosting operations: READC, WRITEC and WRITE0 */
172  is_read_op = true;
173  /* fall through */
176  /* debug operations are redirected when CFG is either DEBUG or ALL */
178  return false;
179  break;
180 
181  /* check stdio semihosting operations: READ and WRITE */
183  is_read_op = true;
184  /* fall through */
186  /* stdio operations are redirected when CFG is either STDIO or ALL */
188  return false;
189  break;
190 
191  default:
192  return false;
193  }
194 
195  if (is_read_op)
196  return fd == semihosting->stdin_fd;
197 
198  /* write operation */
199  return fd == semihosting->stdout_fd || fd == semihosting->stderr_fd;
200 }
201 
202 static ssize_t semihosting_redirect_write(struct semihosting *semihosting, void *buf, int size)
203 {
204  if (!semihosting->tcp_connection) {
205  LOG_ERROR("No connected TCP client for semihosting");
206  semihosting->sys_errno = EBADF; /* Bad file number */
207  return -1;
208  }
209 
211 
212  int retval = connection_write(semihosting->tcp_connection, buf, size);
213 
214  if (retval < 0)
216 
217  return retval;
218 }
219 
220 static ssize_t semihosting_write(struct semihosting *semihosting, int fd, void *buf, int size)
221 {
224 
225  /* default write */
226  int result = write(fd, buf, size);
227  if (result == -1)
228  semihosting->sys_errno = errno;
229  return result;
230 }
231 
232 static ssize_t semihosting_redirect_read(struct semihosting *semihosting, void *buf, int size)
233 {
234  if (!semihosting->tcp_connection) {
235  LOG_ERROR("No connected TCP client for semihosting");
236  semihosting->sys_errno = EBADF; /* Bad file number */
237  return -1;
238  }
239 
241 
242  service->error = ERROR_OK;
244 
245  int retval = connection_read(semihosting->tcp_connection, buf, size);
246 
247  if (retval <= 0)
249 
250  if (retval < 0)
252 
254 
255  return retval;
256 }
257 
258 static inline int semihosting_putchar(struct semihosting *semihosting, int fd, int c)
259 {
262 
263  /* default putchar */
264  return putchar(c);
265 }
266 
267 static inline ssize_t semihosting_read(struct semihosting *semihosting, int fd, void *buf, int size)
268 {
271 
272  /* default read */
273  ssize_t result = read(fd, buf, size);
274  if (result == -1)
275  semihosting->sys_errno = errno;
276 
277  return result;
278 }
279 
280 static inline int semihosting_getchar(struct semihosting *semihosting, int fd)
281 {
283  unsigned char c;
284 
285  if (semihosting_redirect_read(semihosting, &c, 1) > 0)
286  return c;
287 
288  return EOF;
289  }
290 
291  /* default getchar */
292  return getchar();
293 }
294 
300 
301 const char *semihosting_opcode_to_str(const uint64_t opcode)
302 {
303  switch (opcode) {
305  return "CLOSE";
307  return "CLOCK";
309  return "ELAPSED";
311  return "ERRNO";
313  return "EXIT";
315  return "EXIT_EXTENDED";
317  return "FLEN";
319  return "GET_CMDLINE";
321  return "HEAPINFO";
323  return "ISERROR";
325  return "ISTTY";
327  return "OPEN";
329  return "READ";
331  return "READC";
333  return "REMOVE";
335  return "RENAME";
337  return "SEEK";
339  return "SYSTEM";
341  return "TICKFREQ";
343  return "TIME";
345  return "TMPNAM";
347  return "WRITE";
349  return "WRITEC";
351  return "WRITE0";
353  return "USER_CMD";
355  return "ARM_RESERVED_CMD";
356  default:
357  return "<unknown>";
358  }
359 }
360 
367 {
369  if (!semihosting) {
370  /* Silently ignore if the semihosting field was not set. */
371  return ERROR_OK;
372  }
373 
374  struct gdb_fileio_info *fileio_info = target->fileio_info;
375 
376  /*
377  * By default return an error.
378  * The actual result must be set by each function
379  */
380  semihosting->result = -1;
381 
382  /* Most operations are resumable, except the two exit calls. */
383  semihosting->is_resumable = true;
384 
385  int retval;
386 
387  /* Enough space to hold 4 long words. */
388  uint8_t fields[4*8];
389 
390  LOG_DEBUG("op=0x%x (%s), param=0x%" PRIx64, semihosting->op,
392  semihosting->param);
393 
394  switch (semihosting->op) {
395 
396  case SEMIHOSTING_SYS_CLOCK: /* 0x10 */
397  /*
398  * Returns the number of centiseconds (hundredths of a second)
399  * since the execution started.
400  *
401  * Values returned can be of limited use for some benchmarking
402  * purposes because of communication overhead or other
403  * agent-specific factors. For example, with a debug hardware
404  * unit the request is passed back to the host for execution.
405  * This can lead to unpredictable delays in transmission and
406  * process scheduling.
407  *
408  * Use this function to calculate time intervals, by calculating
409  * differences between intervals with and without the code
410  * sequence to be timed.
411  *
412  * Entry
413  * The PARAMETER REGISTER must contain 0. There are no other
414  * parameters.
415  *
416  * Return
417  * On exit, the RETURN REGISTER contains:
418  * - The number of centiseconds since some arbitrary start
419  * point, if the call is successful.
420  * - –1 if the call is not successful. For example, because
421  * of a communications error.
422  */
423  {
424  clock_t delta = clock() - semihosting->setup_time;
425 
426  semihosting->result = delta / (CLOCKS_PER_SEC / 100);
427  }
428  break;
429 
430  case SEMIHOSTING_SYS_CLOSE: /* 0x02 */
431  /*
432  * Closes a file on the host system. The handle must reference
433  * a file that was opened with SYS_OPEN.
434  *
435  * Entry
436  * On entry, the PARAMETER REGISTER contains a pointer to a
437  * one-field argument block:
438  * - field 1 Contains a handle for an open file.
439  *
440  * Return
441  * On exit, the RETURN REGISTER contains:
442  * - 0 if the call is successful
443  * - –1 if the call is not successful.
444  */
445  retval = semihosting_read_fields(target, 1, fields);
446  if (retval != ERROR_OK)
447  return retval;
448  else {
449  int fd = semihosting_get_field(target, 0, fields);
450  /* Do not allow to close OpenOCD's own standard streams */
451  if (fd == 0 || fd == 1 || fd == 2) {
452  LOG_DEBUG("ignoring semihosting attempt to close %s",
453  (fd == 0) ? "stdin" :
454  (fd == 1) ? "stdout" : "stderr");
455  /* Just pretend success */
456  semihosting->result = 0;
457  break;
458  }
459  /* Close the descriptor */
460  if (semihosting->is_fileio) {
461  semihosting->hit_fileio = true;
462  fileio_info->identifier = "close";
463  fileio_info->param_1 = fd;
464  } else {
465  semihosting->result = close(fd);
466  if (semihosting->result == -1)
467  semihosting->sys_errno = errno;
468  LOG_DEBUG("close(%d)=%" PRId64, fd, semihosting->result);
469  }
470  }
471  break;
472 
473  case SEMIHOSTING_SYS_ERRNO: /* 0x13 */
474  /*
475  * Returns the value of the C library errno variable that is
476  * associated with the semihosting implementation. The errno
477  * variable can be set by a number of C library semihosted
478  * functions, including:
479  * - SYS_REMOVE
480  * - SYS_OPEN
481  * - SYS_CLOSE
482  * - SYS_READ
483  * - SYS_WRITE
484  * - SYS_SEEK.
485  *
486  * Whether errno is set or not, and to what value, is entirely
487  * host-specific, except where the ISO C standard defines the
488  * behavior.
489  *
490  * Entry
491  * There are no parameters. The PARAMETER REGISTER must be 0.
492  *
493  * Return
494  * On exit, the RETURN REGISTER contains the value of the C
495  * library errno variable.
496  */
498  break;
499 
500  case SEMIHOSTING_SYS_EXIT: /* 0x18 */
501  /*
502  * Note: SYS_EXIT was called angel_SWIreason_ReportException in
503  * previous versions of the documentation.
504  *
505  * An application calls this operation to report an exception
506  * to the debugger directly. The most common use is to report
507  * that execution has completed, using ADP_Stopped_ApplicationExit.
508  *
509  * Note: This semihosting operation provides no means for 32-bit
510  * callers to indicate an application exit with a specified exit
511  * code. Semihosting callers may prefer to check for the presence
512  * of the SH_EXT_EXTENDED_REPORT_EXCEPTION extension and use
513  * the SYS_REPORT_EXCEPTION_EXTENDED operation instead, if it
514  * is available.
515  *
516  * Entry (32-bit)
517  * On entry, the PARAMETER register is set to a reason code
518  * describing the cause of the trap. Not all semihosting client
519  * implementations will necessarily trap every corresponding
520  * event. Important reason codes are:
521  *
522  * - ADP_Stopped_ApplicationExit 0x20026
523  * - ADP_Stopped_RunTimeErrorUnknown 0x20023
524  *
525  * Entry (64-bit)
526  * On entry, the PARAMETER REGISTER contains a pointer to a
527  * two-field argument block:
528  * - field 1 The exception type, which is one of the set of
529  * reason codes in the above tables.
530  * - field 2 A subcode, whose meaning depends on the reason
531  * code in field 1.
532  * In particular, if field 1 is ADP_Stopped_ApplicationExit
533  * then field 2 is an exit status code, as passed to the C
534  * standard library exit() function. A simulator receiving
535  * this request must notify a connected debugger, if present,
536  * and then exit with the specified status.
537  *
538  * Return
539  * No return is expected from these calls. However, it is
540  * possible for the debugger to request that the application
541  * continues by performing an RDI_Execute request or equivalent.
542  * In this case, execution continues with the registers as they
543  * were on entry to the operation, or as subsequently modified
544  * by the debugger.
545  */
546  if (semihosting->word_size_bytes == 8) {
547  retval = semihosting_read_fields(target, 2, fields);
548  if (retval != ERROR_OK)
549  return retval;
550  else {
551  int type = semihosting_get_field(target, 0, fields);
552  int code = semihosting_get_field(target, 1, fields);
553 
556  exit(code);
557  else {
558  fprintf(stderr,
559  "semihosting: *** application exited with %d ***\n",
560  code);
561  }
562  } else {
563  fprintf(stderr,
564  "semihosting: application exception %#x\n",
565  type);
566  }
567  }
568  } else {
571  exit(0);
572  else {
573  fprintf(stderr,
574  "semihosting: *** application exited normally ***\n");
575  }
577  /* Chosen more or less arbitrarily to have a nicer message,
578  * otherwise all other return the same exit code 1. */
580  exit(1);
581  else {
582  fprintf(stderr,
583  "semihosting: *** application exited with error ***\n");
584  }
585  } else {
587  exit(1);
588  else {
589  fprintf(stderr,
590  "semihosting: application exception %#x\n",
591  (unsigned) semihosting->param);
592  }
593  }
594  }
596  semihosting->is_resumable = false;
598  }
599  break;
600 
601  case SEMIHOSTING_SYS_EXIT_EXTENDED: /* 0x20 */
602  /*
603  * This operation is only supported if the semihosting extension
604  * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is
605  * reported using feature byte 0, bit 0. If this extension is
606  * supported, then the implementation provides a means to
607  * report a normal exit with a nonzero exit status in both 32-bit
608  * and 64-bit semihosting APIs.
609  *
610  * The implementation must provide the semihosting call
611  * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs.
612  *
613  * SYS_EXIT_EXTENDED is used by an application to report an
614  * exception or exit to the debugger directly. The most common
615  * use is to report that execution has completed, using
616  * ADP_Stopped_ApplicationExit.
617  *
618  * Entry
619  * On entry, the PARAMETER REGISTER contains a pointer to a
620  * two-field argument block:
621  * - field 1 The exception type, which should be one of the set
622  * of reason codes that are documented for the SYS_EXIT
623  * (0x18) call. For example, ADP_Stopped_ApplicationExit.
624  * - field 2 A subcode, whose meaning depends on the reason
625  * code in field 1. In particular, if field 1 is
626  * ADP_Stopped_ApplicationExit then field 2 is an exit status
627  * code, as passed to the C standard library exit() function.
628  * A simulator receiving this request must notify a connected
629  * debugger, if present, and then exit with the specified status.
630  *
631  * Return
632  * No return is expected from these calls.
633  *
634  * For the A64 API, this call is identical to the behavior of
635  * the mandatory SYS_EXIT (0x18) call. If this extension is
636  * supported, then both calls must be implemented.
637  */
638  retval = semihosting_read_fields(target, 2, fields);
639  if (retval != ERROR_OK)
640  return retval;
641  else {
642  int type = semihosting_get_field(target, 0, fields);
643  int code = semihosting_get_field(target, 1, fields);
644 
647  exit(code);
648  else {
649  fprintf(stderr,
650  "semihosting: *** application exited with %d ***\n",
651  code);
652  }
653  } else {
654  fprintf(stderr, "semihosting: exception %#x\n",
655  type);
656  }
657  }
659  semihosting->is_resumable = false;
661  }
662  break;
663 
664  case SEMIHOSTING_SYS_FLEN: /* 0x0C */
665  /*
666  * Returns the length of a specified file.
667  *
668  * Entry
669  * On entry, the PARAMETER REGISTER contains a pointer to a
670  * one-field argument block:
671  * - field 1 A handle for a previously opened, seekable file
672  * object.
673  *
674  * Return
675  * On exit, the RETURN REGISTER contains:
676  * - The current length of the file object, if the call is
677  * successful.
678  * - –1 if an error occurs.
679  */
680  if (semihosting->is_fileio) {
681  semihosting->result = -1;
682  semihosting->sys_errno = EINVAL;
683  }
684  retval = semihosting_read_fields(target, 1, fields);
685  if (retval != ERROR_OK)
686  return retval;
687  else {
688  int fd = semihosting_get_field(target, 0, fields);
689  struct stat buf;
690  semihosting->result = fstat(fd, &buf);
691  if (semihosting->result == -1) {
692  semihosting->sys_errno = errno;
693  LOG_DEBUG("fstat(%d)=%" PRId64, fd, semihosting->result);
694  break;
695  }
696  LOG_DEBUG("fstat(%d)=%" PRId64, fd, semihosting->result);
697  semihosting->result = buf.st_size;
698  }
699  break;
700 
701  case SEMIHOSTING_SYS_GET_CMDLINE: /* 0x15 */
702  /*
703  * Returns the command line that is used for the call to the
704  * executable, that is, argc and argv.
705  *
706  * Entry
707  * On entry, the PARAMETER REGISTER points to a two-field data
708  * block to be used for returning the command string and its length:
709  * - field 1 A pointer to a buffer of at least the size that is
710  * specified in field 2.
711  * - field 2 The length of the buffer in bytes.
712  *
713  * Return
714  * On exit:
715  * If the call is successful, then the RETURN REGISTER contains 0,
716  * the PARAMETER REGISTER is unchanged, and the data block is
717  * updated as follows:
718  * - field 1 A pointer to a null-terminated string of the command
719  * line.
720  * - field 2 The length of the string in bytes.
721  * If the call is not successful, then the RETURN REGISTER
722  * contains -1.
723  *
724  * Note: The semihosting implementation might impose limits on
725  * the maximum length of the string that can be transferred.
726  * However, the implementation must be able to support a
727  * command-line length of at least 80 bytes.
728  */
729  retval = semihosting_read_fields(target, 2, fields);
730  if (retval != ERROR_OK)
731  return retval;
732  else {
733  uint64_t addr = semihosting_get_field(target, 0, fields);
734  size_t size = semihosting_get_field(target, 1, fields);
735 
736  char *arg = semihosting->cmdline ?
737  semihosting->cmdline : "";
738  uint32_t len = strlen(arg) + 1;
739  if (len > size)
740  semihosting->result = -1;
741  else {
742  semihosting_set_field(target, len, 1, fields);
743  retval = target_write_buffer(target, addr, len,
744  (uint8_t *)arg);
745  if (retval != ERROR_OK)
746  return retval;
747  semihosting->result = 0;
748 
749  retval = semihosting_write_fields(target, 2, fields);
750  if (retval != ERROR_OK)
751  return retval;
752  }
753  LOG_DEBUG("SYS_GET_CMDLINE=[%s], %" PRId64, arg, semihosting->result);
754  }
755  break;
756 
757  case SEMIHOSTING_SYS_HEAPINFO: /* 0x16 */
758  /*
759  * Returns the system stack and heap parameters.
760  *
761  * Entry
762  * On entry, the PARAMETER REGISTER contains the address of a
763  * pointer to a four-field data block. The contents of the data
764  * block are filled by the function. The following C-like
765  * pseudocode describes the layout of the block:
766  * struct block {
767  * void* heap_base;
768  * void* heap_limit;
769  * void* stack_base;
770  * void* stack_limit;
771  * };
772  *
773  * Return
774  * On exit, the PARAMETER REGISTER is unchanged and the data
775  * block has been updated.
776  */
777  retval = semihosting_read_fields(target, 1, fields);
778  if (retval != ERROR_OK)
779  return retval;
780  else {
781  uint64_t addr = semihosting_get_field(target, 0, fields);
782  /* tell the remote we have no idea */
783  memset(fields, 0, 4 * semihosting->word_size_bytes);
784  retval = target_write_memory(target, addr, 4,
786  fields);
787  if (retval != ERROR_OK)
788  return retval;
789  semihosting->result = 0;
790  }
791  break;
792 
793  case SEMIHOSTING_SYS_ISERROR: /* 0x08 */
794  /*
795  * Determines whether the return code from another semihosting
796  * call is an error status or not.
797  *
798  * This call is passed a parameter block containing the error
799  * code to examine.
800  *
801  * Entry
802  * On entry, the PARAMETER REGISTER contains a pointer to a
803  * one-field data block:
804  * - field 1 The required status word to check.
805  *
806  * Return
807  * On exit, the RETURN REGISTER contains:
808  * - 0 if the status field is not an error indication
809  * - A nonzero value if the status field is an error indication.
810  */
811  retval = semihosting_read_fields(target, 1, fields);
812  if (retval != ERROR_OK)
813  return retval;
814 
815  uint64_t code = semihosting_get_field(target, 0, fields);
816  semihosting->result = (code != 0);
817  break;
818 
819  case SEMIHOSTING_SYS_ISTTY: /* 0x09 */
820  /*
821  * Checks whether a file is connected to an interactive device.
822  *
823  * Entry
824  * On entry, the PARAMETER REGISTER contains a pointer to a
825  * one-field argument block:
826  * field 1 A handle for a previously opened file object.
827  *
828  * Return
829  * On exit, the RETURN REGISTER contains:
830  * - 1 if the handle identifies an interactive device.
831  * - 0 if the handle identifies a file.
832  * - A value other than 1 or 0 if an error occurs.
833  */
834  if (semihosting->is_fileio) {
835  semihosting->hit_fileio = true;
836  fileio_info->identifier = "isatty";
837  fileio_info->param_1 = semihosting->param;
838  } else {
839  retval = semihosting_read_fields(target, 1, fields);
840  if (retval != ERROR_OK)
841  return retval;
842  int fd = semihosting_get_field(target, 0, fields);
843  // isatty() on Windows may return any non-zero value if fd is a terminal
844  semihosting->result = isatty(fd) ? 1 : 0;
845  if (semihosting->result == 0)
846  semihosting->sys_errno = errno;
847  LOG_DEBUG("isatty(%d)=%" PRId64, fd, semihosting->result);
848  }
849  break;
850 
851  case SEMIHOSTING_SYS_OPEN: /* 0x01 */
852  /*
853  * Opens a file on the host system.
854  *
855  * The file path is specified either as relative to the current
856  * directory of the host process, or absolute, using the path
857  * conventions of the host operating system.
858  *
859  * Semihosting implementations must support opening the special
860  * path name :semihosting-features as part of the semihosting
861  * extensions reporting mechanism.
862  *
863  * ARM targets interpret the special path name :tt as meaning
864  * the console input stream, for an open-read or the console
865  * output stream, for an open-write. Opening these streams is
866  * performed as part of the standard startup code for those
867  * applications that reference the C stdio streams. The
868  * semihosting extension SH_EXT_STDOUT_STDERR allows the
869  * semihosting caller to open separate output streams
870  * corresponding to stdout and stderr. This extension is
871  * reported using feature byte 0, bit 1. Use SYS_OPEN with
872  * the special path name :semihosting-features to access the
873  * feature bits.
874  *
875  * If this extension is supported, the implementation must
876  * support the following additional semantics to SYS_OPEN:
877  * - If the special path name :tt is opened with an fopen
878  * mode requesting write access (w, wb, w+, or w+b), then
879  * this is a request to open stdout.
880  * - If the special path name :tt is opened with a mode
881  * requesting append access (a, ab, a+, or a+b), then this is
882  * a request to open stderr.
883  *
884  * Entry
885  * On entry, the PARAMETER REGISTER contains a pointer to a
886  * three-field argument block:
887  * - field 1 A pointer to a null-terminated string containing
888  * a file or device name.
889  * - field 2 An integer that specifies the file opening mode.
890  * - field 3 An integer that gives the length of the string
891  * pointed to by field 1.
892  *
893  * The length does not include the terminating null character
894  * that must be present.
895  *
896  * Return
897  * On exit, the RETURN REGISTER contains:
898  * - A nonzero handle if the call is successful.
899  * - –1 if the call is not successful.
900  */
901  retval = semihosting_read_fields(target, 3, fields);
902  if (retval != ERROR_OK)
903  return retval;
904  else {
905  uint64_t addr = semihosting_get_field(target, 0, fields);
906  uint32_t mode = semihosting_get_field(target, 1, fields);
907  size_t len = semihosting_get_field(target, 2, fields);
908 
909  if (mode > 11) {
910  semihosting->result = -1;
911  semihosting->sys_errno = EINVAL;
912  break;
913  }
914  size_t basedir_len = semihosting->basedir ? strlen(semihosting->basedir) : 0;
915  uint8_t *fn = malloc(basedir_len + len + 2);
916  if (!fn) {
917  semihosting->result = -1;
918  semihosting->sys_errno = ENOMEM;
919  } else {
920  if (basedir_len > 0) {
921  strcpy((char *)fn, semihosting->basedir);
922  if (fn[basedir_len - 1] != '/')
923  fn[basedir_len++] = '/';
924  }
925  retval = target_read_memory(target, addr, 1, len, fn + basedir_len);
926  if (retval != ERROR_OK) {
927  free(fn);
928  return retval;
929  }
930  fn[basedir_len + len] = 0;
931  /* TODO: implement the :semihosting-features special file.
932  * */
933  if (semihosting->is_fileio) {
934  if (strcmp((char *)fn, ":semihosting-features") == 0) {
935  semihosting->result = -1;
936  semihosting->sys_errno = EINVAL;
937  } else if (strcmp((char *)fn, ":tt") == 0) {
938  if (mode == 0) {
939  semihosting->result = 0;
940  } else if (mode == 4) {
941  semihosting->result = 1;
942  } else if (mode == 8) {
943  semihosting->result = 2;
944  } else {
945  semihosting->result = -1;
946  semihosting->sys_errno = EINVAL;
947  }
948  } else {
949  semihosting->hit_fileio = true;
950  fileio_info->identifier = "open";
951  fileio_info->param_1 = addr;
952  fileio_info->param_2 = len;
953  fileio_info->param_3 = open_gdb_modeflags[mode];
954  fileio_info->param_4 = 0644;
955  }
956  } else {
957  if (strcmp((char *)fn, ":tt") == 0) {
958  /* Mode is:
959  * - 0-3 ("r") for stdin,
960  * - 4-7 ("w") for stdout,
961  * - 8-11 ("a") for stderr */
962  int fd;
963  if (mode < 4) {
964  fd = dup(STDIN_FILENO);
965  semihosting->stdin_fd = fd;
966  LOG_DEBUG("dup(STDIN)=%d", fd);
967  } else if (mode < 8) {
968  fd = dup(STDOUT_FILENO);
969  semihosting->stdout_fd = fd;
970  LOG_DEBUG("dup(STDOUT)=%d", fd);
971  } else {
972  fd = dup(STDERR_FILENO);
973  semihosting->stderr_fd = fd;
974  LOG_DEBUG("dup(STDERR)=%d", fd);
975  }
976  semihosting->result = fd;
977  if (fd == -1)
978  semihosting->sys_errno = errno;
979  } else {
980  /* cygwin requires the permission setting
981  * otherwise it will fail to reopen a previously
982  * written file */
983  semihosting->result = open((char *)fn,
985  0644);
986  if (semihosting->result == -1)
987  semihosting->sys_errno = errno;
988  LOG_DEBUG("open('%s')=%" PRId64, fn, semihosting->result);
989  }
990  }
991  free(fn);
992  }
993  }
994  break;
995 
996  case SEMIHOSTING_SYS_READ: /* 0x06 */
997  /*
998  * Reads the contents of a file into a buffer. The file position
999  * is specified either:
1000  * - Explicitly by a SYS_SEEK.
1001  * - Implicitly one byte beyond the previous SYS_READ or
1002  * SYS_WRITE request.
1003  *
1004  * The file position is at the start of the file when it is
1005  * opened, and is lost when the file is closed. Perform the
1006  * file operation as a single action whenever possible. For
1007  * example, do not split a read of 16KB into four 4KB chunks
1008  * unless there is no alternative.
1009  *
1010  * Entry
1011  * On entry, the PARAMETER REGISTER contains a pointer to a
1012  * three-field data block:
1013  * - field 1 Contains a handle for a file previously opened
1014  * with SYS_OPEN.
1015  * - field 2 Points to a buffer.
1016  * - field 3 Contains the number of bytes to read to the buffer
1017  * from the file.
1018  *
1019  * Return
1020  * On exit, the RETURN REGISTER contains the number of bytes not
1021  * filled in the buffer (buffer_length - bytes_read) as follows:
1022  * - If the RETURN REGISTER is 0, the entire buffer was
1023  * successfully filled.
1024  * - If the RETURN REGISTER is the same as field 3, no bytes
1025  * were read (EOF can be assumed).
1026  * - If the RETURN REGISTER contains a value smaller than
1027  * field 3, the read succeeded but the buffer was only partly
1028  * filled. For interactive devices, this is the most common
1029  * return value.
1030  */
1031  retval = semihosting_read_fields(target, 3, fields);
1032  if (retval != ERROR_OK)
1033  return retval;
1034  else {
1035  int fd = semihosting_get_field(target, 0, fields);
1036  uint64_t addr = semihosting_get_field(target, 1, fields);
1037  size_t len = semihosting_get_field(target, 2, fields);
1038  if (semihosting->is_fileio) {
1039  semihosting->hit_fileio = true;
1040  fileio_info->identifier = "read";
1041  fileio_info->param_1 = fd;
1042  fileio_info->param_2 = addr;
1043  fileio_info->param_3 = len;
1044  } else {
1045  uint8_t *buf = malloc(len);
1046  if (!buf) {
1047  semihosting->result = -1;
1048  semihosting->sys_errno = ENOMEM;
1049  } else {
1050  semihosting->result = semihosting_read(semihosting, fd, buf, len);
1051  LOG_DEBUG("read(%d, 0x%" PRIx64 ", %zu)=%" PRId64,
1052  fd,
1053  addr,
1054  len,
1055  semihosting->result);
1056  if (semihosting->result >= 0) {
1057  retval = target_write_buffer(target, addr,
1059  buf);
1060  if (retval != ERROR_OK) {
1061  free(buf);
1062  return retval;
1063  }
1064  /* the number of bytes NOT filled in */
1065  semihosting->result = len -
1067  }
1068  free(buf);
1069  }
1070  }
1071  }
1072  break;
1073 
1074  case SEMIHOSTING_SYS_READC: /* 0x07 */
1075  /*
1076  * Reads a byte from the console.
1077  *
1078  * Entry
1079  * The PARAMETER REGISTER must contain 0. There are no other
1080  * parameters or values possible.
1081  *
1082  * Return
1083  * On exit, the RETURN REGISTER contains the byte read from
1084  * the console.
1085  */
1086  if (semihosting->is_fileio) {
1087  LOG_ERROR("SYS_READC not supported by semihosting fileio");
1088  return ERROR_FAIL;
1089  }
1091  LOG_DEBUG("getchar()=%" PRId64, semihosting->result);
1092  break;
1093 
1094  case SEMIHOSTING_SYS_REMOVE: /* 0x0E */
1095  /*
1096  * Deletes a specified file on the host filing system.
1097  *
1098  * Entry
1099  * On entry, the PARAMETER REGISTER contains a pointer to a
1100  * two-field argument block:
1101  * - field 1 Points to a null-terminated string that gives the
1102  * path name of the file to be deleted.
1103  * - field 2 The length of the string.
1104  *
1105  * Return
1106  * On exit, the RETURN REGISTER contains:
1107  * - 0 if the delete is successful
1108  * - A nonzero, host-specific error code if the delete fails.
1109  */
1110  retval = semihosting_read_fields(target, 2, fields);
1111  if (retval != ERROR_OK)
1112  return retval;
1113  else {
1114  uint64_t addr = semihosting_get_field(target, 0, fields);
1115  size_t len = semihosting_get_field(target, 1, fields);
1116  if (semihosting->is_fileio) {
1117  semihosting->hit_fileio = true;
1118  fileio_info->identifier = "unlink";
1119  fileio_info->param_1 = addr;
1120  fileio_info->param_2 = len;
1121  } else {
1122  uint8_t *fn = malloc(len+1);
1123  if (!fn) {
1124  semihosting->result = -1;
1125  semihosting->sys_errno = ENOMEM;
1126  } else {
1127  retval =
1128  target_read_memory(target, addr, 1, len,
1129  fn);
1130  if (retval != ERROR_OK) {
1131  free(fn);
1132  return retval;
1133  }
1134  fn[len] = 0;
1135  semihosting->result = remove((char *)fn);
1136  if (semihosting->result == -1)
1137  semihosting->sys_errno = errno;
1138  LOG_DEBUG("remove('%s')=%" PRId64, fn, semihosting->result);
1139 
1140  free(fn);
1141  }
1142  }
1143  }
1144  break;
1145 
1146  case SEMIHOSTING_SYS_RENAME: /* 0x0F */
1147  /*
1148  * Renames a specified file.
1149  *
1150  * Entry
1151  * On entry, the PARAMETER REGISTER contains a pointer to a
1152  * four-field data block:
1153  * - field 1 A pointer to the name of the old file.
1154  * - field 2 The length of the old filename.
1155  * - field 3 A pointer to the new filename.
1156  * - field 4 The length of the new filename. Both strings are
1157  * null-terminated.
1158  *
1159  * Return
1160  * On exit, the RETURN REGISTER contains:
1161  * - 0 if the rename is successful.
1162  * - A nonzero, host-specific error code if the rename fails.
1163  */
1164  retval = semihosting_read_fields(target, 4, fields);
1165  if (retval != ERROR_OK)
1166  return retval;
1167  else {
1168  uint64_t addr1 = semihosting_get_field(target, 0, fields);
1169  size_t len1 = semihosting_get_field(target, 1, fields);
1170  uint64_t addr2 = semihosting_get_field(target, 2, fields);
1171  size_t len2 = semihosting_get_field(target, 3, fields);
1172  if (semihosting->is_fileio) {
1173  semihosting->hit_fileio = true;
1174  fileio_info->identifier = "rename";
1175  fileio_info->param_1 = addr1;
1176  fileio_info->param_2 = len1;
1177  fileio_info->param_3 = addr2;
1178  fileio_info->param_4 = len2;
1179  } else {
1180  uint8_t *fn1 = malloc(len1+1);
1181  uint8_t *fn2 = malloc(len2+1);
1182  if (!fn1 || !fn2) {
1183  free(fn1);
1184  free(fn2);
1185  semihosting->result = -1;
1186  semihosting->sys_errno = ENOMEM;
1187  } else {
1188  retval = target_read_memory(target, addr1, 1, len1,
1189  fn1);
1190  if (retval != ERROR_OK) {
1191  free(fn1);
1192  free(fn2);
1193  return retval;
1194  }
1195  retval = target_read_memory(target, addr2, 1, len2,
1196  fn2);
1197  if (retval != ERROR_OK) {
1198  free(fn1);
1199  free(fn2);
1200  return retval;
1201  }
1202  fn1[len1] = 0;
1203  fn2[len2] = 0;
1204  semihosting->result = rename((char *)fn1,
1205  (char *)fn2);
1206  // rename() on Windows returns nonzero on error
1207  if (semihosting->result != 0)
1208  semihosting->sys_errno = errno;
1209  LOG_DEBUG("rename('%s', '%s')=%" PRId64 " %d", fn1, fn2, semihosting->result, errno);
1210  free(fn1);
1211  free(fn2);
1212  }
1213  }
1214  }
1215  break;
1216 
1217  case SEMIHOSTING_SYS_SEEK: /* 0x0A */
1218  /*
1219  * Seeks to a specified position in a file using an offset
1220  * specified from the start of the file. The file is assumed
1221  * to be a byte array and the offset is given in bytes.
1222  *
1223  * Entry
1224  * On entry, the PARAMETER REGISTER contains a pointer to a
1225  * two-field data block:
1226  * - field 1 A handle for a seekable file object.
1227  * - field 2 The absolute byte position to seek to.
1228  *
1229  * Return
1230  * On exit, the RETURN REGISTER contains:
1231  * - 0 if the request is successful.
1232  * - A negative value if the request is not successful.
1233  * Use SYS_ERRNO to read the value of the host errno variable
1234  * describing the error.
1235  *
1236  * Note: The effect of seeking outside the current extent of
1237  * the file object is undefined.
1238  */
1239  retval = semihosting_read_fields(target, 2, fields);
1240  if (retval != ERROR_OK)
1241  return retval;
1242  else {
1243  int fd = semihosting_get_field(target, 0, fields);
1244  off_t pos = semihosting_get_field(target, 1, fields);
1245  if (semihosting->is_fileio) {
1246  semihosting->hit_fileio = true;
1247  fileio_info->identifier = "lseek";
1248  fileio_info->param_1 = fd;
1249  fileio_info->param_2 = pos;
1250  fileio_info->param_3 = SEEK_SET;
1251  } else {
1252  semihosting->result = lseek(fd, pos, SEEK_SET);
1253  if (semihosting->result == -1)
1254  semihosting->sys_errno = errno;
1255  LOG_DEBUG("lseek(%d, %d)=%" PRId64, fd, (int)pos, semihosting->result);
1256  if (semihosting->result == pos)
1257  semihosting->result = 0;
1258  }
1259  }
1260  break;
1261 
1262  case SEMIHOSTING_SYS_SYSTEM: /* 0x12 */
1263  /*
1264  * Passes a command to the host command-line interpreter.
1265  * This enables you to execute a system command such as dir,
1266  * ls, or pwd. The terminal I/O is on the host, and is not
1267  * visible to the target.
1268  *
1269  * Entry
1270  * On entry, the PARAMETER REGISTER contains a pointer to a
1271  * two-field argument block:
1272  * - field 1 Points to a string to be passed to the host
1273  * command-line interpreter.
1274  * - field 2 The length of the string.
1275  *
1276  * Return
1277  * On exit, the RETURN REGISTER contains the return status.
1278  */
1279 
1280  /* Provide SYS_SYSTEM functionality. Uses the
1281  * libc system command, there may be a reason *NOT*
1282  * to use this, but as I can't think of one, I
1283  * implemented it this way.
1284  */
1285  retval = semihosting_read_fields(target, 2, fields);
1286  if (retval != ERROR_OK)
1287  return retval;
1288  else {
1289  uint64_t addr = semihosting_get_field(target, 0, fields);
1290  size_t len = semihosting_get_field(target, 1, fields);
1291  if (semihosting->is_fileio) {
1292  semihosting->hit_fileio = true;
1293  fileio_info->identifier = "system";
1294  fileio_info->param_1 = addr;
1295  fileio_info->param_2 = len;
1296  } else {
1297  uint8_t *cmd = malloc(len+1);
1298  if (!cmd) {
1299  semihosting->result = -1;
1300  semihosting->sys_errno = ENOMEM;
1301  } else {
1302  retval = target_read_memory(target,
1303  addr,
1304  1,
1305  len,
1306  cmd);
1307  if (retval != ERROR_OK) {
1308  free(cmd);
1309  return retval;
1310  } else {
1311  cmd[len] = 0;
1312  semihosting->result = system(
1313  (const char *)cmd);
1314  LOG_DEBUG("system('%s')=%" PRId64, cmd, semihosting->result);
1315  }
1316 
1317  free(cmd);
1318  }
1319  }
1320  }
1321  break;
1322 
1323  case SEMIHOSTING_SYS_TIME: /* 0x11 */
1324  /*
1325  * Returns the number of seconds since 00:00 January 1, 1970.
1326  * This value is real-world time, regardless of any debug agent
1327  * configuration.
1328  *
1329  * Entry
1330  * There are no parameters.
1331  *
1332  * Return
1333  * On exit, the RETURN REGISTER contains the number of seconds.
1334  */
1335  semihosting->result = time(NULL);
1336  break;
1337 
1338  case SEMIHOSTING_SYS_WRITE: /* 0x05 */
1339  /*
1340  * Writes the contents of a buffer to a specified file at the
1341  * current file position. The file position is specified either:
1342  * - Explicitly, by a SYS_SEEK.
1343  * - Implicitly as one byte beyond the previous SYS_READ or
1344  * SYS_WRITE request.
1345  *
1346  * The file position is at the start of the file when the file
1347  * is opened, and is lost when the file is closed.
1348  *
1349  * Perform the file operation as a single action whenever
1350  * possible. For example, do not split a write of 16KB into
1351  * four 4KB chunks unless there is no alternative.
1352  *
1353  * Entry
1354  * On entry, the PARAMETER REGISTER contains a pointer to a
1355  * three-field data block:
1356  * - field 1 Contains a handle for a file previously opened
1357  * with SYS_OPEN.
1358  * - field 2 Points to the memory containing the data to be written.
1359  * - field 3 Contains the number of bytes to be written from
1360  * the buffer to the file.
1361  *
1362  * Return
1363  * On exit, the RETURN REGISTER contains:
1364  * - 0 if the call is successful.
1365  * - The number of bytes that are not written, if there is an error.
1366  */
1367  retval = semihosting_read_fields(target, 3, fields);
1368  if (retval != ERROR_OK)
1369  return retval;
1370  else {
1371  int fd = semihosting_get_field(target, 0, fields);
1372  uint64_t addr = semihosting_get_field(target, 1, fields);
1373  size_t len = semihosting_get_field(target, 2, fields);
1374  if (semihosting->is_fileio) {
1375  semihosting->hit_fileio = true;
1376  fileio_info->identifier = "write";
1377  fileio_info->param_1 = fd;
1378  fileio_info->param_2 = addr;
1379  fileio_info->param_3 = len;
1380  } else {
1381  uint8_t *buf = malloc(len);
1382  if (!buf) {
1383  semihosting->result = -1;
1384  semihosting->sys_errno = ENOMEM;
1385  } else {
1386  retval = target_read_buffer(target, addr, len, buf);
1387  if (retval != ERROR_OK) {
1388  free(buf);
1389  return retval;
1390  }
1391  semihosting->result = semihosting_write(semihosting, fd, buf, len);
1392  LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%" PRId64,
1393  fd,
1394  addr,
1395  len,
1396  semihosting->result);
1397  if (semihosting->result >= 0) {
1398  /* The number of bytes that are NOT written.
1399  * */
1400  semihosting->result = len -
1402  }
1403 
1404  free(buf);
1405  }
1406  }
1407  }
1408  break;
1409 
1410  case SEMIHOSTING_SYS_WRITEC: /* 0x03 */
1411  /*
1412  * Writes a character byte, pointed to by the PARAMETER REGISTER,
1413  * to the debug channel. When executed under a semihosting
1414  * debugger, the character appears on the host debugger console.
1415  *
1416  * Entry
1417  * On entry, the PARAMETER REGISTER contains a pointer to the
1418  * character.
1419  *
1420  * Return
1421  * None. The RETURN REGISTER is corrupted.
1422  */
1423  if (semihosting->is_fileio) {
1424  semihosting->hit_fileio = true;
1425  fileio_info->identifier = "write";
1426  fileio_info->param_1 = 1;
1427  fileio_info->param_2 = semihosting->param;
1428  fileio_info->param_3 = 1;
1429  } else {
1430  uint64_t addr = semihosting->param;
1431  unsigned char c;
1432  retval = target_read_memory(target, addr, 1, 1, &c);
1433  if (retval != ERROR_OK)
1434  return retval;
1436  semihosting->result = 0;
1437  }
1438  break;
1439 
1440  case SEMIHOSTING_SYS_WRITE0: /* 0x04 */
1441  /*
1442  * Writes a null-terminated string to the debug channel.
1443  * When executed under a semihosting debugger, the characters
1444  * appear on the host debugger console.
1445  *
1446  * Entry
1447  * On entry, the PARAMETER REGISTER contains a pointer to the
1448  * first byte of the string.
1449  *
1450  * Return
1451  * None. The RETURN REGISTER is corrupted.
1452  */
1453  if (semihosting->is_fileio) {
1454  size_t count = 0;
1455  uint64_t addr = semihosting->param;
1456  for (;; addr++) {
1457  unsigned char c;
1458  retval = target_read_memory(target, addr, 1, 1, &c);
1459  if (retval != ERROR_OK)
1460  return retval;
1461  if (c == '\0')
1462  break;
1463  count++;
1464  }
1465  semihosting->hit_fileio = true;
1466  fileio_info->identifier = "write";
1467  fileio_info->param_1 = 1;
1468  fileio_info->param_2 = semihosting->param;
1469  fileio_info->param_3 = count;
1470  } else {
1471  uint64_t addr = semihosting->param;
1472  do {
1473  unsigned char c;
1474  retval = target_read_memory(target, addr++, 1, 1, &c);
1475  if (retval != ERROR_OK)
1476  return retval;
1477  if (!c)
1478  break;
1480  } while (1);
1481  semihosting->result = 0;
1482  }
1483  break;
1484 
1506  if (retval != ERROR_NOT_IMPLEMENTED)
1507  break;
1508  /* If custom user command not handled, we are looking for the TCL handler */
1509  }
1510 
1511  assert(!semihosting_user_op_params);
1512  retval = semihosting_read_fields(target, 2, fields);
1513  if (retval != ERROR_OK) {
1514  LOG_ERROR("Failed to read fields for user defined command"
1515  " op=0x%x", semihosting->op);
1516  return retval;
1517  }
1518 
1519  uint64_t addr = semihosting_get_field(target, 0, fields);
1520 
1521  size_t len = semihosting_get_field(target, 1, fields);
1523  LOG_ERROR("The maximum length for user defined command "
1524  "parameter is %u, received length is %zu (op=0x%x)",
1526  len,
1527  semihosting->op);
1528  return ERROR_FAIL;
1529  }
1530 
1531  semihosting_user_op_params = malloc(len + 1);
1533  return ERROR_FAIL;
1534  semihosting_user_op_params[len] = 0;
1535 
1536  retval = target_read_buffer(target, addr, len,
1537  (uint8_t *)(semihosting_user_op_params));
1538  if (retval != ERROR_OK) {
1539  LOG_ERROR("Failed to read from target, semihosting op=0x%x (%s)",
1540  semihosting->op,
1544  return retval;
1545  }
1546 
1550  semihosting->result = 0;
1551  break;
1552 
1553  case SEMIHOSTING_SYS_ELAPSED: /* 0x30 */
1554  /*
1555  * Returns the number of elapsed target ticks since execution
1556  * started.
1557  * Use SYS_TICKFREQ to determine the tick frequency.
1558  *
1559  * Entry (32-bit)
1560  * On entry, the PARAMETER REGISTER points to a two-field data
1561  * block to be used for returning the number of elapsed ticks:
1562  * - field 1 The least significant field and is at the low address.
1563  * - field 2 The most significant field and is at the high address.
1564  *
1565  * Entry (64-bit)
1566  * On entry the PARAMETER REGISTER points to a one-field data
1567  * block to be used for returning the number of elapsed ticks:
1568  * - field 1 The number of elapsed ticks as a 64-bit value.
1569  *
1570  * Return
1571  * On exit:
1572  * - On success, the RETURN REGISTER contains 0, the PARAMETER
1573  * REGISTER is unchanged, and the data block pointed to by the
1574  * PARAMETER REGISTER is filled in with the number of elapsed
1575  * ticks.
1576  * - On failure, the RETURN REGISTER contains -1, and the
1577  * PARAMETER REGISTER contains -1.
1578  *
1579  * Note: Some semihosting implementations might not support this
1580  * semihosting operation, and they always return -1 in the
1581  * RETURN REGISTER.
1582  */
1583 
1584  case SEMIHOSTING_SYS_TICKFREQ: /* 0x31 */
1585  /*
1586  * Returns the tick frequency.
1587  *
1588  * Entry
1589  * The PARAMETER REGISTER must contain 0 on entry to this routine.
1590  *
1591  * Return
1592  * On exit, the RETURN REGISTER contains either:
1593  * - The number of ticks per second.
1594  * - –1 if the target does not know the value of one tick.
1595  *
1596  * Note: Some semihosting implementations might not support
1597  * this semihosting operation, and they always return -1 in the
1598  * RETURN REGISTER.
1599  */
1600 
1601  case SEMIHOSTING_SYS_TMPNAM: /* 0x0D */
1602  /*
1603  * Returns a temporary name for a file identified by a system
1604  * file identifier.
1605  *
1606  * Entry
1607  * On entry, the PARAMETER REGISTER contains a pointer to a
1608  * three-word argument block:
1609  * - field 1 A pointer to a buffer.
1610  * - field 2 A target identifier for this filename. Its value
1611  * must be an integer in the range 0-255.
1612  * - field 3 Contains the length of the buffer. The length must
1613  * be at least the value of L_tmpnam on the host system.
1614  *
1615  * Return
1616  * On exit, the RETURN REGISTER contains:
1617  * - 0 if the call is successful.
1618  * - –1 if an error occurs.
1619  *
1620  * The buffer pointed to by the PARAMETER REGISTER contains
1621  * the filename, prefixed with a suitable directory name.
1622  * If you use the same target identifier again, the same
1623  * filename is returned.
1624  *
1625  * Note: The returned string must be null-terminated.
1626  */
1627 
1628  default:
1629  fprintf(stderr, "semihosting: unsupported call %#x\n",
1630  (unsigned) semihosting->op);
1631  semihosting->result = -1;
1633  }
1634 
1635  if (!semihosting->hit_fileio) {
1636  retval = semihosting->post_result(target);
1637  if (retval != ERROR_OK) {
1638  LOG_ERROR("Failed to post semihosting result");
1639  return retval;
1640  }
1641  }
1642 
1643  return ERROR_OK;
1644 }
1645 
1646 /* -------------------------------------------------------------------------
1647  * Local functions. */
1648 
1650  struct gdb_fileio_info *fileio_info)
1651 {
1653  if (!semihosting)
1654  return ERROR_FAIL;
1655 
1656  /*
1657  * To avoid unnecessary duplication, semihosting prepares the
1658  * fileio_info structure out-of-band when the target halts. See
1659  * do_semihosting for more detail.
1660  */
1662  return ERROR_FAIL;
1663 
1664  return ERROR_OK;
1665 }
1666 
1668  int fileio_errno, bool ctrl_c)
1669 {
1670  struct gdb_fileio_info *fileio_info = target->fileio_info;
1672  if (!semihosting)
1673  return ERROR_FAIL;
1674 
1675  /* clear pending status */
1676  semihosting->hit_fileio = false;
1677 
1679 
1680  /*
1681  * Some fileio results do not match up with what the semihosting
1682  * operation expects; for these operations, we munge the results
1683  * below:
1684  */
1685  switch (semihosting->op) {
1686  case SEMIHOSTING_SYS_WRITE: /* 0x05 */
1687  case SEMIHOSTING_SYS_READ: /* 0x06 */
1688  if (result < 0)
1689  semihosting->result = fileio_info->param_3; /* Zero bytes read/written. */
1690  else
1691  semihosting->result = (int64_t)fileio_info->param_3 - result;
1692  break;
1693 
1694  case SEMIHOSTING_SYS_SEEK: /* 0x0a */
1695  if (result > 0)
1696  semihosting->result = 0;
1697  break;
1698  }
1699 
1700  bool fileio_failed = false;
1702  fileio_failed = (semihosting->result == 0);
1703  else if (semihosting->op == SEMIHOSTING_SYS_RENAME)
1704  fileio_failed = (semihosting->result != 0);
1705  else
1706  fileio_failed = (semihosting->result == -1);
1707 
1708  if (fileio_failed)
1709  semihosting->sys_errno = fileio_errno;
1710 
1711  return semihosting->post_result(target);
1712 }
1713 
1714 /* -------------------------------------------------------------------------
1715  * Utility functions. */
1716 
1721  uint8_t *fields)
1722 {
1724  /* Use 4-byte multiples to trigger fast memory access. */
1726  number * (semihosting->word_size_bytes / 4), fields);
1727 }
1728 
1733  uint8_t *fields)
1734 {
1736  /* Use 4-byte multiples to trigger fast memory access. */
1738  number * (semihosting->word_size_bytes / 4), fields);
1739 }
1740 
1744 uint64_t semihosting_get_field(struct target *target, size_t index,
1745  uint8_t *fields)
1746 {
1748  if (semihosting->word_size_bytes == 8)
1749  return target_buffer_get_u64(target, fields + (index * 8));
1750  else
1751  return target_buffer_get_u32(target, fields + (index * 4));
1752 }
1753 
1757 void semihosting_set_field(struct target *target, uint64_t value,
1758  size_t index,
1759  uint8_t *fields)
1760 {
1762  if (semihosting->word_size_bytes == 8)
1763  target_buffer_set_u64(target, fields + (index * 8), value);
1764  else
1765  target_buffer_set_u32(target, fields + (index * 4), value);
1766 }
1767 
1768 /* -------------------------------------------------------------------------
1769  * Semihosting redirect over TCP structs and functions */
1770 
1772 {
1774  service->semihosting->tcp_connection = connection;
1775 
1776  return ERROR_OK;
1777 }
1778 
1780 {
1782 
1783  if (!connection->input_pending) {
1784  /* consume received data, not for semihosting IO */
1785  const int buf_len = 100;
1786  char buf[buf_len];
1787  int bytes_read = connection_read(connection, buf, buf_len);
1788 
1789  if (bytes_read == 0) {
1791  } else if (bytes_read == -1) {
1792  LOG_ERROR("error during read: %s", strerror(errno));
1794  }
1795  } else if (service->error != ERROR_OK) {
1797  }
1798 
1799  return ERROR_OK;
1800 }
1801 
1803 {
1805  if (service) {
1806  free(service->name);
1807  free(service);
1808  }
1809 
1810  return ERROR_OK;
1811 }
1812 
1814 {
1816  return;
1817 
1821 
1822 }
1823 
1824 static const struct service_driver semihosting_service_driver = {
1825  .name = "semihosting",
1826  .new_connection_during_keep_alive_handler = NULL,
1827  .new_connection_handler = semihosting_service_new_connection_handler,
1828  .input_handler = semihosting_service_input_handler,
1829  .connection_closed_handler = semihosting_service_connection_closed_handler,
1830  .keep_client_alive_handler = NULL,
1831 };
1832 
1833 /* -------------------------------------------------------------------------
1834  * Common semihosting commands handlers. */
1835 
1836 COMMAND_HANDLER(handle_common_semihosting_command)
1837 {
1839 
1840  if (!target) {
1841  LOG_ERROR("No target selected");
1842  return ERROR_FAIL;
1843  }
1844 
1846  if (!semihosting) {
1847  command_print(CMD, "semihosting not supported for current target");
1848  return ERROR_FAIL;
1849  }
1850 
1851  if (CMD_ARGC > 0) {
1852  int is_active;
1853 
1855 
1856  if (!target_was_examined(target)) {
1857  LOG_ERROR("Target not examined yet");
1858  return ERROR_FAIL;
1859  }
1860 
1862  LOG_ERROR("Failed to Configure semihosting");
1863  return ERROR_FAIL;
1864  }
1865 
1866  /* FIXME never let that "catch" be dropped! (???) */
1868  }
1869 
1870  command_print(CMD, "semihosting is %s",
1872  ? "enabled" : "disabled");
1873 
1874  return ERROR_OK;
1875 }
1876 
1877 COMMAND_HANDLER(handle_common_semihosting_redirect_command)
1878 {
1880 
1881  if (!target) {
1882  LOG_ERROR("No target selected");
1883  return ERROR_FAIL;
1884  }
1885 
1887  if (!semihosting) {
1888  command_print(CMD, "semihosting not supported for current target");
1889  return ERROR_FAIL;
1890  }
1891 
1892  if (!semihosting->is_active) {
1893  command_print(CMD, "semihosting not yet enabled for current target");
1894  return ERROR_FAIL;
1895  }
1896 
1897  enum semihosting_redirect_config cfg;
1898  const char *port;
1899 
1900  if (CMD_ARGC < 1)
1902 
1903  if (strcmp(CMD_ARGV[0], "disable") == 0) {
1905  if (CMD_ARGC > 1)
1907  } else if (strcmp(CMD_ARGV[0], "tcp") == 0) {
1908  if (CMD_ARGC < 2 || CMD_ARGC > 3)
1910 
1911  port = CMD_ARGV[1];
1912 
1914  if (CMD_ARGC == 3) {
1915  if (strcmp(CMD_ARGV[2], "debug") == 0)
1917  else if (strcmp(CMD_ARGV[2], "stdio") == 0)
1919  else if (strcmp(CMD_ARGV[2], "all") != 0)
1921  }
1922  } else {
1924  }
1925 
1928 
1929  if (cfg != SEMIHOSTING_REDIRECT_CFG_NONE) {
1931  calloc(1, sizeof(struct semihosting_tcp_service));
1932  if (!service) {
1933  LOG_ERROR("Failed to allocate semihosting TCP service.");
1934  return ERROR_FAIL;
1935  }
1936 
1937  service->semihosting = semihosting;
1938 
1939  service->name = alloc_printf("%s semihosting service", target_name(target));
1940  if (!service->name) {
1941  LOG_ERROR("Out of memory");
1942  free(service);
1943  return ERROR_FAIL;
1944  }
1945 
1947  port, 1, service);
1948 
1949  if (ret != ERROR_OK) {
1950  LOG_ERROR("failed to initialize %s", service->name);
1951  free(service->name);
1952  free(service);
1953  return ERROR_FAIL;
1954  }
1955  }
1956 
1957  semihosting->redirect_cfg = cfg;
1958 
1959  return ERROR_OK;
1960 }
1961 
1962 COMMAND_HANDLER(handle_common_semihosting_fileio_command)
1963 {
1965 
1966  if (!target) {
1967  LOG_ERROR("No target selected");
1968  return ERROR_FAIL;
1969  }
1970 
1972  if (!semihosting) {
1973  command_print(CMD, "semihosting not supported for current target");
1974  return ERROR_FAIL;
1975  }
1976 
1977  if (!semihosting->is_active) {
1978  command_print(CMD, "semihosting not yet enabled for current target");
1979  return ERROR_FAIL;
1980  }
1981 
1982  if (CMD_ARGC > 0)
1984 
1985  command_print(CMD, "semihosting fileio is %s",
1987  ? "enabled" : "disabled");
1988 
1989  return ERROR_OK;
1990 }
1991 
1992 COMMAND_HANDLER(handle_common_semihosting_cmdline)
1993 {
1995  unsigned int i;
1996 
1997  if (!target) {
1998  LOG_ERROR("No target selected");
1999  return ERROR_FAIL;
2000  }
2001 
2003  if (!semihosting) {
2004  command_print(CMD, "semihosting not supported for current target");
2005  return ERROR_FAIL;
2006  }
2007 
2008  free(semihosting->cmdline);
2009  semihosting->cmdline = CMD_ARGC > 0 ? strdup(CMD_ARGV[0]) : NULL;
2010 
2011  for (i = 1; i < CMD_ARGC; i++) {
2012  char *cmdline = alloc_printf("%s %s", semihosting->cmdline, CMD_ARGV[i]);
2013  if (!cmdline)
2014  break;
2015  free(semihosting->cmdline);
2017  }
2018 
2019  command_print(CMD, "semihosting command line is [%s]",
2020  semihosting->cmdline);
2021 
2022  return ERROR_OK;
2023 }
2024 
2025 COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command)
2026 {
2028 
2029  if (!target) {
2030  LOG_ERROR("No target selected");
2031  return ERROR_FAIL;
2032  }
2033 
2035  if (!semihosting) {
2036  command_print(CMD, "semihosting not supported for current target");
2037  return ERROR_FAIL;
2038  }
2039 
2040  if (!semihosting->is_active) {
2041  command_print(CMD, "semihosting not yet enabled for current target");
2042  return ERROR_FAIL;
2043  }
2044 
2045  if (CMD_ARGC > 0)
2047 
2048  command_print(CMD, "semihosting resumable exit is %s",
2050  ? "enabled" : "disabled");
2051 
2052  return ERROR_OK;
2053 }
2054 
2055 COMMAND_HANDLER(handle_common_semihosting_read_user_param_command)
2056 {
2059 
2060  if (CMD_ARGC)
2062 
2063  if (!semihosting->is_active) {
2064  LOG_ERROR("semihosting not yet enabled for current target");
2065  return ERROR_FAIL;
2066  }
2067 
2069  LOG_ERROR("This command is usable only from a registered user "
2070  "semihosting event callback.");
2071  return ERROR_FAIL;
2072  }
2073 
2075 
2076  return ERROR_OK;
2077 }
2078 
2079 COMMAND_HANDLER(handle_common_semihosting_basedir_command)
2080 {
2082 
2083  if (CMD_ARGC > 1)
2085 
2086  if (!target) {
2087  LOG_ERROR("No target selected");
2088  return ERROR_FAIL;
2089  }
2090 
2092  if (!semihosting) {
2093  command_print(CMD, "semihosting not supported for current target");
2094  return ERROR_FAIL;
2095  }
2096 
2097  if (!semihosting->is_active) {
2098  command_print(CMD, "semihosting not yet enabled for current target");
2099  return ERROR_FAIL;
2100  }
2101 
2102  if (CMD_ARGC > 0) {
2103  free(semihosting->basedir);
2104  semihosting->basedir = strdup(CMD_ARGV[0]);
2105  if (!semihosting->basedir) {
2106  command_print(CMD, "semihosting failed to allocate memory for basedir!");
2107  return ERROR_FAIL;
2108  }
2109  }
2110 
2111  command_print(CMD, "semihosting base dir: %s",
2113 
2114  return ERROR_OK;
2115 }
2116 
2118  {
2119  .name = "semihosting",
2120  .handler = handle_common_semihosting_command,
2121  .mode = COMMAND_EXEC,
2122  .usage = "['enable'|'disable']",
2123  .help = "activate support for semihosting operations",
2124  },
2125  {
2126  .name = "semihosting_redirect",
2127  .handler = handle_common_semihosting_redirect_command,
2128  .mode = COMMAND_EXEC,
2129  .usage = "(disable | tcp <port> ['debug'|'stdio'|'all'])",
2130  .help = "redirect semihosting IO",
2131  },
2132  {
2133  .name = "semihosting_cmdline",
2134  .handler = handle_common_semihosting_cmdline,
2135  .mode = COMMAND_EXEC,
2136  .usage = "arguments",
2137  .help = "command line arguments to be passed to program",
2138  },
2139  {
2140  .name = "semihosting_fileio",
2141  .handler = handle_common_semihosting_fileio_command,
2142  .mode = COMMAND_EXEC,
2143  .usage = "['enable'|'disable']",
2144  .help = "activate support for semihosting fileio operations",
2145  },
2146  {
2147  .name = "semihosting_resexit",
2148  .handler = handle_common_semihosting_resumable_exit_command,
2149  .mode = COMMAND_EXEC,
2150  .usage = "['enable'|'disable']",
2151  .help = "activate support for semihosting resumable exit",
2152  },
2153  {
2154  .name = "semihosting_read_user_param",
2155  .handler = handle_common_semihosting_read_user_param_command,
2156  .mode = COMMAND_EXEC,
2157  .usage = "",
2158  .help = "read parameters in semihosting-user-cmd-0x10X callbacks",
2159  },
2160  {
2161  .name = "semihosting_basedir",
2162  .handler = handle_common_semihosting_basedir_command,
2163  .mode = COMMAND_EXEC,
2164  .usage = "[dir]",
2165  .help = "set the base directory for semihosting I/O operations",
2166  },
2168 };
static int post_result(struct target *target)
enum arm_mode mode
Definition: armv4_5.c:277
Support functions to access arbitrary bits in a byte array.
void command_print_sameline(struct command_invocation *cmd, const char *format,...)
Definition: command.c:420
void command_print(struct command_invocation *cmd, const char *format,...)
Definition: command.c:443
#define CMD
Use this macro to access the command being handled, rather than accessing the variable directly.
Definition: command.h:141
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:156
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:402
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:151
#define COMMAND_PARSE_ENABLE(in, out)
parses an enable/disable command argument
Definition: command.h:524
#define CMD_CTX
Use this macro to access the context of the command being handled, rather than accessing the variable...
Definition: command.h:146
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:253
@ COMMAND_EXEC
Definition: command.h:40
enum esirisc_reg_num number
Definition: esirisc.c:87
uint8_t type
Definition: esp_usb_jtag.c:0
int gdb_get_actual_connections(void)
Definition: gdb_server.c:4155
void log_socket_error(const char *socket_desc)
Definition: log.c:484
char * alloc_printf(const char *format,...)
Definition: log.c:364
#define ERROR_NOT_IMPLEMENTED
Definition: log.h:174
#define ERROR_FAIL
Definition: log.h:170
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:164
#define O_BINARY
Definition: replacements.h:37
#define ENOTSUP
Definition: replacements.h:31
target_addr_t addr
Start address to search for the control block.
Definition: rtt/rtt.c:28
size_t size
Size of the control block search area.
Definition: rtt/rtt.c:30
int semihosting_common_init(struct target *target, void *setup, void *post_result)
Initialize common semihosting support.
static ssize_t semihosting_redirect_write(struct semihosting *semihosting, void *buf, int size)
static const int open_host_modeflags[12]
static int semihosting_common_fileio_end(struct target *target, int result, int fileio_errno, bool ctrl_c)
const struct command_registration semihosting_common_handlers[]
static int semihosting_service_connection_closed_handler(struct connection *connection)
uint64_t semihosting_get_field(struct target *target, size_t index, uint8_t *fields)
Extract a field from the buffer, considering register size and endianness.
static const int open_gdb_modeflags[12]
static const struct service_driver semihosting_service_driver
static int semihosting_service_input_handler(struct connection *connection)
static int semihosting_getchar(struct semihosting *semihosting, int fd)
COMMAND_HANDLER(handle_common_semihosting_command)
static ssize_t semihosting_redirect_read(struct semihosting *semihosting, void *buf, int size)
static int semihosting_putchar(struct semihosting *semihosting, int fd, int c)
static int semihosting_service_new_connection_handler(struct connection *connection)
static char * semihosting_user_op_params
User operation parameter string storage buffer.
int semihosting_common(struct target *target)
Portable implementation of ARM semihosting calls.
void semihosting_set_field(struct target *target, uint64_t value, size_t index, uint8_t *fields)
Store a field in the buffer, considering register size and endianness.
static ssize_t semihosting_read(struct semihosting *semihosting, int fd, void *buf, int size)
static ssize_t semihosting_write(struct semihosting *semihosting, int fd, void *buf, int size)
int semihosting_read_fields(struct target *target, size_t number, uint8_t *fields)
Read all fields of a command from target to buffer.
static bool semihosting_is_redirected(struct semihosting *semihosting, int fd)
@ TARGET_O_WRONLY
@ TARGET_O_TRUNC
@ TARGET_O_RDWR
@ TARGET_O_RDONLY
@ TARGET_O_CREAT
@ TARGET_O_APPEND
static void semihosting_tcp_close_cnx(struct semihosting *semihosting)
static int semihosting_common_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info)
int semihosting_write_fields(struct target *target, size_t number, uint8_t *fields)
Write all fields of a command from buffer to target.
const char * semihosting_opcode_to_str(const uint64_t opcode)
Convert the syscall opcode to a human-readable string.
semihosting_redirect_config
@ SEMIHOSTING_REDIRECT_CFG_ALL
@ SEMIHOSTING_REDIRECT_CFG_DEBUG
@ SEMIHOSTING_REDIRECT_CFG_NONE
@ SEMIHOSTING_REDIRECT_CFG_STDIO
@ ADP_STOPPED_RUN_TIME_ERROR
@ ADP_STOPPED_APPLICATION_EXIT
#define SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH
Maximum allowed Tcl command segment length in bytes.
@ SEMIHOSTING_SYS_TICKFREQ
@ SEMIHOSTING_USER_CMD_0X107
@ SEMIHOSTING_SYS_EXIT
@ SEMIHOSTING_SYS_ISERROR
@ SEMIHOSTING_USER_CMD_0X1FF
@ SEMIHOSTING_SYS_WRITE
@ SEMIHOSTING_SYS_FLEN
@ SEMIHOSTING_SYS_GET_CMDLINE
@ SEMIHOSTING_SYS_EXIT_EXTENDED
@ SEMIHOSTING_ARM_RESERVED_END
@ SEMIHOSTING_SYS_REMOVE
@ SEMIHOSTING_SYS_SEEK
@ SEMIHOSTING_ARM_RESERVED_START
@ SEMIHOSTING_SYS_TMPNAM
@ SEMIHOSTING_SYS_TIME
@ SEMIHOSTING_SYS_CLOCK
@ SEMIHOSTING_SYS_WRITEC
@ SEMIHOSTING_SYS_ERRNO
@ SEMIHOSTING_SYS_ISTTY
@ SEMIHOSTING_SYS_HEAPINFO
@ SEMIHOSTING_SYS_WRITE0
@ SEMIHOSTING_SYS_ELAPSED
@ SEMIHOSTING_SYS_READ
@ SEMIHOSTING_SYS_SYSTEM
@ SEMIHOSTING_SYS_CLOSE
@ SEMIHOSTING_SYS_READC
@ SEMIHOSTING_SYS_OPEN
@ SEMIHOSTING_SYS_RENAME
@ SEMIHOSTING_USER_CMD_0X100
int connection_write(struct connection *connection, const void *data, int len)
Definition: server.c:732
int connection_read(struct connection *connection, void *data, int len)
Definition: server.c:744
int remove_service(const char *name, const char *port)
Definition: server.c:355
int add_service(const struct service_driver *driver, const char *port, int max_connections, void *priv)
Definition: server.c:198
#define ERROR_SERVER_REMOTE_CLOSED
Definition: server.h:119
const char * name
Definition: command.h:235
struct service * service
Definition: server.h:41
bool input_pending
Definition: server.h:42
uint64_t param_1
Definition: target.h:219
uint64_t param_4
Definition: target.h:222
uint64_t param_3
Definition: target.h:221
char * identifier
Definition: target.h:218
uint64_t param_2
Definition: target.h:220
struct semihosting * semihosting
bool is_resumable
Most are resumable, except the two exit calls.
int stdin_fd
Semihosting STDIO file descriptors.
bool has_resumable_exit
When SEMIHOSTING_SYS_EXIT is called outside a debug session, things are simple, the openocd process c...
int(* setup)(struct target *target, int enable)
int(* post_result)(struct target *target)
bool hit_fileio
A flag reporting whether semihosting fileio operation is active.
size_t word_size_bytes
The Target (hart) word size; 8 for 64-bits targets.
bool is_fileio
A flag reporting whether semihosting fileio is active.
int(* user_command_extension)(struct target *target)
Target's extension of semihosting user commands.
int64_t result
The current semihosting result to be returned to the application.
char * basedir
Base directory for semihosting I/O operations.
bool is_active
A flag reporting whether semihosting is active.
int op
The current semihosting operation (R0 on ARM).
struct connection * tcp_connection
Handle to redirect semihosting print via tcp.
int sys_errno
The value to be returned by semihosting SYS_ERRNO request.
enum semihosting_redirect_config redirect_cfg
redirection configuration, NONE by default
uint64_t param
The current semihosting parameter (R1 or ARM).
char * cmdline
The semihosting command line to be passed to the target.
clock_t setup_time
The current time when 'execution starts'.
const char * name
the name of the server
Definition: server.h:49
Definition: server.h:67
void * priv
Definition: server.h:81
char * name
Definition: server.h:68
char * port
Definition: server.h:70
int(* gdb_fileio_end)(struct target *target, int retcode, int fileio_errno, bool ctrl_c)
Definition: target_type.h:287
int(* get_gdb_fileio_info)(struct target *target, struct gdb_fileio_info *fileio_info)
Definition: target_type.h:283
Definition: target.h:116
struct semihosting * semihosting
Definition: target.h:209
struct gdb_fileio_info * fileio_info
Definition: target.h:202
struct target_type * type
Definition: target.h:117
uint64_t target_buffer_get_u64(struct target *target, const uint8_t *buffer)
Definition: target.c:307
int target_call_event_callbacks(struct target *target, enum target_event event)
Definition: target.c:1764
void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t value)
Definition: target.c:352
int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
Definition: target.c:2342
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
Definition: target.c:2407
int target_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
Write count items of size bytes to the memory of target at the address given.
Definition: target.c:1265
void target_buffer_set_u64(struct target *target, uint8_t *buffer, uint64_t value)
Definition: target.c:343
int target_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
Read count items of size bytes from the memory of target at the address given.
Definition: target.c:1237
struct target * get_current_target(struct command_context *cmd_ctx)
Definition: target.c:458
void target_handle_event(struct target *target, enum target_event e)
Definition: target.c:4660
uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer)
Definition: target.c:316
static bool target_was_examined(const struct target *target)
Definition: target.h:436
@ TARGET_EVENT_HALTED
Definition: target.h:252
static const char * target_name(const struct target *target)
Returns the instance-specific name of the specified target.
Definition: target.h:233
#define NULL
Definition: usb.h:16
uint8_t cmd
Definition: vdebug.c:1
uint8_t count[4]
Definition: vdebug.c:22