aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sim/ChangeLog9
-rw-r--r--sim/cris/sim-main.h11
-rw-r--r--sim/cris/traps.c46
3 files changed, 61 insertions, 5 deletions
diff --git a/sim/ChangeLog b/sim/ChangeLog
index 9bc31eb..e552e10 100644
--- a/sim/ChangeLog
+++ b/sim/ChangeLog
@@ -1,5 +1,14 @@
2005-11-17 Hans-Peter Nilsson <hp@axis.com>
+ * cris/sim-main.h (struct _sim_cpu): New members last_syscall,
+ last_open_fd, last_open_flags.
+ * cris/traps.c: Don't include targ-vals.h.
+ (TARGET_O_ACCMODE): Define.
+ (cris_break_13_handler): Set new _sim_cpu members.
+ <case TARGET_SYS_fcntl>: Support special case of F_GETFL.
+ Rearrange code as switch. Emit "unimplemented" abort for
+ unimplemented fcntl calls.
+
* cris/traps.c (TARGET_SYS_stat): Define.
(syscall_stat32_map): Add entry for TARGET_SYS_stat.
(cris_break_13_handler) <case TARGET_SYS_stat>: New case.
diff --git a/sim/cris/sim-main.h b/sim/cris/sim-main.h
index b671533..b35b927 100644
--- a/sim/cris/sim-main.h
+++ b/sim/cris/sim-main.h
@@ -166,6 +166,17 @@ struct _sim_cpu {
for sigmasks and sigpendings. */
USI sighandler[64];
+ /* This is a hack to implement just the parts of fcntl F_GETFL that
+ are used in open+fdopen calls for the standard scenario: for such
+ a call we check that the last syscall was open, we check that the
+ passed fd is the same returned then, and so we return the same
+ flags passed to open. This way, we avoid complicating the
+ generic sim callback machinery by introducing fcntl
+ mechanisms. */
+ USI last_syscall;
+ USI last_open_fd;
+ USI last_open_flags;
+
/* Function for initializing CPU thread context, which varies in size
with each CPU model. They should be in some constant parts or
initialized in *_init_cpu, but we can't modify that for now. */
diff --git a/sim/cris/traps.c b/sim/cris/traps.c
index 11cfaae..607f72c 100644
--- a/sim/cris/traps.c
+++ b/sim/cris/traps.c
@@ -20,8 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "sim-main.h"
#include "sim-options.h"
-#include "targ-vals.h"
#include "bfd.h"
+/* FIXME: get rid of targ-vals.h usage everywhere else. */
+
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
@@ -663,6 +664,9 @@ static const CB_TARGET_DEFS_MAP errno_map[] =
installation and removing synonyms and unnecessary items. Don't
forget the end-marker. */
+/* This one we treat specially, as it's used in the fcntl syscall. */
+#define TARGET_O_ACCMODE 3
+
static const CB_TARGET_DEFS_MAP open_map[] = {
#ifdef O_ACCMODE
{ O_ACCMODE, 0x3 },
@@ -1399,8 +1403,9 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
case TARGET_SYS_fcntl64:
case TARGET_SYS_fcntl:
- if (arg2 == 1)
+ switch (arg2)
{
+ case 1:
/* F_GETFD.
Glibc checks stdin, stdout and stderr fd:s for
close-on-exec security sanity. We just need to provide a
@@ -1408,12 +1413,35 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
close-on-exec flag true, we could just do a real fcntl
here. */
retval = 0;
- }
- else if (arg2 == 2)
- {
+ break;
+
+ case 2:
/* F_SETFD. Just ignore attempts to set the close-on-exec
flag. */
retval = 0;
+ break;
+
+ case 3:
+ /* F_GETFL. Check for the special case for open+fdopen. */
+ if (current_cpu->last_syscall == TARGET_SYS_open
+ && arg1 == current_cpu->last_open_fd)
+ {
+ retval = current_cpu->last_open_flags & TARGET_O_ACCMODE;
+ break;
+ }
+ /* FALLTHROUGH */
+ /* Abort for all other cases. */
+ default:
+ sim_io_eprintf (sd, "Unimplemented %s syscall "
+ "(fd: 0x%lx: cmd: 0x%lx arg: 0x%lx)\n",
+ callnum == TARGET_SYS_fcntl
+ ? "fcntl" : "fcntl64",
+ (unsigned long) (USI) arg1,
+ (unsigned long) (USI) arg2,
+ (unsigned long) (USI) arg3);
+ sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
+ SIM_SIGILL);
+ break;
}
break;
@@ -2819,6 +2847,14 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
}
}
+ /* Minimal support for fcntl F_GETFL as used in open+fdopen. */
+ if (callnum == TARGET_SYS_open)
+ {
+ current_cpu->last_open_fd = retval;
+ current_cpu->last_open_flags = arg2;
+ }
+ current_cpu->last_syscall = callnum;
+
/* A system call is a rescheduling point. For the time being, we don't
reschedule anywhere else. */
if (current_cpu->m1threads != 0