klee-uclibc icon indicating copy to clipboard operation
klee-uclibc copied to clipboard

Opt out of inline assembly in libc/sysdeps/linux/*/bits/select.h

Open jordr opened this issue 4 years ago • 8 comments

FD_ZERO and FD_SET use inline assembly that is not supported by KLEE. With this patch, we force the fallback path to C code.

jordr avatar Dec 15 '20 09:12 jordr

Thanks, @jordr. This patch is clearly fine, but nevertheless I wouldn't like to merge any patches before the CI is up again. Could you or @MartinNowack perhaps add here the scripts for GitHub Actions? We don't need all the targets, even the standard one with uclibc + posix would be enough.

ccadar avatar Dec 15 '20 09:12 ccadar

@ccadar I will take care of the script - wanted to try something out in the first place to simplify the build script.

MartinNowack avatar Dec 15 '20 09:12 MartinNowack

@MartinNowack great, thanks!

ccadar avatar Dec 15 '20 09:12 ccadar

@jordr Can you rebase this PR so we can merge it. Thank you.

MartinNowack avatar Dec 18 '20 17:12 MartinNowack

@ccadar sounds good, but this PR should be merged before the KLEE PR, otherwise the KLEE PR will have failing tests and merging blocked, right?

jordr avatar Dec 19 '20 01:12 jordr

No matter how I twist it the klee-uclibc changes seem to have no impact. When I run this test:

#include <sys/select.h>
int main() {
	fd_set fds;
	FD_ZERO(&fds);
	FD_SET(0, &fds);
}

I get

/home/jruiz/code/llvm/3.8.0.obj-auto/llvm-38-build_O_D_A//bin/clang -c -g -emit-llvm inlineasm.c -o inlineasm.bc -I/home/jruiz/code/autochopper-pspa/include/
klee -libc=uclibc --posix-runtime inlineasm.bc
KLEE: NOTE: Using POSIX model: /home/jruiz/code/autochopper-pspa/build/Debug+Asserts/lib/libkleeRuntimePOSIX.bca
KLEE: NOTE: Using klee-uclibc : /home/jruiz/code/autochopper-pspa/build/Debug+Asserts/lib/klee-uclibc.bca
KLEE: output directory is "/home/jruiz/code/autochopper-pspa/examples/inlineasm/klee-out-10"
KLEE: Using STP solver backend
KLEE: WARNING ONCE: function "__klee_posix_wrapped_main" has inline asm
KLEE: WARNING ONCE: calling external: syscall(16, 0, 21505, 93954065671728) at /home/jruiz/code/autochopper-pspa/runtime/POSIX/fd.c:1007 10
KLEE: WARNING ONCE: Alignment of memory from call "malloc" is not modelled. Using alignment of 8.
KLEE: WARNING ONCE: calling __klee_posix_wrapped_main with extra arguments.
KLEE: ERROR: inlineasm.c:8: inline assembly is unsupported
KLEE: NOTE: now ignoring this error at this location

Looking into the LLVM bytecode, there is this:

; Function Attrs: nounwind uwtable
define i32 @__klee_posix_wrapped_main() #0 !dbg !891 {
entry:
  %fds = alloca %struct.fd_set.0, align 8
  %__d0 = alloca i32, align 4
  %__d1 = alloca i32, align 4
  call void @llvm.dbg.declare(metadata %struct.fd_set.0* %fds, metadata !7852, metadata !2637), !dbg !7860
  call void @llvm.dbg.declare(metadata i32* %__d0, metadata !7861, metadata !2637), !dbg !7863
  call void @llvm.dbg.declare(metadata i32* %__d1, metadata !7864, metadata !2637), !dbg !7863
  %__fds_bits = getelementptr inbounds %struct.fd_set.0, %struct.fd_set.0* %fds, i32 0, i32 0, !dbg !7865
  %arrayidx = getelementptr inbounds [16 x i64], [16 x i64]* %__fds_bits, i64 0, i64 0, !dbg !7865
  %0 = call { i64, i64* } asm sideeffect "cld; rep; stosq", "={cx},={di},{ax},0,1,~{memory},~{dirflag},~{fpsr},~{flags}"(i32 0, i64 16, i64* %arrayidx) #8, !dbg !7865, !srcloc !7867
  %asmresult = extractvalue { i64, i64* } %0, 0, !dbg !7865
  %asmresult1 = extractvalue { i64, i64* } %0, 1, !dbg !7865
  %1 = trunc i64 %asmresult to i32, !dbg !7865
  store i32 %1, i32* %__d0, align 4, !dbg !7865
  %2 = ptrtoint i64* %asmresult1 to i64, !dbg !7865
  %3 = trunc i64 %2 to i32, !dbg !7865
  store i32 %3, i32* %__d1, align 4, !dbg !7865
  ret i32 0, !dbg !7868
}

and when I look at the debug locations, it references /usr/include/x86_64-linux-gnu/sys/select.h instead of the klee-uclibc. When I run clang with -E (preprocessor) I get:

typedef __fd_mask fd_mask;
# 101 "/usr/include/x86_64-linux-gnu/sys/select.h" 3 4
extern int select (int __nfds, fd_set *__restrict __readfds,
     fd_set *__restrict __writefds,
     fd_set *__restrict __exceptfds,
     struct timeval *__restrict __timeout);
# 113 "/usr/include/x86_64-linux-gnu/sys/select.h" 3 4
extern int pselect (int __nfds, fd_set *__restrict __readfds,
      fd_set *__restrict __writefds,
      fd_set *__restrict __exceptfds,
      const struct timespec *__restrict __timeout,
      const __sigset_t *__restrict __sigmask);
# 2 "inlineasm.c" 2




int main() { fd_set fds;
 do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq" : "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof (__fd_mask)), "1" (&((&fds)->__fds_bits)[0]) : "memory"); } while (0);
       (0, &fds);
}

Am I doing something wrong? It seems like there is already inline assembly when KLEE is run, so there is no way the klee-uclibc changes have an impact, right?

jordr avatar Dec 19 '20 01:12 jordr

Right, by default we're using the system headers. I need to look closer at this, but that's why I wanted a test ;)

ccadar avatar Dec 19 '20 15:12 ccadar

@ccadar This test file passes for me if you run it in the KLEE test suite, but I hardcoded the klee-uclibc directory path. Not sure how to test for this within klee-uclibc test system...

// RUN: %clang %s -emit-llvm -O0 -c -o %t1.bc -I/home/jruiz/code/klee-uclibc-3.8.0/include/
// RUN: %clang %s -emit-llvm -O0 -c -o %t2.bc
// RUN: rm -rf %t1.klee-out %t2.klee-out
// RUN: %klee --output-dir=%t1.klee-out %t1.bc > %t1.out 2>&1
// RUN: %klee --output-dir=%t2.klee-out %t2.bc > %t2.out 2>&1
// RUN: test ! -f %t1.klee-out/test000001.exec.err
// RUN: test -f %t2.klee-out/test000001.exec.err

#include <sys/select.h>
int main() {
	fd_set fds;
	FD_ZERO(&fds);
	FD_SET(0, &fds);
}

jordr avatar May 05 '22 15:05 jordr