From: Peter Johnson Date: Mon, 15 Oct 2001 07:04:01 +0000 (-0000) Subject: Add _copy() constructor. X-Git-Tag: v0.1.0~246 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6a7504341fcf28a63e9d8d048f7e80bcfc2ff5a0;p=yasm Add _copy() constructor. Add expr_expand_equ(). svn path=/trunk/yasm/; revision=284 --- diff --git a/libyasm/expr.c b/libyasm/expr.c index f4ac1394..49521ee4 100644 --- a/libyasm/expr.c +++ b/libyasm/expr.c @@ -83,8 +83,8 @@ struct expr { static int expr_traverse_nodes_post(expr *e, void *d, int (*func) (expr *e, void *d)); -static int expr_traverse_leaves_in(const expr *e, void *d, - int (*func) (const ExprItem *ei, void *d)); +static int expr_traverse_leaves_in(expr *e, void *d, + int (*func) (ExprItem *ei, void *d)); /* allocate a new expression node, with children as defined. * If it's a unary operator, put the element on the right */ @@ -162,6 +162,51 @@ ExprReg(unsigned char reg, unsigned char size) return e; } +static void +expr_copy_side(ExprItem *dest, const ExprItem *ei) +{ + dest->type = ei->type; + switch (ei->type) { + case EXPR_SYM: + dest->data.sym = ei->data.sym; + break; + case EXPR_EXPR: + dest->data.expn = expr_copy(ei->data.expn); + break; + case EXPR_INT: + dest->data.intn = intnum_copy(ei->data.intn); + break; + case EXPR_FLOAT: + dest->data.flt = floatnum_copy(ei->data.flt); + break; + case EXPR_REG: + dest->data.reg.num = ei->data.reg.num; + dest->data.reg.size = ei->data.reg.size; + break; + default: + break; + } +} + +expr * +expr_copy(const expr *e) +{ + expr *n; + + if (!e) + return 0; + + n = xmalloc(sizeof(expr)); + + expr_copy_side(&n->left, &e->left); + expr_copy_side(&n->right, &e->right); + n->op = e->op; + n->filename = xstrdup(e->filename); + n->line = e->line; + + return n; +} + static int expr_delete_each(expr *e, void *d) { @@ -197,13 +242,13 @@ expr_delete(expr *e) } static int -expr_contains_float_callback(const ExprItem *ei, void *d) +expr_contains_float_callback(ExprItem *ei, void *d) { return (ei->type == EXPR_FLOAT); } int -expr_contains_float(const expr *e) +expr_contains_float(expr *e) { return expr_traverse_leaves_in(e, NULL, expr_contains_float_callback); } @@ -300,7 +345,7 @@ expr_checkea_invalid16_callback(expr *e, void *d) } static int -expr_checkea_getregsize_callback(const ExprItem *ei, void *d) +expr_checkea_getregsize_callback(ExprItem *ei, void *d) { unsigned char *addrsize = (unsigned char *)d; @@ -490,6 +535,26 @@ expr_checkea(expr **e, unsigned char *addrsize, unsigned char bits, return 1; } +static int +expr_expand_equ_callback(ExprItem *ei, void *d) +{ + const expr *equ_expr; + if (ei->type == EXPR_SYM) { + equ_expr = symrec_get_equ(ei->data.sym); + if (equ_expr) { + ei->type = EXPR_EXPR; + ei->data.expn = expr_copy(equ_expr); + } + } + return 0; +} + +void +expr_expand_equ(expr *e) +{ + expr_traverse_leaves_in(e, NULL, expr_expand_equ_callback); +} + /* Traverse over expression tree, calling func for each operation AFTER the * two branches (if expressions) have been traversed (eg, postorder * traversal). The data pointer d is passed to each func call. @@ -522,40 +587,25 @@ expr_traverse_nodes_post(expr *e, void *d, int (*func) (expr *e, void *d)) * Stops early (and returns 1) if func returns 1. Otherwise returns 0. */ static int -expr_traverse_leaves_in(const expr *e, void *d, - int (*func) (const ExprItem *ei, void *d)) +expr_traverse_leaves_in(expr *e, void *d, + int (*func) (ExprItem *ei, void *d)) { if (!e) return 0; - switch (e->left.type) { - case EXPR_SYM: - if (expr_traverse_leaves_in(symrec_get_equ(e->left.data.sym), d, - func)) - return 1; - break; - case EXPR_EXPR: - if (expr_traverse_leaves_in(e->left.data.expn, d, func)) - return 1; - break; - default: - if (func(&e->left, d)) - return 1; + if (e->left.type == EXPR_EXPR) { + if (expr_traverse_leaves_in(e->left.data.expn, d, func)) + return 1; + } else { + if (func(&e->left, d)) + return 1; } - switch (e->right.type) { - case EXPR_SYM: - if (expr_traverse_leaves_in(symrec_get_equ(e->right.data.sym), d, - func)) - return 1; - break; - case EXPR_EXPR: - if (expr_traverse_leaves_in(e->right.data.expn, d, func)) - return 1; - break; - default: - return func(&e->right, d); - } + if (e->right.type == EXPR_EXPR) { + if (expr_traverse_leaves_in(e->right.data.expn, d, func)) + return 1; + } else + return func(&e->right, d); return 0; } diff --git a/libyasm/expr.h b/libyasm/expr.h index 5ce86f72..18de1391 100644 --- a/libyasm/expr.h +++ b/libyasm/expr.h @@ -89,9 +89,12 @@ ExprItem *ExprReg(unsigned char reg, unsigned char size); #define expr_new_ident(r) \ expr_new ((ExprItem *)NULL, EXPR_IDENT, (r)) +/* allocates and makes an exact duplicate of e */ +expr *expr_copy(const expr *e); + void expr_delete(expr *e); -int expr_contains_float(const expr *); +int expr_contains_float(expr *); int expr_checkea(expr **e, unsigned char *addrsize, unsigned char bits, unsigned char *displen, unsigned char *modrm, @@ -99,6 +102,11 @@ int expr_checkea(expr **e, unsigned char *addrsize, unsigned char bits, unsigned char *sib, unsigned char *v_sib, unsigned char *n_sib); +/* Expands all (symrec) equ's in the expression into full expression + * instances. + */ +void expr_expand_equ(expr *e); + /* Simplifies the expression e as much as possible, eliminating extraneous * branches and simplifying integer-only subexpressions. */ diff --git a/libyasm/floatnum.c b/libyasm/floatnum.c index 103e569e..2c1075f1 100644 --- a/libyasm/floatnum.c +++ b/libyasm/floatnum.c @@ -477,6 +477,19 @@ floatnum_new(const char *str) return flt; } +floatnum * +floatnum_copy(const floatnum *flt) +{ + floatnum *f = xmalloc(sizeof(floatnum)); + + f->mantissa = BitVector_Clone(flt->mantissa); + f->exponent = flt->exponent; + f->sign = flt->sign; + f->flags = flt->flags; + + return f; +} + void floatnum_delete(floatnum *flt) { diff --git a/libyasm/floatnum.h b/libyasm/floatnum.h index 1e138951..cf265b2a 100644 --- a/libyasm/floatnum.h +++ b/libyasm/floatnum.h @@ -60,6 +60,7 @@ typedef struct floatnum floatnum; #endif floatnum *floatnum_new(const char *str); +floatnum *floatnum_copy(const floatnum *flt); void floatnum_delete(floatnum *flt); /* calculation function: acc = acc op operand */ diff --git a/libyasm/intnum.c b/libyasm/intnum.c index 0826a7ae..1d6c9fb4 100644 --- a/libyasm/intnum.c +++ b/libyasm/intnum.c @@ -195,6 +195,25 @@ intnum_new_int(unsigned long i) return intn; } +intnum * +intnum_copy(const intnum *intn) +{ + intnum *n = xmalloc(sizeof(intnum)); + + switch (intn->type) { + case INTNUM_UL: + n->val.ul = intn->val.ul; + break; + case INTNUM_BV: + n->val.bv = BitVector_Clone(intn->val.bv); + break; + } + n->type = intn->type; + n->origsize = intn->origsize; + + return n; +} + void intnum_delete(intnum *intn) { diff --git a/libyasm/intnum.h b/libyasm/intnum.h index 38f3248e..5aec7389 100644 --- a/libyasm/intnum.h +++ b/libyasm/intnum.h @@ -64,6 +64,7 @@ intnum *intnum_new_hex(char *str); /* convert character constant to integer value, using NASM rules */ intnum *intnum_new_charconst_nasm(const char *str); intnum *intnum_new_int(unsigned long i); +intnum *intnum_copy(const intnum *intn); void intnum_delete(intnum *intn); /* calculation function: acc = acc op operand */ diff --git a/modules/arch/x86/expr.c b/modules/arch/x86/expr.c index f4ac1394..49521ee4 100644 --- a/modules/arch/x86/expr.c +++ b/modules/arch/x86/expr.c @@ -83,8 +83,8 @@ struct expr { static int expr_traverse_nodes_post(expr *e, void *d, int (*func) (expr *e, void *d)); -static int expr_traverse_leaves_in(const expr *e, void *d, - int (*func) (const ExprItem *ei, void *d)); +static int expr_traverse_leaves_in(expr *e, void *d, + int (*func) (ExprItem *ei, void *d)); /* allocate a new expression node, with children as defined. * If it's a unary operator, put the element on the right */ @@ -162,6 +162,51 @@ ExprReg(unsigned char reg, unsigned char size) return e; } +static void +expr_copy_side(ExprItem *dest, const ExprItem *ei) +{ + dest->type = ei->type; + switch (ei->type) { + case EXPR_SYM: + dest->data.sym = ei->data.sym; + break; + case EXPR_EXPR: + dest->data.expn = expr_copy(ei->data.expn); + break; + case EXPR_INT: + dest->data.intn = intnum_copy(ei->data.intn); + break; + case EXPR_FLOAT: + dest->data.flt = floatnum_copy(ei->data.flt); + break; + case EXPR_REG: + dest->data.reg.num = ei->data.reg.num; + dest->data.reg.size = ei->data.reg.size; + break; + default: + break; + } +} + +expr * +expr_copy(const expr *e) +{ + expr *n; + + if (!e) + return 0; + + n = xmalloc(sizeof(expr)); + + expr_copy_side(&n->left, &e->left); + expr_copy_side(&n->right, &e->right); + n->op = e->op; + n->filename = xstrdup(e->filename); + n->line = e->line; + + return n; +} + static int expr_delete_each(expr *e, void *d) { @@ -197,13 +242,13 @@ expr_delete(expr *e) } static int -expr_contains_float_callback(const ExprItem *ei, void *d) +expr_contains_float_callback(ExprItem *ei, void *d) { return (ei->type == EXPR_FLOAT); } int -expr_contains_float(const expr *e) +expr_contains_float(expr *e) { return expr_traverse_leaves_in(e, NULL, expr_contains_float_callback); } @@ -300,7 +345,7 @@ expr_checkea_invalid16_callback(expr *e, void *d) } static int -expr_checkea_getregsize_callback(const ExprItem *ei, void *d) +expr_checkea_getregsize_callback(ExprItem *ei, void *d) { unsigned char *addrsize = (unsigned char *)d; @@ -490,6 +535,26 @@ expr_checkea(expr **e, unsigned char *addrsize, unsigned char bits, return 1; } +static int +expr_expand_equ_callback(ExprItem *ei, void *d) +{ + const expr *equ_expr; + if (ei->type == EXPR_SYM) { + equ_expr = symrec_get_equ(ei->data.sym); + if (equ_expr) { + ei->type = EXPR_EXPR; + ei->data.expn = expr_copy(equ_expr); + } + } + return 0; +} + +void +expr_expand_equ(expr *e) +{ + expr_traverse_leaves_in(e, NULL, expr_expand_equ_callback); +} + /* Traverse over expression tree, calling func for each operation AFTER the * two branches (if expressions) have been traversed (eg, postorder * traversal). The data pointer d is passed to each func call. @@ -522,40 +587,25 @@ expr_traverse_nodes_post(expr *e, void *d, int (*func) (expr *e, void *d)) * Stops early (and returns 1) if func returns 1. Otherwise returns 0. */ static int -expr_traverse_leaves_in(const expr *e, void *d, - int (*func) (const ExprItem *ei, void *d)) +expr_traverse_leaves_in(expr *e, void *d, + int (*func) (ExprItem *ei, void *d)) { if (!e) return 0; - switch (e->left.type) { - case EXPR_SYM: - if (expr_traverse_leaves_in(symrec_get_equ(e->left.data.sym), d, - func)) - return 1; - break; - case EXPR_EXPR: - if (expr_traverse_leaves_in(e->left.data.expn, d, func)) - return 1; - break; - default: - if (func(&e->left, d)) - return 1; + if (e->left.type == EXPR_EXPR) { + if (expr_traverse_leaves_in(e->left.data.expn, d, func)) + return 1; + } else { + if (func(&e->left, d)) + return 1; } - switch (e->right.type) { - case EXPR_SYM: - if (expr_traverse_leaves_in(symrec_get_equ(e->right.data.sym), d, - func)) - return 1; - break; - case EXPR_EXPR: - if (expr_traverse_leaves_in(e->right.data.expn, d, func)) - return 1; - break; - default: - return func(&e->right, d); - } + if (e->right.type == EXPR_EXPR) { + if (expr_traverse_leaves_in(e->right.data.expn, d, func)) + return 1; + } else + return func(&e->right, d); return 0; } diff --git a/modules/arch/x86/x86expr.c b/modules/arch/x86/x86expr.c index f4ac1394..49521ee4 100644 --- a/modules/arch/x86/x86expr.c +++ b/modules/arch/x86/x86expr.c @@ -83,8 +83,8 @@ struct expr { static int expr_traverse_nodes_post(expr *e, void *d, int (*func) (expr *e, void *d)); -static int expr_traverse_leaves_in(const expr *e, void *d, - int (*func) (const ExprItem *ei, void *d)); +static int expr_traverse_leaves_in(expr *e, void *d, + int (*func) (ExprItem *ei, void *d)); /* allocate a new expression node, with children as defined. * If it's a unary operator, put the element on the right */ @@ -162,6 +162,51 @@ ExprReg(unsigned char reg, unsigned char size) return e; } +static void +expr_copy_side(ExprItem *dest, const ExprItem *ei) +{ + dest->type = ei->type; + switch (ei->type) { + case EXPR_SYM: + dest->data.sym = ei->data.sym; + break; + case EXPR_EXPR: + dest->data.expn = expr_copy(ei->data.expn); + break; + case EXPR_INT: + dest->data.intn = intnum_copy(ei->data.intn); + break; + case EXPR_FLOAT: + dest->data.flt = floatnum_copy(ei->data.flt); + break; + case EXPR_REG: + dest->data.reg.num = ei->data.reg.num; + dest->data.reg.size = ei->data.reg.size; + break; + default: + break; + } +} + +expr * +expr_copy(const expr *e) +{ + expr *n; + + if (!e) + return 0; + + n = xmalloc(sizeof(expr)); + + expr_copy_side(&n->left, &e->left); + expr_copy_side(&n->right, &e->right); + n->op = e->op; + n->filename = xstrdup(e->filename); + n->line = e->line; + + return n; +} + static int expr_delete_each(expr *e, void *d) { @@ -197,13 +242,13 @@ expr_delete(expr *e) } static int -expr_contains_float_callback(const ExprItem *ei, void *d) +expr_contains_float_callback(ExprItem *ei, void *d) { return (ei->type == EXPR_FLOAT); } int -expr_contains_float(const expr *e) +expr_contains_float(expr *e) { return expr_traverse_leaves_in(e, NULL, expr_contains_float_callback); } @@ -300,7 +345,7 @@ expr_checkea_invalid16_callback(expr *e, void *d) } static int -expr_checkea_getregsize_callback(const ExprItem *ei, void *d) +expr_checkea_getregsize_callback(ExprItem *ei, void *d) { unsigned char *addrsize = (unsigned char *)d; @@ -490,6 +535,26 @@ expr_checkea(expr **e, unsigned char *addrsize, unsigned char bits, return 1; } +static int +expr_expand_equ_callback(ExprItem *ei, void *d) +{ + const expr *equ_expr; + if (ei->type == EXPR_SYM) { + equ_expr = symrec_get_equ(ei->data.sym); + if (equ_expr) { + ei->type = EXPR_EXPR; + ei->data.expn = expr_copy(equ_expr); + } + } + return 0; +} + +void +expr_expand_equ(expr *e) +{ + expr_traverse_leaves_in(e, NULL, expr_expand_equ_callback); +} + /* Traverse over expression tree, calling func for each operation AFTER the * two branches (if expressions) have been traversed (eg, postorder * traversal). The data pointer d is passed to each func call. @@ -522,40 +587,25 @@ expr_traverse_nodes_post(expr *e, void *d, int (*func) (expr *e, void *d)) * Stops early (and returns 1) if func returns 1. Otherwise returns 0. */ static int -expr_traverse_leaves_in(const expr *e, void *d, - int (*func) (const ExprItem *ei, void *d)) +expr_traverse_leaves_in(expr *e, void *d, + int (*func) (ExprItem *ei, void *d)) { if (!e) return 0; - switch (e->left.type) { - case EXPR_SYM: - if (expr_traverse_leaves_in(symrec_get_equ(e->left.data.sym), d, - func)) - return 1; - break; - case EXPR_EXPR: - if (expr_traverse_leaves_in(e->left.data.expn, d, func)) - return 1; - break; - default: - if (func(&e->left, d)) - return 1; + if (e->left.type == EXPR_EXPR) { + if (expr_traverse_leaves_in(e->left.data.expn, d, func)) + return 1; + } else { + if (func(&e->left, d)) + return 1; } - switch (e->right.type) { - case EXPR_SYM: - if (expr_traverse_leaves_in(symrec_get_equ(e->right.data.sym), d, - func)) - return 1; - break; - case EXPR_EXPR: - if (expr_traverse_leaves_in(e->right.data.expn, d, func)) - return 1; - break; - default: - return func(&e->right, d); - } + if (e->right.type == EXPR_EXPR) { + if (expr_traverse_leaves_in(e->right.data.expn, d, func)) + return 1; + } else + return func(&e->right, d); return 0; } diff --git a/src/arch/x86/expr.c b/src/arch/x86/expr.c index f4ac1394..49521ee4 100644 --- a/src/arch/x86/expr.c +++ b/src/arch/x86/expr.c @@ -83,8 +83,8 @@ struct expr { static int expr_traverse_nodes_post(expr *e, void *d, int (*func) (expr *e, void *d)); -static int expr_traverse_leaves_in(const expr *e, void *d, - int (*func) (const ExprItem *ei, void *d)); +static int expr_traverse_leaves_in(expr *e, void *d, + int (*func) (ExprItem *ei, void *d)); /* allocate a new expression node, with children as defined. * If it's a unary operator, put the element on the right */ @@ -162,6 +162,51 @@ ExprReg(unsigned char reg, unsigned char size) return e; } +static void +expr_copy_side(ExprItem *dest, const ExprItem *ei) +{ + dest->type = ei->type; + switch (ei->type) { + case EXPR_SYM: + dest->data.sym = ei->data.sym; + break; + case EXPR_EXPR: + dest->data.expn = expr_copy(ei->data.expn); + break; + case EXPR_INT: + dest->data.intn = intnum_copy(ei->data.intn); + break; + case EXPR_FLOAT: + dest->data.flt = floatnum_copy(ei->data.flt); + break; + case EXPR_REG: + dest->data.reg.num = ei->data.reg.num; + dest->data.reg.size = ei->data.reg.size; + break; + default: + break; + } +} + +expr * +expr_copy(const expr *e) +{ + expr *n; + + if (!e) + return 0; + + n = xmalloc(sizeof(expr)); + + expr_copy_side(&n->left, &e->left); + expr_copy_side(&n->right, &e->right); + n->op = e->op; + n->filename = xstrdup(e->filename); + n->line = e->line; + + return n; +} + static int expr_delete_each(expr *e, void *d) { @@ -197,13 +242,13 @@ expr_delete(expr *e) } static int -expr_contains_float_callback(const ExprItem *ei, void *d) +expr_contains_float_callback(ExprItem *ei, void *d) { return (ei->type == EXPR_FLOAT); } int -expr_contains_float(const expr *e) +expr_contains_float(expr *e) { return expr_traverse_leaves_in(e, NULL, expr_contains_float_callback); } @@ -300,7 +345,7 @@ expr_checkea_invalid16_callback(expr *e, void *d) } static int -expr_checkea_getregsize_callback(const ExprItem *ei, void *d) +expr_checkea_getregsize_callback(ExprItem *ei, void *d) { unsigned char *addrsize = (unsigned char *)d; @@ -490,6 +535,26 @@ expr_checkea(expr **e, unsigned char *addrsize, unsigned char bits, return 1; } +static int +expr_expand_equ_callback(ExprItem *ei, void *d) +{ + const expr *equ_expr; + if (ei->type == EXPR_SYM) { + equ_expr = symrec_get_equ(ei->data.sym); + if (equ_expr) { + ei->type = EXPR_EXPR; + ei->data.expn = expr_copy(equ_expr); + } + } + return 0; +} + +void +expr_expand_equ(expr *e) +{ + expr_traverse_leaves_in(e, NULL, expr_expand_equ_callback); +} + /* Traverse over expression tree, calling func for each operation AFTER the * two branches (if expressions) have been traversed (eg, postorder * traversal). The data pointer d is passed to each func call. @@ -522,40 +587,25 @@ expr_traverse_nodes_post(expr *e, void *d, int (*func) (expr *e, void *d)) * Stops early (and returns 1) if func returns 1. Otherwise returns 0. */ static int -expr_traverse_leaves_in(const expr *e, void *d, - int (*func) (const ExprItem *ei, void *d)) +expr_traverse_leaves_in(expr *e, void *d, + int (*func) (ExprItem *ei, void *d)) { if (!e) return 0; - switch (e->left.type) { - case EXPR_SYM: - if (expr_traverse_leaves_in(symrec_get_equ(e->left.data.sym), d, - func)) - return 1; - break; - case EXPR_EXPR: - if (expr_traverse_leaves_in(e->left.data.expn, d, func)) - return 1; - break; - default: - if (func(&e->left, d)) - return 1; + if (e->left.type == EXPR_EXPR) { + if (expr_traverse_leaves_in(e->left.data.expn, d, func)) + return 1; + } else { + if (func(&e->left, d)) + return 1; } - switch (e->right.type) { - case EXPR_SYM: - if (expr_traverse_leaves_in(symrec_get_equ(e->right.data.sym), d, - func)) - return 1; - break; - case EXPR_EXPR: - if (expr_traverse_leaves_in(e->right.data.expn, d, func)) - return 1; - break; - default: - return func(&e->right, d); - } + if (e->right.type == EXPR_EXPR) { + if (expr_traverse_leaves_in(e->right.data.expn, d, func)) + return 1; + } else + return func(&e->right, d); return 0; } diff --git a/src/arch/x86/x86expr.c b/src/arch/x86/x86expr.c index f4ac1394..49521ee4 100644 --- a/src/arch/x86/x86expr.c +++ b/src/arch/x86/x86expr.c @@ -83,8 +83,8 @@ struct expr { static int expr_traverse_nodes_post(expr *e, void *d, int (*func) (expr *e, void *d)); -static int expr_traverse_leaves_in(const expr *e, void *d, - int (*func) (const ExprItem *ei, void *d)); +static int expr_traverse_leaves_in(expr *e, void *d, + int (*func) (ExprItem *ei, void *d)); /* allocate a new expression node, with children as defined. * If it's a unary operator, put the element on the right */ @@ -162,6 +162,51 @@ ExprReg(unsigned char reg, unsigned char size) return e; } +static void +expr_copy_side(ExprItem *dest, const ExprItem *ei) +{ + dest->type = ei->type; + switch (ei->type) { + case EXPR_SYM: + dest->data.sym = ei->data.sym; + break; + case EXPR_EXPR: + dest->data.expn = expr_copy(ei->data.expn); + break; + case EXPR_INT: + dest->data.intn = intnum_copy(ei->data.intn); + break; + case EXPR_FLOAT: + dest->data.flt = floatnum_copy(ei->data.flt); + break; + case EXPR_REG: + dest->data.reg.num = ei->data.reg.num; + dest->data.reg.size = ei->data.reg.size; + break; + default: + break; + } +} + +expr * +expr_copy(const expr *e) +{ + expr *n; + + if (!e) + return 0; + + n = xmalloc(sizeof(expr)); + + expr_copy_side(&n->left, &e->left); + expr_copy_side(&n->right, &e->right); + n->op = e->op; + n->filename = xstrdup(e->filename); + n->line = e->line; + + return n; +} + static int expr_delete_each(expr *e, void *d) { @@ -197,13 +242,13 @@ expr_delete(expr *e) } static int -expr_contains_float_callback(const ExprItem *ei, void *d) +expr_contains_float_callback(ExprItem *ei, void *d) { return (ei->type == EXPR_FLOAT); } int -expr_contains_float(const expr *e) +expr_contains_float(expr *e) { return expr_traverse_leaves_in(e, NULL, expr_contains_float_callback); } @@ -300,7 +345,7 @@ expr_checkea_invalid16_callback(expr *e, void *d) } static int -expr_checkea_getregsize_callback(const ExprItem *ei, void *d) +expr_checkea_getregsize_callback(ExprItem *ei, void *d) { unsigned char *addrsize = (unsigned char *)d; @@ -490,6 +535,26 @@ expr_checkea(expr **e, unsigned char *addrsize, unsigned char bits, return 1; } +static int +expr_expand_equ_callback(ExprItem *ei, void *d) +{ + const expr *equ_expr; + if (ei->type == EXPR_SYM) { + equ_expr = symrec_get_equ(ei->data.sym); + if (equ_expr) { + ei->type = EXPR_EXPR; + ei->data.expn = expr_copy(equ_expr); + } + } + return 0; +} + +void +expr_expand_equ(expr *e) +{ + expr_traverse_leaves_in(e, NULL, expr_expand_equ_callback); +} + /* Traverse over expression tree, calling func for each operation AFTER the * two branches (if expressions) have been traversed (eg, postorder * traversal). The data pointer d is passed to each func call. @@ -522,40 +587,25 @@ expr_traverse_nodes_post(expr *e, void *d, int (*func) (expr *e, void *d)) * Stops early (and returns 1) if func returns 1. Otherwise returns 0. */ static int -expr_traverse_leaves_in(const expr *e, void *d, - int (*func) (const ExprItem *ei, void *d)) +expr_traverse_leaves_in(expr *e, void *d, + int (*func) (ExprItem *ei, void *d)) { if (!e) return 0; - switch (e->left.type) { - case EXPR_SYM: - if (expr_traverse_leaves_in(symrec_get_equ(e->left.data.sym), d, - func)) - return 1; - break; - case EXPR_EXPR: - if (expr_traverse_leaves_in(e->left.data.expn, d, func)) - return 1; - break; - default: - if (func(&e->left, d)) - return 1; + if (e->left.type == EXPR_EXPR) { + if (expr_traverse_leaves_in(e->left.data.expn, d, func)) + return 1; + } else { + if (func(&e->left, d)) + return 1; } - switch (e->right.type) { - case EXPR_SYM: - if (expr_traverse_leaves_in(symrec_get_equ(e->right.data.sym), d, - func)) - return 1; - break; - case EXPR_EXPR: - if (expr_traverse_leaves_in(e->right.data.expn, d, func)) - return 1; - break; - default: - return func(&e->right, d); - } + if (e->right.type == EXPR_EXPR) { + if (expr_traverse_leaves_in(e->right.data.expn, d, func)) + return 1; + } else + return func(&e->right, d); return 0; } diff --git a/src/expr.c b/src/expr.c index f4ac1394..49521ee4 100644 --- a/src/expr.c +++ b/src/expr.c @@ -83,8 +83,8 @@ struct expr { static int expr_traverse_nodes_post(expr *e, void *d, int (*func) (expr *e, void *d)); -static int expr_traverse_leaves_in(const expr *e, void *d, - int (*func) (const ExprItem *ei, void *d)); +static int expr_traverse_leaves_in(expr *e, void *d, + int (*func) (ExprItem *ei, void *d)); /* allocate a new expression node, with children as defined. * If it's a unary operator, put the element on the right */ @@ -162,6 +162,51 @@ ExprReg(unsigned char reg, unsigned char size) return e; } +static void +expr_copy_side(ExprItem *dest, const ExprItem *ei) +{ + dest->type = ei->type; + switch (ei->type) { + case EXPR_SYM: + dest->data.sym = ei->data.sym; + break; + case EXPR_EXPR: + dest->data.expn = expr_copy(ei->data.expn); + break; + case EXPR_INT: + dest->data.intn = intnum_copy(ei->data.intn); + break; + case EXPR_FLOAT: + dest->data.flt = floatnum_copy(ei->data.flt); + break; + case EXPR_REG: + dest->data.reg.num = ei->data.reg.num; + dest->data.reg.size = ei->data.reg.size; + break; + default: + break; + } +} + +expr * +expr_copy(const expr *e) +{ + expr *n; + + if (!e) + return 0; + + n = xmalloc(sizeof(expr)); + + expr_copy_side(&n->left, &e->left); + expr_copy_side(&n->right, &e->right); + n->op = e->op; + n->filename = xstrdup(e->filename); + n->line = e->line; + + return n; +} + static int expr_delete_each(expr *e, void *d) { @@ -197,13 +242,13 @@ expr_delete(expr *e) } static int -expr_contains_float_callback(const ExprItem *ei, void *d) +expr_contains_float_callback(ExprItem *ei, void *d) { return (ei->type == EXPR_FLOAT); } int -expr_contains_float(const expr *e) +expr_contains_float(expr *e) { return expr_traverse_leaves_in(e, NULL, expr_contains_float_callback); } @@ -300,7 +345,7 @@ expr_checkea_invalid16_callback(expr *e, void *d) } static int -expr_checkea_getregsize_callback(const ExprItem *ei, void *d) +expr_checkea_getregsize_callback(ExprItem *ei, void *d) { unsigned char *addrsize = (unsigned char *)d; @@ -490,6 +535,26 @@ expr_checkea(expr **e, unsigned char *addrsize, unsigned char bits, return 1; } +static int +expr_expand_equ_callback(ExprItem *ei, void *d) +{ + const expr *equ_expr; + if (ei->type == EXPR_SYM) { + equ_expr = symrec_get_equ(ei->data.sym); + if (equ_expr) { + ei->type = EXPR_EXPR; + ei->data.expn = expr_copy(equ_expr); + } + } + return 0; +} + +void +expr_expand_equ(expr *e) +{ + expr_traverse_leaves_in(e, NULL, expr_expand_equ_callback); +} + /* Traverse over expression tree, calling func for each operation AFTER the * two branches (if expressions) have been traversed (eg, postorder * traversal). The data pointer d is passed to each func call. @@ -522,40 +587,25 @@ expr_traverse_nodes_post(expr *e, void *d, int (*func) (expr *e, void *d)) * Stops early (and returns 1) if func returns 1. Otherwise returns 0. */ static int -expr_traverse_leaves_in(const expr *e, void *d, - int (*func) (const ExprItem *ei, void *d)) +expr_traverse_leaves_in(expr *e, void *d, + int (*func) (ExprItem *ei, void *d)) { if (!e) return 0; - switch (e->left.type) { - case EXPR_SYM: - if (expr_traverse_leaves_in(symrec_get_equ(e->left.data.sym), d, - func)) - return 1; - break; - case EXPR_EXPR: - if (expr_traverse_leaves_in(e->left.data.expn, d, func)) - return 1; - break; - default: - if (func(&e->left, d)) - return 1; + if (e->left.type == EXPR_EXPR) { + if (expr_traverse_leaves_in(e->left.data.expn, d, func)) + return 1; + } else { + if (func(&e->left, d)) + return 1; } - switch (e->right.type) { - case EXPR_SYM: - if (expr_traverse_leaves_in(symrec_get_equ(e->right.data.sym), d, - func)) - return 1; - break; - case EXPR_EXPR: - if (expr_traverse_leaves_in(e->right.data.expn, d, func)) - return 1; - break; - default: - return func(&e->right, d); - } + if (e->right.type == EXPR_EXPR) { + if (expr_traverse_leaves_in(e->right.data.expn, d, func)) + return 1; + } else + return func(&e->right, d); return 0; } diff --git a/src/expr.h b/src/expr.h index 5ce86f72..18de1391 100644 --- a/src/expr.h +++ b/src/expr.h @@ -89,9 +89,12 @@ ExprItem *ExprReg(unsigned char reg, unsigned char size); #define expr_new_ident(r) \ expr_new ((ExprItem *)NULL, EXPR_IDENT, (r)) +/* allocates and makes an exact duplicate of e */ +expr *expr_copy(const expr *e); + void expr_delete(expr *e); -int expr_contains_float(const expr *); +int expr_contains_float(expr *); int expr_checkea(expr **e, unsigned char *addrsize, unsigned char bits, unsigned char *displen, unsigned char *modrm, @@ -99,6 +102,11 @@ int expr_checkea(expr **e, unsigned char *addrsize, unsigned char bits, unsigned char *sib, unsigned char *v_sib, unsigned char *n_sib); +/* Expands all (symrec) equ's in the expression into full expression + * instances. + */ +void expr_expand_equ(expr *e); + /* Simplifies the expression e as much as possible, eliminating extraneous * branches and simplifying integer-only subexpressions. */ diff --git a/src/floatnum.c b/src/floatnum.c index 103e569e..2c1075f1 100644 --- a/src/floatnum.c +++ b/src/floatnum.c @@ -477,6 +477,19 @@ floatnum_new(const char *str) return flt; } +floatnum * +floatnum_copy(const floatnum *flt) +{ + floatnum *f = xmalloc(sizeof(floatnum)); + + f->mantissa = BitVector_Clone(flt->mantissa); + f->exponent = flt->exponent; + f->sign = flt->sign; + f->flags = flt->flags; + + return f; +} + void floatnum_delete(floatnum *flt) { diff --git a/src/floatnum.h b/src/floatnum.h index 1e138951..cf265b2a 100644 --- a/src/floatnum.h +++ b/src/floatnum.h @@ -60,6 +60,7 @@ typedef struct floatnum floatnum; #endif floatnum *floatnum_new(const char *str); +floatnum *floatnum_copy(const floatnum *flt); void floatnum_delete(floatnum *flt); /* calculation function: acc = acc op operand */ diff --git a/src/intnum.c b/src/intnum.c index 0826a7ae..1d6c9fb4 100644 --- a/src/intnum.c +++ b/src/intnum.c @@ -195,6 +195,25 @@ intnum_new_int(unsigned long i) return intn; } +intnum * +intnum_copy(const intnum *intn) +{ + intnum *n = xmalloc(sizeof(intnum)); + + switch (intn->type) { + case INTNUM_UL: + n->val.ul = intn->val.ul; + break; + case INTNUM_BV: + n->val.bv = BitVector_Clone(intn->val.bv); + break; + } + n->type = intn->type; + n->origsize = intn->origsize; + + return n; +} + void intnum_delete(intnum *intn) { diff --git a/src/intnum.h b/src/intnum.h index 38f3248e..5aec7389 100644 --- a/src/intnum.h +++ b/src/intnum.h @@ -64,6 +64,7 @@ intnum *intnum_new_hex(char *str); /* convert character constant to integer value, using NASM rules */ intnum *intnum_new_charconst_nasm(const char *str); intnum *intnum_new_int(unsigned long i); +intnum *intnum_copy(const intnum *intn); void intnum_delete(intnum *intn); /* calculation function: acc = acc op operand */