* Initialize common semihosting support.
*
* @param target Pointer to the target to initialize.
+ * @param setup
+ * @param post_result
* @return An error status if there is a problem during initialization.
*/
int semihosting_common_init(struct target *target, void *setup,
LOG_DEBUG(" ");
target->fileio_info = malloc(sizeof(*target->fileio_info));
- if (target->fileio_info == NULL) {
+ if (!target->fileio_info) {
LOG_ERROR("out of memory");
return ERROR_FAIL;
}
struct semihosting *semihosting;
semihosting = malloc(sizeof(*target->semihosting));
- if (semihosting == NULL) {
+ if (!semihosting) {
LOG_ERROR("out of memory");
return ERROR_FAIL;
}
{
struct semihosting *semihosting = target->semihosting;
if (!semihosting) {
- /* Silently ignore if the semhosting field was not set. */
+ /* Silently ignore if the semihosting field was not set. */
return ERROR_OK;
}
return retval;
else {
int fd = semihosting_get_field(target, 0, fields);
- if (semihosting->is_fileio) {
- if (fd == 0 || fd == 1 || fd == 2) {
+ /* Do not allow to close OpenOCD's own standard streams */
+ if (fd == 0 || fd == 1 || fd == 2) {
+ LOG_DEBUG("ignoring semihosting attempt to close %s",
+ (fd == 0) ? "stdin" :
+ (fd == 1) ? "stdout" : "stderr");
+ /* Just pretend success */
+ if (semihosting->is_fileio) {
semihosting->result = 0;
- break;
+ } else {
+ semihosting->result = 0;
+ semihosting->sys_errno = 0;
}
+ break;
+ }
+ /* Close the descriptor */
+ if (semihosting->is_fileio) {
semihosting->hit_fileio = true;
fileio_info->identifier = "close";
fileio_info->param_1 = fd;
} else {
semihosting->result = close(fd);
semihosting->sys_errno = errno;
-
LOG_DEBUG("close(%d)=%d", fd, (int)semihosting->result);
}
}
"semihosting: *** application exited normally ***\n");
}
} else if (semihosting->param == ADP_STOPPED_RUN_TIME_ERROR) {
- /* Chosen more or less arbitrarly to have a nicer message,
+ /* Chosen more or less arbitrarily to have a nicer message,
* otherwise all other return the same exit code 1. */
if (!gdb_actual_connections)
exit(1);
uint64_t addr = semihosting_get_field(target, 0, fields);
size_t size = semihosting_get_field(target, 1, fields);
- char *arg = semihosting->cmdline != NULL ?
+ char *arg = semihosting->cmdline ?
semihosting->cmdline : "";
uint32_t len = strlen(arg) + 1;
if (len > size)
return retval;
int fd = semihosting_get_field(target, 0, fields);
semihosting->result = isatty(fd);
+ semihosting->sys_errno = errno;
LOG_DEBUG("isatty(%d)=%d", fd, (int)semihosting->result);
}
break;
uint8_t *fn1 = malloc(len1+1);
uint8_t *fn2 = malloc(len2+1);
if (!fn1 || !fn2) {
+ free(fn1);
+ free(fn2);
semihosting->result = -1;
semihosting->sys_errno = ENOMEM;
} else {
/* -------------------------------------------------------------------------
* Common semihosting commands handlers. */
-__COMMAND_HANDLER(handle_common_semihosting_command)
+static __COMMAND_HANDLER(handle_common_semihosting_command)
{
struct target *target = get_current_target(CMD_CTX);
- if (target == NULL) {
+ if (!target) {
LOG_ERROR("No target selected");
return ERROR_FAIL;
}
return ERROR_OK;
}
-
-__COMMAND_HANDLER(handle_common_semihosting_fileio_command)
+static __COMMAND_HANDLER(handle_common_semihosting_fileio_command)
{
struct target *target = get_current_target(CMD_CTX);
- if (target == NULL) {
+ if (!target) {
LOG_ERROR("No target selected");
return ERROR_FAIL;
}
return ERROR_OK;
}
-__COMMAND_HANDLER(handle_common_semihosting_cmdline)
+static __COMMAND_HANDLER(handle_common_semihosting_cmdline)
{
struct target *target = get_current_target(CMD_CTX);
unsigned int i;
- if (target == NULL) {
+ if (!target) {
LOG_ERROR("No target selected");
return ERROR_FAIL;
}
for (i = 1; i < CMD_ARGC; i++) {
char *cmdline = alloc_printf("%s %s", semihosting->cmdline, CMD_ARGV[i]);
- if (cmdline == NULL)
+ if (!cmdline)
break;
free(semihosting->cmdline);
semihosting->cmdline = cmdline;
return ERROR_OK;
}
-__COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command)
+static __COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command)
{
struct target *target = get_current_target(CMD_CTX);
- if (target == NULL) {
+ if (!target) {
LOG_ERROR("No target selected");
return ERROR_FAIL;
}
return ERROR_OK;
}
+
+const struct command_registration semihosting_common_handlers[] = {
+ {
+ "semihosting",
+ .handler = handle_common_semihosting_command,
+ .mode = COMMAND_EXEC,
+ .usage = "['enable'|'disable']",
+ .help = "activate support for semihosting operations",
+ },
+ {
+ "semihosting_cmdline",
+ .handler = handle_common_semihosting_cmdline,
+ .mode = COMMAND_EXEC,
+ .usage = "arguments",
+ .help = "command line arguments to be passed to program",
+ },
+ {
+ "semihosting_fileio",
+ .handler = handle_common_semihosting_fileio_command,
+ .mode = COMMAND_EXEC,
+ .usage = "['enable'|'disable']",
+ .help = "activate support for semihosting fileio operations",
+ },
+ {
+ "semihosting_resexit",
+ .handler = handle_common_semihosting_resumable_exit_command,
+ .mode = COMMAND_EXEC,
+ .usage = "['enable'|'disable']",
+ .help = "activate support for semihosting resumable exit",
+ },
+ COMMAND_REGISTRATION_DONE
+};