mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-07 03:16:05 +03:00
libFuzzer: support LLVM 6.0 compiler-rt fuzzer (#2285)
libFuzzer was moved to compiler-rt, and therefore its location and filename has changed. Tested locally on OSX only.
This commit is contained in:
parent
f981955e22
commit
4a820f1449
5 changed files with 65 additions and 74 deletions
|
@ -766,21 +766,31 @@ function(copy_compilerrt_lib llvm_lib_name ldc_lib_name fixup_dylib)
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
if (LDC_INSTALL_LLVM_RUNTIME_LIBS)
|
if (LDC_INSTALL_LLVM_RUNTIME_LIBS)
|
||||||
|
# Locate LLVM sanitizer runtime libraries, and copy them to our lib folder
|
||||||
|
# Note: libFuzzer is part of compiler-rt version >= 6.0, but was part of LLVM =< 5.0
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
copy_compilerrt_lib("darwin/libclang_rt.asan_osx_dynamic.dylib" "libldc_rt.asan_osx_dynamic.dylib" TRUE)
|
copy_compilerrt_lib("darwin/libclang_rt.asan_osx_dynamic.dylib" "libldc_rt.asan_osx_dynamic.dylib" TRUE)
|
||||||
|
if(NOT (LDC_LLVM_VER LESS 600))
|
||||||
|
copy_compilerrt_lib("darwin/libclang_rt.fuzzer_osx.a" "libldc_rt.fuzzer_osx.a" FALSE)
|
||||||
|
endif()
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
copy_compilerrt_lib("linux/libclang_rt.asan-x86_64.a" "libldc_rt.asan-x86_64.a" FALSE)
|
copy_compilerrt_lib("linux/libclang_rt.asan-x86_64.a" "libldc_rt.asan-x86_64.a" FALSE)
|
||||||
|
if(NOT (LDC_LLVM_VER LESS 600))
|
||||||
|
copy_compilerrt_lib("linux/libclang_rt.fuzzer-x86_64.a" "libldc_rt.fuzzer-x86_64.a" FALSE)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Locate libFuzzer runtime library, and copy it to our lib folder
|
if(LDC_LLVM_VER LESS 600)
|
||||||
set(LLVM_LIBFUZZER_PATH ${LLVM_LIBRARY_DIRS}/libFuzzer.a)
|
set(LLVM_LIBFUZZER_PATH ${LLVM_LIBRARY_DIRS}/libFuzzer.a)
|
||||||
if(EXISTS ${LLVM_LIBFUZZER_PATH})
|
if(EXISTS ${LLVM_LIBFUZZER_PATH})
|
||||||
message(STATUS "Copying libFuzzer library: ${LLVM_LIBFUZZER_PATH} --> libFuzzer.a")
|
message(STATUS "Copying libFuzzer library: ${LLVM_LIBFUZZER_PATH} --> libFuzzer.a")
|
||||||
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX})
|
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX})
|
||||||
configure_file(${LLVM_LIBFUZZER_PATH} ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/libFuzzer.a COPYONLY)
|
configure_file(${LLVM_LIBFUZZER_PATH} ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/libFuzzer.a COPYONLY)
|
||||||
install(FILES ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/libFuzzer.a DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
|
install(FILES ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/libFuzzer.a DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
|
||||||
else()
|
else()
|
||||||
message(STATUS "Not found: ${LLVM_LIBFUZZER_PATH}")
|
message(STATUS "Not found: ${LLVM_LIBFUZZER_PATH}")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -180,58 +180,38 @@ void ArgsBuilder::addLTOLinkFlags() {
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Returns true on success.
|
|
||||||
bool addDarwinASanLinkFlags(std::vector<std::string> &args) {
|
|
||||||
std::string searchPaths[] = {
|
|
||||||
exe_path::prependLibDir("libldc_rt.asan_osx_dynamic.dylib"),
|
|
||||||
exe_path::prependLibDir("libclang_rt.asan_osx_dynamic.dylib"),
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const auto &filepath : searchPaths) {
|
|
||||||
if (llvm::sys::fs::exists(filepath)) {
|
|
||||||
args.push_back(filepath);
|
|
||||||
|
|
||||||
// Add @executable_path to rpath to support having the dylib copied with
|
|
||||||
// the executable.
|
|
||||||
args.push_back("-rpath");
|
|
||||||
args.push_back("@executable_path");
|
|
||||||
|
|
||||||
// Add the path to the resource dir to rpath to support using the dylib
|
|
||||||
// from the default location without copying.
|
|
||||||
args.push_back("-rpath");
|
|
||||||
args.push_back(llvm::sys::path::parent_path(filepath));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We did not find the library.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the arch name as used in the compiler_rt libs.
|
// Returns the arch name as used in the compiler_rt libs.
|
||||||
// FIXME: implement correctly for non-x86 platforms (e.g. ARM)
|
// FIXME: implement correctly for non-x86 platforms (e.g. ARM)
|
||||||
llvm::StringRef getCompilerRTArchName() {
|
llvm::StringRef getCompilerRTArchName() {
|
||||||
return global.params.targetTriple->getArchName();
|
return global.params.targetTriple->getArchName();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addUnixlikeASanLinkFlags(std::vector<std::string> &args) {
|
// Returns the libname as full path and with arch suffix and extension.
|
||||||
|
// For example, with name="libldc_rt.fuzzer", the returned string is
|
||||||
|
// "libldc_rt.fuzzer_osx.a" on Darwin.
|
||||||
|
std::string getFullCompilerRTLibPath(llvm::StringRef name,
|
||||||
|
bool sharedLibrary = false) {
|
||||||
|
if (global.params.targetTriple->isOSDarwin()) {
|
||||||
|
return exe_path::prependLibDir(
|
||||||
|
name + (sharedLibrary ? "_osx_dynamic.dylib" : "_osx.a"));
|
||||||
|
} else {
|
||||||
|
return exe_path::prependLibDir(name + "-" + getCompilerRTArchName() +
|
||||||
|
(sharedLibrary ? ".so" : ".a"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArgsBuilder::addASanLinkFlags() {
|
||||||
// Examples: "libclang_rt.asan-x86_64.a" or "libclang_rt.asan-arm.a" and
|
// Examples: "libclang_rt.asan-x86_64.a" or "libclang_rt.asan-arm.a" and
|
||||||
// "libclang_rt.asan-x86_64.so"
|
// "libclang_rt.asan-x86_64.so"
|
||||||
|
|
||||||
auto arch = getCompilerRTArchName();
|
// TODO: let user choose to link with shared lib.
|
||||||
|
// In case of shared ASan, I think we also need to statically link with
|
||||||
// TODO: let user choose to link with shared lib. In case of shared ASan, I
|
// libclang_rt.asan-preinit-<arch>.a on Linux. On Darwin, the only option is
|
||||||
// think we also need to statically link with
|
// to use the shared library.
|
||||||
// libclang_rt.asan-preinit-<arch>.a
|
bool linkSharedASan = global.params.targetTriple->isOSDarwin();
|
||||||
bool linkSharedASan = false;
|
|
||||||
const char *extension = linkSharedASan ? ".so" : ".a";
|
|
||||||
|
|
||||||
std::string searchPaths[] = {
|
std::string searchPaths[] = {
|
||||||
exe_path::prependLibDir("libldc_rt.asan-" + llvm::Twine(arch) +
|
getFullCompilerRTLibPath("libldc_rt.asan", linkSharedASan),
|
||||||
extension),
|
getFullCompilerRTLibPath("libclang_rt.asan", linkSharedASan),
|
||||||
exe_path::prependLibDir("libclang_rt.asan-" + llvm::Twine(arch) +
|
|
||||||
extension),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &filepath : searchPaths) {
|
for (const auto &filepath : searchPaths) {
|
||||||
|
@ -239,39 +219,39 @@ bool addUnixlikeASanLinkFlags(std::vector<std::string> &args) {
|
||||||
args.push_back(filepath);
|
args.push_back(filepath);
|
||||||
|
|
||||||
if (linkSharedASan) {
|
if (linkSharedASan) {
|
||||||
// TODO: add -rpath
|
// Add @executable_path to rpath to support having the shared lib copied
|
||||||
|
// with the executable.
|
||||||
|
args.push_back("-rpath");
|
||||||
|
args.push_back("@executable_path");
|
||||||
|
|
||||||
|
// Add the path to the resource dir to rpath to support using the shared
|
||||||
|
// lib from the default location without copying.
|
||||||
|
args.push_back("-rpath");
|
||||||
|
args.push_back(llvm::sys::path::parent_path(filepath));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We did not find the library.
|
// When we reach here, we did not find the ASan library.
|
||||||
return false;
|
// Fallback, requires Clang. The asan library contains a versioned symbol
|
||||||
}
|
// name and a linker error will happen when the LDC-LLVM and Clang-LLVM
|
||||||
|
// versions don't match.
|
||||||
void ArgsBuilder::addASanLinkFlags() {
|
args.push_back("-fsanitize=address");
|
||||||
bool success = false;
|
|
||||||
if (global.params.targetTriple->isOSDarwin()) {
|
|
||||||
success = addDarwinASanLinkFlags(args);
|
|
||||||
} else {
|
|
||||||
success = addUnixlikeASanLinkFlags(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
// Fallback, requires Clang. The asan library contains a versioned symbol
|
|
||||||
// name and a linker error will happen when the LDC-LLVM and Clang-LLVM
|
|
||||||
// versions don't match.
|
|
||||||
args.push_back("-fsanitize=address");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds all required link flags for -fsanitize=fuzzer when libFuzzer library is
|
// Adds all required link flags for -fsanitize=fuzzer when libFuzzer library is
|
||||||
// found.
|
// found.
|
||||||
void ArgsBuilder::addFuzzLinkFlags() {
|
void ArgsBuilder::addFuzzLinkFlags() {
|
||||||
std::string searchPaths[] = {
|
std::string searchPaths[] = {
|
||||||
|
#if LDC_LLVM_VER >= 600
|
||||||
|
getFullCompilerRTLibPath("libldc_rt.fuzzer"),
|
||||||
|
getFullCompilerRTLibPath("libclang_rt.fuzzer"),
|
||||||
|
#else
|
||||||
exe_path::prependLibDir("libFuzzer.a"),
|
exe_path::prependLibDir("libFuzzer.a"),
|
||||||
exe_path::prependLibDir("libLLVMFuzzer.a"),
|
exe_path::prependLibDir("libLLVMFuzzer.a"),
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &filepath : searchPaths) {
|
for (const auto &filepath : searchPaths) {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
bool FuzzMe(const ubyte* data, size_t dataSize)
|
bool FuzzMe(const ubyte* data, size_t dataSize)
|
||||||
{
|
{
|
||||||
// CHECK: call {{.*}}_sanitizer_cov_trace_pc_guard
|
// CHECK: call {{.*}}_sanitizer_cov_trace_pc_guard
|
||||||
// CHECK: call {{.*}}_sanitizer_cov_trace_cmp
|
// CHECK: call {{.*}}_sanitizer_cov_trace_{{(const_)?}}cmp
|
||||||
|
|
||||||
return dataSize >= 3 &&
|
return dataSize >= 3 &&
|
||||||
data[0] == 'F' &&
|
data[0] == 'F' &&
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
// RUN: %ldc -v -fsanitize=fuzzer %s | FileCheck %s
|
// RUN: %ldc -v -fsanitize=fuzzer %s | FileCheck %s
|
||||||
// RUN: not %ldc -v -fsanitize=fuzzer -link-no-cpp %s | FileCheck %s --check-prefix=NOCPP
|
// RUN: not %ldc -v -fsanitize=fuzzer -link-no-cpp %s | FileCheck %s --check-prefix=NOCPP
|
||||||
|
|
||||||
// CHECK: libFuzzer.a
|
// "libFuzzer.a" before LLVM 6.0, "lib(ldc|clang)_rt.fuzzer.*.a" since LLVM 6.0
|
||||||
|
// CHECK: {{(libFuzzer\.a|_rt\.fuzzer.*\.a)}}
|
||||||
// CHECK-SAME: -l{{(c|stdc)}}++
|
// CHECK-SAME: -l{{(c|stdc)}}++
|
||||||
|
|
||||||
// NOCPP-NOT: -l{{(c|stdc)}}++
|
// NOCPP-NOT: -l{{(c|stdc)}}++
|
||||||
|
|
|
@ -9,7 +9,7 @@ if (platform.system() == 'Darwin') or (platform.system() == 'Linux'):
|
||||||
if m is not None:
|
if m is not None:
|
||||||
config.available_features.add('ASan')
|
config.available_features.add('ASan')
|
||||||
continue
|
continue
|
||||||
m = re.match('.*Fuzzer.*', file)
|
m = re.match('.*(F|f)uzzer.*', file)
|
||||||
if m is not None:
|
if m is not None:
|
||||||
config.available_features.add('Fuzzer')
|
config.available_features.add('Fuzzer')
|
||||||
continue
|
continue
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue