about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
-rw-r--r--runtime/klee-libc/__cxa_atexit.c5
-rw-r--r--test/Runtime/klee-libc/cxa_thread_atexit_impl.c20
2 files changed, 25 insertions, 0 deletions
diff --git a/runtime/klee-libc/__cxa_atexit.c b/runtime/klee-libc/__cxa_atexit.c
index 990b645d..eb0c3e41 100644
--- a/runtime/klee-libc/__cxa_atexit.c
+++ b/runtime/klee-libc/__cxa_atexit.c
@@ -47,3 +47,8 @@ int __cxa_atexit(void (*fn)(void*),
   return 0;
 }
 
+// This variant is part of more recent glibc versions and
+// is required by the Rust standard library
+int __cxa_thread_atexit_impl(void (*fn)(void*), void *arg, void *dso_handle) {
+  return __cxa_atexit(fn, arg, dso_handle);
+}
diff --git a/test/Runtime/klee-libc/cxa_thread_atexit_impl.c b/test/Runtime/klee-libc/cxa_thread_atexit_impl.c
new file mode 100644
index 00000000..18dc7e08
--- /dev/null
+++ b/test/Runtime/klee-libc/cxa_thread_atexit_impl.c
@@ -0,0 +1,20 @@
+// RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out --exit-on-error --libc=klee %t1.bc
+
+// just make sure __cxa_thread_atexit_impl works ok
+
+#include <assert.h>
+
+extern int __cxa_thread_atexit_impl(void (*)(void*), void*, void *);
+
+static int x; // a global whose address we can take
+
+void boo(void *h) {
+  assert(h == (void*)&x);
+}
+
+int main() {
+  __cxa_thread_atexit_impl(boo, (void*)&x, (void*)0);
+  return 0;
+}