syscall_emul: fix warn_once behavior

The current ignoreWarnOnceFunc doesn't really work as expected,
since it will only generate one warning total, for whichever
"warn-once" syscall is invoked first.  This patch fixes that
behavior by keeping a "warned" flag in the SyscallDesc object,
allowing suitably flagged syscalls to warn exactly once per
syscall.
This commit is contained in:
Steve Reinhardt
2015-05-05 09:25:59 -07:00
parent 40e180ecbe
commit c65fa3dceb
4 changed files with 26 additions and 25 deletions

View File

@@ -99,20 +99,18 @@ ignoreFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
int index = 0;
warn("ignoring syscall %s(%d, ...)", desc->name,
process->getSyscallArg(tc, index));
const char *extra_text = "";
return 0;
}
if (desc->warnOnce()) {
if (desc->warned)
return 0;
desc->warned = true;
extra_text = "\n (further warnings will be suppressed)";
}
SyscallReturn
ignoreWarnOnceFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
int index = 0;
warn_once("ignoring syscall %s(%d, ...)", desc->name,
process->getSyscallArg(tc, index));
warn("ignoring syscall %s(%d, ...)%s", desc->name,
process->getSyscallArg(tc, index), extra_text);
return 0;
}

View File

@@ -97,6 +97,7 @@ class SyscallDesc {
const char *name; //!< Syscall name (e.g., "open").
FuncPtr funcPtr; //!< Pointer to emulation function.
int flags; //!< Flags (see Flags enum).
bool warned; //!< Have we warned about unimplemented syscall?
/// Flag values for controlling syscall behavior.
enum Flags {
@@ -104,17 +105,21 @@ class SyscallDesc {
/// Used for syscalls with non-standard return conventions
/// that explicitly set the ThreadContext regs (e.g.,
/// sigreturn).
SuppressReturnValue = 1
SuppressReturnValue = 1,
WarnOnce = 2
};
/// Constructor.
SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0)
: name(_name), funcPtr(_funcPtr), flags(_flags)
: name(_name), funcPtr(_funcPtr), flags(_flags), warned(false)
{
}
/// Emulate the syscall. Public interface for calling through funcPtr.
void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc);
/// Is the WarnOnce flag set?
bool warnOnce() const { return (flags & WarnOnce); }
};
@@ -137,8 +142,6 @@ SyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
/// trace flag is enabled. Return success to the target program.
SyscallReturn ignoreFunc(SyscallDesc *desc, int num,
LiveProcess *p, ThreadContext *tc);
SyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, int num,
LiveProcess *p, ThreadContext *tc);
/// Target exit() handler: terminate current context.
SyscallReturn exitFunc(SyscallDesc *desc, int num,