2
* JIT compile ClamAV bytecode.
4
* Copyright (C) 2009-2010 Sourcefire, Inc.
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License version 2 as
10
* published by the Free Software Foundation.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22
#define DEBUG_TYPE "clamavjit"
23
#include "ClamBCModule.h"
24
#include "llvm/ADT/DenseMap.h"
25
#include "llvm/ADT/BitVector.h"
26
#include "llvm/ADT/StringMap.h"
27
#include "llvm/ADT/StringSwitch.h"
28
#include "llvm/ADT/Triple.h"
29
#include "llvm/CallingConv.h"
30
#include "llvm/DerivedTypes.h"
31
#include "llvm/Function.h"
32
#include "llvm/ExecutionEngine/ExecutionEngine.h"
33
#include "llvm/ExecutionEngine/JIT.h"
34
#include "llvm/ExecutionEngine/JITEventListener.h"
35
#include "llvm/LLVMContext.h"
36
#include "llvm/Module.h"
37
#include "llvm/PassManager.h"
38
#include "llvm/Support/Compiler.h"
39
#include "llvm/Support/Debug.h"
40
#include "llvm/Support/CommandLine.h"
41
#include "llvm/Support/ErrorHandling.h"
42
#include "llvm/Support/ManagedStatic.h"
43
#include "llvm/Support/MemoryBuffer.h"
44
#include "llvm/Support/raw_ostream.h"
45
#include "llvm/Support/SourceMgr.h"
46
#include "llvm/Support/IRBuilder.h"
47
#include "llvm/Support/PrettyStackTrace.h"
48
#include "llvm/System/DataTypes.h"
49
#include "llvm/System/Host.h"
50
#include "llvm/System/Mutex.h"
51
#include "llvm/System/Signals.h"
52
#include "llvm/System/Threading.h"
53
#include "llvm/Target/TargetSelect.h"
54
#include "llvm/Target/TargetData.h"
55
#include "llvm/Target/TargetOptions.h"
56
#include "llvm/Support/TargetFolder.h"
57
#include "llvm/Analysis/Verifier.h"
58
#include "llvm/Transforms/Scalar.h"
59
#include "llvm/System/ThreadLocal.h"
64
#include "llvm/Config/config.h"
66
#error "Thread support was explicitly disabled. Cannot continue"
69
#ifdef _GLIBCXX_PARALLEL
70
#error "libstdc++ parallel mode is not supported for ClamAV. Please remove -D_GLIBCXX_PARALLEL from CXXFLAGS!"
74
#undef PACKAGE_BUGREPORT
77
#undef PACKAGE_TARNAME
78
#undef PACKAGE_VERSION
80
#include "clamav-config.h"
86
#include "bytecode_priv.h"
87
#include "type_desc.h"
92
#define MODULE "libclamav JIT: "
94
extern "C" unsigned int cli_rndnum(unsigned int max);
96
typedef DenseMap<const struct cli_bc_func*, void*> FunctionMapTy;
100
FunctionMapTy compiledFunctions;
103
void* align;/* just to align field to ptr */
109
static sys::ThreadLocal<const jmp_buf> ExceptionReturn;
115
static void NORETURN jit_exception_handler(void)
117
longjmp(*(jmp_buf*)(ExceptionReturn.get()), 1);
120
static void NORETURN jit_ssp_handler(void)
122
errs() << "Bytecode JIT: *** stack smashing detected, bytecode aborted\n";
123
jit_exception_handler();
126
void llvm_error_handler(void *user_data, const std::string &reason)
128
// Output it to stderr, it might exceed the 1k/4k limit of cli_errmsg
129
errs() << MODULE << reason;
130
jit_exception_handler();
133
// Since libgcc is not available on all compilers (for example on win32),
134
// just define what these functions should do, the compiler will forward to
135
// the appropriate libcall if needed.
136
static int64_t rtlib_sdiv_i64(int64_t a, int64_t b)
141
static uint64_t rtlib_udiv_i64(uint64_t a, uint64_t b)
146
static int64_t rtlib_srem_i64(int64_t a, int64_t b)
151
static uint64_t rtlib_urem_i64(uint64_t a, uint64_t b)
156
static int64_t rtlib_mul_i64(uint64_t a, uint64_t b)
161
static int64_t rtlib_shl_i64(int64_t a, int32_t b)
166
static int64_t rtlib_srl_i64(int64_t a, int32_t b)
168
return (uint64_t)a >> b;
170
/* Implementation independent sign-extended signed right shift */
172
#define CLI_SRS(n,s) ((n)>>(s))
174
#define CLI_SRS(n,s) ((((n)>>(s)) ^ (1<<(sizeof(n)*8-1-s))) - (1<<(sizeof(n)*8-1-s)))
176
static int64_t rtlib_sra_i64(int64_t a, int32_t b)
178
return CLI_SRS(a, b);//CLI_./..
181
// Resolve integer libcalls, but nothing else.
182
static void* noUnknownFunctions(const std::string& name) {
184
StringSwitch<void*>(name)
185
.Case("__divdi3", (void*)(intptr_t)rtlib_sdiv_i64)
186
.Case("__udivdi3", (void*)(intptr_t)rtlib_udiv_i64)
187
.Case("__moddi3", (void*)(intptr_t)rtlib_srem_i64)
188
.Case("__umoddi3", (void*)(intptr_t)rtlib_urem_i64)
189
.Case("__muldi3", (void*)(intptr_t)rtlib_mul_i64)
190
.Case("__ashrdi3", (void*)(intptr_t)rtlib_sra_i64)
191
.Case("__ashldi3", (void*)(intptr_t)rtlib_shl_i64)
192
.Case("__lshrdi3", (void*)(intptr_t)rtlib_srl_i64)
193
.Case("memmove", (void*)(intptr_t)memmove)
194
.Case("memcpy", (void*)(intptr_t)memcpy)
195
.Case("memset", (void*)(intptr_t)memset)
196
.Case("abort", (void*)(intptr_t)jit_exception_handler)
201
std::string reason((Twine("Attempt to call external function ")+name).str());
202
llvm_error_handler(0, reason);
206
class LLVMTypeMapper {
208
std::vector<PATypeHolder> TypeMap;
209
LLVMContext &Context;
211
const Type *getStatic(uint16_t ty)
214
return Type::getVoidTy(Context);
216
return IntegerType::get(Context, ty);
219
return PointerType::getUnqual(Type::getInt8Ty(Context));
221
return PointerType::getUnqual(Type::getInt16Ty(Context));
223
return PointerType::getUnqual(Type::getInt32Ty(Context));
225
return PointerType::getUnqual(Type::getInt64Ty(Context));
227
llvm_unreachable("getStatic");
230
LLVMTypeMapper(LLVMContext &Context, const struct cli_bc_type *types,
231
unsigned count, const Type *Hidden=0) : Context(Context), numTypes(count)
233
TypeMap.reserve(count);
234
// During recursive type construction pointers to Type* may be
235
// invalidated, so we must use a TypeHolder to an Opaque type as a
237
for (unsigned i=0;i<count;i++) {
238
TypeMap.push_back(OpaqueType::get(Context));
240
std::vector<const Type*> Elts;
241
for (unsigned i=0;i<count;i++) {
242
const struct cli_bc_type *type = &types[i];
244
unsigned n = type->kind == DArrayType ? 1 : type->numElements;
245
for (unsigned j=0;j<n;j++) {
246
Elts.push_back(get(type->containedTypes[j]));
249
switch (type->kind) {
252
assert(Elts.size() > 0 && "Function with no return type?");
253
const Type *RetTy = Elts[0];
257
Elts.erase(Elts.begin());
258
Ty = FunctionType::get(RetTy, Elts, false);
262
if (!PointerType::isValidElementType(Elts[0]))
263
Ty = PointerType::getUnqual(Type::getInt8Ty(Context));
265
Ty = PointerType::getUnqual(Elts[0]);
268
Ty = StructType::get(Context, Elts);
270
case DPackedStructType:
271
Ty = StructType::get(Context, Elts, true);
274
Ty = ArrayType::get(Elts[0], type->numElements);
277
llvm_unreachable("type->kind");
279
// Make the opaque type a concrete type, doing recursive type
280
// unification if needed.
281
cast<OpaqueType>(TypeMap[i].get())->refineAbstractTypeTo(Ty);
285
const Type *get(uint16_t ty)
289
return getStatic(ty);
291
assert(ty < numTypes && "TypeID out of range");
292
return TypeMap[ty].get();
296
struct CommonFunctions {
301
Function *FRealmemset;
302
Function *FRealMemmove;
303
Function *FRealmemcmp;
304
Function *FRealmemcpy;
310
class VISIBILITY_HIDDEN LLVMCodegen {
312
const struct cli_bc *bc;
314
LLVMContext &Context;
316
FunctionPassManager &PM;
317
LLVMTypeMapper *TypeMap;
320
LLVMTypeMapper &apiMap;
321
FunctionMapTy &compiledFunctions;
325
IRBuilder<false, TargetFolder> Builder;
327
std::vector<Value*> globals;
328
DenseMap<unsigned, unsigned> GVoffsetMap;
329
DenseMap<unsigned, const Type*> GVtypeMap;
333
std::vector<MDNode*> mdnodes;
335
struct CommonFunctions *CF;
337
Value *getOperand(const struct cli_bc_func *func, const Type *Ty, operand_t operand)
339
unsigned map[] = {0, 1, 2, 3, 3, 4, 4, 4, 4};
340
if (operand < func->numValues)
341
return Values[operand];
342
unsigned w = (Ty->getPrimitiveSizeInBits()+7)/8;
343
return convertOperand(func, map[w], operand);
346
Value *convertOperand(const struct cli_bc_func *func, const Type *Ty, operand_t operand)
348
unsigned map[] = {0, 1, 2, 3, 3, 4, 4, 4, 4};
349
if (operand < func->numArgs)
350
return Values[operand];
351
if (operand < func->numValues) {
352
Value *V = Values[operand];
353
if (func->types[operand]&0x8000 && V->getType() == Ty) {
356
V = Builder.CreateLoad(V);
357
if (V->getType() != Ty &&
358
isa<PointerType>(V->getType()) &&
359
isa<PointerType>(Ty))
360
V = Builder.CreateBitCast(V, Ty);
361
if (V->getType() != Ty) {
362
errs() << operand << " ";
365
llvm_report_error("(libclamav) Type mismatch converting operand");
369
unsigned w = (Ty->getPrimitiveSizeInBits()+7)/8;
370
return convertOperand(func, map[w], operand);
373
Value *convertOperand(const struct cli_bc_func *func,
374
const struct cli_bc_inst *inst, operand_t operand)
376
return convertOperand(func, inst->interp_op%5, operand);
379
Value *convertOperand(const struct cli_bc_func *func,
380
unsigned w, operand_t operand) {
381
if (operand < func->numArgs)
382
return Values[operand];
383
if (operand < func->numValues) {
384
if (func->types[operand]&0x8000)
385
return Values[operand];
386
return Builder.CreateLoad(Values[operand]);
389
if (operand & 0x80000000) {
390
operand &= 0x7fffffff;
391
assert(operand < globals.size() && "Global index out of range");
394
return ConstantPointerNull::get(PointerType::getUnqual(Type::getInt8Ty(Context)));
395
assert(globals[operand]);
396
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(globals[operand])) {
397
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(GV->getInitializer())) {
402
return globals[operand];
405
operand -= func->numValues;
406
// This was already validated by libclamav.
407
assert(operand < func->numConstants && "Constant out of range");
408
uint64_t *c = &func->constants[operand];
414
Ty = w ? Type::getInt8Ty(Context) :
415
Type::getInt1Ty(Context);
419
Ty = Type::getInt16Ty(Context);
423
Ty = Type::getInt32Ty(Context);
427
Ty = Type::getInt64Ty(Context);
431
llvm_unreachable("width");
433
return ConstantInt::get(Ty, v);
436
void Store(uint16_t dest, Value *V)
438
assert(dest >= numArgs && dest < numLocals+numArgs && "Instruction destination out of range");
439
Builder.CreateStore(V, Values[dest]);
442
// Insert code that calls \arg CF->FHandler if \arg FailCond is true.
443
void InsertVerify(Value *FailCond, BasicBlock *&Fail, Function *FHandler,
446
Fail = BasicBlock::Create(Context, "fail", F);
447
CallInst::Create(FHandler,"",Fail);
448
new UnreachableInst(Context, Fail);
450
BasicBlock *OkBB = BasicBlock::Create(Context, "", F);
451
Builder.CreateCondBr(FailCond, Fail, OkBB);
452
Builder.SetInsertPoint(OkBB);
455
const Type* mapType(uint16_t typeID)
457
return TypeMap->get(typeID&0x7fffffff);
460
Constant *buildConstant(const Type *Ty, uint64_t *components, unsigned &c)
462
if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
465
ConstantInt::get(Type::getInt64Ty(Context), components[c++])
467
unsigned idx = components[c++];
469
return ConstantPointerNull::get(PTy);
470
assert(idx < globals.size());
471
GlobalVariable *GV = cast<GlobalVariable>(globals[idx]);
472
const Type *IP8Ty = PointerType::getUnqual(Type::getInt8Ty(Ty->getContext()));
473
Constant *C = ConstantExpr::getPointerCast(GV, IP8Ty);
474
//TODO: check constant bounds here
475
return ConstantExpr::getPointerCast(
476
ConstantExpr::getInBoundsGetElementPtr(C, idxs, 1),
479
if (isa<IntegerType>(Ty)) {
480
return ConstantInt::get(Ty, components[c++]);
482
if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
483
std::vector<Constant*> elements;
484
elements.reserve(ATy->getNumElements());
485
for (unsigned i=0;i<ATy->getNumElements();i++) {
486
elements.push_back(buildConstant(ATy->getElementType(), components, c));
488
return ConstantArray::get(ATy, elements);
490
if (const StructType *STy = dyn_cast<StructType>(Ty)) {
491
std::vector<Constant*> elements;
492
elements.reserve(STy->getNumElements());
493
for (unsigned i=0;i<STy->getNumElements();i++) {
494
elements.push_back(buildConstant(STy->getElementType(i), components, c));
496
return ConstantStruct::get(STy, elements);
499
llvm_unreachable("invalid type");
505
LLVMCodegen(const struct cli_bc *bc, Module *M, struct CommonFunctions *CF, FunctionMapTy &cFuncs,
506
ExecutionEngine *EE, FunctionPassManager &PM,
507
Function **apiFuncs, LLVMTypeMapper &apiMap)
508
: bc(bc), M(M), Context(M->getContext()), EE(EE),
509
PM(PM), apiFuncs(apiFuncs),apiMap(apiMap),
510
compiledFunctions(cFuncs), BytecodeID("bc"+Twine(bc->id)),
511
Folder(EE->getTargetData()), Builder(Context, Folder), CF(CF) {
513
for (unsigned i=0;i<cli_apicall_maxglobal - _FIRST_GLOBAL;i++) {
514
unsigned id = cli_globals[i].globalid;
515
GVoffsetMap[id] = cli_globals[i].offset;
519
template <typename InputIterator>
520
Value* createGEP(Value *Base, const Type *ETy, InputIterator Start, InputIterator End) {
521
const Type *Ty = GetElementPtrInst::getIndexedType(Base->getType(), Start, End);
522
if (!Ty || (ETy && (Ty != ETy && (!isa<IntegerType>(Ty) || !isa<IntegerType>(ETy))))) {
523
errs() << MODULE << "Wrong indices for GEP opcode: "
524
<< " expected type: " << *ETy;
526
errs() << " actual type: " << *Ty;
527
errs() << " base: " << *Base << ";";
528
Base->getType()->dump();
529
errs() << "\n indices: ";
530
for (InputIterator I=Start; I != End; I++) {
531
errs() << **I << ", ";
536
return Builder.CreateGEP(Base, Start, End);
539
template <typename InputIterator>
540
bool createGEP(unsigned dest, Value *Base, InputIterator Start, InputIterator End) {
541
assert(dest >= numArgs && dest < numLocals+numArgs && "Instruction destination out of range");
542
const Type *ETy = cast<PointerType>(cast<PointerType>(Values[dest]->getType())->getElementType())->getElementType();
543
Value *V = createGEP(Base, ETy, Start, End);
545
errs() << "@ " << dest << "\n";
548
V = Builder.CreateBitCast(V, PointerType::getUnqual(ETy));
553
MDNode *convertMDNode(unsigned i) {
554
if (i < mdnodes.size()) {
559
assert(i < mdnodes.size());
560
const struct cli_bc_dbgnode *node = &bc->dbgnodes[i];
561
Value **Vals = new Value*[node->numelements];
562
for (unsigned j=0;j<node->numelements;j++) {
563
const struct cli_bc_dbgnode_element* el = &node->elements[j];
566
if (el->nodeid == ~0u)
569
V = convertMDNode(el->nodeid);
571
V = MDString::get(Context, "");
572
} else if (el->string) {
573
V = MDString::get(Context, StringRef(el->string, el->len));
575
V = ConstantInt::get(IntegerType::get(Context, el->len),
580
MDNode *N = MDNode::get(Context, Vals, node->numelements);
586
void AddStackProtect(Function *F)
588
BasicBlock &BB = F->getEntryBlock();
589
if (isa<AllocaInst>(BB.begin())) {
590
// Have an alloca -> some instruction uses its address otherwise
591
// mem2reg would have converted it to an SSA register.
592
// Enable stack protector for this function.
593
F->addFnAttr(Attribute::StackProtect);
594
F->addFnAttr(Attribute::StackProtectReq);
599
TypeMap = new LLVMTypeMapper(Context, bc->types + 4, bc->num_types - 5);
600
for (unsigned i=0;i<bc->dbgnode_cnt;i++) {
601
mdnodes.push_back(convertMDNode(i));
604
for (unsigned i=0;i<cli_apicall_maxglobal - _FIRST_GLOBAL;i++) {
605
unsigned id = cli_globals[i].globalid;
606
const Type *Ty = apiMap.get(cli_globals[i].type);
607
/*if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty))
608
Ty = PointerType::getUnqual(ATy->getElementType());*/
612
// The hidden ctx param to all functions
613
const Type *HiddenCtx = PointerType::getUnqual(Type::getInt8Ty(Context));
615
globals.reserve(bc->num_globals);
617
FakeGVs.resize(bc->num_globals);
618
globals.push_back(0);
619
for (unsigned i=1;i<bc->num_globals;i++) {
620
const Type *Ty = mapType(bc->globaltys[i]);
622
// TODO: validate number of components against type_components
625
if (isa<PointerType>(Ty)) {
626
unsigned g = bc->globals[i][1];
627
if (GVoffsetMap.count(g)) {
629
globals.push_back(0);
633
Constant *C = buildConstant(Ty, bc->globals[i], c);
634
GV = new GlobalVariable(*M, Ty, true,
635
GlobalValue::InternalLinkage,
637
globals.push_back(GV);
639
Function **Functions = new Function*[bc->num_func];
640
for (unsigned j=0;j<bc->num_func;j++) {
641
PrettyStackTraceString CrashInfo("Generate LLVM IR functions");
642
// Create LLVM IR Function
643
const struct cli_bc_func *func = &bc->funcs[j];
644
std::vector<const Type*> argTypes;
645
argTypes.push_back(HiddenCtx);
646
for (unsigned a=0;a<func->numArgs;a++) {
647
argTypes.push_back(mapType(func->types[a]));
649
const Type *RetTy = mapType(func->returnType);
650
FunctionType *FTy = FunctionType::get(RetTy, argTypes,
652
Functions[j] = Function::Create(FTy, Function::InternalLinkage,
653
BytecodeID+"f"+Twine(j), M);
654
Functions[j]->setDoesNotThrow();
655
Functions[j]->setCallingConv(CallingConv::Fast);
657
const Type *I32Ty = Type::getInt32Ty(Context);
659
PM.add(createClamBCRTChecks());
660
for (unsigned j=0;j<bc->num_func;j++) {
661
PrettyStackTraceString CrashInfo("Generate LLVM IR");
662
const struct cli_bc_func *func = &bc->funcs[j];
664
// Create all BasicBlocks
665
Function *F = Functions[j];
666
BasicBlock **BB = new BasicBlock*[func->numBB];
667
for (unsigned i=0;i<func->numBB;i++) {
668
BB[i] = BasicBlock::Create(Context, "", F);
671
BasicBlock *Fail = 0;
672
Values = new Value*[func->numValues];
673
Builder.SetInsertPoint(BB[0]);
674
Function::arg_iterator I = F->arg_begin();
675
assert(F->arg_size() == (unsigned)(func->numArgs + 1) && "Mismatched args");
677
for (unsigned i=0;i<func->numArgs; i++) {
678
assert(I != F->arg_end());
682
for (unsigned i=func->numArgs;i<func->numValues;i++) {
683
if (!func->types[i]) {
684
//instructions without return value, like store
688
Values[i] = Builder.CreateAlloca(mapType(func->types[i]));
690
numLocals = func->numLocals;
691
numArgs = func->numArgs;
694
Argument *Ctx = F->arg_begin();
695
for (unsigned i=0;i<bc->num_globals;i++) {
698
unsigned g = bc->globals[i][1];
699
unsigned offset = GVoffsetMap[g];
700
Constant *Idx = ConstantInt::get(Type::getInt32Ty(Context),
702
Value *GEP = Builder.CreateInBoundsGEP(Ctx, Idx);
703
const Type *Ty = GVtypeMap[g];
704
Ty = PointerType::getUnqual(PointerType::getUnqual(Ty));
705
Value *Cast = Builder.CreateBitCast(GEP, Ty);
706
Value *SpecialGV = Builder.CreateLoad(Cast);
707
const Type *IP8Ty = Type::getInt8Ty(Context);
708
IP8Ty = PointerType::getUnqual(IP8Ty);
709
SpecialGV = Builder.CreateBitCast(SpecialGV, IP8Ty);
710
SpecialGV->setName("g"+Twine(g-_FIRST_GLOBAL)+"_");
712
ConstantInt::get(Type::getInt32Ty(Context), bc->globals[i][0])
714
globals[i] = createGEP(SpecialGV, 0, C, C+1);
716
errs() << i << ":" << g << ":" << bc->globals[i][0] <<"\n";
718
llvm_report_error("(libclamav) unable to create fake global");
720
globals[i] = Builder.CreateBitCast(globals[i], Ty);
721
if(GetElementPtrInst *GI = dyn_cast<GetElementPtrInst>(globals[i])) {
722
GI->setIsInBounds(true);
723
GI->setName("geped"+Twine(i)+"_");
728
// Generate LLVM IR for each BB
729
for (unsigned i=0;i<func->numBB;i++) {
730
bool unreachable = false;
731
const struct cli_bc_bb *bb = &func->BB[i];
732
Builder.SetInsertPoint(BB[i]);
734
for (unsigned j=0;j<bb->numInsts;j++) {
735
const struct cli_bc_inst *inst = &bb->insts[j];
736
Value *Op0=0, *Op1=0, *Op2=0;
737
// libclamav has already validated this.
738
assert(inst->opcode < OP_BC_INVALID && "Invalid opcode");
739
if (func->dbgnodes) {
740
if (func->dbgnodes[c] != ~0u) {
741
unsigned j = func->dbgnodes[c];
742
assert(j < mdnodes.size());
743
Builder.SetCurrentDebugLocation(mdnodes[j]);
745
Builder.SetCurrentDebugLocation(0);
748
switch (inst->opcode) {
752
case OP_BC_CALL_DIRECT:
762
case OP_BC_PTRDIFF32:
763
// these instructions represents operands differently
766
switch (operand_counts[inst->opcode]) {
768
Op0 = convertOperand(func, inst, inst->u.unaryop);
771
Op0 = convertOperand(func, inst, inst->u.binop[0]);
772
Op1 = convertOperand(func, inst, inst->u.binop[1]);
773
if (Op0->getType() != Op1->getType()) {
776
llvm_report_error("(libclamav) binop type mismatch");
780
Op0 = convertOperand(func, inst, inst->u.three[0]);
781
Op1 = convertOperand(func, inst, inst->u.three[1]);
782
Op2 = convertOperand(func, inst, inst->u.three[2]);
787
switch (inst->opcode) {
789
Store(inst->dest, Builder.CreateAdd(Op0, Op1));
792
Store(inst->dest, Builder.CreateSub(Op0, Op1));
795
Store(inst->dest, Builder.CreateMul(Op0, Op1));
799
Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0));
800
InsertVerify(Bad, Fail, CF->FHandler, F);
801
Store(inst->dest, Builder.CreateUDiv(Op0, Op1));
806
//TODO: also verify Op0 == -1 && Op1 = INT_MIN
807
Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0));
808
InsertVerify(Bad, Fail, CF->FHandler, F);
809
Store(inst->dest, Builder.CreateSDiv(Op0, Op1));
814
Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0));
815
InsertVerify(Bad, Fail, CF->FHandler, F);
816
Store(inst->dest, Builder.CreateURem(Op0, Op1));
821
//TODO: also verify Op0 == -1 && Op1 = INT_MIN
822
Value *Bad = Builder.CreateICmpEQ(Op1, ConstantInt::get(Op1->getType(), 0));
823
InsertVerify(Bad, Fail, CF->FHandler, F);
824
Store(inst->dest, Builder.CreateSRem(Op0, Op1));
828
Store(inst->dest, Builder.CreateShl(Op0, Op1));
831
Store(inst->dest, Builder.CreateLShr(Op0, Op1));
834
Store(inst->dest, Builder.CreateAShr(Op0, Op1));
837
Store(inst->dest, Builder.CreateAnd(Op0, Op1));
840
Store(inst->dest, Builder.CreateOr(Op0, Op1));
843
Store(inst->dest, Builder.CreateXor(Op0, Op1));
847
Value *Src = convertOperand(func, inst, inst->u.cast.source);
848
const Type *Ty = mapType(func->types[inst->dest]);
849
Store(inst->dest, Builder.CreateTrunc(Src, Ty));
854
Value *Src = convertOperand(func, inst, inst->u.cast.source);
855
const Type *Ty = mapType(func->types[inst->dest]);
856
Store(inst->dest, Builder.CreateZExt(Src, Ty));
861
Value *Src = convertOperand(func, inst, inst->u.cast.source);
862
const Type *Ty = mapType(func->types[inst->dest]);
863
Store(inst->dest, Builder.CreateSExt(Src, Ty));
868
Value *Cond = convertOperand(func, inst, inst->u.branch.condition);
869
BasicBlock *True = BB[inst->u.branch.br_true];
870
BasicBlock *False = BB[inst->u.branch.br_false];
871
if (Cond->getType() != Type::getInt1Ty(Context)) {
872
errs() << MODULE << "type mismatch in condition\n";
875
Builder.CreateCondBr(Cond, True, False);
880
BasicBlock *Jmp = BB[inst->u.jump];
881
Builder.CreateBr(Jmp);
886
Op0 = convertOperand(func, F->getReturnType(), inst->u.unaryop);
887
Builder.CreateRet(Op0);
891
Builder.CreateRetVoid();
894
Store(inst->dest, Builder.CreateICmpEQ(Op0, Op1));
897
Store(inst->dest, Builder.CreateICmpNE(Op0, Op1));
900
Store(inst->dest, Builder.CreateICmpUGT(Op0, Op1));
903
Store(inst->dest, Builder.CreateICmpUGE(Op0, Op1));
906
Store(inst->dest, Builder.CreateICmpULT(Op0, Op1));
909
Store(inst->dest, Builder.CreateICmpULE(Op0, Op1));
912
Store(inst->dest, Builder.CreateICmpSGT(Op0, Op1));
915
Store(inst->dest, Builder.CreateICmpSGE(Op0, Op1));
918
Store(inst->dest, Builder.CreateICmpSLT(Op0, Op1));
921
Store(inst->dest, Builder.CreateSelect(Op0, Op1, Op2));
925
Value *Dest = Values[inst->u.binop[1]];
926
const PointerType *PTy = cast<PointerType>(Dest->getType());
927
Op0 = convertOperand(func, PTy->getElementType(), inst->u.binop[0]);
928
Builder.CreateStore(Op0, Dest);
931
case OP_BC_CALL_DIRECT:
933
Function *DestF = Functions[inst->u.ops.funcid];
934
SmallVector<Value*, 2> args;
935
args.push_back(&*F->arg_begin()); // pass hidden arg
936
for (unsigned a=0;a<inst->u.ops.numOps;a++) {
937
operand_t op = inst->u.ops.ops[a];
938
args.push_back(convertOperand(func, DestF->getFunctionType()->getParamType(a+1), op));
940
CallInst *CI = Builder.CreateCall(DestF, args.begin(), args.end());
941
CI->setCallingConv(CallingConv::Fast);
942
if (CI->getType()->getTypeID() != Type::VoidTyID)
943
Store(inst->dest, CI);
948
assert(inst->u.ops.funcid < cli_apicall_maxapi && "APICall out of range");
949
std::vector<Value*> args;
950
Function *DestF = apiFuncs[inst->u.ops.funcid];
951
args.push_back(&*F->arg_begin()); // pass hidden arg
952
for (unsigned a=0;a<inst->u.ops.numOps;a++) {
953
operand_t op = inst->u.ops.ops[a];
954
args.push_back(convertOperand(func, DestF->getFunctionType()->getParamType(a+1), op));
956
Store(inst->dest, Builder.CreateCall(DestF, args.begin(), args.end()));
961
const Type *SrcTy = mapType(inst->u.three[0]);
962
Value *V = convertOperand(func, SrcTy, inst->u.three[1]);
963
Value *Op = convertOperand(func, I32Ty, inst->u.three[2]);
964
// Op = Builder.CreateTrunc(Op, I32Ty);
965
if (!createGEP(inst->dest, V, &Op, &Op+1))
972
Ops[0] = ConstantInt::get(Type::getInt32Ty(Context), 0);
973
const Type *SrcTy = mapType(inst->u.three[0]);
974
Value *V = convertOperand(func, SrcTy, inst->u.three[1]);
975
Ops[1] = convertOperand(func, I32Ty, inst->u.three[2]);
976
// Ops[1] = Builder.CreateTrunc(Ops[1], I32Ty);
977
if (!createGEP(inst->dest, V, Ops, Ops+2))
983
std::vector<Value*> Idxs;
984
assert(inst->u.ops.numOps > 2);
985
const Type *SrcTy = mapType(inst->u.ops.ops[0]);
986
Value *V = convertOperand(func, SrcTy, inst->u.ops.ops[1]);
987
for (unsigned a=2;a<inst->u.ops.numOps;a++) {
988
Value *Op = convertOperand(func, I32Ty, inst->u.ops.ops[a]);
989
// Op = Builder.CreateTrunc(Op, I32Ty);
992
if (!createGEP(inst->dest, V, Idxs.begin(), Idxs.end()))
998
Value *Dest = convertOperand(func, inst, inst->u.binop[1]);
999
Value *V = convertOperand(func, inst, inst->u.binop[0]);
1000
const Type *VPTy = PointerType::getUnqual(V->getType());
1001
if (VPTy != Dest->getType())
1002
Dest = Builder.CreateBitCast(Dest, VPTy);
1003
Builder.CreateStore(V, Dest);
1008
Op0 = Builder.CreateBitCast(Op0,
1009
Values[inst->dest]->getType());
1010
Op0 = Builder.CreateLoad(Op0);
1011
Store(inst->dest, Op0);
1016
Value *Dst = convertOperand(func, inst, inst->u.three[0]);
1017
Value *Val = convertOperand(func, Type::getInt8Ty(Context), inst->u.three[1]);
1018
Value *Len = convertOperand(func, Type::getInt32Ty(Context), inst->u.three[2]);
1019
CallInst *c = Builder.CreateCall4(CF->FMemset, Dst, Val, Len,
1020
ConstantInt::get(Type::getInt32Ty(Context), 1));
1021
c->setTailCall(true);
1022
c->setDoesNotThrow();
1027
Value *Dst = convertOperand(func, inst, inst->u.three[0]);
1028
Value *Src = convertOperand(func, inst, inst->u.three[1]);
1029
Value *Len = convertOperand(func, Type::getInt32Ty(Context), inst->u.three[2]);
1030
CallInst *c = Builder.CreateCall4(CF->FMemcpy, Dst, Src, Len,
1031
ConstantInt::get(Type::getInt32Ty(Context), 1));
1032
c->setTailCall(true);
1033
c->setDoesNotThrow();
1038
Value *Dst = convertOperand(func, inst, inst->u.three[0]);
1039
Value *Src = convertOperand(func, inst, inst->u.three[1]);
1040
Value *Len = convertOperand(func, Type::getInt32Ty(Context), inst->u.three[2]);
1041
CallInst *c = Builder.CreateCall4(CF->FMemmove, Dst, Src, Len,
1042
ConstantInt::get(Type::getInt32Ty(Context), 1));
1043
c->setTailCall(true);
1044
c->setDoesNotThrow();
1049
Value *Dst = convertOperand(func, inst, inst->u.three[0]);
1050
Value *Src = convertOperand(func, inst, inst->u.three[1]);
1051
Value *Len = convertOperand(func, EE->getTargetData()->getIntPtrType(Context), inst->u.three[2]);
1052
CallInst *c = Builder.CreateCall3(CF->FRealmemcmp, Dst, Src, Len);
1053
c->setTailCall(true);
1054
c->setDoesNotThrow();
1055
Store(inst->dest, c);
1058
case OP_BC_ISBIGENDIAN:
1059
Store(inst->dest, WORDS_BIGENDIAN ?
1060
ConstantInt::getTrue(Context) :
1061
ConstantInt::getFalse(Context));
1065
CallInst *CI = Builder.CreateCall(CF->FHandler);
1066
CI->setDoesNotReturn();
1067
CI->setDoesNotThrow();
1068
Builder.CreateUnreachable();
1074
CallInst *C = Builder.CreateCall(CF->FBSwap16, convertOperand(func, inst, inst->u.unaryop));
1075
C->setTailCall(true);
1076
C->setDoesNotThrow(true);
1077
Store(inst->dest, C);
1082
CallInst *C = Builder.CreateCall(CF->FBSwap32, convertOperand(func, inst, inst->u.unaryop));
1083
C->setTailCall(true);
1084
C->setDoesNotThrow(true);
1085
Store(inst->dest, C);
1090
CallInst *C = Builder.CreateCall(CF->FBSwap64, convertOperand(func, inst, inst->u.unaryop));
1091
C->setTailCall(true);
1092
C->setDoesNotThrow(true);
1093
Store(inst->dest, C);
1096
case OP_BC_PTRDIFF32:
1098
Value *P1 = convertOperand(func, inst, inst->u.binop[0]);
1099
Value *P2 = convertOperand(func, inst, inst->u.binop[1]);
1100
P1 = Builder.CreatePtrToInt(P1, Type::getInt64Ty(Context));
1101
P2 = Builder.CreatePtrToInt(P2, Type::getInt64Ty(Context));
1102
Value *R = Builder.CreateSub(P1, P2);
1103
R = Builder.CreateTrunc(R, Type::getInt32Ty(Context));
1104
Store(inst->dest, R);
1108
errs() << MODULE << "JIT doesn't implement opcode " <<
1109
inst->opcode << " yet!\n";
1115
if (verifyFunction(*F, PrintMessageAction)) {
1116
errs() << MODULE << "Verification failed\n";
1118
// verification failed
1128
std::vector<const Type*> args;
1130
args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context)));
1131
FunctionType *Callable = FunctionType::get(Type::getInt32Ty(Context),
1133
for (unsigned j=0;j<bc->num_func;j++) {
1134
const struct cli_bc_func *func = &bc->funcs[j];
1135
PrettyStackTraceString CrashInfo2("Native machine codegen");
1137
// If prototype matches, add to callable functions
1138
if (Functions[j]->getFunctionType() == Callable) {
1139
// All functions have the Fast calling convention, however
1140
// entrypoint can only be C, emit wrapper
1141
Function *F = Function::Create(Functions[j]->getFunctionType(),
1142
Function::ExternalLinkage,
1143
Functions[j]->getName()+"_wrap", M);
1144
F->setDoesNotThrow();
1145
BasicBlock *BB = BasicBlock::Create(Context, "", F);
1146
std::vector<Value*> args;
1147
for (Function::arg_iterator J=F->arg_begin(),
1148
JE=F->arg_end(); J != JE; ++JE) {
1149
args.push_back(&*J);
1151
CallInst *CI = CallInst::Create(Functions[j], args.begin(), args.end(), "", BB);
1152
CI->setCallingConv(CallingConv::Fast);
1153
ReturnInst::Create(Context, CI, BB);
1155
if (verifyFunction(*F, PrintMessageAction) == 0) {
1156
DEBUG(errs() << "Generating code\n");
1157
// Codegen current function as executable machine code.
1158
void *code = EE->getPointerToFunction(F);
1159
DEBUG(errs() << "Code generation finished\n");
1161
compiledFunctions[func] = code;
1165
delete [] Functions;
1170
static sys::Mutex llvm_api_lock;
1172
// This class automatically acquires the lock when instantiated,
1173
// and releases the lock when leaving scope.
1174
class LLVMApiScopedLock {
1176
// when multithreaded mode is false (no atomics available),
1177
// we need to wrap all LLVM API calls with a giant mutex lock, but
1179
LLVMApiScopedLock() {
1180
if (!llvm_is_multithreaded())
1181
llvm_api_lock.acquire();
1183
~LLVMApiScopedLock() {
1184
if (!llvm_is_multithreaded())
1185
llvm_api_lock.release();
1189
static void addFunctionProtos(struct CommonFunctions *CF, ExecutionEngine *EE, Module *M)
1191
LLVMContext &Context = M->getContext();
1192
FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context),
1194
CF->FHandler = Function::Create(FTy, Function::ExternalLinkage,
1196
CF->FHandler->setDoesNotReturn();
1197
CF->FHandler->setDoesNotThrow();
1198
CF->FHandler->addFnAttr(Attribute::NoInline);
1200
EE->addGlobalMapping(CF->FHandler, (void*)(intptr_t)jit_exception_handler);
1201
EE->InstallLazyFunctionCreator(noUnknownFunctions);
1203
std::vector<const Type*> args;
1204
args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context)));
1205
args.push_back(Type::getInt8Ty(Context));
1206
args.push_back(Type::getInt32Ty(Context));
1207
args.push_back(Type::getInt32Ty(Context));
1208
FunctionType* FuncTy_3 = FunctionType::get(Type::getVoidTy(Context),
1210
CF->FMemset = Function::Create(FuncTy_3, GlobalValue::ExternalLinkage,
1211
"llvm.memset.i32", M);
1212
CF->FMemset->setDoesNotThrow();
1213
CF->FMemset->setDoesNotCapture(1, true);
1216
args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context)));
1217
args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context)));
1218
args.push_back(Type::getInt32Ty(Context));
1219
args.push_back(Type::getInt32Ty(Context));
1220
FunctionType* FuncTy_4 = FunctionType::get(Type::getVoidTy(Context),
1222
CF->FMemmove = Function::Create(FuncTy_4, GlobalValue::ExternalLinkage,
1223
"llvm.memmove.i32", M);
1224
CF->FMemmove->setDoesNotThrow();
1225
CF->FMemmove->setDoesNotCapture(1, true);
1227
CF->FMemcpy = Function::Create(FuncTy_4, GlobalValue::ExternalLinkage,
1228
"llvm.memcpy.i32", M);
1229
CF->FMemcpy->setDoesNotThrow();
1230
CF->FMemcpy->setDoesNotCapture(1, true);
1233
args.push_back(Type::getInt16Ty(Context));
1234
FunctionType *FuncTy_5 = FunctionType::get(Type::getInt16Ty(Context), args, false);
1235
CF->FBSwap16 = Function::Create(FuncTy_5, GlobalValue::ExternalLinkage,
1236
"llvm.bswap.i16", M);
1237
CF->FBSwap16->setDoesNotThrow();
1240
args.push_back(Type::getInt32Ty(Context));
1241
FunctionType *FuncTy_6 = FunctionType::get(Type::getInt32Ty(Context), args, false);
1242
CF->FBSwap32 = Function::Create(FuncTy_6, GlobalValue::ExternalLinkage,
1243
"llvm.bswap.i32", M);
1244
CF->FBSwap32->setDoesNotThrow();
1247
args.push_back(Type::getInt64Ty(Context));
1248
FunctionType *FuncTy_7 = FunctionType::get(Type::getInt64Ty(Context), args, false);
1249
CF->FBSwap64 = Function::Create(FuncTy_7, GlobalValue::ExternalLinkage,
1250
"llvm.bswap.i64", M);
1251
CF->FBSwap64->setDoesNotThrow();
1253
FunctionType* DummyTy = FunctionType::get(Type::getVoidTy(Context), false);
1254
CF->FRealmemset = Function::Create(DummyTy, GlobalValue::ExternalLinkage,
1256
EE->addGlobalMapping(CF->FRealmemset, (void*)(intptr_t)memset);
1257
CF->FRealMemmove = Function::Create(DummyTy, GlobalValue::ExternalLinkage,
1259
EE->addGlobalMapping(CF->FRealMemmove, (void*)(intptr_t)memmove);
1260
CF->FRealmemcpy = Function::Create(DummyTy, GlobalValue::ExternalLinkage,
1262
EE->addGlobalMapping(CF->FRealmemcpy, (void*)(intptr_t)memcpy);
1265
args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context)));
1266
args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context)));
1267
args.push_back(EE->getTargetData()->getIntPtrType(Context));
1268
FuncTy_5 = FunctionType::get(Type::getInt32Ty(Context),
1270
CF->FRealmemcmp = Function::Create(FuncTy_5, GlobalValue::ExternalLinkage, "memcmp", M);
1271
EE->addGlobalMapping(CF->FRealmemcmp, (void*)(intptr_t)memcmp);
1276
int cli_vm_execute_jit(const struct cli_all_bc *bcs, struct cli_bc_ctx *ctx,
1277
const struct cli_bc_func *func)
1279
// no locks needed here, since LLVM automatically acquires a JIT lock
1282
void *code = bcs->engine->compiledFunctions[func];
1284
errs() << MODULE << "Unable to find compiled function\n";
1286
errs() << MODULE << "Function has "
1287
<< (unsigned)func->numArgs << " arguments, it must have 0 to be called as entrypoint\n";
1288
return CL_EBYTECODE;
1291
if (setjmp(env) == 0) {
1292
// setup exception handler to longjmp back here
1293
ExceptionReturn.set((const jmp_buf*)&env);
1294
uint32_t result = ((uint32_t (*)(struct cli_bc_ctx *))(intptr_t)code)(ctx);
1295
*(uint32_t*)ctx->values = result;
1299
errs().changeColor(raw_ostream::RED, true) << MODULE
1300
<< "*** JITed code intercepted runtime error!\n";
1301
errs().resetColor();
1302
return CL_EBYTECODE;
1305
static unsigned char name_salt[16] = { 16, 38, 97, 12, 8, 4, 72, 196, 217, 144, 33, 124, 18, 11, 17, 253 };
1306
static void setGuard(unsigned char* guardbuf)
1310
memcpy(salt, name_salt, 16);
1311
for(unsigned i = 16; i < 48; i++)
1312
salt[i] = cli_rndnum(255);
1315
cli_md5_update(&ctx, salt, 48);
1316
cli_md5_final(guardbuf, &ctx);
1319
int cli_bytecode_prepare_jit(struct cli_all_bc *bcs)
1322
return CL_EBYTECODE;
1324
LLVMApiScopedLock scopedLock;
1325
// setup exception handler to longjmp back here
1326
ExceptionReturn.set((const jmp_buf*)&env);
1327
if (setjmp(env) != 0) {
1329
errs().changeColor(raw_ostream::RED, true) << MODULE
1330
<< "*** FATAL error encountered during bytecode generation\n";
1331
errs().resetColor();
1332
return CL_EBYTECODE;
1334
// LLVM itself never throws exceptions, but operator new may throw bad_alloc
1336
Module *M = new Module("ClamAV jit module", bcs->engine->Context);
1339
std::string ErrorMsg;
1340
EngineBuilder builder(M);
1341
builder.setErrorStr(&ErrorMsg);
1342
builder.setEngineKind(EngineKind::JIT);
1343
builder.setOptLevel(CodeGenOpt::Default);
1344
ExecutionEngine *EE = bcs->engine->EE = builder.create();
1346
if (!ErrorMsg.empty())
1347
errs() << MODULE << "error creating execution engine: " << ErrorMsg << "\n";
1349
errs() << MODULE << "JIT not registered?\n";
1350
return CL_EBYTECODE;
1353
// EE->RegisterJITEventListener(createOProfileJITEventListener());
1354
// Due to LLVM PR4816 only X86 supports non-lazy compilation, disable
1356
EE->DisableLazyCompilation();
1357
EE->DisableSymbolSearching();
1359
struct CommonFunctions CF;
1360
addFunctionProtos(&CF, EE, M);
1362
FunctionPassManager OurFPM(M);
1363
// Set up the optimizer pipeline. Start with registering info about how
1364
// the target lays out data structures.
1365
OurFPM.add(new TargetData(*EE->getTargetData()));
1366
// Promote allocas to registers.
1367
OurFPM.add(createPromoteMemoryToRegisterPass());
1368
OurFPM.doInitialization();
1370
//TODO: create a wrapper that calls pthread_getspecific
1371
const Type *HiddenCtx = PointerType::getUnqual(Type::getInt8Ty(bcs->engine->Context));
1373
LLVMTypeMapper apiMap(bcs->engine->Context, cli_apicall_types, cli_apicall_maxtypes, HiddenCtx);
1374
Function **apiFuncs = new Function *[cli_apicall_maxapi];
1375
for (unsigned i=0;i<cli_apicall_maxapi;i++) {
1376
const struct cli_apicall *api = &cli_apicalls[i];
1377
const FunctionType *FTy = cast<FunctionType>(apiMap.get(69+api->type));
1378
Function *F = Function::Create(FTy, Function::ExternalLinkage,
1381
switch (api->kind) {
1383
dest = (void*)(intptr_t)cli_apicalls0[api->idx];
1386
dest = (void*)(intptr_t)cli_apicalls1[api->idx];
1389
dest = (void*)(intptr_t)cli_apicalls2[api->idx];
1392
dest = (void*)(intptr_t)cli_apicalls3[api->idx];
1395
llvm_unreachable("invalid api type");
1397
EE->addGlobalMapping(F, dest);
1402
FunctionType *FTy = FunctionType::get(Type::getVoidTy(M->getContext()),
1404
GlobalVariable *Guard = new GlobalVariable(*M, PointerType::getUnqual(Type::getInt8Ty(M->getContext())),
1405
true, GlobalValue::ExternalLinkage, 0, "__stack_chk_guard");
1407
if (2*sizeof(void*) <= 16 && cli_rndnum(2)==2) {
1408
plus = sizeof(void*);
1410
EE->addGlobalMapping(Guard, (void*)(&bcs->engine->guard.b[plus]));
1411
setGuard(bcs->engine->guard.b);
1412
bcs->engine->guard.b[plus+sizeof(void*)-1] = 0x00;
1413
// printf("%p\n", *(void**)(&bcs->engine->guard.b[plus]));
1414
Function *SFail = Function::Create(FTy, Function::ExternalLinkage,
1415
"__stack_chk_fail", M);
1416
EE->addGlobalMapping(SFail, (void*)(intptr_t)jit_ssp_handler);
1418
for (unsigned i=0;i<bcs->count;i++) {
1419
const struct cli_bc *bc = &bcs->all_bcs[i];
1420
if (bc->state == bc_skip)
1422
LLVMCodegen Codegen(bc, M, &CF, bcs->engine->compiledFunctions, EE,
1423
OurFPM, apiFuncs, apiMap);
1424
if (!Codegen.generate()) {
1425
errs() << MODULE << "JIT codegen failed\n";
1426
return CL_EBYTECODE;
1430
for (unsigned i=0;i<bcs->count;i++) {
1431
bcs->all_bcs[i].state = bc_jit;
1433
// compile all functions now, not lazily!
1434
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
1436
if (!Fn->isDeclaration())
1437
EE->getPointerToFunction(Fn);
1442
} catch (std::bad_alloc &badalloc) {
1443
errs() << MODULE << badalloc.what() << "\n";
1446
errs() << MODULE << "Unexpected unknown exception occurred.\n";
1447
return CL_EBYTECODE;
1451
int bytecode_init(void)
1453
// If already initialized return
1454
if (llvm_is_multithreaded()) {
1455
errs() << "bytecode_init: already initialized";
1458
llvm_install_error_handler(llvm_error_handler);
1460
sys::PrintStackTraceOnErrorSignal();
1462
llvm::DisablePrettyStackTrace = true;
1464
atexit(do_shutdown);
1467
llvm::JITEmitDebugInfo = true;
1469
llvm::JITEmitDebugInfo = false;
1471
llvm::DwarfExceptionHandling = false;
1472
llvm_start_multithreaded();
1474
// If we have a native target, initialize it to ensure it is linked in and
1475
// usable by the JIT.
1476
InitializeNativeTarget();
1478
if (!llvm_is_multithreaded()) {
1480
DEBUG(errs() << "WARNING: ClamAV JIT built w/o atomic builtins\n"
1481
<< "On x86 for best performance ClamAV should be built for i686, not i386!\n");
1486
extern "C" uint8_t cli_debug_flag;
1487
// Called once when loading a new set of BC files
1488
int cli_bytecode_init_jit(struct cli_all_bc *bcs, unsigned dconfmask)
1490
LLVMApiScopedLock scopedLock;
1491
Triple triple(sys::getHostTriple());
1493
errs() << "host triple is: " << sys::getHostTriple() << "\n";
1494
enum Triple::ArchType arch = triple.getArch();
1497
if (!(dconfmask & BYTECODE_JIT_ARM)) {
1499
errs() << "host triple is: " << sys::getHostTriple() << "\n";
1505
if (!(dconfmask & BYTECODE_JIT_PPC)) {
1507
errs() << "JIT disabled for ppc\n";
1512
case Triple::x86_64:
1513
if (!(dconfmask & BYTECODE_JIT_X86)) {
1515
errs() << "JIT disabled for x86\n";
1520
errs() << "Not supported architecture for " << triple.str() << "\n";
1521
return CL_EBYTECODE;
1524
std::string cpu = sys::getHostCPUName();
1526
errs() << "host cpu is: " << cpu << "\n";
1527
if (!cpu.compare("i386") ||
1528
!cpu.compare("i486")) {
1530
DEBUG(errs() << "i[34]86 detected, falling back to interpreter (JIT needs pentium or better\n");
1531
/* i386 and i486 has to fallback to interpreter */
1534
bcs->engine = new(std::nothrow) cli_bcengine;
1537
bcs->engine->EE = 0;
1541
int cli_bytecode_done_jit(struct cli_all_bc *bcs)
1543
LLVMApiScopedLock scopedLock;
1545
if (bcs->engine->EE)
1546
delete bcs->engine->EE;
1553
void cli_bytecode_debug(int argc, char **argv)
1555
cl::ParseCommandLineOptions(argc, argv);
1558
typedef struct lines {
1559
MemoryBuffer *buffer;
1560
std::vector<const char*> linev;
1563
static struct lineprinter {
1564
StringMap<linesTy*> files;
1567
void cli_bytecode_debug_printsrc(const struct cli_bc_ctx *ctx)
1569
if (!ctx->file || !ctx->directory || !ctx->line) {
1570
errs() << (ctx->directory ? "d":"null") << ":" << (ctx->file ? "f" : "null")<< ":" << ctx->line << "\n";
1573
// acquire a mutex here
1574
sys::Mutex mtx(false);
1575
sys::SmartScopedLock<false> lock(mtx);
1577
std::string path = std::string(ctx->directory) + "/" + std::string(ctx->file);
1578
StringMap<linesTy*>::iterator I = LinePrinter.files.find(path);
1580
if (I == LinePrinter.files.end()) {
1581
lines = new linesTy;
1582
std::string ErrorMessage;
1583
lines->buffer = MemoryBuffer::getFile(path, &ErrorMessage);
1584
if (!lines->buffer) {
1585
errs() << "Unable to open file '" << path << "'\n";
1588
LinePrinter.files[path] = lines;
1590
lines = I->getValue();
1592
while (lines->linev.size() <= ctx->line+1) {
1594
if (lines->linev.empty()) {
1595
p = lines->buffer->getBufferStart();
1596
lines->linev.push_back(p);
1598
p = lines->linev.back();
1599
if (p == lines->buffer->getBufferEnd())
1601
p = strchr(p, '\n');
1603
p = lines->buffer->getBufferEnd();
1604
lines->linev.push_back(p);
1606
lines->linev.push_back(p+1);
1609
if (ctx->line >= lines->linev.size()) {
1610
errs() << "Line number " << ctx->line << "out of file\n";
1613
assert(ctx->line < lines->linev.size());
1614
SMDiagnostic diag(ctx->file, ctx->line ? ctx->line : -1,
1615
ctx->col ? ctx->col-1 : -1,
1616
"", std::string(lines->linev[ctx->line-1], lines->linev[ctx->line]-1));
1617
diag.Print("[trace]", errs());
1621
void cli_bytecode_printversion()
1623
cl::PrintVersionMessage();