diff --git a/CMakeLists.txt b/CMakeLists.txt index e8317d04c0..18d853e189 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -506,19 +506,29 @@ endif() # KLEE uclibc support ################################################################################ set(KLEE_UCLIBC_PATH "" CACHE PATH "Path to klee-uclibc root directory") -set(KLEE_UCLIBC_BCA_NAME "klee-uclibc.bca") + +set(KLEE_UCLIBC_BCA_32_NAME "klee-uclibc-32.bca") +set(KLEE_UCLIBC_BCA_64_NAME "klee-uclibc-64.bca") + if (NOT KLEE_UCLIBC_PATH STREQUAL "") # Find the C library bitcode archive - set(KLEE_UCLIBC_C_BCA "${KLEE_UCLIBC_PATH}/lib/libc.a") - if (NOT EXISTS "${KLEE_UCLIBC_C_BCA}") + set(KLEE_UCLIBC_C_32_BCA "${KLEE_UCLIBC_PATH}-32/lib/libc.a") + set(KLEE_UCLIBC_C_64_BCA "${KLEE_UCLIBC_PATH}-64/lib/libc.a") + + if (NOT EXISTS "${KLEE_UCLIBC_C_32_BCA}" OR NOT EXISTS "${KLEE_UCLIBC_C_64_BCA}") message(FATAL_ERROR - "klee-uclibc library not found at \"${KLEE_UCLIBC_C_BCA}\". Set KLEE_UCLIBC_PATH to klee-uclibc root directory or empty string.") + "klee-uclibc library not found at \"${KLEE_UCLIBC_C_32_BCA}\" or \"${KLEE_UCLIBC_C_64_BCA}\". Set KLEE_UCLIBC_PATH to klee-uclibc root directory or empty string.") endif() - message(STATUS "Found klee-uclibc library: \"${KLEE_UCLIBC_C_BCA}\"") + message(STATUS "Found klee-uclibc library: \"${KLEE_UCLIBC_C_32_BCA}\" and \"${KLEE_UCLIBC_C_64_BCA}\"") # Copy KLEE_UCLIBC_C_BCA so KLEE can find it where it is expected. + # Create 32 and 64 bit versions + execute_process(COMMAND ${CMAKE_COMMAND} -E copy + "${KLEE_UCLIBC_C_32_BCA}" + "${KLEE_RUNTIME_DIRECTORY}/${KLEE_UCLIBC_BCA_32_NAME}" + ) execute_process(COMMAND ${CMAKE_COMMAND} -E copy - "${KLEE_UCLIBC_C_BCA}" - "${KLEE_RUNTIME_DIRECTORY}/${KLEE_UCLIBC_BCA_NAME}" + "${KLEE_UCLIBC_C_64_BCA}" + "${KLEE_RUNTIME_DIRECTORY}/${KLEE_UCLIBC_BCA_64_NAME}" ) else() message(STATUS "Skipping copying of klee-uclibc runtime") diff --git a/include/klee/Config/config.h.cmin b/include/klee/Config/config.h.cmin index 29a48405b7..91dbaf6868 100644 --- a/include/klee/Config/config.h.cmin +++ b/include/klee/Config/config.h.cmin @@ -102,7 +102,10 @@ #define RUNTIME_CONFIGURATION "@KLEE_RUNTIME_BUILD_TYPE@" /* Configure name of KLEE's uClibc library */ -#cmakedefine KLEE_UCLIBC_BCA_NAME "@KLEE_UCLIBC_BCA_NAME@" +#cmakedefine KLEE_UCLIBC_BCA_32_NAME "@KLEE_UCLIBC_BCA_32_NAME@" + +/* Configure name of KLEE's uClibc library */ +#cmakedefine KLEE_UCLIBC_BCA_64_NAME "@KLEE_UCLIBC_BCA_64_NAME@" /* Configure name of the libCXX bitcode library */ #cmakedefine KLEE_LIBCXX_BC_NAME "@KLEE_LIBCXX_BC_NAME@" diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 064935305d..df6816f3a2 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -720,14 +720,29 @@ void Executor::allocateGlobalObjects(ExecutionState &state) { } #ifndef WINDOWS - int *errno_addr = getErrnoLocation(state); + llvm::Type *pointerErrnoAddr = llvm::PointerType::get( llvm::IntegerType::get(m->getContext(), sizeof(*errno_addr) * CHAR_BIT), adressSpaceNum); - MemoryObject *errnoObj = - addExternalObject(state, (void *)errno_addr, - typeSystemManager->getWrappedType(pointerErrnoAddr), - sizeof *errno_addr, false); + MemoryObject *errnoObj = nullptr; + + if (Context::get().getPointerWidth() == 32) { + errnoObj = allocate(state, Expr::createPointer(sizeof(*errno_addr)), false, + true, nullptr, 8); + errnoObj->isFixed = true; + + ObjectState *os = bindObjectInState( + state, errnoObj, typeSystemManager->getWrappedType(pointerErrnoAddr), + false); + errno_addr = reinterpret_cast(errnoObj->address); + } else { + errno_addr = getErrnoLocation(state); + errnoObj = + addExternalObject(state, (void *)errno_addr, + typeSystemManager->getWrappedType(pointerErrnoAddr), + sizeof *errno_addr, false); + } + // Copy values from and to program space explicitly errnoObj->isUserSpecified = true; #endif @@ -4867,7 +4882,6 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, state.addressSpace.copyOutConcretes(); #ifndef WINDOWS // Update external errno state with local state value - int *errno_addr = getErrnoLocation(state); IDType idResult; llvm::Type *pointerErrnoAddr = llvm::PointerType::get( diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index d66ff5986f..79f99dd0eb 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -122,6 +122,8 @@ class Executor : public Interpreter { RNG theRNG; private: + int *errno_addr; + using SetOfStates = std::set; /* Set of Intrinsic::ID. Plain type is used here to avoid including llvm in * the header */ diff --git a/lib/Core/SpecialFunctionHandler.cpp b/lib/Core/SpecialFunctionHandler.cpp index 1d3e07b85f..6138eabe1b 100644 --- a/lib/Core/SpecialFunctionHandler.cpp +++ b/lib/Core/SpecialFunctionHandler.cpp @@ -734,7 +734,8 @@ void SpecialFunctionHandler::handleErrnoLocation( "invalid number of arguments to __errno_location/__error"); #ifndef WINDOWS - int *errno_addr = executor.getErrnoLocation(state); + // int *errno_addr = executor.getErrnoLocation(state); + int *errno_addr = executor.errno_addr; #else int *errno_addr = nullptr; #endif diff --git a/scripts/build/p-uclibc.inc b/scripts/build/p-uclibc.inc index 95af975137..f7cce95f2d 100644 --- a/scripts/build/p-uclibc.inc +++ b/scripts/build/p-uclibc.inc @@ -6,11 +6,18 @@ setup_build_variables_uclibc() { download_uclibc() { source "${DIR}/common-functions" - git_clone_or_update "${uclibc_url}" "${UCLIBC_PATH}" "${UCLIBC_VERSION}" + git_clone_or_update "${uclibc_url}" "${UCLIBC_PATH}-32" "${UCLIBC_VERSION}" + git_clone_or_update "${uclibc_url}" "${UCLIBC_PATH}-64" "${UCLIBC_VERSION}" } build_uclibc() { - cd "${UCLIBC_PATH}" || return 1 + pushd "${UCLIBC_PATH}-32" || return 1 + ./configure --make-llvm-lib --with-cc "${BITCODE_CC}" --with-llvm-config "${LLVM_CONFIG}" + make KLEE_CFLAGS="-m32" || return 1 + touch .is_installed + popd &>/dev/null + + pushd "${UCLIBC_PATH}-64" || return 1 ./configure --make-llvm-lib --with-cc "${BITCODE_CC}" --with-llvm-config "${LLVM_CONFIG}" make || return 1 touch .is_installed @@ -24,7 +31,11 @@ install_uclibc() { is_installed_uclibc() { ( setup_build_variables_uclibc - [[ -f "${UCLIBC_PATH}"/.is_installed ]] + [[ -f "${UCLIBC_PATH}-32"/.is_installed ]] + ) || return 1 + ( + setup_build_variables_uclibc + [[ -f "${UCLIBC_PATH}-64"/.is_installed ]] ) || return 1 } @@ -40,7 +51,8 @@ get_docker_config_id_uclibc() { get_build_artifacts_uclibc() { ( setup_build_variables_uclibc - echo "${UCLIBC_PATH}" + echo "${UCLIBC_PATH}-32" + echo "${UCLIBC_PATH}-64" ) } diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index 1099b9da14..b1dee0fb34 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -1221,7 +1221,17 @@ linkWithUclibc(StringRef libDir, std::string opt_suffix, // Ensure that klee-uclibc exists SmallString<128> uclibcBCA(libDir); - llvm::sys::path::append(uclibcBCA, KLEE_UCLIBC_BCA_NAME); + // Hack to find out bitness of .bc file + + if (opt_suffix.substr(0, 2) == "32") { + llvm::sys::path::append(uclibcBCA, KLEE_UCLIBC_BCA_32_NAME); + } else if (opt_suffix.substr(0, 2) == "64") { + llvm::sys::path::append(uclibcBCA, KLEE_UCLIBC_BCA_64_NAME); + } else { + klee_error("Cannot determine bitness of source file from the name %s", + uclibcBCA.c_str()); + } + if (!klee::loadFileAsOneModule(uclibcBCA.c_str(), ctx, libsModules, errorMsg)) klee_error("Cannot find klee-uclibc '%s': %s", uclibcBCA.c_str(), errorMsg.c_str());