Browse code

Add support for tracing (if bytecode compiled with support).

TODO: global id 0 is now a null pointer, need to adjust rest of conversion code
accordingly.

Török Edvin authored on 2009/12/09 06:02:49
Showing 13 changed files
... ...
@@ -26,6 +26,7 @@
26 26
 #include <sys/time.h>
27 27
 #include <stdlib.h>
28 28
 #include "bytecode.h"
29
+#include "bytecode_priv.h"
29 30
 #include "clamav.h"
30 31
 #include "shared/optparser.h"
31 32
 #include "shared/misc.h"
... ...
@@ -141,6 +142,7 @@ int main(int argc, char *argv[])
141 141
 	fprintf(stderr,"Out of memory\n");
142 142
 	exit(3);
143 143
     }
144
+    ctx->trace_mask = BC_TRACE_ALL;
144 145
 
145 146
     if (opts->filename[1]) {
146 147
 	funcid = atoi(opts->filename[1]);
... ...
@@ -52,6 +52,13 @@ struct cli_bc_ctx *cli_bytecode_context_alloc(void)
52 52
     ctx->outfd = -1;
53 53
     ctx->tempfile = NULL;
54 54
     ctx->written = 0;
55
+    ctx->trace_mask = 0;
56
+    ctx->scope = NULL;
57
+    ctx->scopeid = 0;
58
+    ctx->file = NULL;
59
+    ctx->directory = NULL;
60
+    ctx->lastline = 0;
61
+    ctx->lastcol = 0;
55 62
     return ctx;
56 63
 }
57 64
 
... ...
@@ -108,6 +108,7 @@ extern "C" {
108 108
 #endif
109 109
 
110 110
 void cli_bytecode_debug(int argc, char **argv);
111
+void cli_bytecode_debug_printsrc(const struct cli_bc_ctx *ctx);
111 112
 int bytecode_init(void);
112 113
 
113 114
 #ifdef __cplusplus
... ...
@@ -98,6 +98,10 @@ uint32_t cli_bcapi_disasm_x86(struct cli_bc_ctx *ctx, struct DISASM_RESULT *res,
98 98
     //TODO: call disasm_x86_wrap, which outputs a MARIO struct
99 99
 }
100 100
 
101
+/* TODO: field in ctx, id of last bytecode that called magicscandesc, reset
102
+ * after hooks/other bytecodes are run. TODO: need a more generic solution
103
+ * to avoid uselessly recursing on bytecode-unpacked files, but also a way to
104
+ * override the limit if we need it in a special situation */
101 105
 int32_t cli_bcapi_write(struct cli_bc_ctx *ctx, uint8_t*data, int32_t len)
102 106
 {
103 107
     int32_t res;
... ...
@@ -128,4 +132,101 @@ int32_t cli_bcapi_write(struct cli_bc_ctx *ctx, uint8_t*data, int32_t len)
128 128
     return res;
129 129
 }
130 130
 
131
+uint32_t cli_bcapi_trace_scope(struct cli_bc_ctx *ctx, const const uint8_t *scope, uint32_t scopeid)
132
+{
133
+    if (LIKELY(!ctx->trace_mask))
134
+	return 0;
135
+    if ((ctx->trace_mask&BC_TRACE_FUNC) && (scope != ctx->scope)) {
136
+	ctx->scope = scope;
137
+	ctx->trace_mask |= BC_TRACE_TMP_FUNC;
138
+    }
139
+    if ((ctx->trace_mask&BC_TRACE_SCOPE) && (scopeid != ctx->scopeid)) {
140
+	ctx->scopeid = scopeid;
141
+	ctx->trace_mask |= BC_TRACE_TMP_SCOPE;
142
+    }
143
+}
144
+
145
+uint32_t cli_bcapi_trace_source(struct cli_bc_ctx *ctx, const const uint8_t *file, uint32_t line)
146
+{
147
+    if (LIKELY(!ctx->trace_mask))
148
+	return 0;
149
+    if (ctx->trace_mask&BC_TRACE_TMP_FUNC) {
150
+	cli_dbgmsg("[trace] %s:%u:%u -> %s:%u\t Entering function %s\n",
151
+		   ctx->file ? ctx->file : "??", ctx->lastline,
152
+		   ctx->lastcol, file ? file : "??", line,
153
+		   ctx->scope);
154
+	ctx->file = file;
155
+	ctx->lastline = line;
156
+	cli_bytecode_debug_printsrc(ctx);
157
+    } else if (ctx->trace_mask&BC_TRACE_TMP_SCOPE) {
158
+	cli_dbgmsg("[trace] %s:%u:%u -> %s:%u\t entering scope\n",
159
+		   ctx->file ? ctx->file : "??", ctx->lastline,
160
+		   ctx->lastcol, file ? file : "??", line,
161
+		   ctx->scope);
162
+	ctx->file = file;
163
+	ctx->lastline = line;
164
+	cli_bytecode_debug_printsrc(ctx);
165
+    } else {
166
+	if (ctx->file != file || ctx->lastline != line) {
167
+	    ctx->file = file;
168
+	    ctx->lastline = line;
169
+	    if (ctx->trace_mask&BC_TRACE_LINE)
170
+		ctx->trace_mask |= BC_TRACE_TMP_SRC;
171
+	}
172
+    }
173
+    ctx->trace_mask &= ~(BC_TRACE_TMP_FUNC|BC_TRACE_TMP_SCOPE);
174
+    return 0;
175
+}
176
+
177
+uint32_t cli_bcapi_trace_op(struct cli_bc_ctx *ctx, const const uint8_t *op, uint32_t col)
178
+{
179
+    if (LIKELY(!ctx->trace_mask))
180
+	return 0;
181
+    if (ctx->lastcol != col) {
182
+	ctx->lastcol = col;
183
+	if (ctx->trace_mask&BC_TRACE_COL)
184
+	    ctx->trace_mask |= BC_TRACE_TMP_SRC;
185
+    }
186
+    if ((ctx->trace_mask&BC_TRACE_OP) && op) {
187
+	if (ctx->trace_mask&BC_TRACE_TMP_SRC) {
188
+	    cli_dbgmsg("[trace] %s:%u:%u\t %s\n",
189
+		       ctx->file ? ctx->file : "??", ctx->lastline, col,
190
+		       op);
191
+	    cli_bytecode_debug_printsrc(ctx);
192
+	    ctx->trace_mask &= ~BC_TRACE_TMP_SRC;
193
+	} else
194
+	    cli_dbgmsg("[trace] %s\n", op);
195
+    }
196
+    return 0;
197
+}
198
+
199
+uint32_t cli_bcapi_trace_value(struct cli_bc_ctx *ctx, const const uint8_t* name, uint32_t value)
200
+{
201
+    if (LIKELY(!ctx->trace_mask))
202
+	return 0;
203
+    if ((ctx->trace_mask&BC_TRACE_VAL) && name) {
204
+	if (ctx->trace_mask&BC_TRACE_TMP_SRC) {
205
+	    cli_dbgmsg("[trace] %s:%u:%u\t %s = %u\n",
206
+		       ctx->file ? ctx->file : "??",
207
+		       ctx->lastline, ctx->lastcol,
208
+		       name, value);
209
+	    cli_bytecode_debug_printsrc(ctx);
210
+	} else {
211
+	    cli_dbgmsg("[trace]\t %s = %u\n", name, value);
212
+	}
213
+    } else if (ctx->trace_mask&BC_TRACE_TMP_SRC) {
214
+	cli_dbgmsg("[trace] %s:%u:%u\n",
215
+		   ctx->file ? ctx->file : "??",
216
+		   ctx->lastline, ctx->lastcol);
217
+	cli_bytecode_debug_printsrc(ctx);
218
+    }
219
+    ctx->trace_mask &= ~BC_TRACE_TMP_SRC;
220
+    return 0;
221
+}
131 222
 
223
+uint32_t cli_bcapi_trace_directory(struct cli_bc_ctx *ctx, const const uint8_t* dir, uint32_t dummy)
224
+{
225
+    if (LIKELY(!ctx->trace_mask))
226
+	return 0;
227
+    ctx->directory = dir;
228
+}
... ...
@@ -155,5 +155,15 @@ uint32_t debug_print_uint(uint32_t a, uint32_t b);
155 155
  *  \sa DisassembleAt
156 156
  * */
157 157
 uint32_t disasm_x86(struct DISASM_RESULT* result, uint32_t len);
158
+
159
+/* tracing API */
160
+
161
+/* a scope: lexical block, function, or compile unit */
162
+uint32_t trace_directory(const uint8_t* directory, uint32_t dummy);
163
+uint32_t trace_scope(const uint8_t* newscope, uint32_t scopeid);
164
+uint32_t trace_source(const uint8_t* srcfile, uint32_t line);
165
+uint32_t trace_op(const uint8_t* opname, uint32_t column);
166
+uint32_t trace_value(const uint8_t* name, uint32_t v);
167
+
158 168
 #endif
159 169
 #endif
... ...
@@ -42,6 +42,11 @@ uint32_t cli_bcapi_setvirusname(struct cli_bc_ctx *ctx, const const uint8_t*, ui
42 42
 uint32_t cli_bcapi_debug_print_str(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t);
43 43
 uint32_t cli_bcapi_debug_print_uint(struct cli_bc_ctx *ctx, uint32_t, uint32_t);
44 44
 uint32_t cli_bcapi_disasm_x86(struct cli_bc_ctx *ctx, struct DISASM_RESULT*, uint32_t);
45
+uint32_t cli_bcapi_trace_directory(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t);
46
+uint32_t cli_bcapi_trace_scope(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t);
47
+uint32_t cli_bcapi_trace_source(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t);
48
+uint32_t cli_bcapi_trace_op(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t);
49
+uint32_t cli_bcapi_trace_value(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t);
45 50
 
46 51
 const struct cli_apiglobal cli_globals[] = {
47 52
 /* Bytecode globals BEGIN */
... ...
@@ -70,14 +75,14 @@ static uint16_t cli_tmp10[]={80, 32, 32, 16};
70 70
 static uint16_t cli_tmp11[]={81};
71 71
 static uint16_t cli_tmp12[]={32, 32, 32, 32, 32, 32, 32, 32, 32};
72 72
 static uint16_t cli_tmp13[]={32};
73
-static uint16_t cli_tmp14[]={32, 84, 32};
74
-static uint16_t cli_tmp15[]={85};
75
-static uint16_t cli_tmp16[]={16, 8, 8, 8, 87, 86};
76
-static uint16_t cli_tmp17[]={8};
77
-static uint16_t cli_tmp18[]={88};
78
-static uint16_t cli_tmp19[]={8};
79
-static uint16_t cli_tmp20[]={32, 32, 32};
80
-static uint16_t cli_tmp21[]={32, 65, 32};
73
+static uint16_t cli_tmp14[]={32, 65, 32};
74
+static uint16_t cli_tmp15[]={32, 85, 32};
75
+static uint16_t cli_tmp16[]={86};
76
+static uint16_t cli_tmp17[]={16, 8, 8, 8, 88, 87};
77
+static uint16_t cli_tmp18[]={8};
78
+static uint16_t cli_tmp19[]={89};
79
+static uint16_t cli_tmp20[]={8};
80
+static uint16_t cli_tmp21[]={32, 32, 32};
81 81
 static uint16_t cli_tmp22[]={32, 92, 32};
82 82
 static uint16_t cli_tmp23[]={93};
83 83
 static uint16_t cli_tmp24[]={92};
... ...
@@ -98,12 +103,12 @@ const struct cli_bc_type cli_apicall_types[]={
98 98
 	{DStructType, cli_tmp12, 9, 0, 0},
99 99
 	{DArrayType, cli_tmp13, 64, 0, 0},
100 100
 	{DFunctionType, cli_tmp14, 3, 0, 0},
101
-	{DPointerType, cli_tmp15, 1, 0, 0},
102
-	{DStructType, cli_tmp16, 6, 0, 0},
103
-	{DArrayType, cli_tmp17, 29, 0, 0},
104
-	{DArrayType, cli_tmp18, 10, 0, 0},
105
-	{DArrayType, cli_tmp19, 3, 0, 0},
106
-	{DFunctionType, cli_tmp20, 3, 0, 0},
101
+	{DFunctionType, cli_tmp15, 3, 0, 0},
102
+	{DPointerType, cli_tmp16, 1, 0, 0},
103
+	{DStructType, cli_tmp17, 6, 0, 0},
104
+	{DArrayType, cli_tmp18, 29, 0, 0},
105
+	{DArrayType, cli_tmp19, 10, 0, 0},
106
+	{DArrayType, cli_tmp20, 3, 0, 0},
107 107
 	{DFunctionType, cli_tmp21, 3, 0, 0},
108 108
 	{DFunctionType, cli_tmp22, 3, 0, 0},
109 109
 	{DPointerType, cli_tmp23, 1, 0, 0},
... ...
@@ -114,14 +119,19 @@ const unsigned cli_apicall_maxtypes=sizeof(cli_apicall_types)/sizeof(cli_apicall
114 114
 const struct cli_apicall cli_apicalls[]={
115 115
 /* Bytecode APIcalls BEGIN */
116 116
 	{"test0", 22, 0, 1},
117
-	{"test1", 20, 0, 0},
118
-	{"read", 21, 1, 1},
119
-	{"write", 21, 2, 1},
120
-	{"seek", 20, 1, 0},
121
-	{"setvirusname", 21, 3, 1},
122
-	{"debug_print_str", 21, 4, 1},
123
-	{"debug_print_uint", 20, 2, 0},
124
-	{"disasm_x86", 14, 5, 1}
117
+	{"test1", 21, 0, 0},
118
+	{"read", 14, 1, 1},
119
+	{"write", 14, 2, 1},
120
+	{"seek", 21, 1, 0},
121
+	{"setvirusname", 14, 3, 1},
122
+	{"debug_print_str", 14, 4, 1},
123
+	{"debug_print_uint", 21, 2, 0},
124
+	{"disasm_x86", 15, 5, 1},
125
+	{"trace_directory", 14, 6, 1},
126
+	{"trace_scope", 14, 7, 1},
127
+	{"trace_source", 14, 8, 1},
128
+	{"trace_op", 14, 9, 1},
129
+	{"trace_value", 14, 10, 1}
125 130
 /* Bytecode APIcalls END */
126 131
 };
127 132
 const cli_apicall_int2 cli_apicalls0[] = {
... ...
@@ -135,6 +145,11 @@ const cli_apicall_pointer cli_apicalls1[] = {
135 135
 	(cli_apicall_pointer)cli_bcapi_write,
136 136
 	(cli_apicall_pointer)cli_bcapi_setvirusname,
137 137
 	(cli_apicall_pointer)cli_bcapi_debug_print_str,
138
-	(cli_apicall_pointer)cli_bcapi_disasm_x86
138
+	(cli_apicall_pointer)cli_bcapi_disasm_x86,
139
+	(cli_apicall_pointer)cli_bcapi_trace_directory,
140
+	(cli_apicall_pointer)cli_bcapi_trace_scope,
141
+	(cli_apicall_pointer)cli_bcapi_trace_source,
142
+	(cli_apicall_pointer)cli_bcapi_trace_op,
143
+	(cli_apicall_pointer)cli_bcapi_trace_value
139 144
 };
140 145
 const unsigned cli_apicall_maxapi = sizeof(cli_apicalls)/sizeof(cli_apicalls[0]);
... ...
@@ -39,5 +39,10 @@ uint32_t cli_bcapi_setvirusname(struct cli_bc_ctx *ctx, const const uint8_t*, ui
39 39
 uint32_t cli_bcapi_debug_print_str(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t);
40 40
 uint32_t cli_bcapi_debug_print_uint(struct cli_bc_ctx *ctx, uint32_t, uint32_t);
41 41
 uint32_t cli_bcapi_disasm_x86(struct cli_bc_ctx *ctx, struct DISASM_RESULT*, uint32_t);
42
+uint32_t cli_bcapi_trace_directory(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t);
43
+uint32_t cli_bcapi_trace_scope(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t);
44
+uint32_t cli_bcapi_trace_source(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t);
45
+uint32_t cli_bcapi_trace_op(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t);
46
+uint32_t cli_bcapi_trace_value(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t);
42 47
 
43 48
 #endif
... ...
@@ -66,4 +66,7 @@ int bytecode_init(void)
66 66
     return 0;
67 67
 }
68 68
 
69
+void cli_bytecode_debug_printsrc(const struct cli_bc_ctx *ctx) {
70
+    // Empty
71
+}
69 72
 int have_clamjit=0;
... ...
@@ -103,6 +103,18 @@ struct cli_bc_dbgnode {
103 103
 };
104 104
 
105 105
 #define MAX_OP ~0u
106
+#define BC_TRACE_FUNC  0x1
107
+#define BC_TRACE_SCOPE 0x2
108
+#define BC_TRACE_LINE  0x4
109
+#define BC_TRACE_COL   0x8
110
+#define BC_TRACE_OP    0x10
111
+#define BC_TRACE_VAL   0x20
112
+#define BC_TRACE_TMP_FUNC  0x40
113
+#define BC_TRACE_TMP_SCOPE 0x80
114
+#define BC_TRACE_TMP_SRC  0x100
115
+#define BC_TRACE_SHOW_SOURCE 0x200
116
+#define BC_TRACE_ALL (BC_TRACE_FUNC | BC_TRACE_SCOPE | BC_TRACE_LINE | BC_TRACE_COL | BC_TRACE_OP | BC_TRACE_VAL | BC_TRACE_SHOW_SOURCE)
117
+
106 118
 struct cli_bc_ctx {
107 119
     /* id and params of toplevel function called */
108 120
     const struct cli_bc *bc;
... ...
@@ -122,6 +134,13 @@ struct cli_bc_ctx {
122 122
     char *tempfile;
123 123
     void *ctx;
124 124
     unsigned written;
125
+    unsigned trace_mask;
126
+    const char *scope;
127
+    uint32_t scopeid;
128
+    const char *file;
129
+    const char *directory;
130
+    unsigned lastline;
131
+    unsigned lastcol;
125 132
 };
126 133
 struct cli_all_bc;
127 134
 int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct cli_bc_func *func, const struct cli_bc_inst *inst);
... ...
@@ -22,6 +22,7 @@
22 22
 #define DEBUG_TYPE "clamavjit"
23 23
 #include "llvm/ADT/DenseMap.h"
24 24
 #include "llvm/ADT/BitVector.h"
25
+#include "llvm/ADT/StringMap.h"
25 26
 #include "llvm/CallingConv.h"
26 27
 #include "llvm/DerivedTypes.h"
27 28
 #include "llvm/Function.h"
... ...
@@ -37,10 +38,13 @@
37 37
 #include "llvm/Support/CommandLine.h"
38 38
 #include "llvm/Support/ErrorHandling.h"
39 39
 #include "llvm/Support/ManagedStatic.h"
40
+#include "llvm/Support/MemoryBuffer.h"
40 41
 #include "llvm/Support/raw_ostream.h"
42
+#include "llvm/Support/SourceMgr.h"
41 43
 #include "llvm/Support/IRBuilder.h"
42 44
 #include "llvm/Support/PrettyStackTrace.h"
43 45
 #include "llvm/System/DataTypes.h"
46
+#include "llvm/System/Mutex.h"
44 47
 #include "llvm/System/Signals.h"
45 48
 #include "llvm/System/Threading.h"
46 49
 #include "llvm/Target/TargetSelect.h"
... ...
@@ -264,6 +268,8 @@ private:
264 264
 	    operand &= 0x7fffffff;
265 265
 	    assert(operand < globals.size() && "Global index out of range");
266 266
 	    // Global
267
+	    if (!operand)
268
+		return ConstantPointerNull::get(PointerType::getUnqual(Type::getInt8Ty(Context)));
267 269
 	    if (GlobalVariable *GV = dyn_cast<GlobalVariable>(globals[operand])) {
268 270
 		if (ConstantExpr *CE = dyn_cast<ConstantExpr>(GV->getInitializer())) {
269 271
 		    return CE;
... ...
@@ -328,14 +334,22 @@ private:
328 328
 
329 329
     Constant *buildConstant(const Type *Ty, uint64_t *components, unsigned &c)
330 330
     {
331
-        if (isa<PointerType>(Ty)) {
332
-          Constant *idxs[2] = {
331
+        if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
332
+          Value *idxs[2] = {
333 333
 	      ConstantInt::get(Type::getInt32Ty(Context), 0),
334 334
 	      ConstantInt::get(Type::getInt32Ty(Context), components[c++])
335 335
 	  };
336 336
 	  unsigned idx = components[c++];
337
+	  if (!idx)
338
+	      return ConstantPointerNull::get(PTy);
337 339
 	  assert(idx < globals.size());
338 340
 	  GlobalVariable *GV = cast<GlobalVariable>(globals[idx]);
341
+	  const Type *GTy = GetElementPtrInst::getIndexedType(GV->getType(), idxs, 2);
342
+	  if (!GTy || GTy != PTy->getElementType()) {
343
+	      errs() << "Type mismatch for GEP: " << *PTy->getElementType() << " != " << *GTy
344
+		  << "; base is " << *GV << "\n";
345
+	      llvm_report_error("(libclamav) Type mismatch converting constant");
346
+	  }
339 347
 	  return ConstantExpr::getInBoundsGetElementPtr(GV, idxs, 2);
340 348
         }
341 349
 	if (isa<IntegerType>(Ty)) {
... ...
@@ -517,8 +531,8 @@ public:
517 517
 
518 518
 	globals.reserve(bc->num_globals);
519 519
 	BitVector FakeGVs;
520
-	FakeGVs.resize(bc->num_globals);
521
-
520
+	FakeGVs.resize(bc->num_globals+1);
521
+	globals.push_back(0);
522 522
 	for (unsigned i=0;i<bc->num_globals;i++) {
523 523
 	    const Type *Ty = mapType(bc->globaltys[i]);
524 524
 
... ...
@@ -528,7 +542,7 @@ public:
528 528
 	    if (isa<PointerType>(Ty)) {
529 529
 		unsigned g = bc->globals[i][1];
530 530
 		if (GVoffsetMap.count(g)) {
531
-		    FakeGVs.set(i);
531
+		    FakeGVs.set(i+1);
532 532
 		    globals.push_back(0);
533 533
 		    continue;
534 534
 		}
... ...
@@ -596,7 +610,7 @@ public:
596 596
 		Argument *Ctx = F->arg_begin();
597 597
 		struct cli_bc_ctx *N = 0;
598 598
 		for (unsigned i=0;i<bc->num_globals;i++) {
599
-		    if (!FakeGVs[i])
599
+		    if (!FakeGVs[i+1])
600 600
 			continue;
601 601
 		    unsigned g = bc->globals[i][1];
602 602
 		    unsigned offset = GVoffsetMap[g];
... ...
@@ -1207,4 +1221,67 @@ void cli_bytecode_debug(int argc, char **argv)
1207 1207
   cl::ParseCommandLineOptions(argc, argv);
1208 1208
 }
1209 1209
 
1210
+struct lines {
1211
+    MemoryBuffer *buffer;
1212
+    std::vector<const char*> lines;
1213
+};
1214
+
1215
+static struct lineprinter {
1216
+    StringMap<struct lines*> files;
1217
+} LinePrinter;
1218
+
1219
+void cli_bytecode_debug_printsrc(const struct cli_bc_ctx *ctx)
1220
+{
1221
+    if (!ctx->file || !ctx->directory || !ctx->lastline) {
1222
+	errs() << (ctx->directory ? "d":"null") << ":" << (ctx->file ? "f" : "null")<< ":" << ctx->lastline << "\n";
1223
+	return;
1224
+    }
1225
+    // acquire a mutex here
1226
+    sys::Mutex mtx(false);
1227
+    sys::SmartScopedLock<false> lock(mtx);
1228
+
1229
+    std::string path = std::string(ctx->directory) + "/" + std::string(ctx->file);
1230
+    StringMap<struct lines*>::iterator I = LinePrinter.files.find(path);
1231
+    struct lines *lines;
1232
+    if (I == LinePrinter.files.end()) {
1233
+	lines = new struct lines;
1234
+	std::string ErrorMessage;
1235
+	lines->buffer = MemoryBuffer::getFile(path, &ErrorMessage);
1236
+	if (!lines->buffer) {
1237
+	    errs() << "Unable to open file '" << path << "'\n";
1238
+	    return ;
1239
+	}
1240
+	LinePrinter.files[path] = lines;
1241
+    } else {
1242
+	lines = I->getValue();
1243
+    }
1244
+    const char *linestart;
1245
+    while (lines->lines.size() <= ctx->lastline+1) {
1246
+	const char *p;
1247
+	if (lines->lines.empty()) {
1248
+	    p = lines->buffer->getBufferStart();
1249
+	    lines->lines.push_back(p);
1250
+	} else {
1251
+	    p = lines->lines.back();
1252
+	    if (p == lines->buffer->getBufferEnd())
1253
+		break;
1254
+	    p = strchr(p, '\n');
1255
+	    if (!p) {
1256
+		p = lines->buffer->getBufferEnd();
1257
+		lines->lines.push_back(p);
1258
+	    } else
1259
+		lines->lines.push_back(p+1);
1260
+	}
1261
+    }
1262
+    if (ctx->lastline >= lines->lines.size()) {
1263
+	errs() << "Line number " << ctx->lastline << "out of file\n";
1264
+	return;
1265
+    }
1266
+    assert(ctx->lastline < lines->lines.size());
1267
+    SMDiagnostic diag(ctx->file, ctx->lastline ? ctx->lastline : -1,
1268
+		 ctx->lastcol ? ctx->lastcol-1 : -1,
1269
+		 "", std::string(lines->lines[ctx->lastline-1], lines->lines[ctx->lastline]-1));
1270
+    diag.Print("[trace]", errs());
1271
+}
1272
+
1210 1273
 int have_clamjit=1;
... ...
@@ -353,8 +353,10 @@ void cli_errmsg(const char *str, ...);
353 353
  * such as debug paths, and error paths */
354 354
 #if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)
355 355
 #define UNLIKELY(cond) __builtin_expect(!!(cond), 0)
356
+#define LIKELY(cond) __builtin_expect(!!(cond), 1)
356 357
 #else
357 358
 #define UNLIKELY(cond) (cond)
359
+#define LIKELY(cond) (cond)
358 360
 #endif
359 361
 
360 362
 #ifdef __GNUC__
... ...
@@ -1949,6 +1949,7 @@ int cli_scanpe(cli_ctx *ctx)
1949 1949
 	    return CL_EREAD;
1950 1950
 	}
1951 1951
 
1952
+	cli_dbgmsg("%d,%d,%d,%d\n", nsections-1, e_lfanew, ecx, offset);
1952 1953
 	CLI_UNPTEMP("yC",(spinned,exe_sections,0));
1953 1954
 	CLI_UNPRESULTS("yC",(yc_decrypt(spinned, fsize, exe_sections, nsections-1, e_lfanew, ndesc, ecx, offset)),0,(spinned,0));
1954 1955
 	}
... ...
@@ -2,10 +2,10 @@ ClamBCaa`|``c``a```|`bjaabp`clamcoincidencejb
2 2
 Trojan.Foo.{A,B};Target:1;(((0|1|2)=42,2)|(3=10));EP+0:aabb;ffff;aaccee;f00d;dead
3 3
 Tedebieebheebgeebfeebeeebdeebbeebaeebadebcdaaa`aacb`bbadb`bdb`db`bcajbadbcebadbcebadbcebadbcebadbcecaab`bdagahdaeahdajahdabbaddabahdakah
4 4
 Eafaaafb`e|amcgefdgfgifbgegcgnfafmfef``
5
-Gd```hbhabieBdeBbgBofBjfBafBnfBnbBfdBofBof@`bheBad@`bheBbd@`bge@Aa@Ab`b`aAa`b`aC``a`bfeBedB`eBkbB`cBjcBafBafBbfBbf@`beeBffBffBffBff@`beeBffB`cB`cBdf@`bdeBafBafBcfBcfBefBef@`beeBdfBefBafBdf@`bbe@Af@@AgAa@AhAc@AiAb@AjAd`bad@Aa`bad@Ab`bad@Af`bad@Ag`bad@Ah`bad@Ai`bad@Aj`bcdAdD```h`bcdAcD```h`bcdAbD```h`bcdAaD```h`bcd@D```h`
5
+Gd```hbhabieBdeBbgBofBjfBafBnfBnbBfdBofBof@`bheBad@`bheBbd@`bge@Ab@Ac`b`aAa`b`aC``a`bfeBedB`eBkbB`cBjcBafBafBbfBbf@`beeBffBffBffBff@`beeBffB`cB`cBdf@`bdeBafBafBcfBcfBefBef@`beeBdfBefBafBdf@`bbe@Ag@@AhAa@AiAc@AjAb@AkAd`bad@Ab`bad@Ac`bad@Ag`bad@Ah`bad@Ai`bad@Aj`bad@Ak`bcdAdD```h`bcdAcD```h`bcdAbD```h`bcdAaD```h`bcd@D```h`
6 6
 A`b`bLaeb`b`aa`aa`bad`b`b`Fahac
7
-Bb`b`gbBca`aaaagab`b`AadTaaaaaaab
8
-Baaabeab`b`AbdbadacoaabAl`Am`b`badabbafac@dTcab`b@d
7
+Bb`b`gbBda`aaaagab`b`AadTaaaaaaab
8
+Baaabeab`b`AbdbadacoaabAm`An`b`badabbafac@dTcab`b@d
9 9
 BTcab`b@dE
10 10
 A`aaLbcab`b`b`b`b`b`b`b`b`b`aa`aa`aa`aa`b`b`b`b`b`b`b`b`b`b`aa`aa`b`b`aa`aa`Fbdaaa
11
-Bb`b`gbBga`b`baagbBfa`b`babgbBea`b`baca`aa`b`bada`acabaaaeeab`badBjbdaaaffab`bab@daaagfab`baa@daaahfab`b`@db`bai`aafb`baj`aagb`bak`aahb`bala`ajakb`bama`alaiaaaneab`bamAbdaaaok`anaeb`bb`agbBda`aabaaeab`bb`aAjdaabbal`aobaaTcaaabbaE
11
+Bb`b`gbBha`b`baagbBga`b`babgbBfa`b`baca`aa`b`bada`acabaaaeeab`badBjbdaaaffab`bab@daaagfab`baa@daaahfab`b`@db`bai`aafb`baj`aagb`bak`aahb`bala`ajakb`bama`alaiaaaneab`bamAbdaaaok`anaeb`bb`agbBea`aabaaeab`bb`aAjdaabbal`aobaaTcaaabbaE