Browse code

Support for constant global with global initializers.

Török Edvin authored on 2009/09/11 04:51:11
Showing 3 changed files
... ...
@@ -268,9 +268,8 @@ static inline operand_t readOperand(struct cli_bc_func *func, unsigned char *p,
268 268
 	*dest= 0;
269 269
 	ty = 8*readFixedNumber(p, off, len, ok, 1);
270 270
 	if (!ty) {
271
-	    cli_errmsg("bytecode: void type constant is invalid!\n");
272
-	    *ok = 0;
273
-	    return MAX_OP;
271
+	    /* This is a global variable */
272
+	    return 0x80000000 | v;
274 273
 	}
275 274
 	if (ty <= 8)
276 275
 	    *(uint8_t*)dest = v;
... ...
@@ -652,6 +651,99 @@ static int parseApis(struct cli_bc *bc, unsigned char *buffer)
652 652
     return CL_SUCCESS;
653 653
 }
654 654
 
655
+static uint16_t type_components(struct cli_bc *bc, uint16_t id, char *ok)
656
+{
657
+    unsigned i, sum=0;
658
+    const struct cli_bc_type *ty;
659
+    if (id <= 64)
660
+	return 1;
661
+    ty = &bc->types[id-65];
662
+    /* TODO: protect against recursive types */
663
+    switch (ty->kind) {
664
+	case DFunctionType:
665
+	    cli_errmsg("bytecode: function type not accepted for constant: %u\n", id);
666
+	    /* don't accept functions as constant initializers */
667
+	    *ok = 0;
668
+	    return 0;
669
+	case DPointerType:
670
+	    cli_errmsg("bytecode: pointer type not accepted for constant: %u\n", id);
671
+	    /* don't accept pointer initializers */
672
+	    *ok = 0;
673
+	    return 0;
674
+	case DStructType:
675
+	case DPackedStructType:
676
+	    for (i=0;i<ty->numElements;i++) {
677
+		sum += type_components(bc, ty->containedTypes[i], ok);
678
+	    }
679
+	    return sum;
680
+	case DArrayType:
681
+	    return type_components(bc, ty->containedTypes[0], ok)*ty->numElements;
682
+	default:
683
+	    *ok = 0;
684
+	    return 0;
685
+    }
686
+}
687
+
688
+static void readConstant(struct cli_bc *bc, unsigned i, unsigned comp,
689
+			 unsigned char *buffer, unsigned *offset,
690
+			 unsigned len, char *ok)
691
+{
692
+    unsigned j=0;
693
+    while (*ok && buffer[*offset] != 0x60) {
694
+	if (j > comp) {
695
+	    cli_errmsg("bytecode: constant has too many subcomponents, expected %u\n", comp);
696
+	    *ok = 0;
697
+	    return;
698
+	}
699
+	buffer[*offset] |= 0x20;
700
+	bc->globals[i][j++] = readNumber(buffer, offset, len, ok);
701
+    }
702
+    if (*ok && j != comp) {
703
+	cli_errmsg("bytecode: constant has too few subcomponents: %u < %u\n", j, comp);
704
+    }
705
+    *offset++;
706
+}
707
+
708
+/* parse constant globals with constant initializers */
709
+static int parseGlobals(struct cli_bc *bc, unsigned char *buffer)
710
+{
711
+    unsigned i, offset = 1, len = strlen((const char*)buffer), numglobals;
712
+    char ok=1;
713
+
714
+    if (buffer[0] != 'G') {
715
+	cli_errmsg("bytecode: Invalid globals header: %c\n", buffer[0]);
716
+	return CL_EMALFDB;
717
+    }
718
+    numglobals = readNumber(buffer, &offset, len, &ok);
719
+    bc->globals = cli_calloc(numglobals, sizeof(*bc->globals));
720
+    if (!bc->globals) {
721
+	cli_errmsg("bytecode: OOM allocating memory for %u globals\n", numglobals);
722
+	return CL_EMEM;
723
+    }
724
+    bc->globaltys = cli_calloc(numglobals, sizeof(*bc->globaltys));
725
+    if (!bc->globaltys) {
726
+	cli_errmsg("bytecode: OOM allocating memory for %u global types\n", numglobals);
727
+	return CL_EMEM;
728
+    }
729
+    bc->num_globals = numglobals;
730
+    if (!ok)
731
+	return CL_EMALFDB;
732
+    for (i=0;i<numglobals;i++) {
733
+	unsigned comp;
734
+	bc->globaltys[i] = readTypeID(bc, buffer, &offset, len, &ok);
735
+	comp = type_components(bc, bc->globaltys[i], &ok);
736
+	if (!ok)
737
+	    return CL_EMALFDB;
738
+	bc->globals[i] = cli_malloc(sizeof(bc->globals[0])*comp);
739
+	if (!bc->globals[i])
740
+	    return CL_EMEM;
741
+	readConstant(bc, i, comp, buffer, &offset, len, &ok);
742
+    }
743
+    if (!ok)
744
+	return CL_EMALFDB;
745
+    return CL_SUCCESS;
746
+}
747
+
655 748
 static int parseFunctionHeader(struct cli_bc *bc, unsigned fn, unsigned char *buffer)
656 749
 {
657 750
     char ok=1;
... ...
@@ -921,6 +1013,7 @@ enum parse_state {
921 921
     PARSE_BC_HEADER=0,
922 922
     PARSE_BC_TYPES,
923 923
     PARSE_BC_APIS,
924
+    PARSE_BC_GLOBALS,
924 925
     PARSE_FUNC_HEADER,
925 926
     PARSE_BB
926 927
 };
... ...
@@ -970,6 +1063,18 @@ int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio)
970 970
 		    cli_errmsg("Error at bytecode line %u\n", row);
971 971
 		    return rc;
972 972
 		}
973
+		state = PARSE_BC_GLOBALS;
974
+		break;
975
+	    case PARSE_BC_GLOBALS:
976
+		rc = parseGlobals(bc, (unsigned char*)buffer);
977
+		if (rc == CL_BREAK) /* skip */ {
978
+		    bc->state = bc_skip;
979
+		    return CL_SUCCESS;
980
+		}
981
+		if (rc != CL_SUCCESS) {
982
+		    cli_errmsg("Error at bytecode line %u\n", row);
983
+		    return rc;
984
+		}
973 985
 		state = PARSE_FUNC_HEADER;
974 986
 		break;
975 987
 	    case PARSE_FUNC_HEADER:
... ...
@@ -1079,6 +1184,11 @@ void cli_bytecode_destroy(struct cli_bc *bc)
1079 1079
 	    free(bc->types[i].containedTypes);
1080 1080
     }
1081 1081
     free(bc->types);
1082
+    for (i=0;i<bc->num_globals;i++) {
1083
+	free(bc->globals[i]);
1084
+    }
1085
+    free(bc->globals);
1086
+    free(bc->globaltys);
1082 1087
     if (bc->uses_apis)
1083 1088
 	cli_bitset_free(bc->uses_apis);
1084 1089
 }
... ...
@@ -49,6 +49,9 @@ struct cli_bc {
49 49
   unsigned num_func;
50 50
   struct cli_bc_func *funcs;
51 51
   struct cli_bc_type *types;
52
+  uint64_t **globals;
53
+  uint16_t *globaltys;
54
+  size_t num_globals;
52 55
   enum bc_state state;
53 56
   uint16_t start_tid;
54 57
   struct bitset_tag *uses_apis;
... ...
@@ -187,6 +187,7 @@ private:
187 187
     ExecutionEngine *EE;
188 188
     TargetFolder Folder;
189 189
     IRBuilder<false, TargetFolder> Builder;
190
+    std::vector<GlobalVariable*> globals;
190 191
     Value **Values;
191 192
     FunctionPassManager &PM;
192 193
     unsigned numLocals;
... ...
@@ -229,6 +230,12 @@ private:
229 229
 	if (operand < func->numValues)
230 230
 	    return Builder.CreateLoad(Values[operand]);
231 231
 
232
+	if (operand & 0x80000000) {
233
+	    operand &= 0x7fffffff;
234
+	    assert(operand < globals.size() && "Global index out of range");
235
+	    // Global
236
+	    return globals[operand];
237
+	}
232 238
 	// Constant
233 239
 	operand -= func->numValues;
234 240
 	// This was already validated by libclamav.
... ...
@@ -282,6 +289,33 @@ private:
282 282
     {
283 283
 	return TypeMap->get(typeID);
284 284
     }
285
+
286
+    Constant *buildConstant(const Type *Ty, uint64_t *components, unsigned &c)
287
+    {
288
+	if (isa<IntegerType>(Ty)) {
289
+	    return ConstantInt::get(Ty, components[c++]);
290
+	}
291
+	if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
292
+	   std::vector<Constant*> elements;
293
+	   elements.reserve(ATy->getNumElements());
294
+	   for (unsigned i=0;i<ATy->getNumElements();i++) {
295
+	       elements.push_back(buildConstant(ATy->getElementType(), components, c));
296
+	   }
297
+	   return ConstantArray::get(ATy, elements);
298
+	}
299
+	if (const StructType *STy = dyn_cast<StructType>(Ty)) {
300
+	   std::vector<Constant*> elements;
301
+	   elements.reserve(STy->getNumElements());
302
+	   for (unsigned i=0;i<STy->getNumElements();i++) {
303
+	       elements.push_back(buildConstant(STy->getElementType(i), components, c));
304
+	   }
305
+	   return ConstantStruct::get(STy, elements);
306
+	}
307
+	Ty->dump();
308
+	assert(0 && "Not reached");
309
+	return 0;
310
+    }
311
+
285 312
 public:
286 313
     LLVMCodegen(const struct cli_bc *bc, Module *M, FunctionMapTy &cFuncs,
287 314
 		ExecutionEngine *EE, FunctionPassManager &PM, Function **apiFuncs)
... ...
@@ -302,11 +336,22 @@ public:
302 302
 	FHandler->setDoesNotReturn();
303 303
 	FHandler->setDoesNotThrow();
304 304
 	FHandler->addFnAttr(Attribute::NoInline);
305
-	EE->addGlobalMapping(FHandler, (void*)jit_exception_handler); 
305
+	EE->addGlobalMapping(FHandler, (void*)jit_exception_handler);
306 306
 
307 307
 	// The hidden ctx param to all functions
308 308
 	const Type *HiddenCtx = PointerType::getUnqual(Type::getInt8Ty(Context));
309 309
 
310
+	globals.reserve(bc->num_globals);
311
+	for (unsigned i=0;i<bc->num_globals;i++) {
312
+	    const Type *Ty = mapType(bc->globaltys[i]);
313
+	    GlobalVariable *GV = cast<GlobalVariable>(M->getOrInsertGlobal("glob"+i,
314
+									   Ty));
315
+	    // TODO: validate number of components against type_components
316
+	    unsigned c = 0;
317
+	    GV->setInitializer(buildConstant(Ty, bc->globals[i], c));
318
+	    globals.push_back(GV);
319
+	}
320
+
310 321
 	Function **Functions = new Function*[bc->num_func];
311 322
 	for (unsigned j=0;j<bc->num_func;j++) {
312 323
 	    PrettyStackTraceString CrashInfo("Generate LLVM IR functions");