~ubuntu-branches/ubuntu/saucy/clamav/saucy-backports

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
 *  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"
#include "llvm/Support/raw_ostream.h"
#ifdef LLVM29
#include "llvm/Support/Host.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Memory.h"
#else
#include "llvm/System/Host.h"
#include "llvm/System/DataTypes.h"
#include "llvm/System/Memory.h"
#endif

#include "llvm/Config/config.h"

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 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)
{
    std::string host_triple = sys::getHostTriple();
    INIT_STRFIELD(env->triple, host_triple.c_str());

    std::string cpu = sys::getHostCPUName();
    INIT_STRFIELD(env->cpu, cpu.c_str());

    if (env->big_endian != (int)sys::isBigEndianHost()) {
	warn_assumptions("host endianness", env->big_endian, sys::isBigEndianHost());
	env->big_endian = sys::isBigEndianHost();
    }

#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;
	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);
#ifndef LLVM29
	CASE_OS(MinGW64, os_win64);
#endif
	CASE_OS(NetBSD,  os_bsd);
	CASE_OS(OpenBSD, os_bsd);
	CASE_OS(Psp, os_unknown);
	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);
    }
}