@noɥʇʎԀʎzɐɹƆ 正在寻找可以在 x86 上构建并为任何布尔表达式生成 x86 asm JIT 评估器的规范解析器和评估器。
这是一个 ANSI C99 基本解析器和求值器,它使用 构建表达式树parse_tree
并使用eval_expr
. 这避免了大多数常见的指针算术,应该很容易翻译成许多语言。
错误管理设置为基本最小值(缺少或意外的表达式,错误的表达式,如 NOT 1 NOT 0)。如果解析时出现错误的表达式,它不应该泄漏内存,但没有真正以这种方式进行测试。
可以用eval_leaf
一种 libc 替换strtol()
,但这里似乎更好地执行由偏移量分隔的基本 int 解析以避免字符串分配,因为我们通常处理简单的 int 。
该compile_expr
方法为表达式生成一个 x86 asm 求值器,该exec_expr_JIT
方法执行生成的 x86 asm 求值器。exec_expr_JIT
实际上只使用了Linux/BSD/MacOS和Windows的mmap和MapViewOfFile。更通用的方法是在学习中。
编辑:添加按位非运算符 (BNOT) 作为~
in 表达式。
要对其进行测试,只需使用 ANSI C99 编译器构建它,然后使用预期的表达式启动它,以作为第一个参数进行解析和评估:
$ cc -o parser parser.c
$ ./parser '(NOT0AND(1OR(1 AND 0))AND(1OR(0OR0)))AND1ANDNOT!~0'
<<<<[NOT]0>[AND]<1[OR]<1 [AND] 0>>>[AND]<1[OR]<0[OR]0>>>[AND]1>[AND]<[NOT]<[NOT]<[BNOT]0>>>
=> 1
Compiled: 88 [B8 00 00 00 00 F7 D0 25 01 00 00 00 50 B8 01 00 00 00 50 B8 01 00 00 00 25 00 00 00 00 59 09 C1 59 21 C1 50 B8 01 00 00 00 50 B8 00 00 00 00 0D 00 00 00 00 59 09 C1 59 21 C1 25 01 00 00 00 50 B8 00 00 00 00 F7 D0 F7 D0 25 01 00 00 00 F7 D0 25 01 00 00 00 59 21 C1]
Res JIT : 1
它将首先使用<leaf>
和以扁平树形式显示解析的表达式[operand]
,然后使用 显示其评估结果 => <result>
。接下来,它将显示为已解析表达式构建的求值器的 x86 asm 代码及其大小(以字节为单位),然后是该求值器的执行结果。
解析器和评估器来源:
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdint.h>
#ifdef _MSC_VER
#include <windows.h>
#include <memoryapi.h>
#else
#include <sys/mman.h>
#endif
enum e_operand { NONE, AND, OR, NOT, BNOT };
struct s_expr {
struct s_expr_leaf {
char* value;
int offset;
struct s_expr* expr;
} *left;
enum e_operand operand;
struct s_expr_leaf* right;
};
struct s_expr* build_expr() {
struct s_expr* lExpr = (struct s_expr*)malloc(sizeof(struct s_expr));
if (lExpr == NULL) return(NULL);
lExpr->left = NULL;
lExpr->operand = NONE;
lExpr->right = NULL;
return(lExpr);
}
struct s_expr_leaf* build_leaf(struct s_expr* pExpr) {
struct s_expr_leaf* lLeaf = (struct s_expr_leaf*)malloc(sizeof(struct s_expr_leaf));
if (lLeaf == NULL) return(NULL);
lLeaf->value = NULL;
lLeaf->offset = 0;
lLeaf->expr = pExpr;
return(lLeaf);
}
struct s_expr* left_expr(struct s_expr** pExpr) {
struct s_expr* lExprParent = build_expr();
if (lExprParent == NULL) {
perror("Can't allocate enough memory...");
return(NULL);
}
lExprParent->left = build_leaf(*pExpr);
if (lExprParent->left == NULL) {
perror("Can't allocate enough memory...");
free(lExprParent);
return(NULL);
}
*(pExpr) = lExprParent;
return lExprParent;
}
int free_expr(struct s_expr*);
struct s_expr* parse_tree(char** pExpr) {
if (pExpr == NULL || *pExpr == NULL) return(NULL);
struct s_expr* lExpr = build_expr();
if (lExpr == NULL) {
perror("Can't allocate enough memory...");
return(NULL);
}
struct s_expr_leaf** lSide = &lExpr->left;
while (**pExpr != 0) {
switch (**pExpr & 0xDF) {
case 8: // (
(*pExpr)++;
if (*lSide == NULL) {
*lSide = build_leaf(NULL);
}
if (*lSide != NULL) (*lSide)->expr = parse_tree(pExpr);
if (*lSide == NULL || (*lSide)->expr == NULL) {
perror("Can't allocate enough memory...");
free_expr(lExpr);
return(NULL);
}
break;
case 9: // )
return(lExpr);
case 'N': // NOT?
case 1:
if (**pExpr == '!' || (((*pExpr)[1] & 0xDF) == 'O' && ((*pExpr)[2] & 0xDF) == 'T')) {
if (lExpr->operand != NONE) {
if (lExpr->right != NULL) {
printf("Wrong expression\n");
free_expr(lExpr);
return(NULL);
}
lExpr->right = build_leaf(parse_tree(pExpr));
if (lExpr->right == NULL || lExpr->right->expr == NULL) {
perror("Can't allocate enough memory...");
free_expr(lExpr);
return(NULL);
}
return(lExpr);
}
lExpr->operand = NOT;
if (**pExpr != '!') (*pExpr) += 2;
lSide = &lExpr->right;
}
break;
case '^': // Bitwise NOT ?
if (**pExpr == '~') {
if (lExpr->operand != NONE) {
if (lExpr->right != NULL) {
printf("Wrong expression\n");
free_expr(lExpr);
return(NULL);
}
lExpr->right = build_leaf(parse_tree(pExpr));
if (lExpr->right == NULL || lExpr->right->expr == NULL) {
perror("Can't allocate enough memory...");
free_expr(lExpr);
return(NULL);
}
return(lExpr);
}
lExpr->operand = BNOT;
lSide = &lExpr->right;
}
break;
case 'A': // AND?
if (((*pExpr)[1] & 0xDF) == 'N' && ((*pExpr)[2] & 0xDF) == 'D') {
if (lExpr->operand != NONE) {
if (left_expr(&lExpr) == NULL) {
free_expr(lExpr);
return(NULL);
}
}
lExpr->operand = AND;
(*pExpr) += 2;
lSide = &lExpr->right;
}
break;
case 'O': // OR?
if (((*pExpr)[1] & 0xDF) == 'R') {
if (lExpr->operand != NONE) {
if (left_expr(&lExpr) == NULL) {
free_expr(lExpr);
return(NULL);
}
}
lExpr->operand = OR;
(*pExpr)++;
lSide = &lExpr->right;
}
break;
default:
if (*lSide == NULL) {
*lSide = build_leaf(NULL);
if (*lSide == NULL) {
perror("Can't allocate enough memory...");
free_expr(lExpr);
return(NULL);
}
(*lSide)->value = *pExpr;
}
if ((*lSide)->value == NULL) (*lSide)->value = *pExpr;
(*lSide)->offset++;
};
(*pExpr)++;
};
return(lExpr);
}
int free_expr(struct s_expr* pExpr) {
int lFlag = 0;
if (pExpr == NULL) return(0);
if (pExpr->left != NULL) {
lFlag = free_expr(pExpr->left->expr);
free(pExpr->left);
}
if (pExpr->right != NULL) {
lFlag = free_expr(pExpr->right->expr);
free(pExpr->right);
}
free(pExpr);
return(lFlag);
}
int display_expr(struct s_expr* pExpr) {
if (pExpr == NULL) return 0;
if (pExpr->left != NULL) {
if (pExpr->left->expr != NULL) {
printf("<");
display_expr(pExpr->left->expr);
printf(">");
} else {
if (pExpr->left->value != NULL) printf("%.*s", pExpr->left->offset, pExpr->left->value);
}
}
switch (pExpr->operand) {
case NONE:
break;
case AND:
printf("[AND]");
break;
case OR:
printf("[OR]");
break;
case NOT:
printf("[NOT]");
break;
case BNOT:
printf("[BNOT]");
break;
};
if (pExpr->right != NULL) {
if (pExpr->right->expr != NULL) {
printf("<");
display_expr(pExpr->right->expr);
printf(">");
} else {
if (pExpr->right->value != NULL) printf("%.*s", pExpr->right->offset, pExpr->right->value);
}
}
return(0);
}
int eval_leaf(struct s_expr_leaf* pValue, int* pRes) {
char* lValue;
int lLimit = 0;
int lStart = -1;
int lSign = 1;
if (pRes == NULL) return(1);
if (pValue == NULL) return(1);
lValue = pValue->value;
lLimit = pValue->offset;
if (lValue == NULL) return(1);
*pRes = 0;
while (lLimit > 0 && *lValue == ' ') { lValue++; lLimit--; }
if (lLimit > 0 && (*lValue == '-' || *lValue == '+')) {
if (*lValue == '-') lSign = -1;
lLimit--;
lValue++;
}
while (lLimit > 0 && *lValue != 0) {
if (*lValue >= 0x30 && *lValue <= 0x39) {
if (lStart == -1) lStart = lLimit;
} else {
break;
}
lLimit--;
lValue++;
}
if (lStart > 0) {
lStart -= lLimit;
lValue--;
lLimit = 1;
while (lStart > 0) {
*pRes += ((*lValue & 0xF) * lLimit);
lLimit *= 10;
lStart--;
lValue--;
};
} else {
printf("Expr or value missing ...\n");
return(2);
}
*pRes *= lSign;
return(0);
}
int eval_expr(struct s_expr* pExpr, int* pRes) {
int lResLeft = 0;
int lResRight = 0;
enum e_operand lOperand = NONE;
if (pRes == NULL) return(1);
*pRes = 0;
if (pExpr == NULL) return(1);
if (pExpr->left != NULL) {
if (pExpr->left->expr != NULL) {
if (pExpr->left->value != NULL) {
printf("Unexpected left value... %.*s\n", pExpr->left->offset, pExpr->left->value);
return(2);
}
switch (eval_expr(pExpr->left->expr, &lResLeft)) {
case 2:
display_expr(pExpr); printf("\n");
return(1);
case 1:
return(1);
};
} else {
if (pExpr->left->value != NULL) {
switch (eval_leaf(pExpr->left, &lResLeft)) {
case 2:
display_expr(pExpr); printf("\n");
return(1);
case 1:
return(1);
};
}
}
}
if (pExpr->right != NULL) {
if (pExpr->right->expr != NULL) {
if (pExpr->right->value != NULL) {
printf("Unexpected right value... %.*s\n", pExpr->right->offset, pExpr->right->value);
return(2);
}
switch (eval_expr(pExpr->right->expr, &lResRight)) {
case 2:
display_expr(pExpr); printf("\n");
return(1);
case 1:
return(1);
};
} else {
if (pExpr->right->value != NULL) {
switch (eval_leaf(pExpr->right, &lResRight)) {
case 2:
display_expr(pExpr); printf("\n");
return(1);
case 1:
return(1);
};
}
}
}
switch (pExpr->operand) {
case NONE:
if (pExpr->left == NULL) {
printf("Expr or value missing ...\n");
return(2);
}
*pRes = lResLeft;
break;
case AND:
if (pExpr->left == NULL || pExpr->right == NULL) {
printf("Expr or value missing ...\n");
return(2);
}
*pRes = (lResLeft & lResRight);
break;
case OR:
if (pExpr->left == NULL || pExpr->right == NULL) {
printf("Expr or value missing ...\n");
return(2);
}
*pRes = (lResLeft | lResRight);
break;
case NOT:
if (pExpr->right == NULL) {
printf("Expr or value missing ...\n");
return(2);
}
*pRes = !lResRight;
break;
case BNOT:
if (pExpr->right == NULL) {
printf("Expr or value missing ...\n");
return(2);
}
*pRes = ~lResRight;
break;
};
return(0);
}
// Expr compilation
struct s_expr_JIT {
unsigned char* JIT;
int size;
int nbargs;
};
struct s_expr_JIT* build_expr_JIT() {
struct s_expr_JIT* lExprJIT = (struct s_expr_JIT*)malloc(sizeof(struct s_expr_JIT));
if (lExprJIT == NULL) {
perror("Can't allocate enough memory...");
return(NULL);
}
lExprJIT->JIT = NULL;
lExprJIT->size = 0;
lExprJIT->nbargs = 0;
return(lExprJIT);
}
int free_expr_JIT(struct s_expr_JIT* pExpr) {
if (pExpr == NULL) return(1);
if (pExpr->JIT != NULL) free(pExpr->JIT);
free(pExpr);
return(0);
}
int set_expr_JIT(struct s_expr_JIT* pExpr, unsigned char* pOpCodes, int pNbOpCodes, int* pValue, unsigned char* pOpCodesNext, int pNbOpCodesNext) {
unsigned char* lOffset;
int lSizeref;
if (pExpr == NULL) return(1);
if (pExpr->JIT != NULL) {
lSizeref = pExpr->size;
pExpr->size += pNbOpCodes;
pExpr->size += pNbOpCodesNext;
if (pValue != NULL) pExpr->size += sizeof(int32_t);
lOffset = (unsigned char*)realloc(pExpr->JIT, pExpr->size);
if (lOffset == NULL) {
perror("Can't allocate enough memory...");
return(1);
}
pExpr->JIT = lOffset;
lOffset = &pExpr->JIT[lSizeref];
} else {
pExpr->size = pNbOpCodes;
pExpr->size += pNbOpCodesNext;
if (pValue != NULL) pExpr->size += sizeof(int32_t);
pExpr->JIT = (unsigned char*)malloc(pExpr->size);
if (pExpr->JIT == NULL) {
perror("Can't allocate enough memory...");
return(1);
}
lOffset = pExpr->JIT;
}
if (pOpCodes != NULL) {
if (memcpy(lOffset, pOpCodes, pNbOpCodes) == NULL) return(1);
lOffset += pNbOpCodes;
}
if (pValue != NULL) {
*((int32_t*)lOffset) = (int32_t)*pValue; // Keep endianness
lOffset += sizeof(int32_t);
}
if (pOpCodesNext != NULL) {
if (memcpy(lOffset, pOpCodesNext, pNbOpCodesNext) == NULL) return(1);
lOffset += pNbOpCodesNext;
}
return(0);
}
int merge_expr_JIT(struct s_expr_JIT* pExpr, unsigned char* pOpCodes, int pNbOpCodes, struct s_expr_JIT* pSrc, unsigned char* pOpCodesMerge, int pNbOpCodesMerge) {
unsigned char* lOffset;
int lSizeref;
if (pExpr == NULL) return(1);
if (pExpr->JIT != NULL) {
lSizeref = pExpr->size;
pExpr->size += pNbOpCodes;
pExpr->size += pNbOpCodesMerge;
if (pSrc != NULL) pExpr->size += pSrc->size;
lOffset = (unsigned char*)realloc(pExpr->JIT, pExpr->size);
if (lOffset == NULL) {
perror("Can't allocate enough memory...");
return(1);
}
pExpr->JIT = lOffset;
lOffset = &pExpr->JIT[lSizeref];
} else {
pExpr->size = pNbOpCodes;
pExpr->size += pNbOpCodesMerge;
if (pSrc != NULL) pExpr->size += pSrc->size;
pExpr->JIT = (unsigned char*)malloc(pExpr->size);
if (pExpr->JIT == NULL) {
perror("Can't allocate enough memory...");
return(1);
}
lOffset = pExpr->JIT;
}
if (pOpCodes != NULL) {
if (memcpy(lOffset, pOpCodes, pNbOpCodes) == NULL) return(1);
lOffset += pNbOpCodes;
}
if (pSrc != NULL) {
if (memcpy(lOffset, pSrc->JIT, pSrc->size) == NULL) return(1);
lOffset += pSrc->size;
}
if (pOpCodesMerge != NULL) {
if (memcpy(lOffset, pOpCodesMerge, pNbOpCodesMerge) == NULL) return(1);
lOffset += pNbOpCodesMerge;
}
return(0);
}
int compile_expr(struct s_expr* pExpr, struct s_expr_JIT** pRes) {
int lResLeftValue = 0;
int lResRightValue = 0;
if (pExpr == NULL) return(1);
if (pRes == NULL) return(1);
struct s_expr_JIT* lResLeft = NULL;
struct s_expr_JIT* lResRight = NULL;
enum e_operand lOperand = NONE;
*pRes = build_expr_JIT();
if (*pRes == NULL) {
return(1);
}
if (pExpr->left != NULL) {
if (pExpr->left->expr != NULL) {
if (pExpr->left->value != NULL) {
printf("Unexpected left value... %.*s\n", pExpr->left->offset, pExpr->left->value);
free_expr_JIT(*pRes);
return(2);
}
switch (compile_expr(pExpr->left->expr, &lResLeft)) {
case 2:
display_expr(pExpr); printf("\n");
free_expr_JIT(*pRes);
return(1);
case 1:
free_expr_JIT(*pRes);
return(1);
};
} else {
if (pExpr->left->value != NULL) {
switch (eval_leaf(pExpr->left, &lResLeftValue)) {
case 2:
display_expr(pExpr); printf("\n");
free_expr_JIT(*pRes);
return(1);
case 1:
free_expr_JIT(*pRes);
return(1);
};
}
}
}
if (pExpr->right != NULL) {
if (pExpr->right->expr != NULL) {
if (pExpr->right->value != NULL) {
printf("Unexpected right value... %.*s\n", pExpr->right->offset, pExpr->right->value);
free_expr_JIT(lResLeft); free_expr_JIT(*pRes);
return(2);
}
switch (compile_expr(pExpr->right->expr, &lResRight)) {
case 2:
display_expr(pExpr); printf("\n");
free_expr_JIT(lResLeft); free_expr_JIT(*pRes);
return(1);
case 1:
free_expr_JIT(lResLeft); free_expr_JIT(*pRes);
return(1);
};
} else {
if (pExpr->right->value != NULL) {
switch (eval_leaf(pExpr->right, &lResRightValue)) {
case 2:
display_expr(pExpr); printf("\n");
free_expr_JIT(lResLeft); free_expr_JIT(*pRes);
return(1);
case 1:
free_expr_JIT(lResLeft); free_expr_JIT(*pRes);
return(1);
};
}
}
}
switch (pExpr->operand) {
case NONE:
if (pExpr->left == NULL) {
printf("Expr or value missing ...\n");
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(2);
}
if (lResLeft != NULL) {
if (merge_expr_JIT(*pRes, NULL, 0, lResLeft, NULL, 0) != 0) {
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(1);
}
} else {
if (set_expr_JIT(*pRes, (unsigned char[]) { 0xB8 }, 1, & lResLeftValue, NULL, 0) != 0) { // MOVL <int32 value>, %EAX
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(1);
}
}
break;
case AND:
if (pExpr->left == NULL || pExpr->right == NULL) {
printf("Expr or value missing ...\n");
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(2);
}
if (lResLeft != NULL) {
if (merge_expr_JIT(*pRes, NULL, 0, lResLeft, NULL, 0) != 0) {
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(1);
}
} else {
if (set_expr_JIT(*pRes, (unsigned char[]) { 0xB8 }, 1, & lResLeftValue, NULL, 0) != 0) { // MOVL <int32 value>, %EAX
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(1);
}
}
if (lResRight != NULL) { // 0x91 XCHG %EAX,%ECX
if (merge_expr_JIT(*pRes, (unsigned char[]) { 0x50 }, 1, lResRight, (unsigned char[]) { 0x59, 0x21, 0xC1 }, 3) != 0) { // PUSH %EAX POP %ECX AND %EAX,%ECX
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(1);
}
} else {
if (set_expr_JIT(*pRes, (unsigned char[]) { 0x25 }, 1, & lResRightValue, NULL, 0) != 0) { // AND %EAX, <int32 value>
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(1);
}
}
break;
case OR:
if (pExpr->left == NULL || pExpr->right == NULL) {
printf("Expr or value missing ...\n");
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(2);
}
if (lResLeft != NULL) {
if (merge_expr_JIT(*pRes, NULL, 0, lResLeft, NULL, 0) != 0) {
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(1);
}
} else {
if (set_expr_JIT(*pRes, (unsigned char[]) { 0xB8 }, 1, & lResLeftValue, NULL, 0) != 0) { // MOVL <int32 value>, %EAX
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(1);
}
}
if (lResRight != NULL) { // 0x91 XCHG %EAX,%ECX
if (merge_expr_JIT(*pRes, (unsigned char[]) { 0x50 }, 1, lResRight, (unsigned char[]) { 0x59, 0x09, 0xC1 }, 3) != 0) { // PUSH %EAX POP %ECX OR %EAX,%ECX
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(1);
}
} else {
if (set_expr_JIT(*pRes, (unsigned char[]) { 0x0D }, 1, & lResRightValue, NULL, 0) != 0) { // OR %EAX, <int32 value>
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(1);
}
}
break;
case NOT:
if (pExpr->right == NULL) {
printf("Expr or value missing ...\n");
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(2);
}
if (lResRight != NULL) {
if (merge_expr_JIT(*pRes, NULL, 0, lResRight, (unsigned char[]) { 0xF7, 0xD0, 0x25, 0x01, 0x00, 0x00, 0x00 }, 7) != 0) { // NOT %EAX AND %EAX,1
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(1);
}
} else {
if (set_expr_JIT(*pRes, (unsigned char[]) { 0xB8 }, 1, & lResRightValue, (unsigned char[]) { 0xF7, 0xD0, 0x25, 0x01, 0x00, 0x00, 0x00 }, 7) != 0) { // MOV %EAX, <int32 value> NOT %EAX
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(1);
}
}
break;
case BNOT:
if (pExpr->right == NULL) {
printf("Expr or value missing ...\n");
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(2);
}
if (lResRight != NULL) {
if (merge_expr_JIT(*pRes, NULL, 0, lResRight, (unsigned char[]) { 0xF7, 0xD0 }, 2) != 0) { // NOT %EAX
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(1);
}
} else {
if (set_expr_JIT(*pRes, (unsigned char[]) { 0xB8 }, 1, & lResRightValue, (unsigned char[]) { 0xF7, 0xD0 }, 2) != 0) { // MOV %EAX, <int32 value> NOT %EAX
free_expr_JIT(lResLeft); free_expr_JIT(lResRight); free_expr_JIT(*pRes);
return(1);
}
}
break;
};
if (lResLeft != NULL) free_expr_JIT(lResLeft);
if (lResRight != NULL) free_expr_JIT(lResRight);
return(0);
}
int dump_expr_JIT(struct s_expr_JIT* pExpr) {
unsigned char* lOffset;
int lSize;
if (pExpr != NULL) {
lOffset = pExpr->JIT;
lSize = pExpr->size;
while (lSize > 0) {
printf("%02X", lOffset[0]);
lOffset++;
lSize--;
if (lSize > 0) printf(" ");
}
}
return(0);
}
int exec_expr_JIT(struct s_expr_JIT* pExpr, int* pRes) {
unsigned char* lOffset;
int (*lJit)();
if (pRes == NULL) return(1);
if (pExpr != NULL) {
#ifdef _MSC_VER
HANDLE lHandle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE | SEC_COMMIT, 0, pExpr->size + 10, NULL);
if (lHandle == NULL) {
perror("Mapping failed...");
return 1;
}
lOffset = (unsigned char*)MapViewOfFile(lHandle, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, pExpr->size + 10);
if (lOffset == NULL) {
perror("Mapping failed...");
return 1;
}
#else
lOffset = (unsigned char*)mmap(NULL, pExpr->size + 10, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
if (lOffset == MAP_FAILED) {
perror("Mapping failed...");
return 1;
}
#endif
lOffset[0] = 0x55; // PUSH %EBP
lOffset[1] = 0x48; // MOV %ESP, %EBP
lOffset[2] = 0x89;
lOffset[3] = 0xE5;
lOffset[4] = 0x9C; // PUSHFD
lOffset[5] = 0x51; // PUSH %ECX
if (memcpy(&lOffset[6], pExpr->JIT, pExpr->size) == NULL) {
#ifdef _MSC_VER
if (!UnmapViewOfFile(lOffset)) {
perror("Unmapping failed...");
return 1;
}
CloseHandle(lHandle);
#else
if (munmap(lOffset, pExpr->size + 10) != 0) {
perror("Unmapping failed...");
return 1;
}
#endif
return(1);
}
lOffset[pExpr->size + 6] = 0x59; // POP %ECX
lOffset[pExpr->size + 7] = 0x9D; // POPF
lOffset[pExpr->size + 8] = 0xC9; // LEAVE
lOffset[pExpr->size + 9] = 0xC3; // RETF
lJit = (int (*)())lOffset;
*pRes = lJit();
#ifdef _MSC_VER
if (!UnmapViewOfFile(lOffset)) {
perror("Unmapping failed...");
return 1;
}
CloseHandle(lHandle);
#else
if (munmap(lOffset, pExpr->size + 10) != 0) {
perror("Unmapping failed...");
return 1;
}
#endif
}
return(0);
}
int parse(char* pExpr, int* pRes) {
// Decomposing pExpr in tree form
struct s_expr* lRoot = parse_tree(&pExpr);
int lRes = 0;
if (lRoot == NULL) return(1);
display_expr(lRoot);
printf("\n");
if (eval_expr(lRoot, &lRes) == 0) {
printf(" => %d\n", lRes);
} else {
printf(" Error in expr...\n");
}
struct s_expr_JIT* lCompile;
if (compile_expr(lRoot, &lCompile) == 0) {
printf("Compiled: %d [", lCompile->size);
dump_expr_JIT(lCompile);
printf("]\n");
if (exec_expr_JIT(lCompile, &lRes) == 0) {
printf("Res JIT : %d\n", lRes);
} else {
printf("Failed to exec JIT..\n");
}
free_expr_JIT(lCompile);
}
free_expr(lRoot);
return(0);
}
int main(int nbargs, char* args[]) {
int lRes = 0;
if (nbargs > 0) parse(args[1], &lRes);
return(0);
}