mirror of
				https://github.com/Cisco-Talos/clamav.git
				synced 2025-10-31 08:00:54 +00:00 
			
		
		
		
	 da23b1ceab
			
		
	
	
		da23b1ceab
		
	
	
	
	
		
			
			Have to manually link libtinfo (`-ltinfo`) because our FindLLVM didn't add it to the LLVM_LIBRARIES variable for us. See: - https://stackoverflow.com/questions/21477407/llvm-3-5-fails-to-link Have to remove the CXX_STANDARD setting at the top of CMakeLists.txt because of c++90 / c++11 ABI compatibility issues w/ LLVM. See: - https://maleadt.github.io/LLVM.jl/dev/man/troubleshooting/ Rename "llvm/Config/config.h" "llvm/Config/llvm-config.h" because LLVM renamed it in 2.8. Have to link LLVM manually with the test binaries that use the clamav object library instead of libclamav shared library. CMake does not propagate library dependencies from object files. I tested on ubuntu:16.04 with LLVM 3.6 built from source using: ``` /usr/local/bin/cmake .. -D CMAKE_INSTALL_PREFIX=/opt/llvm/3.6 \ -D LLVM_ENABLE_RTTI=ON ``` Then built clamav w/: ``` /usr/local/bin/cmake .. -D CMAKE_INSTALL_PREFIX=`pwd`/install \ -D BYTECODE_RUNTIME="llvm" \ -D LLVM_ROOT_DIR="/opt/llvm/3.6" \ -D LLVM_FIND_VERSION="3.6.0" && make && make install ```
		
			
				
	
	
		
			188 lines
		
	
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			188 lines
		
	
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  *  JIT detection for ClamAV bytecode.
 | |
|  *
 | |
|  *  Copyright (C) 2013-2021 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
 | |
|  *  Copyright (C) 2010-2013 Sourcefire, Inc.
 | |
|  *
 | |
|  *  Authors: Török Edvin
 | |
|  *
 | |
|  *  This program is free software; you can redistribute it and/or modify
 | |
|  *  it under the terms of the GNU General Public License version 2 as
 | |
|  *  published by the Free Software Foundation.
 | |
|  *
 | |
|  *  This program is distributed in the hope that it will be useful,
 | |
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|  *  GNU General Public License for more details.
 | |
|  *
 | |
|  *  You should have received a copy of the GNU General Public License
 | |
|  *  along with this program; if not, write to the Free Software
 | |
|  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 | |
|  *  MA 02110-1301, USA.
 | |
|  */
 | |
| 
 | |
| #include "llvm/ADT/Triple.h"
 | |
| #include "llvm/Config/llvm-config.h"
 | |
| #include "llvm/Support/raw_ostream.h"
 | |
| #if LLVM_VERSION < 29
 | |
| #include "llvm/System/DataTypes.h"
 | |
| #include "llvm/System/Host.h"
 | |
| #include "llvm/System/Memory.h"
 | |
| #else
 | |
| #include "llvm/Support/DataTypes.h"
 | |
| #include "llvm/Support/Host.h"
 | |
| #include "llvm/Support/Memory.h"
 | |
| #endif
 | |
| 
 | |
| extern "C" {
 | |
| #include "bytecode_detect.h"
 | |
| }
 | |
| 
 | |
| using namespace llvm;
 | |
| 
 | |
| static void warn_assumptions(const char *msg, int a, int b)
 | |
| {
 | |
|     errs() << "LibClamAV Warning: libclamav and llvm make inconsistent "
 | |
| 	<< "assumptions about " << msg << ": " <<
 | |
| 	a << " and " << b << "."
 | |
| 	<< "Please report to https://bugzilla.clamav.net\n";
 | |
| }
 | |
| 
 | |
| #define CASE_OS(theos, compat) case Triple::theos:\
 | |
|     env->os = llvm_os_##theos;\
 | |
|     if (env->os_category != compat)\
 | |
|         warn_assumptions("Operating System", env->os_category, Triple::theos);\
 | |
|     break
 | |
| 
 | |
| void cli_detect_env_jit(struct cli_environment *env)
 | |
| {
 | |
| #if LLVM_VERSION < 31
 | |
|     std::string host_triple = sys::getHostTriple();
 | |
| #else
 | |
|     std::string host_triple = sys::getDefaultTargetTriple();
 | |
| #endif
 | |
|     INIT_STRFIELD(env->triple, host_triple.c_str());
 | |
| 
 | |
|     std::string cpu = sys::getHostCPUName();
 | |
|     INIT_STRFIELD(env->cpu, cpu.c_str());
 | |
| 
 | |
| #if LLVM_VERSION < 33
 | |
|     if (env->big_endian != (int)sys::isBigEndianHost()) {
 | |
| 	warn_assumptions("host endianness", env->big_endian, sys::isBigEndianHost());
 | |
| 	env->big_endian = sys::isBigEndianHost();
 | |
|     }
 | |
| #else
 | |
|     if (env->big_endian != (int)sys::IsBigEndianHost) {
 | |
| 	warn_assumptions("host endianness", env->big_endian, sys::IsBigEndianHost);
 | |
| 	env->big_endian = sys::IsBigEndianHost;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
| #ifdef __GNUC__
 | |
|     env->cpp_version = MAKE_VERSION(0, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
 | |
| #elif defined (__INTEL_COMPILER)
 | |
|     env->cpp_version = __INTEL_COMPILER;
 | |
| #elif defined (_MSC_VER)
 | |
|     env->cpp_version = _MSC_VER;
 | |
| #endif
 | |
| 
 | |
|     Triple triple(host_triple);
 | |
| 
 | |
|     // CPU architecture
 | |
|     enum Triple::ArchType arch = triple.getArch();
 | |
|     enum arch_list earch;
 | |
|     bool conflicts = false;
 | |
|     switch (arch) {
 | |
| 	case Triple::arm:
 | |
| 	    earch = arch_arm;
 | |
| 	    if (env->arch != earch) conflicts = true;
 | |
| 	    break;
 | |
| 	case Triple::ppc:
 | |
| 	    earch = arch_ppc32;
 | |
| 	    if (env->arch != earch &&
 | |
| 		env->arch != arch_ppc64) conflicts = true;
 | |
| 	    break;
 | |
| 	case Triple::ppc64:
 | |
| 	    earch = arch_ppc64;
 | |
| 	    // ppc64 is fixed up by llvm
 | |
| 	    if (env->arch != arch_ppc32 &&
 | |
| 		env->arch != arch_ppc64) conflicts = true;
 | |
| 	    break;
 | |
| 	case Triple::x86:
 | |
| 	    earch = arch_i386;
 | |
| 	    if (env->arch != earch) {
 | |
| 		/* bb #2153 */
 | |
| 		if (env->arch != arch_x86_64)
 | |
| 		    conflicts = true;
 | |
| 	    }
 | |
| 	    break;
 | |
| 	case Triple::x86_64:
 | |
| 	    earch = arch_x86_64;
 | |
| 	    if (env->arch != earch) {
 | |
| 		/* bb #2153, bb #2214 */
 | |
| 		/* configure can't detect -m32, so it thinks we are x86_64, when
 | |
| 		 * in fact we are i386 only.
 | |
| 		 * LLVM correctly detects which one it is using preprocessor
 | |
| 		 * macros, so don't warn here, startup.cbc will just have to
 | |
| 		 * rely on the LLVM provided info, and not the configure
 | |
| 		 * provided one! */
 | |
| 		if (env->arch != arch_i386)
 | |
| 		    conflicts = true;
 | |
| 	    }
 | |
| 	    break;
 | |
| 	default:
 | |
| 	    earch = arch_unknown;
 | |
| 	    break;
 | |
|     }
 | |
| #ifndef AC_APPLE_UNIVERSAL_BUILD
 | |
|     if (conflicts)
 | |
| 	warn_assumptions("CPU architecture", env->arch, earch);
 | |
| #endif
 | |
|     if (earch != arch_unknown)
 | |
| 	env->arch = earch;
 | |
| 
 | |
|     // OS
 | |
|     Triple::OSType os = triple.getOS();
 | |
|     switch (os) {
 | |
| 	case Triple::UnknownOS:
 | |
| 	    env->os = llvm_os_UnknownOS;
 | |
| 	    break;
 | |
| #if LLVM_VERSION < 36
 | |
| 	CASE_OS(AuroraUX, os_solaris);
 | |
| 	CASE_OS(Cygwin, os_win32);
 | |
| 	CASE_OS(MinGW32, os_win32);
 | |
| #endif
 | |
| 	CASE_OS(Darwin, os_darwin);
 | |
| 	CASE_OS(DragonFly, os_bsd);
 | |
| 	CASE_OS(FreeBSD, os_bsd);
 | |
| 	CASE_OS(Linux, os_linux);
 | |
| 	CASE_OS(Lv2, os_unknown);
 | |
| #if LLVM_VERSION < 29
 | |
| 	CASE_OS(MinGW64, os_win64);
 | |
| #endif
 | |
| 	CASE_OS(NetBSD,  os_bsd);
 | |
| 	CASE_OS(OpenBSD, os_bsd);
 | |
| #if LLVM_VERSION < 31
 | |
| 	CASE_OS(Psp, os_unknown);
 | |
| #endif
 | |
| 	CASE_OS(Solaris, os_solaris);
 | |
| 	case Triple::Win32:
 | |
| 	     env->os = llvm_os_Win32;
 | |
| 	     if (env->os_category != os_win32 &&
 | |
| 		 env->os_category != os_win64)
 | |
| 		 warn_assumptions("Operating System", env->os_category, Triple::Win32);
 | |
| 	     break;
 | |
| 	CASE_OS(Haiku, os_unknown);
 | |
| 	CASE_OS(Minix, os_unknown);
 | |
|     }
 | |
| 
 | |
|     // mmap RWX
 | |
|     std::string ErrMsg;
 | |
|     sys::MemoryBlock B = sys::Memory::AllocateRWX(4096, NULL, &ErrMsg);
 | |
|     if (B.base() == 0) {
 | |
| 	errs() << "LibClamAV Warning: RWX mapping denied: " << ErrMsg << "\n";
 | |
|     } else {
 | |
| 	env->os_features |= 1 << feature_map_rwx;
 | |
| 	sys::Memory::ReleaseRWX(B);
 | |
|     }
 | |
| }
 |