aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMartin Nowack <martin.nowack@gmail.com>2018-05-05 00:04:13 +0100
committerCristian Cadar <c.cadar@imperial.ac.uk>2018-05-05 10:35:28 +0100
commitab03c1cdce90660dcb75d000ebda817ae589aaec (patch)
tree7d884b530e8940bc0de8d3227ac944d3798282bb
parent4211cea27f1903f68c2b32267eb34cb95c24b9f3 (diff)
downloadklee-ab03c1cdce90660dcb75d000ebda817ae589aaec.tar.gz
Fix handling of errno if external functions are invoked
If an external function in KLEE is invoked, it might update errno. Previously, the errno specific variable in a state was only updated if it was part of the executed instructions. That opened up a timeframe that increased the likelihood of errno being overwritten by another method call. This patch fixes two issues: * the errno of the KLEE process state is updated before the external function call allowing to detect changes to it later on * after the external call, the memory object of errno is directly updated with its new value, reducing the likelihood to be overwritten by another call Additional features: * Add support for `errno()` for Darwin as well. * Simplified errno handling in POSIX layer
-rw-r--r--include/klee/klee.h3
-rw-r--r--lib/Core/Executor.cpp52
-rw-r--r--lib/Core/Executor.h3
-rw-r--r--lib/Core/ExternalDispatcher.cpp19
-rw-r--r--lib/Core/ExternalDispatcher.h3
-rw-r--r--lib/Core/Memory.h1
-rw-r--r--lib/Core/SpecialFunctionHandler.cpp40
-rw-r--r--lib/Core/SpecialFunctionHandler.h1
-rw-r--r--runtime/POSIX/fd.c203
-rw-r--r--test/Runtime/POSIX/DirSeek.c12
-rw-r--r--test/Runtime/POSIX/Ioctl.c1
-rw-r--r--tools/klee/main.cpp2
12 files changed, 174 insertions, 166 deletions
diff --git a/include/klee/klee.h b/include/klee/klee.h
index 644c498e..8b9cd2e2 100644
--- a/include/klee/klee.h
+++ b/include/klee/klee.h
@@ -157,6 +157,9 @@ extern "C" {
/* Merge all paths of the state that went through klee_open_merge */
void klee_close_merge();
+
+ /* Get errno value of the current state */
+ int klee_get_errno(void);
#ifdef __cplusplus
}
#endif
diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp
index 81b9ec3c..7b054e5b 100644
--- a/lib/Core/Executor.cpp
+++ b/lib/Core/Executor.cpp
@@ -524,14 +524,18 @@ void Executor::initializeGlobals(ExecutionState &state) {
globalAddresses.insert(std::make_pair(f, addr));
}
+#ifndef WINDOWS
+ int *errno_addr = getErrnoLocation(state);
+ MemoryObject *errnoObj =
+ addExternalObject(state, (void *)errno_addr, sizeof *errno_addr, false);
+ // Copy values from and to program space explicitly
+ errnoObj->isUserSpecified = true;
+#endif
+
// Disabled, we don't want to promote use of live externals.
#ifdef HAVE_CTYPE_EXTERNALS
#ifndef WINDOWS
#ifndef DARWIN
- /* From /usr/include/errno.h: it [errno] is a per-thread variable. */
- int *errno_addr = __errno_location();
- addExternalObject(state, (void *)errno_addr, sizeof *errno_addr, false);
-
/* from /usr/include/ctype.h:
These point into arrays of 384, so they can be indexed by any `unsigned
char' value [0,255]; by EOF (-1); or by any `signed char' value
@@ -3035,7 +3039,28 @@ void Executor::callExternalFunction(ExecutionState &state,
}
}
+ // Prepare external memory for invoking the function
state.addressSpace.copyOutConcretes();
+#ifndef WINDOWS
+ // Update external errno state with local state value
+ int *errno_addr = getErrnoLocation(state);
+ ObjectPair result;
+ bool resolved = state.addressSpace.resolveOne(
+ ConstantExpr::create((uint64_t)errno_addr, Expr::Int64), result);
+ if (!resolved)
+ klee_error("Could not resolve memory object for errno");
+ ref<Expr> errValueExpr = result.second->read(0, sizeof(*errno_addr) * 8);
+ ConstantExpr *errnoValue = dyn_cast<ConstantExpr>(errValueExpr);
+ if (!errnoValue) {
+ terminateStateOnExecError(state,
+ "external call with errno value symbolic: " +
+ function->getName());
+ return;
+ }
+
+ externalDispatcher->setLastErrno(
+ errnoValue->getZExtValue(sizeof(*errno_addr) * 8));
+#endif
if (!SuppressExternalWarnings) {
@@ -3055,6 +3080,7 @@ void Executor::callExternalFunction(ExecutionState &state,
else
klee_warning_once(function, "%s", os.str().c_str());
}
+
bool success = externalDispatcher->executeCall(function, target->inst, args);
if (!success) {
terminateStateOnError(state, "failed external call: " + function->getName(),
@@ -3068,6 +3094,13 @@ void Executor::callExternalFunction(ExecutionState &state,
return;
}
+#ifndef WINDOWS
+ // Update errno memory object with the errno value from the call
+ int error = externalDispatcher->getLastErrno();
+ state.addressSpace.copyInConcrete(result.first, result.second,
+ (uint64_t)&error);
+#endif
+
Type *resultType = target->inst->getType();
if (resultType != Type::getVoidTy(function->getContext())) {
ref<Expr> e = ConstantExpr::fromMemory((void*) args,
@@ -3814,6 +3847,17 @@ void Executor::prepareForEarlyExit() {
statsTracker->done();
}
}
+
+/// Returns the errno location in memory
+int *Executor::getErrnoLocation(const ExecutionState &state) const {
+#ifndef __APPLE__
+ /* From /usr/include/errno.h: it [errno] is a per-thread variable. */
+ return __errno_location();
+#else
+ return __error();
+#endif
+}
+
///
Interpreter *Interpreter::create(LLVMContext &ctx, const InterpreterOptions &opts,
diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h
index 71b1f5f7..1bc91be0 100644
--- a/lib/Core/Executor.h
+++ b/lib/Core/Executor.h
@@ -525,6 +525,9 @@ public:
Expr::Width getWidthForLLVMType(llvm::Type *type) const;
size_t getAllocationAlignment(const llvm::Value *allocSite) const;
+
+ /// Returns the errno location in memory of the state
+ int *getErrnoLocation(const ExecutionState &state) const;
};
} // End klee namespace
diff --git a/lib/Core/ExternalDispatcher.cpp b/lib/Core/ExternalDispatcher.cpp
index 6c54d34b..70c14050 100644
--- a/lib/Core/ExternalDispatcher.cpp
+++ b/lib/Core/ExternalDispatcher.cpp
@@ -65,6 +65,7 @@ private:
llvm::Module *singleDispatchModule;
std::vector<std::string> moduleIDs;
std::string &getFreshModuleID();
+ int lastErrno;
public:
ExternalDispatcherImpl(llvm::LLVMContext &ctx);
@@ -72,6 +73,8 @@ public:
bool executeCall(llvm::Function *function, llvm::Instruction *i,
uint64_t *args);
void *resolveSymbol(const std::string &name);
+ int getLastErrno();
+ void setLastErrno(int newErrno);
};
std::string &ExternalDispatcherImpl::getFreshModuleID() {
@@ -114,7 +117,8 @@ void *ExternalDispatcherImpl::resolveSymbol(const std::string &name) {
return addr;
}
-ExternalDispatcherImpl::ExternalDispatcherImpl(LLVMContext &ctx) : ctx(ctx) {
+ExternalDispatcherImpl::ExternalDispatcherImpl(LLVMContext &ctx)
+ : ctx(ctx), lastErrno(0) {
std::string error;
singleDispatchModule = new Module(getFreshModuleID(), ctx);
#if LLVM_VERSION_CODE < LLVM_VERSION(3, 6)
@@ -252,7 +256,10 @@ bool ExternalDispatcherImpl::runProtectedCall(Function *f, uint64_t *args) {
if (setjmp(escapeCallJmpBuf)) {
res = false;
} else {
+ errno = lastErrno;
executionEngine->runFunction(f, gvArgs);
+ // Explicitly acquire errno information
+ lastErrno = errno;
res = true;
}
@@ -346,6 +353,11 @@ Function *ExternalDispatcherImpl::createDispatcher(Function *target,
return dispatcher;
}
+int ExternalDispatcherImpl::getLastErrno() { return lastErrno; }
+void ExternalDispatcherImpl::setLastErrno(int newErrno) {
+ lastErrno = newErrno;
+}
+
ExternalDispatcher::ExternalDispatcher(llvm::LLVMContext &ctx)
: impl(new ExternalDispatcherImpl(ctx)) {}
@@ -359,4 +371,9 @@ bool ExternalDispatcher::executeCall(llvm::Function *function,
void *ExternalDispatcher::resolveSymbol(const std::string &name) {
return impl->resolveSymbol(name);
}
+
+int ExternalDispatcher::getLastErrno() { return impl->getLastErrno(); }
+void ExternalDispatcher::setLastErrno(int newErrno) {
+ impl->setLastErrno(newErrno);
+}
}
diff --git a/lib/Core/ExternalDispatcher.h b/lib/Core/ExternalDispatcher.h
index c64dc7d8..7c3a1d79 100644
--- a/lib/Core/ExternalDispatcher.h
+++ b/lib/Core/ExternalDispatcher.h
@@ -40,6 +40,9 @@ public:
bool executeCall(llvm::Function *function, llvm::Instruction *i,
uint64_t *args);
void *resolveSymbol(const std::string &name);
+
+ int getLastErrno();
+ void setLastErrno(int newErrno);
};
}
diff --git a/lib/Core/Memory.h b/lib/Core/Memory.h
index 3084cf32..e854502c 100644
--- a/lib/Core/Memory.h
+++ b/lib/Core/Memory.h
@@ -154,6 +154,7 @@ private:
const MemoryObject *object;
uint8_t *concreteStore;
+
// XXX cleanup name of flushMask (its backwards or something)
BitArray *concreteMask;
diff --git a/lib/Core/SpecialFunctionHandler.cpp b/lib/Core/SpecialFunctionHandler.cpp
index 6587c30b..75456856 100644
--- a/lib/Core/SpecialFunctionHandler.cpp
+++ b/lib/Core/SpecialFunctionHandler.cpp
@@ -91,6 +91,11 @@ static SpecialFunctionHandler::HandlerInfo handlerInfo[] = {
add("klee_define_fixed_object", handleDefineFixedObject, false),
add("klee_get_obj_size", handleGetObjSize, true),
add("klee_get_errno", handleGetErrno, true),
+#ifndef __APPLE__
+ add("__errno_location", handleErrnoLocation, true),
+#else
+ add("__error", handleErrnoLocation, true),
+#endif
add("klee_is_symbolic", handleIsSymbolic, true),
add("klee_make_symbolic", handleMakeSymbolic, false),
add("klee_mark_global", handleMarkGlobal, false),
@@ -578,10 +583,41 @@ void SpecialFunctionHandler::handleGetErrno(ExecutionState &state,
// XXX should type check args
assert(arguments.size()==0 &&
"invalid number of arguments to klee_get_errno");
- executor.bindLocal(target, state,
- ConstantExpr::create(errno, Expr::Int32));
+#ifndef WINDOWS
+ int *errno_addr = executor.getErrnoLocation(state);
+#else
+ int *errno_addr = nullptr;
+#endif
+
+ // Retrieve the memory object of the errno variable
+ ObjectPair result;
+ bool resolved = state.addressSpace.resolveOne(
+ ConstantExpr::create((uint64_t)errno_addr, Expr::Int64), result);
+ if (!resolved)
+ executor.terminateStateOnError(state, "Could not resolve address for errno",
+ Executor::User);
+ executor.bindLocal(target, state, result.second->read(0, Expr::Int32));
}
+void SpecialFunctionHandler::handleErrnoLocation(
+ ExecutionState &state, KInstruction *target,
+ std::vector<ref<Expr> > &arguments) {
+ // Returns the address of the errno variable
+ assert(arguments.size() == 0 &&
+ "invalid number of arguments to __errno_location/__error");
+
+#ifndef WINDOWS
+ int *errno_addr = executor.getErrnoLocation(state);
+#else
+ int *errno_addr = nullptr;
+#endif
+
+ executor.bindLocal(
+ target, state,
+ ConstantExpr::create((uint64_t)errno_addr,
+ executor.kmodule->targetData->getTypeSizeInBits(
+ target->inst->getType())));
+}
void SpecialFunctionHandler::handleCalloc(ExecutionState &state,
KInstruction *target,
std::vector<ref<Expr> > &arguments) {
diff --git a/lib/Core/SpecialFunctionHandler.h b/lib/Core/SpecialFunctionHandler.h
index 7e58018f..b11a4974 100644
--- a/lib/Core/SpecialFunctionHandler.h
+++ b/lib/Core/SpecialFunctionHandler.h
@@ -107,6 +107,7 @@ namespace klee {
HANDLER(handleDelete);
HANDLER(handleDeleteArray);
HANDLER(handleExit);
+ HANDLER(handleErrnoLocation);
HANDLER(handleAliasFunction);
HANDLER(handleFree);
HANDLER(handleGetErrno);
diff --git a/runtime/POSIX/fd.c b/runtime/POSIX/fd.c
index 6f78c747..e0e87604 100644
--- a/runtime/POSIX/fd.c
+++ b/runtime/POSIX/fd.c
@@ -29,12 +29,6 @@
#include <sys/select.h>
#include <klee/klee.h>
-/* #define DEBUG */
-
-void klee_warning(const char*);
-void klee_warning_once(const char*);
-int klee_get_errno(void);
-
/* Returns pointer to the symbolic file structure fs the pathname is symbolic */
static exe_disk_file_t *__get_sym_file(const char *pathname) {
if (!pathname)
@@ -80,12 +74,8 @@ int access(const char *pathname, int mode) {
/* XXX we should check against stat values but we also need to
enforce in open and friends then. */
return 0;
- } else {
- int r = syscall(__NR_access, __concretize_string(pathname), mode);
- if (r == -1)
- errno = klee_get_errno();
- return r;
- }
+ }
+ return syscall(__NR_access, __concretize_string(pathname), mode);
}
mode_t umask(mode_t mask) {
@@ -182,10 +172,8 @@ int __fd_open(const char *pathname, int flags, mode_t mode) {
(mode & ~__exe_env.umask));
} else {
int os_fd = syscall(__NR_open, __concretize_string(pathname), flags, mode);
- if (os_fd == -1) {
- errno = klee_get_errno();
+ if (os_fd == -1)
return -1;
- }
f->fd = os_fd;
}
@@ -237,10 +225,8 @@ int __fd_openat(int basefd, const char *pathname, int flags, mode_t mode) {
memset(f, 0, sizeof *f);
int os_fd = syscall(__NR_openat, (long)basefd, __concretize_string(pathname), (long)flags, mode);
- if (os_fd == -1) {
- errno = klee_get_errno();
+ if (os_fd == -1)
return -1;
- }
f->fd = os_fd;
f->flags = eOpen;
@@ -269,11 +255,7 @@ int utimes(const char *path, const struct timeval times[2]) {
#endif
return 0;
}
- int r = syscall(__NR_utimes, __concretize_string(path), times);
- if (r == -1)
- errno = klee_get_errno();
-
- return r;
+ return syscall(__NR_utimes, __concretize_string(path), times);
}
@@ -295,12 +277,8 @@ int futimesat(int fd, const char* path, const struct timeval times[2]) {
return utimes(path, times);
}
- int r = syscall(__NR_futimesat, (long)fd,
- (path ? __concretize_string(path) : NULL),
- times);
- if (r == -1)
- errno = klee_get_errno();
- return r;
+ return syscall(__NR_futimesat, (long)fd,
+ (path ? __concretize_string(path) : NULL), times);
}
int close(int fd) {
@@ -376,10 +354,8 @@ ssize_t read(int fd, void *buf, size_t count) {
else
r = syscall(__NR_pread64, f->fd, buf, count, (off64_t) f->off);
- if (r == -1) {
- errno = klee_get_errno();
+ if (r == -1)
return -1;
- }
if (f->fd != 0)
f->off += r;
@@ -434,11 +410,9 @@ ssize_t write(int fd, const void *buf, size_t count) {
if (f->fd == 1 || f->fd == 2)
r = syscall(__NR_write, f->fd, buf, count);
else r = syscall(__NR_pwrite64, f->fd, buf, count, (off64_t) f->off);
-
- if (r == -1) {
- errno = klee_get_errno();
+
+ if (r == -1)
return -1;
- }
assert(r >= 0);
if (f->fd != 1 && f->fd != 2)
@@ -504,10 +478,8 @@ off64_t __fd_lseek(int fd, off64_t offset, int whence) {
}
}
- if (new_off == -1) {
- errno = klee_get_errno();
+ if (new_off == -1)
return -1;
- }
f->off = new_off;
return new_off;
@@ -541,13 +513,10 @@ int __fd_stat(const char *path, struct stat64 *buf) {
{
#if __WORDSIZE == 64
- int r = syscall(__NR_stat, __concretize_string(path), buf);
+ return syscall(__NR_stat, __concretize_string(path), buf);
#else
- int r = syscall(__NR_stat64, __concretize_string(path), buf);
+ return syscall(__NR_stat64, __concretize_string(path), buf);
#endif
- if (r == -1)
- errno = klee_get_errno();
- return r;
}
}
@@ -572,18 +541,12 @@ int fstatat(int fd, const char *path, struct stat *buf, int flags) {
}
#if (defined __NR_newfstatat) && (__NR_newfstatat != 0)
- int r = syscall(__NR_newfstatat, (long)fd,
- (path ? __concretize_string(path) : NULL),
- buf, (long)flags);
+ return syscall(__NR_newfstatat, (long)fd,
+ (path ? __concretize_string(path) : NULL), buf, (long)flags);
#else
- int r = syscall(__NR_fstatat64, (long)fd,
- (path ? __concretize_string(path) : NULL),
- buf, (long)flags);
+ return syscall(__NR_fstatat64, (long)fd,
+ (path ? __concretize_string(path) : NULL), buf, (long)flags);
#endif
-
- if (r == -1)
- errno = klee_get_errno();
- return r;
}
@@ -596,13 +559,10 @@ int __fd_lstat(const char *path, struct stat64 *buf) {
{
#if __WORDSIZE == 64
- int r = syscall(__NR_lstat, __concretize_string(path), buf);
+ return syscall(__NR_lstat, __concretize_string(path), buf);
#else
- int r = syscall(__NR_lstat64, __concretize_string(path), buf);
+ return syscall(__NR_lstat64, __concretize_string(path), buf);
#endif
- if (r == -1)
- errno = klee_get_errno();
- return r;
}
}
@@ -616,12 +576,7 @@ int chdir(const char *path) {
return -1;
}
- {
- int r = syscall(__NR_chdir, __concretize_string(path));
- if (r == -1)
- errno = klee_get_errno();
- return r;
- }
+ return syscall(__NR_chdir, __concretize_string(path));
}
int fchdir(int fd) {
@@ -636,12 +591,9 @@ int fchdir(int fd) {
klee_warning("symbolic file, ignoring (ENOENT)");
errno = ENOENT;
return -1;
- } else {
- int r = syscall(__NR_fchdir, f->fd);
- if (r == -1)
- errno = klee_get_errno();
- return r;
}
+
+ return syscall(__NR_fchdir, f->fd);
}
/* Sets mode and or errno and return appropriate result. */
@@ -672,12 +624,9 @@ int chmod(const char *path, mode_t mode) {
if (dfile) {
return __df_chmod(dfile, mode);
- } else {
- int r = syscall(__NR_chmod, __concretize_string(path), mode);
- if (r == -1)
- errno = klee_get_errno();
- return r;
}
+
+ return syscall(__NR_chmod, __concretize_string(path), mode);
}
int fchmod(int fd, mode_t mode) {
@@ -699,12 +648,9 @@ int fchmod(int fd, mode_t mode) {
if (f->dfile) {
return __df_chmod(f->dfile, mode);
- } else {
- int r = syscall(__NR_fchmod, f->fd, mode);
- if (r == -1)
- errno = klee_get_errno();
- return r;
- }
+ }
+
+ return syscall(__NR_fchmod, f->fd, mode);
}
static int __df_chown(exe_disk_file_t *df, uid_t owner, gid_t group) {
@@ -718,12 +664,9 @@ int chown(const char *path, uid_t owner, gid_t group) {
if (df) {
return __df_chown(df, owner, group);
- } else {
- int r = syscall(__NR_chown, __concretize_string(path), owner, group);
- if (r == -1)
- errno = klee_get_errno();
- return r;
}
+
+ return syscall(__NR_chown, __concretize_string(path), owner, group);
}
int fchown(int fd, uid_t owner, gid_t group) {
@@ -736,12 +679,9 @@ int fchown(int fd, uid_t owner, gid_t group) {
if (f->dfile) {
return __df_chown(f->dfile, owner, group);
- } else {
- int r = syscall(__NR_fchown, fd, owner, group);
- if (r == -1)
- errno = klee_get_errno();
- return r;
}
+
+ return syscall(__NR_fchown, fd, owner, group);
}
int lchown(const char *path, uid_t owner, gid_t group) {
@@ -750,12 +690,9 @@ int lchown(const char *path, uid_t owner, gid_t group) {
if (df) {
return __df_chown(df, owner, group);
- } else {
- int r = syscall(__NR_chown, __concretize_string(path), owner, group);
- if (r == -1)
- errno = klee_get_errno();
- return r;
}
+
+ return syscall(__NR_chown, __concretize_string(path), owner, group);
}
int __fd_fstat(int fd, struct stat64 *buf) {
@@ -768,13 +705,10 @@ int __fd_fstat(int fd, struct stat64 *buf) {
if (!f->dfile) {
#if __WORDSIZE == 64
- int r = syscall(__NR_fstat, f->fd, buf);
+ return syscall(__NR_fstat, f->fd, buf);
#else
- int r = syscall(__NR_fstat64, f->fd, buf);
+ return syscall(__NR_fstat64, f->fd, buf);
#endif
- if (r == -1)
- errno = klee_get_errno();
- return r;
}
memcpy(buf, f->dfile->stat, sizeof(*f->dfile->stat));
@@ -802,16 +736,12 @@ int __fd_ftruncate(int fd, off64_t length) {
klee_warning("symbolic file, ignoring (EIO)");
errno = EIO;
return -1;
- } else {
+ }
#if __WORDSIZE == 64
- int r = syscall(__NR_ftruncate, f->fd, length);
+ return syscall(__NR_ftruncate, f->fd, length);
#else
- int r = syscall(__NR_ftruncate64, f->fd, length);
+ return syscall(__NR_ftruncate64, f->fd, length);
#endif
- if (r == -1)
- errno = klee_get_errno();
- return r;
- }
}
int __fd_getdents(unsigned int fd, struct dirent64 *dirp, unsigned int count) {
@@ -877,19 +807,17 @@ int __fd_getdents(unsigned int fd, struct dirent64 *dirp, unsigned int count) {
s = syscall(__NR_lseek, f->fd, os_pos, SEEK_SET);
assert(s != (off64_t) -1);
res = syscall(__NR_getdents64, f->fd, dirp, count);
- if (res == -1) {
- errno = klee_get_errno();
- } else {
+ if (res > -1) {
int pos = 0;
- f->off = syscall(__NR_lseek, f->fd, 0, SEEK_CUR) + 4096;
+ f->off = syscall(__NR_lseek, f->fd, 0, SEEK_CUR);
+ assert(f->off != (off64_t)-1);
+ f->off += 4096;
/* Patch offsets */
-
while (pos < res) {
struct dirent64 *dp = (struct dirent64*) ((char*) dirp + pos);
dp->d_off += 4096;
pos += dp->d_reclen;
-
}
}
return res;
@@ -918,7 +846,6 @@ int ioctl(int fd, unsigned long request, ...) {
va_start(ap, request);
buf = va_arg(ap, void*);
va_end(ap);
-
if (f->dfile) {
struct stat *stat = (struct stat*) f->dfile->stat;
@@ -1040,12 +967,8 @@ int ioctl(int fd, unsigned long request, ...) {
errno = EINVAL;
return -1;
}
- } else {
- int r = syscall(__NR_ioctl, f->fd, request, buf );
- if (r == -1)
- errno = klee_get_errno();
- return r;
}
+ return syscall(__NR_ioctl, f->fd, request, buf);
}
int fcntl(int fd, int cmd, ...) {
@@ -1095,12 +1018,8 @@ int fcntl(int fd, int cmd, ...) {
errno = EINVAL;
return -1;
}
- } else {
- int r = syscall(__NR_fcntl, f->fd, cmd, arg );
- if (r == -1)
- errno = klee_get_errno();
- return r;
}
+ return syscall(__NR_fcntl, f->fd, cmd, arg);
}
int __fd_statfs(const char *path, struct statfs *buf) {
@@ -1112,12 +1031,7 @@ int __fd_statfs(const char *path, struct statfs *buf) {
return -1;
}
- {
- int r = syscall(__NR_statfs, __concretize_string(path), buf);
- if (r == -1)
- errno = klee_get_errno();
- return r;
- }
+ return syscall(__NR_statfs, __concretize_string(path), buf);
}
int fstatfs(int fd, struct statfs *buf) {
@@ -1132,12 +1046,8 @@ int fstatfs(int fd, struct statfs *buf) {
klee_warning("symbolic file, ignoring (EBADF)");
errno = EBADF;
return -1;
- } else {
- int r = syscall(__NR_fstatfs, f->fd, buf);
- if (r == -1)
- errno = klee_get_errno();
- return r;
}
+ return syscall(__NR_fstatfs, f->fd, buf);
}
int fsync(int fd) {
@@ -1148,12 +1058,8 @@ int fsync(int fd) {
return -1;
} else if (f->dfile) {
return 0;
- } else {
- int r = syscall(__NR_fsync, f->fd);
- if (r == -1)
- errno = klee_get_errno();
- return r;
}
+ return syscall(__NR_fsync, f->fd);
}
int dup2(int oldfd, int newfd) {
@@ -1278,12 +1184,8 @@ ssize_t readlink(const char *path, char *buf, size_t bufsize) {
errno = EINVAL;
return -1;
}
- } else {
- int r = syscall(__NR_readlink, path, buf, bufsize);
- if (r == -1)
- errno = klee_get_errno();
- return r;
}
+ return syscall(__NR_readlink, path, buf, bufsize);
}
#undef FD_SET
@@ -1356,10 +1258,8 @@ int select(int nfds, fd_set *read, fd_set *write,
if (r == -1) {
/* If no symbolic results, return error. Otherwise we will
silently ignore the OS error. */
- if (!count) {
- errno = klee_get_errno();
+ if (!count)
return -1;
- }
} else {
count += r;
@@ -1405,11 +1305,8 @@ char *getcwd(char *buf, size_t size) {
to properly work with symbolics. */
klee_check_memory_access(buf, size);
r = syscall(__NR_getcwd, buf, size);
- if (r == -1) {
- errno = klee_get_errno();
+ if (r == -1)
return NULL;
- }
-
return buf;
}
diff --git a/test/Runtime/POSIX/DirSeek.c b/test/Runtime/POSIX/DirSeek.c
index 3908b4e2..4c68a30c 100644
--- a/test/Runtime/POSIX/DirSeek.c
+++ b/test/Runtime/POSIX/DirSeek.c
@@ -1,4 +1,4 @@
-// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t2.bc
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -g -o %t2.bc
// RUN: rm -rf %t.klee-out %t.klee-out-tmp
// RUN: %gentmp %t.klee-out-tmp
// RUN: %klee --output-dir=%t.klee-out --run-in=%t.klee-out-tmp --libc=uclibc --posix-runtime --exit-on-error %t2.bc --sym-files 2 2
@@ -11,8 +11,8 @@
// For this test really to work as intended it needs to be run in a
// directory large enough to cause uclibc to do multiple getdents
-// calls (otherwise uclibc will handle the seeks itself). We should
-// create a bunch of files or something.
+// calls (otherwise uclibc will handle the seeks itself).
+// Therefore gentmp generates a directory with a specific amount of entries
#include <assert.h>
#include <stdio.h>
@@ -29,7 +29,6 @@ int main(int argc, char **argv) {
assert(de);
strcpy(first, de->d_name);
off_t pos = telldir(d);
- printf("pos: %ld\n", telldir(d));
de = readdir(d);
assert(de);
strcpy(second, de->d_name);
@@ -41,9 +40,10 @@ int main(int argc, char **argv) {
assert(strcmp(de->d_name, second) == 0);
// Go to end, then back to 2nd
- while (de)
+ while (de) {
de = readdir(d);
- assert(!errno);
+ assert(!errno);
+ }
seekdir(d, pos);
assert(telldir(d) == pos);
de = readdir(d);
diff --git a/test/Runtime/POSIX/Ioctl.c b/test/Runtime/POSIX/Ioctl.c
index e8220276..f1caaf77 100644
--- a/test/Runtime/POSIX/Ioctl.c
+++ b/test/Runtime/POSIX/Ioctl.c
@@ -5,6 +5,7 @@
#include <assert.h>
#include <fcntl.h>
#include <sys/stat.h>
+#include <sys/ioctl.h>
#include <termios.h>
#include <asm/ioctls.h>
#include <errno.h>
diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp
index ec951609..44bc5407 100644
--- a/tools/klee/main.cpp
+++ b/tools/klee/main.cpp
@@ -698,6 +698,8 @@ static const char *modelledExternals[] = {
"_assert",
"__assert_fail",
"__assert_rtn",
+ "__errno_location",
+ "__error",
"calloc",
"_exit",
"exit",