c85060ff |
/*
* JIT detection for ClamAV bytecode.
*
* Copyright (C) 2010 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" |
9f8df4ae |
#include "llvm/Config/config.h" |
c85060ff |
#include "llvm/Support/raw_ostream.h" |
9f8df4ae |
#if LLVM_VERSION < 29 |
c85060ff |
#include "llvm/System/DataTypes.h" |
9f8df4ae |
#include "llvm/System/Host.h" |
c85060ff |
#include "llvm/System/Memory.h" |
9f8df4ae |
#else
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Memory.h" |
0c79cc55 |
#endif
|
c85060ff |
extern "C" {
#include "bytecode_detect.h"
}
using namespace llvm;
static void warn_assumptions(const char *msg, int a, int b)
{ |
1bb5a24d |
errs() << "LibClamAV Warning: libclamav and llvm make inconsistent " |
c85060ff |
<< "assumptions about " << msg << ": " <<
a << " and " << b << "."
<< "Please report to http://bugs.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)
{ |
34d8b8cf |
#if LLVM_VERSION < 31 |
c85060ff |
std::string host_triple = sys::getHostTriple(); |
34d8b8cf |
#else
std::string host_triple = sys::getDefaultTargetTriple();
#endif |
c85060ff |
INIT_STRFIELD(env->triple, host_triple.c_str());
std::string cpu = sys::getHostCPUName();
INIT_STRFIELD(env->cpu, cpu.c_str());
|
34d8b8cf |
#if LLVM_VERSION < 33 |
69650bea |
if (env->big_endian != (int)sys::isBigEndianHost()) { |
c85060ff |
warn_assumptions("host endianness", env->big_endian, sys::isBigEndianHost());
env->big_endian = sys::isBigEndianHost();
} |
34d8b8cf |
#else
if (env->big_endian != (int)sys::IsBigEndianHost) {
warn_assumptions("host endianness", env->big_endian, sys::IsBigEndianHost);
env->big_endian = sys::IsBigEndianHost;
}
#endif |
c85060ff |
#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; |
5cd4ee88 |
if (env->arch != earch &&
env->arch != arch_ppc64) conflicts = true; |
c85060ff |
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; |
5cd4ee88 |
if (env->arch != earch) {
/* bb #2153 */ |
ef226b8a |
if (env->arch != arch_x86_64) |
5cd4ee88 |
conflicts = true;
} |
c85060ff |
break;
case Triple::x86_64:
earch = arch_x86_64; |
5cd4ee88 |
if (env->arch != earch) { |
f4253c16 |
/* 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) |
5cd4ee88 |
conflicts = true;
} |
c85060ff |
break;
default:
earch = arch_unknown;
break;
} |
dec93ea8 |
#ifndef AC_APPLE_UNIVERSAL_BUILD |
c85060ff |
if (conflicts)
warn_assumptions("CPU architecture", env->arch, earch); |
dec93ea8 |
#endif |
c85060ff |
if (earch != arch_unknown)
env->arch = earch;
// OS
Triple::OSType os = triple.getOS();
switch (os) {
case Triple::UnknownOS:
env->os = llvm_os_UnknownOS;
break;
CASE_OS(AuroraUX, os_solaris);
CASE_OS(Cygwin, os_win32);
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);
CASE_OS(MinGW32, os_win32); |
9f8df4ae |
#if LLVM_VERSION < 29 |
c85060ff |
CASE_OS(MinGW64, os_win64); |
0c79cc55 |
#endif |
c85060ff |
CASE_OS(NetBSD, os_bsd);
CASE_OS(OpenBSD, os_bsd); |
34d8b8cf |
#if LLVM_VERSION < 31 |
c85060ff |
CASE_OS(Psp, os_unknown); |
34d8b8cf |
#endif |
c85060ff |
CASE_OS(Solaris, os_solaris); |
f55cd65e |
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; |
c85060ff |
CASE_OS(Haiku, os_unknown); |
19f9dadf |
CASE_OS(Minix, os_unknown); |
c85060ff |
}
// 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);
}
}
|