[Pkg-clamav-commits] [SCM] Debian repository for ClamAV branch, debian/unstable, updated. debian/0.95+dfsg-1-6156-g094ec9b

Török Edvin edwin at clamav.net
Sun Apr 4 01:03:54 UTC 2010


The following commit has been merged in the debian/unstable branch:
commit e32caecb83ebc54183ce4f478027ec9296406ce1
Author: Török Edvin <edwin at clamav.net>
Date:   Wed Sep 2 15:29:55 2009 +0300

    Add APIcall support to JIT.

diff --git a/libclamav/bytecode.c b/libclamav/bytecode.c
index db9d12d..ab1455b 100644
--- a/libclamav/bytecode.c
+++ b/libclamav/bytecode.c
@@ -479,7 +479,7 @@ static int parseTypes(struct cli_bc *bc, unsigned char *buffer)
 	return CL_BREAK;
     }
     add_static_types(bc);
-    for (i=(BC_START_TID - 64);i<bc->num_types;i++) {
+    for (i=(BC_START_TID - 65);i<bc->num_types-1;i++) {
 	struct cli_bc_type *ty = &bc->types[i];
 	uint8_t t = readFixedNumber(buffer, &offset, len, &ok, 1);
 	if (!ok) {
@@ -495,6 +495,10 @@ static int parseTypes(struct cli_bc *bc, unsigned char *buffer)
 		    cli_errmsg("Error parsing type %u\n", i);
 		    return CL_EMALFDB;
 		}
+		if (!ty->numElements) {
+		    cli_errmsg("Function with no return type? %u\n", i);
+		    return CL_EMALFDB;
+		}
 		break;
 	    case 2:
 	    case 3:
@@ -550,7 +554,7 @@ static int parseTypes(struct cli_bc *bc, unsigned char *buffer)
 static int types_equal(const struct cli_bc *bc, uint16_t *apity2ty, uint16_t tid, uint16_t apitid)
 {
     unsigned i;
-    const struct cli_bc_type *ty = &bc->types[tid - 63];
+    const struct cli_bc_type *ty = &bc->types[tid - 64];
     const struct cli_bc_type *apity = &cli_apicall_types[apitid];
     /* If we've already verified type equality, return.
      * Since we need to check equality of recursive types, we assume types are
diff --git a/libclamav/c++/bytecode2llvm.cpp b/libclamav/c++/bytecode2llvm.cpp
index 4072618..749bcc2 100644
--- a/libclamav/c++/bytecode2llvm.cpp
+++ b/libclamav/c++/bytecode2llvm.cpp
@@ -1,5 +1,5 @@
 /*
- *  Load, and verify ClamAV bytecode.
+ *  JIT compile ClamAV bytecode.
  *
  *  Copyright (C) 2009 Sourcefire, Inc.
  *
@@ -89,23 +89,12 @@ void llvm_error_handler(void *user_data, const std::string &reason)
     jit_exception_handler();
 }
 
-class VISIBILITY_HIDDEN LLVMCodegen {
+class LLVMTypeMapper {
 private:
-    const struct cli_bc *bc;
-    Module *M;
+    std::vector<PATypeHolder> TypeMap;
     LLVMContext &Context;
-    FunctionMapTy &compiledFunctions;
-    const Type **TypeMap;
-    Twine BytecodeID;
-    ExecutionEngine *EE;
-    TargetFolder Folder;
-    IRBuilder<false, TargetFolder> Builder;
-    Value **Values;
-    FunctionPassManager &PM;
-    unsigned numLocals;
-    unsigned numArgs;
-
-    const Type *mapType(uint16_t ty)
+    unsigned numTypes;
+    const Type *getStatic(uint16_t ty)
     {
 	if (!ty)
 	    return Type::getVoidTy(Context);
@@ -121,17 +110,83 @@ private:
 	    case 68:
 		return PointerType::getUnqual(Type::getInt64Ty(Context));
 	}
+	llvm_unreachable("getStatic");
+    }
+public:
+    LLVMTypeMapper(LLVMContext &Context, const struct cli_bc_type *types,
+		   unsigned count) : Context(Context), numTypes(count)
+    {
+	TypeMap.reserve(count);
+	// During recursive type construction pointers to Type* may be
+	// invalidated, so we must use a TypeHolder to an Opaque type as a
+	// start.
+	for (unsigned i=0;i<count;i++) {
+	    TypeMap.push_back(OpaqueType::get(Context));
+	}
+	std::vector<const Type*> Elts;
+	for (unsigned i=0;i<count;i++) {
+	    const struct cli_bc_type *type = &types[i];
+	    Elts.clear();
+	    unsigned n = type->kind == DArrayType ? 1 : type->numElements;
+	    for (unsigned j=0;j<n;j++) {
+		Elts.push_back(get(type->containedTypes[j]));
+	    }
+	    const Type *Ty;
+	    switch (type->kind) {
+		case DFunctionType:
+		{
+		    assert(Elts.size() > 0 && "Function with no return type?");
+		    const Type *RetTy = Elts[0];
+		    Elts.erase(Elts.begin());
+		    Ty = FunctionType::get(RetTy, Elts, false);
+		    break;
+		}
+		case DPointerType:
+		    Ty = PointerType::getUnqual(Elts[0]);
+		    break;
+		case DStructType:
+		    Ty = StructType::get(Context, Elts);
+		    break;
+		case DPackedStructType:
+		    Ty = StructType::get(Context, Elts, true);
+		    break;
+		case DArrayType:
+		    Ty = ArrayType::get(Elts[0], type->numElements);
+		    break;
+	    }
+	    // Make the opaque type a concrete type, doing recursive type
+	    // unification if needed.
+	    cast<OpaqueType>(TypeMap[i].get())->refineAbstractTypeTo(Ty);
+	}
+    }
+
+    const Type *get(uint16_t ty)
+    {
+	if (ty < 69)
+	    return getStatic(ty);
 	ty -= 69;
-	// This was validated by libclamav already.
-	assert(ty < bc->num_types && "Out of range type ID");
-	return TypeMap[ty];
+	assert(ty < numTypes && "TypeID out of range");
+	return TypeMap[ty].get();
     }
+};
 
-    void convertTypes() {
-	for (unsigned j=0;j<bc->num_types;j++) {
 
-	}
-    }
+class VISIBILITY_HIDDEN LLVMCodegen {
+private:
+    const struct cli_bc *bc;
+    Module *M;
+    LLVMContext &Context;
+    LLVMTypeMapper *TypeMap;
+    Function **apiFuncs;
+    FunctionMapTy &compiledFunctions;
+    Twine BytecodeID;
+    ExecutionEngine *EE;
+    TargetFolder Folder;
+    IRBuilder<false, TargetFolder> Builder;
+    Value **Values;
+    FunctionPassManager &PM;
+    unsigned numLocals;
+    unsigned numArgs;
 
     Value *convertOperand(const struct cli_bc_func *func, const Type *Ty, operand_t operand)
     {
@@ -167,7 +222,7 @@ private:
 	switch (w) {
 	    case 0:
 	    case 1:
-		Ty = w ? Type::getInt8Ty(Context) : 
+		Ty = w ? Type::getInt8Ty(Context) :
 		    Type::getInt1Ty(Context);
 		v = *(uint8_t*)c;
 		break;
@@ -205,18 +260,23 @@ private:
 	Builder.CreateCondBr(FailCond, Fail, OkBB);
 	Builder.SetInsertPoint(OkBB);
     }
+
+    const Type* mapType(uint16_t typeID)
+    {
+	return TypeMap->get(typeID);
+    }
 public:
     LLVMCodegen(const struct cli_bc *bc, Module *M, FunctionMapTy &cFuncs,
-		ExecutionEngine *EE, FunctionPassManager &PM)
+		ExecutionEngine *EE, FunctionPassManager &PM, Function **apiFuncs)
 	: bc(bc), M(M), Context(M->getContext()), compiledFunctions(cFuncs), 
 	BytecodeID("bc"+Twine(bc->id)), EE(EE), 
-	Folder(EE->getTargetData(), Context), Builder(Context, Folder), PM(PM) {
-	    TypeMap = new const Type*[bc->num_types];
-    }
+	Folder(EE->getTargetData(), Context), Builder(Context, Folder), PM(PM), 
+	apiFuncs(apiFuncs) 
+    {}
 
     bool generate() {
 	PrettyStackTraceString Trace(BytecodeID.str().c_str());
-	convertTypes();
+	TypeMap = new LLVMTypeMapper(Context, bc->types + 4, bc->num_types - 5);
 
 	FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context),
 						    false);
@@ -246,6 +306,7 @@ public:
 	for (unsigned j=0;j<bc->num_func;j++) {
 	    PrettyStackTraceString CrashInfo("Generate LLVM IR");
 	    const struct cli_bc_func *func = &bc->funcs[j];
+
 	    // Create all BasicBlocks
 	    Function *F = Functions[j];
 	    BasicBlock **BB = new BasicBlock*[func->numBB];
@@ -447,6 +508,19 @@ public:
 			    Store(inst->dest, Builder.CreateCall(DestF, args.begin(), args.end()));
 			    break;
 			}
+			case OP_CALL_API:
+			{
+			    assert(inst->u.ops.funcid < cli_apicall_maxapi && "APICall out of range");
+			    const struct cli_apicall *api = &cli_apicalls[inst->u.ops.funcid];
+			    std::vector<Value*> args;
+			    Function *DestF = apiFuncs[inst->u.ops.funcid];
+			    for (unsigned a=0;a<inst->u.ops.numOps;a++) {
+				operand_t op = inst->u.ops.ops[a];
+				args.push_back(convertOperand(func, DestF->getFunctionType()->getParamType(a), op));
+			    }
+			    Store(inst->dest, Builder.CreateCall(DestF, args.begin(), args.end()));
+			    break;
+			}
 			default:
 			    errs() << "JIT doesn't implement opcode " <<
 				inst->opcode << " yet!\n";
@@ -466,7 +540,7 @@ public:
 	}
 
 	DEBUG(M->dump());
-	delete [] TypeMap;
+	delete TypeMap;
 	FunctionType *Callable = FunctionType::get(Type::getInt32Ty(Context),false);
 	for (unsigned j=0;j<bc->num_func;j++) {
 	    const struct cli_bc_func *func = &bc->funcs[j];
@@ -556,9 +630,31 @@ int cli_bytecode_prepare_jit(struct cli_all_bc *bcs)
 	// Promote allocas to registers.
 	OurFPM.add(createPromoteMemoryToRegisterPass());
 	OurFPM.doInitialization();
+
+	LLVMTypeMapper apiMap(bcs->engine->Context, cli_apicall_types, cli_apicall_maxtypes);
+	Function **apiFuncs = new Function *[cli_apicall_maxapi];
+	for (unsigned i=0;i<cli_apicall_maxapi;i++) {
+	    const struct cli_apicall *api = &cli_apicalls[i];
+	    const FunctionType *FTy = cast<FunctionType>(apiMap.get(69+api->type));
+	    Function *F = Function::Create(FTy, Function::ExternalLinkage,
+					   api->name, M);
+	    void *dest;
+	    switch (api->kind) {
+		case 0:
+		    dest = (void*)cli_apicalls0[api->idx];
+		    break;
+		case 1:
+		    dest = (void*)cli_apicalls1[api->idx];
+		    break;
+	    }
+	    EE->addGlobalMapping(F, dest);
+	    apiFuncs[i] = F;
+	}
+
 	for (unsigned i=0;i<bcs->count;i++) {
 	    const struct cli_bc *bc = &bcs->all_bcs[i];
-	    LLVMCodegen Codegen(bc, M, bcs->engine->compiledFunctions, EE, OurFPM);
+	    LLVMCodegen Codegen(bc, M, bcs->engine->compiledFunctions, EE, 
+				OurFPM, apiFuncs);
 	    if (!Codegen.generate()) {
 		errs() << MODULE << "JIT codegen failed\n";
 		return CL_EBYTECODE;
@@ -574,6 +670,7 @@ int cli_bytecode_prepare_jit(struct cli_all_bc *bcs)
 	    if (!Fn->isDeclaration())
 		EE->getPointerToFunction(Fn);
 	}
+	delete [] apiFuncs;
     }
     return -1;
   } catch (std::bad_alloc &badalloc) {

-- 
Debian repository for ClamAV



More information about the Pkg-clamav-commits mailing list