target/semihosting: Fix of close(): Never close standard streams
authorJan Matyas <matyas@codasip.com>
Fri, 4 Jun 2021 08:44:44 +0000 (10:44 +0200)
committerAntonio Borneo <borneo.antonio@gmail.com>
Sat, 10 Jul 2021 14:29:58 +0000 (15:29 +0100)
This change fixes behavior of the SEMIHOSTING_SYS_CLOSE operation.
It ensures that OpenOCD's own stdin/stdout/stderr streams are never
closed, not even if the target requests it via semihosting.

Change-Id: Ia85af5963d1a3516284fd834f7197369a8fb268c
Signed-off-by: Jan Matyas <matyas@codasip.com>
Reviewed-on: http://openocd.zylin.com/6291
Tested-by: jenkins
Reviewed-by: Tim Newsome <tim@sifive.com>
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
src/target/semihosting_common.c

index bfb1ecaa7981b30fa3637dd1adda91ec77166264..ffed7350edd5794612b0b6ed9ec1de4909af57a3 100644 (file)
@@ -226,18 +226,28 @@ int semihosting_common(struct target *target)
                                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);
                                }
                        }