Skip to content

Commit

Permalink
semihosting: fix handling of errno
Browse files Browse the repository at this point in the history
This patch fixes the handling of errno by setting the sys_errn
only if error has actually occurred during the semihosting call.
It also fixes few issues where error was not set in the first place.

Change-Id: I2fbe562f3ec5e6220b800de04cd33aa1f409c7a0
Signed-off-by: Marek Vrbka <[email protected]>
Reviewed-on: https://review.openocd.org/c/openocd/+/7730
Tested-by: jenkins
Reviewed-by: Antonio Borneo <[email protected]>
Reviewed-by: Jan Matyas <[email protected]>
  • Loading branch information
MarekVCodasip authored and borneoa committed Jul 1, 2023
1 parent 6ef7535 commit 56fd048
Showing 1 changed file with 47 additions and 32 deletions.
79 changes: 47 additions & 32 deletions src/target/semihosting_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,10 @@ static ssize_t semihosting_write(struct semihosting *semihosting, int fd, void *
return semihosting_redirect_write(semihosting, buf, size);

/* default write */
return write(fd, buf, size);
int result = write(fd, buf, size);
if (result == -1)
semihosting->sys_errno = errno;
return result;
}

static ssize_t semihosting_redirect_read(struct semihosting *semihosting, void *buf, int size)
Expand Down Expand Up @@ -268,7 +271,8 @@ static inline ssize_t semihosting_read(struct semihosting *semihosting, int fd,

/* default read */
ssize_t result = read(fd, buf, size);
semihosting->sys_errno = errno;
if (result == -1)
semihosting->sys_errno = errno;

return result;
}
Expand Down Expand Up @@ -449,12 +453,7 @@ int semihosting_common(struct target *target)
(fd == 0) ? "stdin" :
(fd == 1) ? "stdout" : "stderr");
/* Just pretend success */
if (semihosting->is_fileio) {
semihosting->result = 0;
} else {
semihosting->result = 0;
semihosting->sys_errno = 0;
}
semihosting->result = 0;
break;
}
/* Close the descriptor */
Expand All @@ -464,7 +463,8 @@ int semihosting_common(struct target *target)
fileio_info->param_1 = fd;
} else {
semihosting->result = close(fd);
semihosting->sys_errno = errno;
if (semihosting->result == -1)
semihosting->sys_errno = errno;
LOG_DEBUG("close(%d)=%" PRId64, fd, semihosting->result);
}
}
Expand Down Expand Up @@ -842,7 +842,8 @@ int semihosting_common(struct target *target)
int fd = semihosting_get_field(target, 0, fields);
// isatty() on Windows may return any non-zero value if fd is a terminal
semihosting->result = isatty(fd) ? 1 : 0;
semihosting->sys_errno = errno;
if (semihosting->result == 0)
semihosting->sys_errno = errno;
LOG_DEBUG("isatty(%d)=%" PRId64, fd, semihosting->result);
}
break;
Expand Down Expand Up @@ -934,14 +935,16 @@ int semihosting_common(struct target *target)
semihosting->result = -1;
semihosting->sys_errno = EINVAL;
} else if (strcmp((char *)fn, ":tt") == 0) {
if (mode == 0)
if (mode == 0) {
semihosting->result = 0;
else if (mode == 4)
} else if (mode == 4) {
semihosting->result = 1;
else if (mode == 8)
} else if (mode == 8) {
semihosting->result = 2;
else
} else {
semihosting->result = -1;
semihosting->sys_errno = EINVAL;
}
} else {
semihosting->hit_fileio = true;
fileio_info->identifier = "open";
Expand All @@ -956,33 +959,32 @@ int semihosting_common(struct target *target)
* - 0-3 ("r") for stdin,
* - 4-7 ("w") for stdout,
* - 8-11 ("a") for stderr */
int fd;
if (mode < 4) {
int fd = dup(STDIN_FILENO);
semihosting->result = fd;
fd = dup(STDIN_FILENO);
semihosting->stdin_fd = fd;
semihosting->sys_errno = errno;
LOG_DEBUG("dup(STDIN)=%" PRId64, semihosting->result);
LOG_DEBUG("dup(STDIN)=%d", fd);
} else if (mode < 8) {
int fd = dup(STDOUT_FILENO);
semihosting->result = fd;
fd = dup(STDOUT_FILENO);
semihosting->stdout_fd = fd;
semihosting->sys_errno = errno;
LOG_DEBUG("dup(STDOUT)=%" PRId64, semihosting->result);
LOG_DEBUG("dup(STDOUT)=%d", fd);
} else {
int fd = dup(STDERR_FILENO);
semihosting->result = fd;
fd = dup(STDERR_FILENO);
semihosting->stderr_fd = fd;
semihosting->sys_errno = errno;
LOG_DEBUG("dup(STDERR)=%" PRId64, semihosting->result);
LOG_DEBUG("dup(STDERR)=%d", fd);
}
semihosting->result = fd;
if (fd == -1)
semihosting->sys_errno = errno;
} else {
/* cygwin requires the permission setting
* otherwise it will fail to reopen a previously
* written file */
semihosting->result = open((char *)fn,
open_host_modeflags[mode],
0644);
semihosting->sys_errno = errno;
if (semihosting->result == -1)
semihosting->sys_errno = errno;
LOG_DEBUG("open('%s')=%" PRId64, fn, semihosting->result);
}
}
Expand Down Expand Up @@ -1131,7 +1133,8 @@ int semihosting_common(struct target *target)
}
fn[len] = 0;
semihosting->result = remove((char *)fn);
semihosting->sys_errno = errno;
if (semihosting->result == -1)
semihosting->sys_errno = errno;
LOG_DEBUG("remove('%s')=%" PRId64, fn, semihosting->result);

free(fn);
Expand Down Expand Up @@ -1200,7 +1203,9 @@ int semihosting_common(struct target *target)
fn2[len2] = 0;
semihosting->result = rename((char *)fn1,
(char *)fn2);
semihosting->sys_errno = errno;
// rename() on Windows returns nonzero on error
if (semihosting->result != 0)
semihosting->sys_errno = errno;
LOG_DEBUG("rename('%s', '%s')=%" PRId64 " %d", fn1, fn2, semihosting->result, errno);
free(fn1);
free(fn2);
Expand Down Expand Up @@ -1245,7 +1250,8 @@ int semihosting_common(struct target *target)
fileio_info->param_3 = SEEK_SET;
} else {
semihosting->result = lseek(fd, pos, SEEK_SET);
semihosting->sys_errno = errno;
if (semihosting->result == -1)
semihosting->sys_errno = errno;
LOG_DEBUG("lseek(%d, %d)=%" PRId64, fd, (int)pos, semihosting->result);
if (semihosting->result == pos)
semihosting->result = 0;
Expand Down Expand Up @@ -1383,7 +1389,6 @@ int semihosting_common(struct target *target)
return retval;
}
semihosting->result = semihosting_write(semihosting, fd, buf, len);
semihosting->sys_errno = errno;
LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%" PRId64,
fd,
addr,
Expand Down Expand Up @@ -1671,7 +1676,6 @@ static int semihosting_common_fileio_end(struct target *target, int result,
semihosting->hit_fileio = false;

semihosting->result = result;
semihosting->sys_errno = fileio_errno;

/*
* Some fileio results do not match up with what the semihosting
Expand All @@ -1693,6 +1697,17 @@ static int semihosting_common_fileio_end(struct target *target, int result,
break;
}

bool fileio_failed = false;
if (semihosting->op == SEMIHOSTING_SYS_ISTTY)
fileio_failed = (semihosting->result == 0);
else if (semihosting->op == SEMIHOSTING_SYS_RENAME)
fileio_failed = (semihosting->result != 0);
else
fileio_failed = (semihosting->result == -1);

if (fileio_failed)
semihosting->sys_errno = fileio_errno;

return semihosting->post_result(target);
}

Expand Down

0 comments on commit 56fd048

Please sign in to comment.