From ad54f1bf5c134e5858d14c51a132837c2792e7c1 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Wed, 10 May 2006 04:18:23 +0000 Subject: [PATCH] * bc-int.h (yasm_bytecode_callback): Add reserve flag to indicate if the bytecode outputs just space and not data. * bytecode.pxi: Update to match. * bytecode.c (yasm_bc_tobytes): Use reserve flag instead of checking against bytecode_reserve as special case. * dwarf2-info.c, dwarf2-line.c, dwarf2-dbgfmt.c, cv-symline.c, cv-type.c, * stabs-dbgfmt.c, lc3bbc.c, x86bc.c: Update to set reserve=0. * bc-align.c, bc-insn.c, bc-reserve.c, bc-org.c, bc-incbin.c, bc-data.c, * bytecode.c: Split out bytecodes into separate files. While we're here, merge LEB128 into general data bytecode. svn path=/trunk/yasm/; revision=1532 --- libyasm/Makefile.inc | 6 + libyasm/bc-align.c | 224 ++++ libyasm/bc-data.c | 457 ++++++++ libyasm/bc-incbin.c | 271 +++++ libyasm/bc-insn.c | 349 ++++++ libyasm/bc-int.h | 1 + libyasm/bc-org.c | 132 +++ libyasm/bc-reserve.c | 162 +++ libyasm/bytecode.c | 1399 +----------------------- modules/arch/lc3b/lc3bbc.c | 3 +- modules/arch/x86/x86bc.c | 9 +- modules/dbgfmts/codeview/cv-symline.c | 12 +- modules/dbgfmts/codeview/cv-type.c | 3 +- modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c | 3 +- modules/dbgfmts/dwarf2/dwarf2-info.c | 3 +- modules/dbgfmts/dwarf2/dwarf2-line.c | 6 +- modules/dbgfmts/stabs/stabs-dbgfmt.c | 6 +- tools/python-yasm/bytecode.pxi | 1 + 18 files changed, 1634 insertions(+), 1413 deletions(-) create mode 100644 libyasm/bc-align.c create mode 100644 libyasm/bc-data.c create mode 100644 libyasm/bc-incbin.c create mode 100644 libyasm/bc-insn.c create mode 100644 libyasm/bc-org.c create mode 100644 libyasm/bc-reserve.c diff --git a/libyasm/Makefile.inc b/libyasm/Makefile.inc index 105173cb..d411e71a 100644 --- a/libyasm/Makefile.inc +++ b/libyasm/Makefile.inc @@ -3,6 +3,12 @@ libyasm_a_SOURCES += libyasm/arch.c libyasm_a_SOURCES += libyasm/assocdat.c libyasm_a_SOURCES += libyasm/bitvect.c +libyasm_a_SOURCES += libyasm/bc-align.c +libyasm_a_SOURCES += libyasm/bc-data.c +libyasm_a_SOURCES += libyasm/bc-incbin.c +libyasm_a_SOURCES += libyasm/bc-insn.c +libyasm_a_SOURCES += libyasm/bc-org.c +libyasm_a_SOURCES += libyasm/bc-reserve.c libyasm_a_SOURCES += libyasm/bytecode.c libyasm_a_SOURCES += libyasm/errwarn.c libyasm_a_SOURCES += libyasm/expr.c diff --git a/libyasm/bc-align.c b/libyasm/bc-align.c new file mode 100644 index 00000000..ed2fab83 --- /dev/null +++ b/libyasm/bc-align.c @@ -0,0 +1,224 @@ +/* + * Align bytecode + * + * Copyright (C) 2005-2006 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#define YASM_LIB_INTERNAL +#include "util.h" +/*@unused@*/ RCSID("$Id$"); + +#include "coretype.h" + +#include "errwarn.h" +#include "intnum.h" +#include "expr.h" + +#include "bytecode.h" + +#include "bc-int.h" + + +typedef struct bytecode_align { + /*@only@*/ yasm_expr *boundary; /* alignment boundary */ + + /* What to fill intervening locations with, NULL if using code_fill */ + /*@only@*/ /*@null@*/ yasm_expr *fill; + + /* Maximum number of bytes to skip, NULL if no maximum. */ + /*@only@*/ /*@null@*/ yasm_expr *maxskip; + + /* Code fill, NULL if using 0 fill */ + /*@null@*/ const unsigned char **code_fill; +} bytecode_align; + +static void bc_align_destroy(void *contents); +static void bc_align_print(const void *contents, FILE *f, int indent_level); +static void bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc); +static yasm_bc_resolve_flags bc_align_resolve + (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist); +static int bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, + yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc); + +static const yasm_bytecode_callback bc_align_callback = { + bc_align_destroy, + bc_align_print, + bc_align_finalize, + bc_align_resolve, + bc_align_tobytes, + 0 +}; + + +static void +bc_align_destroy(void *contents) +{ + bytecode_align *align = (bytecode_align *)contents; + if (align->boundary) + yasm_expr_destroy(align->boundary); + if (align->fill) + yasm_expr_destroy(align->fill); + if (align->maxskip) + yasm_expr_destroy(align->maxskip); + yasm_xfree(contents); +} + +static void +bc_align_print(const void *contents, FILE *f, int indent_level) +{ + const bytecode_align *align = (const bytecode_align *)contents; + fprintf(f, "%*s_Align_\n", indent_level, ""); + fprintf(f, "%*sBoundary=", indent_level, ""); + yasm_expr_print(align->boundary, f); + fprintf(f, "\n%*sFill=", indent_level, ""); + yasm_expr_print(align->fill, f); + fprintf(f, "\n%*sMax Skip=", indent_level, ""); + yasm_expr_print(align->maxskip, f); + fprintf(f, "\n"); +} + +static void +bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc) +{ + bytecode_align *align = (bytecode_align *)bc->contents; + if (!yasm_expr_get_intnum(&align->boundary, NULL)) + yasm_error_set(YASM_ERROR_NOT_CONSTANT, + N_("align boundary must be a constant")); + if (align->fill && !yasm_expr_get_intnum(&align->fill, NULL)) + yasm_error_set(YASM_ERROR_NOT_CONSTANT, + N_("align fill must be a constant")); + if (align->maxskip && !yasm_expr_get_intnum(&align->maxskip, NULL)) + yasm_error_set(YASM_ERROR_NOT_CONSTANT, + N_("align maximum skip must be a constant")); +} + +static yasm_bc_resolve_flags +bc_align_resolve(yasm_bytecode *bc, int save, + yasm_calc_bc_dist_func calc_bc_dist) +{ + bytecode_align *align = (bytecode_align *)bc->contents; + unsigned long end; + unsigned long boundary = + yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, NULL)); + + if (boundary == 0) { + bc->len = 0; + return YASM_BC_RESOLVE_MIN_LEN; + } + + end = bc->offset; + if (bc->offset & (boundary-1)) + end = (bc->offset & ~(boundary-1)) + boundary; + + bc->len = end - bc->offset; + + if (align->maxskip) { + unsigned long maxskip = + yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, NULL)); + if ((end - bc->offset) > maxskip) + bc->len = 0; + } + return YASM_BC_RESOLVE_MIN_LEN; +} + +static int +bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, + yasm_output_value_func output_value, + /*@unused@*/ yasm_output_reloc_func output_reloc) +{ + bytecode_align *align = (bytecode_align *)bc->contents; + unsigned long len; + unsigned long boundary = + yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, NULL)); + + if (boundary == 0) + return 0; + else { + unsigned long end = bc->offset; + if (bc->offset & (boundary-1)) + end = (bc->offset & ~(boundary-1)) + boundary; + len = end - bc->offset; + if (len == 0) + return 0; + if (align->maxskip) { + unsigned long maxskip = + yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, + NULL)); + if (len > maxskip) + return 0; + } + } + + if (align->fill) { + unsigned long v; + v = yasm_intnum_get_uint(yasm_expr_get_intnum(&align->fill, NULL)); + memset(*bufp, (int)v, len); + *bufp += len; + } else if (align->code_fill) { + unsigned long maxlen = 15; + while (!align->code_fill[maxlen] && maxlen>0) + maxlen--; + if (maxlen == 0) { + yasm_error_set(YASM_ERROR_GENERAL, + N_("could not find any code alignment size")); + return 1; + } + + /* Fill with maximum code fill as much as possible */ + while (len > maxlen) { + memcpy(*bufp, align->code_fill[maxlen], maxlen); + *bufp += maxlen; + len -= maxlen; + } + + if (!align->code_fill[len]) { + yasm_error_set(YASM_ERROR_VALUE, + N_("invalid alignment size %d"), len); + return 1; + } + /* Handle rest of code fill */ + memcpy(*bufp, align->code_fill[len], len); + *bufp += len; + } else { + /* Just fill with 0 */ + memset(*bufp, 0, len); + *bufp += len; + } + return 0; +} + +yasm_bytecode * +yasm_bc_create_align(yasm_expr *boundary, yasm_expr *fill, + yasm_expr *maxskip, const unsigned char **code_fill, + unsigned long line) +{ + bytecode_align *align = yasm_xmalloc(sizeof(bytecode_align)); + + align->boundary = boundary; + align->fill = fill; + align->maxskip = maxskip; + align->code_fill = code_fill; + + return yasm_bc_create_common(&bc_align_callback, align, line); +} diff --git a/libyasm/bc-data.c b/libyasm/bc-data.c new file mode 100644 index 00000000..5fe15a23 --- /dev/null +++ b/libyasm/bc-data.c @@ -0,0 +1,457 @@ +/* + * Data (and LEB128) bytecode + * + * Copyright (C) 2001-2006 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#define YASM_LIB_INTERNAL +#include "util.h" +/*@unused@*/ RCSID("$Id$"); + +#include "coretype.h" + +#include "errwarn.h" +#include "intnum.h" +#include "expr.h" +#include "value.h" + +#include "bytecode.h" +#include "arch.h" + +#include "bc-int.h" + + +struct yasm_dataval { + /*@reldef@*/ STAILQ_ENTRY(yasm_dataval) link; + + enum { DV_EMPTY, DV_VALUE, DV_RAW, DV_ULEB128, DV_SLEB128 } type; + + union { + yasm_value val; + struct { + /*@only@*/ unsigned char *contents; + unsigned long len; + } raw; + } data; +}; + +typedef struct bytecode_data { + /* converted data (linked list) */ + yasm_datavalhead datahead; + + /* final (converted) size of each value element (in bytes) */ + unsigned int size; +} bytecode_data; + +static void bc_data_destroy(void *contents); +static void bc_data_print(const void *contents, FILE *f, int indent_level); +static void bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc); +static yasm_bc_resolve_flags bc_data_resolve + (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist); +static int bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, + yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc); + +static const yasm_bytecode_callback bc_data_callback = { + bc_data_destroy, + bc_data_print, + bc_data_finalize, + bc_data_resolve, + bc_data_tobytes, + 0 +}; + + +static void +bc_data_destroy(void *contents) +{ + bytecode_data *bc_data = (bytecode_data *)contents; + yasm_dvs_destroy(&bc_data->datahead); + yasm_xfree(contents); +} + +static void +bc_data_print(const void *contents, FILE *f, int indent_level) +{ + const bytecode_data *bc_data = (const bytecode_data *)contents; + fprintf(f, "%*s_Data_\n", indent_level, ""); + fprintf(f, "%*sElements:\n", indent_level+1, ""); + yasm_dvs_print(&bc_data->datahead, f, indent_level+2); +} + +static void +bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc) +{ + bytecode_data *bc_data = (bytecode_data *)bc->contents; + yasm_dataval *dv; + yasm_intnum *intn; + + /* Convert values from simple expr to value. */ + STAILQ_FOREACH(dv, &bc_data->datahead, link) { + switch (dv->type) { + case DV_VALUE: + if (yasm_value_finalize(&dv->data.val)) { + yasm_error_set(YASM_ERROR_TOO_COMPLEX, + N_("data expression too complex")); + return; + } + break; + case DV_ULEB128: + case DV_SLEB128: + intn = yasm_expr_get_intnum(&dv->data.val.abs, NULL); + if (!intn) { + yasm_error_set(YASM_ERROR_NOT_CONSTANT, + N_("LEB128 requires constant values")); + return; + } + /* Warn for negative values in unsigned environment. + * This could be an error instead: the likelihood this is + * desired is very low! + */ + if (yasm_intnum_sign(intn) == -1 && dv->type == DV_ULEB128) + yasm_warn_set(YASM_WARN_GENERAL, + N_("negative value in unsigned LEB128")); + break; + default: + break; + } + } +} + +static yasm_bc_resolve_flags +bc_data_resolve(yasm_bytecode *bc, int save, + yasm_calc_bc_dist_func calc_bc_dist) +{ + bytecode_data *bc_data = (bytecode_data *)bc->contents; + yasm_dataval *dv; + yasm_intnum *intn; + + /* Count up element sizes, rounding up string length. */ + STAILQ_FOREACH(dv, &bc_data->datahead, link) { + switch (dv->type) { + case DV_EMPTY: + break; + case DV_VALUE: + bc->len += bc_data->size; + break; + case DV_RAW: + bc->len += dv->data.raw.len; + break; + case DV_ULEB128: + case DV_SLEB128: + intn = yasm_expr_get_intnum(&dv->data.val.abs, NULL); + if (!intn) + yasm_internal_error(N_("non-constant in data_tobytes")); + bc->len += + yasm_intnum_size_leb128(intn, dv->type == DV_SLEB128); + break; + } + } + + return YASM_BC_RESOLVE_MIN_LEN; +} + +static int +bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, + yasm_output_value_func output_value, + /*@unused@*/ yasm_output_reloc_func output_reloc) +{ + bytecode_data *bc_data = (bytecode_data *)bc->contents; + yasm_dataval *dv; + unsigned char *bufp_orig = *bufp; + yasm_intnum *intn; + + STAILQ_FOREACH(dv, &bc_data->datahead, link) { + switch (dv->type) { + case DV_EMPTY: + break; + case DV_VALUE: + if (output_value(&dv->data.val, *bufp, bc_data->size, + (size_t)(bc_data->size*8), 0, + (unsigned long)(*bufp-bufp_orig), bc, 1, d)) + return 1; + *bufp += bc_data->size; + break; + case DV_RAW: + memcpy(*bufp, dv->data.raw.contents, dv->data.raw.len); + *bufp += dv->data.raw.len; + break; + case DV_ULEB128: + case DV_SLEB128: + intn = yasm_expr_get_intnum(&dv->data.val.abs, NULL); + if (!intn) + yasm_internal_error(N_("non-constant in data_tobytes")); + *bufp += + yasm_intnum_get_leb128(intn, *bufp, dv->type == DV_SLEB128); + } + } + + return 0; +} + +yasm_bytecode * +yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size, + int append_zero, yasm_arch *arch, unsigned long line) +{ + bytecode_data *data = yasm_xmalloc(sizeof(bytecode_data)); + yasm_bytecode *bc = yasm_bc_create_common(&bc_data_callback, data, line); + yasm_dataval *dv, *dv2, *dvo; + yasm_intnum *intn; + unsigned long len = 0, rlen, i; + + + yasm_dvs_initialize(&data->datahead); + data->size = size; + + /* Prescan input data for length, etc. Careful: this needs to be + * precisely paired with the second loop. + */ + STAILQ_FOREACH(dv, datahead, link) { + switch (dv->type) { + case DV_EMPTY: + break; + case DV_VALUE: + case DV_ULEB128: + case DV_SLEB128: + intn = yasm_expr_get_intnum(&dv->data.val.abs, NULL); + if (intn && dv->type == DV_VALUE && (arch || size == 1)) + len += size; + else if (intn && dv->type == DV_ULEB128) + len += yasm_intnum_size_leb128(intn, 0); + else if (intn && dv->type == DV_SLEB128) + len += yasm_intnum_size_leb128(intn, 1); + else { + if (len > 0) { + /* Create bytecode for all previous len */ + dvo = yasm_dv_create_raw(yasm_xmalloc(len), len); + STAILQ_INSERT_TAIL(&data->datahead, dvo, link); + len = 0; + } + + /* Create bytecode for this value */ + dvo = yasm_xmalloc(sizeof(yasm_dataval)); + STAILQ_INSERT_TAIL(&data->datahead, dvo, link); + } + break; + case DV_RAW: + rlen = dv->data.raw.len; + /* find count, rounding up to nearest multiple of size */ + rlen = (rlen + size - 1) / size; + len += rlen*size; + break; + } + if (append_zero) + len++; + } + + /* Create final dataval for any trailing length */ + if (len > 0) { + dvo = yasm_dv_create_raw(yasm_xmalloc(len), len); + STAILQ_INSERT_TAIL(&data->datahead, dvo, link); + } + + /* Second iteration: copy data and delete input datavals. */ + dv = STAILQ_FIRST(datahead); + dvo = STAILQ_FIRST(&data->datahead); + len = 0; + while (dv) { + switch (dv->type) { + case DV_EMPTY: + break; + case DV_VALUE: + case DV_ULEB128: + case DV_SLEB128: + intn = yasm_expr_get_intnum(&dv->data.val.abs, NULL); + if (intn && dv->type == DV_VALUE && (arch || size == 1)) { + if (size == 1) + yasm_intnum_get_sized(intn, + &dvo->data.raw.contents[len], + 1, 8, 0, 0, 1); + else + yasm_arch_intnum_tobytes(arch, intn, + &dvo->data.raw.contents[len], + size, size*8, 0, bc, 1); + yasm_value_delete(&dv->data.val); + len += size; + } else if (intn && dv->type == DV_ULEB128) { + len += yasm_intnum_get_leb128(intn, + &dvo->data.raw.contents[len], + 0); + } else if (intn && dv->type == DV_SLEB128) { + len += yasm_intnum_get_leb128(intn, + &dvo->data.raw.contents[len], + 1); + } else { + dvo->type = dv->type; + dvo->data.val = dv->data.val; /* structure copy */ + dvo = STAILQ_NEXT(dvo, link); + len = 0; + } + break; + case DV_RAW: + rlen = dv->data.raw.len; + memcpy(&dvo->data.raw.contents[len], dv->data.raw.contents, + rlen); + yasm_xfree(dv->data.raw.contents); + len += rlen; + /* pad with 0's to nearest multiple of size */ + rlen %= size; + if (rlen > 0) { + rlen = size-rlen; + for (i=0; idata.raw.contents[len++] = 0; + } + break; + } + if (append_zero) + dvo->data.raw.contents[len++] = 0; + dv2 = STAILQ_NEXT(dv, link); + yasm_xfree(dv); + dv = dv2; + } + + return bc; +} + +yasm_bytecode * +yasm_bc_create_leb128(yasm_datavalhead *datahead, int sign, unsigned long line) +{ + yasm_dataval *dv; + + /* Convert all values into LEB type, error on strings/raws */ + STAILQ_FOREACH(dv, datahead, link) { + switch (dv->type) { + case DV_VALUE: + dv->type = sign ? DV_SLEB128 : DV_ULEB128; + break; + case DV_RAW: + yasm_error_set(YASM_ERROR_VALUE, + N_("LEB128 does not allow string constants")); + break; + default: + break; + } + } + + return yasm_bc_create_data(datahead, 0, 0, 0, line); +} + +yasm_dataval * +yasm_dv_create_expr(yasm_expr *e) +{ + yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval)); + + retval->type = DV_VALUE; + yasm_value_initialize(&retval->data.val, e); + + return retval; +} + +yasm_dataval * +yasm_dv_create_raw(unsigned char *contents, unsigned long len) +{ + yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval)); + + retval->type = DV_RAW; + retval->data.raw.contents = contents; + retval->data.raw.len = len; + + return retval; +} + +void +yasm_dvs_destroy(yasm_datavalhead *headp) +{ + yasm_dataval *cur, *next; + + cur = STAILQ_FIRST(headp); + while (cur) { + next = STAILQ_NEXT(cur, link); + switch (cur->type) { + case DV_VALUE: + yasm_value_delete(&cur->data.val); + break; + case DV_RAW: + yasm_xfree(cur->data.raw.contents); + break; + default: + break; + } + yasm_xfree(cur); + cur = next; + } + STAILQ_INIT(headp); +} + +yasm_dataval * +yasm_dvs_append(yasm_datavalhead *headp, yasm_dataval *dv) +{ + if (dv) { + STAILQ_INSERT_TAIL(headp, dv, link); + return dv; + } + return (yasm_dataval *)NULL; +} + +void +yasm_dvs_print(const yasm_datavalhead *head, FILE *f, int indent_level) +{ + yasm_dataval *cur; + unsigned long i; + + STAILQ_FOREACH(cur, head, link) { + switch (cur->type) { + case DV_EMPTY: + fprintf(f, "%*sEmpty\n", indent_level, ""); + break; + case DV_VALUE: + fprintf(f, "%*sValue:\n", indent_level, ""); + yasm_value_print(&cur->data.val, f, indent_level+1); + break; + case DV_RAW: + fprintf(f, "%*sLength=%lu\n", indent_level, "", + cur->data.raw.len); + fprintf(f, "%*sBytes=[", indent_level, ""); + for (i=0; idata.raw.len; i++) + fprintf(f, "0x%02x, ", cur->data.raw.contents[i]); + fprintf(f, "]\n"); + break; + case DV_ULEB128: + fprintf(f, "%*sULEB128 value:\n", indent_level, ""); + yasm_value_print(&cur->data.val, f, indent_level+1); + break; + case DV_SLEB128: + fprintf(f, "%*sSLEB128 value:\n", indent_level, ""); + yasm_value_print(&cur->data.val, f, indent_level+1); + break; + } + } +} + +/* Non-macro yasm_dvs_initialize() for non-YASM_LIB_INTERNAL users. */ +#undef yasm_dvs_initialize +void +yasm_dvs_initialize(yasm_datavalhead *headp) +{ + STAILQ_INIT(headp); +} diff --git a/libyasm/bc-incbin.c b/libyasm/bc-incbin.c new file mode 100644 index 00000000..d9da18fc --- /dev/null +++ b/libyasm/bc-incbin.c @@ -0,0 +1,271 @@ +/* + * Incbin bytecode + * + * Copyright (C) 2001-2006 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#define YASM_LIB_INTERNAL +#include "util.h" +/*@unused@*/ RCSID("$Id$"); + +#include "coretype.h" + +#include "errwarn.h" +#include "intnum.h" +#include "expr.h" +#include "value.h" + +#include "bytecode.h" + +#include "bc-int.h" + + +typedef struct bytecode_incbin { + /*@only@*/ char *filename; /* file to include data from */ + + /* starting offset to read from (NULL=0) */ + /*@only@*/ /*@null@*/ yasm_expr *start; + + /* maximum number of bytes to read (NULL=no limit) */ + /*@only@*/ /*@null@*/ yasm_expr *maxlen; +} bytecode_incbin; + +static void bc_incbin_destroy(void *contents); +static void bc_incbin_print(const void *contents, FILE *f, int indent_level); +static void bc_incbin_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc); +static yasm_bc_resolve_flags bc_incbin_resolve + (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist); +static int bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, + yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc); + +static const yasm_bytecode_callback bc_incbin_callback = { + bc_incbin_destroy, + bc_incbin_print, + bc_incbin_finalize, + bc_incbin_resolve, + bc_incbin_tobytes, + 0 +}; + + +static void +bc_incbin_destroy(void *contents) +{ + bytecode_incbin *incbin = (bytecode_incbin *)contents; + yasm_xfree(incbin->filename); + yasm_expr_destroy(incbin->start); + yasm_expr_destroy(incbin->maxlen); + yasm_xfree(contents); +} + +static void +bc_incbin_print(const void *contents, FILE *f, int indent_level) +{ + const bytecode_incbin *incbin = (const bytecode_incbin *)contents; + fprintf(f, "%*s_IncBin_\n", indent_level, ""); + fprintf(f, "%*sFilename=`%s'\n", indent_level, "", + incbin->filename); + fprintf(f, "%*sStart=", indent_level, ""); + if (!incbin->start) + fprintf(f, "nil (0)"); + else + yasm_expr_print(incbin->start, f); + fprintf(f, "%*sMax Len=", indent_level, ""); + if (!incbin->maxlen) + fprintf(f, "nil (unlimited)"); + else + yasm_expr_print(incbin->maxlen, f); + fprintf(f, "\n"); +} + +static void +bc_incbin_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc) +{ + bytecode_incbin *incbin = (bytecode_incbin *)bc->contents; + yasm_value val; + + if (yasm_value_finalize_expr(&val, incbin->start)) + yasm_error_set(YASM_ERROR_TOO_COMPLEX, + N_("start expression too complex")); + else if (val.rel) + yasm_error_set(YASM_ERROR_NOT_ABSOLUTE, + N_("start expression not absolute")); + incbin->start = val.abs; + + if (yasm_value_finalize_expr(&val, incbin->maxlen)) + yasm_error_set(YASM_ERROR_TOO_COMPLEX, + N_("maximum length expression too complex")); + else if (val.rel) + yasm_error_set(YASM_ERROR_NOT_ABSOLUTE, + N_("maximum length expression not absolute")); + incbin->maxlen = val.abs; +} + +static yasm_bc_resolve_flags +bc_incbin_resolve(yasm_bytecode *bc, int save, + yasm_calc_bc_dist_func calc_bc_dist) +{ + bytecode_incbin *incbin = (bytecode_incbin *)bc->contents; + FILE *f; + /*@null@*/ yasm_expr *temp; + yasm_expr **tempp; + /*@dependent@*/ /*@null@*/ const yasm_intnum *num; + unsigned long start = 0, maxlen = 0xFFFFFFFFUL, flen; + + /* Try to convert start to integer value */ + if (incbin->start) { + if (save) { + temp = NULL; + tempp = &incbin->start; + } else { + temp = yasm_expr_copy(incbin->start); + assert(temp != NULL); + tempp = &temp; + } + num = yasm_expr_get_intnum(tempp, calc_bc_dist); + if (num) + start = yasm_intnum_get_uint(num); + yasm_expr_destroy(temp); + if (!num) + return YASM_BC_RESOLVE_UNKNOWN_LEN; + } + + /* Try to convert maxlen to integer value */ + if (incbin->maxlen) { + if (save) { + temp = NULL; + tempp = &incbin->maxlen; + } else { + temp = yasm_expr_copy(incbin->maxlen); + assert(temp != NULL); + tempp = &temp; + } + num = yasm_expr_get_intnum(tempp, calc_bc_dist); + if (num) + maxlen = yasm_intnum_get_uint(num); + yasm_expr_destroy(temp); + if (!num) + return YASM_BC_RESOLVE_UNKNOWN_LEN; + } + + /* FIXME: Search include path for filename. Save full path back into + * filename if save is true. + */ + + /* Open file and determine its length */ + f = fopen(incbin->filename, "rb"); + if (!f) { + yasm_error_set(YASM_ERROR_IO, + N_("`incbin': unable to open file `%s'"), + incbin->filename); + return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN; + } + if (fseek(f, 0L, SEEK_END) < 0) { + yasm_error_set(YASM_ERROR_IO, + N_("`incbin': unable to seek on file `%s'"), + incbin->filename); + return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN; + } + flen = (unsigned long)ftell(f); + fclose(f); + + /* Compute length of incbin from start, maxlen, and len */ + if (start > flen) { + yasm_warn_set(YASM_WARN_GENERAL, + N_("`incbin': start past end of file `%s'"), + incbin->filename); + start = flen; + } + flen -= start; + if (incbin->maxlen) + if (maxlen < flen) + flen = maxlen; + bc->len += flen; + return YASM_BC_RESOLVE_MIN_LEN; +} + +static int +bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, + yasm_output_value_func output_value, + /*@unused@*/ yasm_output_reloc_func output_reloc) +{ + bytecode_incbin *incbin = (bytecode_incbin *)bc->contents; + FILE *f; + /*@dependent@*/ /*@null@*/ const yasm_intnum *num; + unsigned long start = 0; + + /* Convert start to integer value */ + if (incbin->start) { + num = yasm_expr_get_intnum(&incbin->start, NULL); + if (!num) + yasm_internal_error( + N_("could not determine start in bc_tobytes_incbin")); + start = yasm_intnum_get_uint(num); + } + + /* Open file */ + f = fopen(incbin->filename, "rb"); + if (!f) { + yasm_error_set(YASM_ERROR_IO, N_("`incbin': unable to open file `%s'"), + incbin->filename); + return 1; + } + + /* Seek to start of data */ + if (fseek(f, (long)start, SEEK_SET) < 0) { + yasm_error_set(YASM_ERROR_IO, + N_("`incbin': unable to seek on file `%s'"), + incbin->filename); + fclose(f); + return 1; + } + + /* Read len bytes */ + if (fread(*bufp, 1, (size_t)bc->len, f) < (size_t)bc->len) { + yasm_error_set(YASM_ERROR_IO, + N_("`incbin': unable to read %lu bytes from file `%s'"), + bc->len, incbin->filename); + fclose(f); + return 1; + } + + *bufp += bc->len; + fclose(f); + return 0; +} + +yasm_bytecode * +yasm_bc_create_incbin(char *filename, yasm_expr *start, yasm_expr *maxlen, + unsigned long line) +{ + bytecode_incbin *incbin = yasm_xmalloc(sizeof(bytecode_incbin)); + + /*@-mustfree@*/ + incbin->filename = filename; + incbin->start = start; + incbin->maxlen = maxlen; + /*@=mustfree@*/ + + return yasm_bc_create_common(&bc_incbin_callback, incbin, line); +} diff --git a/libyasm/bc-insn.c b/libyasm/bc-insn.c new file mode 100644 index 00000000..531ba5da --- /dev/null +++ b/libyasm/bc-insn.c @@ -0,0 +1,349 @@ +/* + * Insn bytecode + * + * Copyright (C) 2005-2006 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#define YASM_LIB_INTERNAL +#include "util.h" +/*@unused@*/ RCSID("$Id$"); + +#include "coretype.h" + +#include "errwarn.h" +#include "expr.h" +#include "value.h" + +#include "bytecode.h" +#include "arch.h" + +#include "bc-int.h" + + +typedef struct bytecode_insn { + /*@dependent@*/ yasm_arch *arch; + unsigned long insn_data[4]; + + int num_operands; + /*@null@*/ yasm_insn_operands operands; + + /* array of 4-element prefix_data arrays */ + int num_prefixes; + /*@null@*/ unsigned long **prefixes; + + /* array of segment prefixes */ + int num_segregs; + /*@null@*/ unsigned long *segregs; +} bytecode_insn; + +static void bc_insn_destroy(void *contents); +static void bc_insn_print(const void *contents, FILE *f, int indent_level); +static void bc_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc); +static yasm_bc_resolve_flags bc_insn_resolve + (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist); +static int bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, + yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc); + +static const yasm_bytecode_callback bc_insn_callback = { + bc_insn_destroy, + bc_insn_print, + bc_insn_finalize, + bc_insn_resolve, + bc_insn_tobytes, + 0 +}; + + +yasm_immval * +yasm_imm_create_expr(yasm_expr *e) +{ + yasm_immval *im = yasm_xmalloc(sizeof(yasm_immval)); + + if (yasm_value_finalize_expr(&im->val, e)) + yasm_error_set(YASM_ERROR_TOO_COMPLEX, + N_("immediate expression too complex")); + im->len = 0; + im->sign = 0; + + return im; +} + +const yasm_expr * +yasm_ea_get_disp(const yasm_effaddr *ea) +{ + return ea->disp.abs; +} + +void +yasm_ea_set_len(yasm_effaddr *ptr, unsigned int len) +{ + if (!ptr) + return; + + /* Currently don't warn if length truncated, as this is called only from + * an explicit override, where we expect the user knows what they're doing. + */ + + ptr->disp_len = (unsigned char)len; +} + +void +yasm_ea_set_nosplit(yasm_effaddr *ptr, unsigned int nosplit) +{ + if (!ptr) + return; + + ptr->nosplit = (unsigned char)nosplit; +} + +void +yasm_ea_set_strong(yasm_effaddr *ptr, unsigned int strong) +{ + if (!ptr) + return; + + ptr->strong = (unsigned char)strong; +} + +void +yasm_ea_set_segreg(yasm_effaddr *ea, unsigned long segreg) +{ + if (!ea) + return; + + if (segreg != 0 && ea->segreg != 0) + yasm_warn_set(YASM_WARN_GENERAL, + N_("multiple segment overrides, using leftmost")); + + ea->segreg = segreg; +} + +/*@-nullstate@*/ +void +yasm_ea_destroy(yasm_effaddr *ea) +{ + ea->callback->destroy(ea); + yasm_value_delete(&ea->disp); + yasm_xfree(ea); +} +/*@=nullstate@*/ + +/*@-nullstate@*/ +void +yasm_ea_print(const yasm_effaddr *ea, FILE *f, int indent_level) +{ + fprintf(f, "%*sDisp:\n", indent_level, ""); + yasm_value_print(&ea->disp, f, indent_level+1); + fprintf(f, "%*sLen=%u\n", indent_level, "", (unsigned int)ea->disp_len); + fprintf(f, "%*sNoSplit=%u\n", indent_level, "", (unsigned int)ea->nosplit); + ea->callback->print(ea, f, indent_level); +} +/*@=nullstate@*/ + +static void +bc_insn_destroy(void *contents) +{ + bytecode_insn *insn = (bytecode_insn *)contents; + if (insn->num_operands > 0) + yasm_ops_delete(&insn->operands, 0); + if (insn->num_prefixes > 0) { + int i; + for (i=0; inum_prefixes; i++) + yasm_xfree(insn->prefixes[i]); + yasm_xfree(insn->prefixes); + } + if (insn->num_segregs > 0) + yasm_xfree(insn->segregs); + yasm_xfree(contents); +} + +static void +bc_insn_print(const void *contents, FILE *f, int indent_level) +{ +} + +static void +bc_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc) +{ + bytecode_insn *insn = (bytecode_insn *)bc->contents; + int i; + yasm_insn_operand *op; + yasm_error_class eclass; + char *str, *xrefstr; + unsigned long xrefline; + + /* Simplify the operands' expressions first. */ + for (i = 0, op = yasm_ops_first(&insn->operands); + op && inum_operands; op = yasm_operand_next(op), i++) { + /* Check operand type */ + switch (op->type) { + case YASM_INSN__OPERAND_MEMORY: + /* Don't get over-ambitious here; some archs' memory expr + * parser are sensitive to the presence of *1, etc, so don't + * simplify reg*1 identities. + */ + if (op->data.ea) + op->data.ea->disp.abs = + yasm_expr__level_tree(op->data.ea->disp.abs, 1, 1, 0, + NULL, NULL, NULL, NULL); + if (yasm_error_occurred()) { + /* Add a pointer to where it was used to the error */ + yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr); + if (xrefstr) { + yasm_error_set_xref(xrefline, "%s", xrefstr); + yasm_xfree(xrefstr); + } + if (str) { + yasm_error_set(eclass, "%s in memory expression", str); + yasm_xfree(str); + } + return; + } + break; + case YASM_INSN__OPERAND_IMM: + op->data.val = + yasm_expr__level_tree(op->data.val, 1, 1, 1, NULL, NULL, + NULL, NULL); + if (yasm_error_occurred()) { + /* Add a pointer to where it was used to the error */ + yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr); + if (xrefstr) { + yasm_error_set_xref(xrefline, "%s", xrefstr); + yasm_xfree(xrefstr); + } + if (str) { + yasm_error_set(eclass, "%s in immediate expression", + str); + yasm_xfree(str); + } + return; + } + break; + default: + break; + } + } + + yasm_arch_finalize_insn(insn->arch, bc, prev_bc, insn->insn_data, + insn->num_operands, &insn->operands, + insn->num_prefixes, insn->prefixes, + insn->num_segregs, insn->segregs); +} + +static yasm_bc_resolve_flags +bc_insn_resolve(yasm_bytecode *bc, int save, + yasm_calc_bc_dist_func calc_bc_dist) +{ + yasm_internal_error(N_("bc_insn_resolve() is not implemented")); + /*@notreached@*/ + return YASM_BC_RESOLVE_ERROR; +} + +static int +bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, + yasm_output_value_func output_value, + /*@unused@*/ yasm_output_reloc_func output_reloc) +{ + yasm_internal_error(N_("bc_insn_tobytes() is not implemented")); + /*@notreached@*/ + return 1; +} + +yasm_bytecode * +yasm_bc_create_insn(yasm_arch *arch, const unsigned long insn_data[4], + int num_operands, /*@null@*/ yasm_insn_operands *operands, + unsigned long line) +{ + bytecode_insn *insn = yasm_xmalloc(sizeof(bytecode_insn)); + + insn->arch = arch; + insn->insn_data[0] = insn_data[0]; + insn->insn_data[1] = insn_data[1]; + insn->insn_data[2] = insn_data[2]; + insn->insn_data[3] = insn_data[3]; + insn->num_operands = num_operands; + if (operands) + insn->operands = *operands; /* structure copy */ + else + yasm_ops_initialize(&insn->operands); + insn->num_prefixes = 0; + insn->prefixes = NULL; + insn->num_segregs = 0; + insn->segregs = NULL; + + return yasm_bc_create_common(&bc_insn_callback, insn, line); +} + +yasm_bytecode * +yasm_bc_create_empty_insn(yasm_arch *arch, unsigned long line) +{ + bytecode_insn *insn = yasm_xmalloc(sizeof(bytecode_insn)); + + insn->arch = arch; + insn->insn_data[0] = 0; + insn->insn_data[1] = 0; + insn->insn_data[2] = 0; + insn->insn_data[3] = 0; + insn->num_operands = 0; + yasm_ops_initialize(&insn->operands); + insn->num_prefixes = 0; + insn->prefixes = NULL; + insn->num_segregs = 0; + insn->segregs = NULL; + + return yasm_bc_create_common(&bc_insn_callback, insn, line); +} + +void +yasm_bc_insn_add_prefix(yasm_bytecode *bc, const unsigned long prefix_data[4]) +{ + bytecode_insn *insn = (bytecode_insn *)bc->contents; + + assert(bc->callback == bc_insn_callback); + + insn->prefixes = + yasm_xrealloc(insn->prefixes, + (insn->num_prefixes+1)*sizeof(unsigned long *)); + insn->prefixes[insn->num_prefixes] = + yasm_xmalloc(4*sizeof(unsigned long)); + insn->prefixes[insn->num_prefixes][0] = prefix_data[0]; + insn->prefixes[insn->num_prefixes][1] = prefix_data[1]; + insn->prefixes[insn->num_prefixes][2] = prefix_data[2]; + insn->prefixes[insn->num_prefixes][3] = prefix_data[3]; + insn->num_prefixes++; +} + +void +yasm_bc_insn_add_seg_prefix(yasm_bytecode *bc, unsigned long segreg) +{ + bytecode_insn *insn = (bytecode_insn *)bc->contents; + + assert(bc->callback == bc_insn_callback); + + insn->segregs = + yasm_xrealloc(insn->segregs, + (insn->num_segregs+1)*sizeof(unsigned long)); + insn->segregs[insn->num_segregs] = segreg; + insn->num_segregs++; +} diff --git a/libyasm/bc-int.h b/libyasm/bc-int.h index ff0636b1..5bb86357 100644 --- a/libyasm/bc-int.h +++ b/libyasm/bc-int.h @@ -36,6 +36,7 @@ typedef struct yasm_bytecode_callback { int (*tobytes) (yasm_bytecode *bc, unsigned char **bufp, void *d, yasm_output_value_func output_value, /*@null@*/ yasm_output_reloc_func output_reloc); + int reserve; /* Reserve space instead of outputting data */ } yasm_bytecode_callback; struct yasm_bytecode { diff --git a/libyasm/bc-org.c b/libyasm/bc-org.c new file mode 100644 index 00000000..0d4da09f --- /dev/null +++ b/libyasm/bc-org.c @@ -0,0 +1,132 @@ +/* + * ORG bytecode + * + * Copyright (C) 2005-2006 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#define YASM_LIB_INTERNAL +#include "util.h" +/*@unused@*/ RCSID("$Id$"); + +#include "coretype.h" +#include "file.h" + +#include "errwarn.h" +#include "intnum.h" +#include "expr.h" +#include "value.h" + +#include "bytecode.h" + +#include "bc-int.h" + + +typedef struct bytecode_org { + unsigned long start; /* target starting offset within section */ +} bytecode_org; + +static void bc_org_destroy(void *contents); +static void bc_org_print(const void *contents, FILE *f, int indent_level); +static void bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc); +static yasm_bc_resolve_flags bc_org_resolve + (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist); +static int bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, + yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc); + +static const yasm_bytecode_callback bc_org_callback = { + bc_org_destroy, + bc_org_print, + bc_org_finalize, + bc_org_resolve, + bc_org_tobytes, + 0 +}; + + +static void +bc_org_destroy(void *contents) +{ + yasm_xfree(contents); +} + +static void +bc_org_print(const void *contents, FILE *f, int indent_level) +{ + const bytecode_org *org = (const bytecode_org *)contents; + fprintf(f, "%*s_Org_\n", indent_level, ""); + fprintf(f, "%*sStart=%lu\n", indent_level, "", org->start); +} + +static void +bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc) +{ +} + +static yasm_bc_resolve_flags +bc_org_resolve(yasm_bytecode *bc, int save, + yasm_calc_bc_dist_func calc_bc_dist) +{ + bytecode_org *org = (bytecode_org *)bc->contents; + + /* Check for overrun */ + if (bc->offset > org->start) { + yasm_error_set(YASM_ERROR_GENERAL, + N_("ORG overlap with already existing data")); + return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN; + } + + /* Generate space to start offset */ + bc->len = org->start - bc->offset; + return YASM_BC_RESOLVE_MIN_LEN; +} + +static int +bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, + yasm_output_value_func output_value, + /*@unused@*/ yasm_output_reloc_func output_reloc) +{ + bytecode_org *org = (bytecode_org *)bc->contents; + unsigned long len, i; + + /* Sanity check for overrun */ + if (bc->offset > org->start) { + yasm_error_set(YASM_ERROR_GENERAL, + N_("ORG overlap with already existing data")); + return 1; + } + len = org->start - bc->offset; + for (i=0; istart = start; + + return yasm_bc_create_common(&bc_org_callback, org, line); +} diff --git a/libyasm/bc-reserve.c b/libyasm/bc-reserve.c new file mode 100644 index 00000000..782fb0b6 --- /dev/null +++ b/libyasm/bc-reserve.c @@ -0,0 +1,162 @@ +/* + * Bytecode utility functions + * + * Copyright (C) 2001 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#define YASM_LIB_INTERNAL +#include "util.h" +/*@unused@*/ RCSID("$Id$"); + +#include "coretype.h" + +#include "errwarn.h" +#include "intnum.h" +#include "expr.h" +#include "value.h" + +#include "bytecode.h" + +#include "bc-int.h" +#include "expr-int.h" + + +typedef struct bytecode_reserve { + /*@only@*/ /*@null@*/ yasm_expr *numitems; /* number of items to reserve */ + unsigned char itemsize; /* size of each item (in bytes) */ +} bytecode_reserve; + +static void bc_reserve_destroy(void *contents); +static void bc_reserve_print(const void *contents, FILE *f, int indent_level); +static void bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc); +static yasm_bc_resolve_flags bc_reserve_resolve + (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist); +static int bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, + yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc); + +static const yasm_bytecode_callback bc_reserve_callback = { + bc_reserve_destroy, + bc_reserve_print, + bc_reserve_finalize, + bc_reserve_resolve, + bc_reserve_tobytes, + 1 +}; + + +static void +bc_reserve_destroy(void *contents) +{ + bytecode_reserve *reserve = (bytecode_reserve *)contents; + yasm_expr_destroy(reserve->numitems); + yasm_xfree(contents); +} + +static void +bc_reserve_print(const void *contents, FILE *f, int indent_level) +{ + const bytecode_reserve *reserve = (const bytecode_reserve *)contents; + fprintf(f, "%*s_Reserve_\n", indent_level, ""); + fprintf(f, "%*sNum Items=", indent_level, ""); + yasm_expr_print(reserve->numitems, f); + fprintf(f, "\n%*sItem Size=%u\n", indent_level, "", + (unsigned int)reserve->itemsize); +} + +static void +bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc) +{ + bytecode_reserve *reserve = (bytecode_reserve *)bc->contents; + yasm_value val; + + if (yasm_value_finalize_expr(&val, reserve->numitems)) + yasm_error_set(YASM_ERROR_TOO_COMPLEX, + N_("reserve expression too complex")); + else if (val.rel) + yasm_error_set(YASM_ERROR_NOT_ABSOLUTE, + N_("reserve expression not absolute")); + else if (val.abs && yasm_expr__contains(val.abs, YASM_EXPR_FLOAT)) + yasm_error_set(YASM_ERROR_VALUE, + N_("expression must not contain floating point value")); + reserve->numitems = val.abs; +} + +static yasm_bc_resolve_flags +bc_reserve_resolve(yasm_bytecode *bc, int save, + yasm_calc_bc_dist_func calc_bc_dist) +{ + bytecode_reserve *reserve = (bytecode_reserve *)bc->contents; + yasm_bc_resolve_flags retval = YASM_BC_RESOLVE_MIN_LEN; + /*@null@*/ yasm_expr *temp; + yasm_expr **tempp; + /*@dependent@*/ /*@null@*/ const yasm_intnum *num; + + if (!reserve->numitems) + return YASM_BC_RESOLVE_MIN_LEN; + + if (save) { + temp = NULL; + tempp = &reserve->numitems; + } else { + temp = yasm_expr_copy(reserve->numitems); + assert(temp != NULL); + tempp = &temp; + } + num = yasm_expr_get_intnum(tempp, calc_bc_dist); + if (!num) { + /* For reserve, just say non-constant quantity instead of allowing + * the circular reference error to filter through. + */ + yasm_error_set(YASM_ERROR_NOT_CONSTANT, + N_("attempt to reserve non-constant quantity of space")); + retval = YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN; + } else + bc->len += yasm_intnum_get_uint(num)*reserve->itemsize; + yasm_expr_destroy(temp); + return retval; +} + +static int +bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, + yasm_output_value_func output_value, + /*@unused@*/ yasm_output_reloc_func output_reloc) +{ + yasm_internal_error(N_("bc_reserve_tobytes called")); + /*@notreached@*/ + return 1; +} + +yasm_bytecode * +yasm_bc_create_reserve(yasm_expr *numitems, unsigned int itemsize, + unsigned long line) +{ + bytecode_reserve *reserve = yasm_xmalloc(sizeof(bytecode_reserve)); + + /*@-mustfree@*/ + reserve->numitems = numitems; + /*@=mustfree@*/ + reserve->itemsize = (unsigned char)itemsize; + + return yasm_bc_create_common(&bc_reserve_callback, reserve, line); +} diff --git a/libyasm/bytecode.c b/libyasm/bytecode.c index 7207bd59..99a4c741 100644 --- a/libyasm/bytecode.c +++ b/libyasm/bytecode.c @@ -29,7 +29,6 @@ /*@unused@*/ RCSID("$Id$"); #include "coretype.h" -#include "file.h" #include "errwarn.h" #include "intnum.h" @@ -38,311 +37,11 @@ #include "symrec.h" #include "bytecode.h" -#include "arch.h" -#include "objfmt.h" -#include "dbgfmt.h" #include "bc-int.h" #include "expr-int.h" -struct yasm_dataval { - /*@reldef@*/ STAILQ_ENTRY(yasm_dataval) link; - - enum { DV_EMPTY, DV_VALUE, DV_RAW } type; - - union { - yasm_value val; - struct { - /*@only@*/ unsigned char *contents; - unsigned long len; - } raw; - } data; -}; - -/* Standard bytecode types */ - -typedef struct bytecode_data { - /* converted data (linked list) */ - yasm_datavalhead datahead; - - /* final (converted) size of each value element (in bytes) */ - unsigned int size; -} bytecode_data; - -typedef struct bytecode_leb128 { - /* source data (linked list) */ - yasm_datavalhead datahead; - - /* signedness (0=unsigned, 1=signed) */ - int sign; - - /* total length (calculated at finalize time) */ - unsigned long len; -} bytecode_leb128; - -typedef struct bytecode_reserve { - /*@only@*/ /*@null@*/ yasm_expr *numitems; /* number of items to reserve */ - unsigned char itemsize; /* size of each item (in bytes) */ -} bytecode_reserve; - -typedef struct bytecode_incbin { - /*@only@*/ char *filename; /* file to include data from */ - - /* starting offset to read from (NULL=0) */ - /*@only@*/ /*@null@*/ yasm_expr *start; - - /* maximum number of bytes to read (NULL=no limit) */ - /*@only@*/ /*@null@*/ yasm_expr *maxlen; -} bytecode_incbin; - -typedef struct bytecode_align { - /*@only@*/ yasm_expr *boundary; /* alignment boundary */ - - /* What to fill intervening locations with, NULL if using code_fill */ - /*@only@*/ /*@null@*/ yasm_expr *fill; - - /* Maximum number of bytes to skip, NULL if no maximum. */ - /*@only@*/ /*@null@*/ yasm_expr *maxskip; - - /* Code fill, NULL if using 0 fill */ - /*@null@*/ const unsigned char **code_fill; -} bytecode_align; - -typedef struct bytecode_org { - unsigned long start; /* target starting offset within section */ -} bytecode_org; - -typedef struct bytecode_insn { - /*@dependent@*/ yasm_arch *arch; - unsigned long insn_data[4]; - - int num_operands; - /*@null@*/ yasm_insn_operands operands; - - /* array of 4-element prefix_data arrays */ - int num_prefixes; - /*@null@*/ unsigned long **prefixes; - - /* array of segment prefixes */ - int num_segregs; - /*@null@*/ unsigned long *segregs; -} bytecode_insn; - -/* Standard bytecode callback function prototypes */ - -static void bc_data_destroy(void *contents); -static void bc_data_print(const void *contents, FILE *f, int indent_level); -static void bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc); -static yasm_bc_resolve_flags bc_data_resolve - (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist); -static int bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, - yasm_output_value_func output_value, - /*@null@*/ yasm_output_reloc_func output_reloc); - -static void bc_leb128_destroy(void *contents); -static void bc_leb128_print(const void *contents, FILE *f, int indent_level); -static void bc_leb128_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc); -static yasm_bc_resolve_flags bc_leb128_resolve - (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist); -static int bc_leb128_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, - yasm_output_value_func output_value, - /*@null@*/ yasm_output_reloc_func output_reloc); - -static void bc_reserve_destroy(void *contents); -static void bc_reserve_print(const void *contents, FILE *f, int indent_level); -static void bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc); -static yasm_bc_resolve_flags bc_reserve_resolve - (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist); -static int bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, - yasm_output_value_func output_value, - /*@null@*/ yasm_output_reloc_func output_reloc); - -static void bc_incbin_destroy(void *contents); -static void bc_incbin_print(const void *contents, FILE *f, int indent_level); -static void bc_incbin_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc); -static yasm_bc_resolve_flags bc_incbin_resolve - (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist); -static int bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, - yasm_output_value_func output_value, - /*@null@*/ yasm_output_reloc_func output_reloc); - -static void bc_align_destroy(void *contents); -static void bc_align_print(const void *contents, FILE *f, int indent_level); -static void bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc); -static yasm_bc_resolve_flags bc_align_resolve - (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist); -static int bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, - yasm_output_value_func output_value, - /*@null@*/ yasm_output_reloc_func output_reloc); - -static void bc_org_destroy(void *contents); -static void bc_org_print(const void *contents, FILE *f, int indent_level); -static void bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc); -static yasm_bc_resolve_flags bc_org_resolve - (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist); -static int bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, - yasm_output_value_func output_value, - /*@null@*/ yasm_output_reloc_func output_reloc); - -static void bc_insn_destroy(void *contents); -static void bc_insn_print(const void *contents, FILE *f, int indent_level); -static void bc_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc); -static yasm_bc_resolve_flags bc_insn_resolve - (yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist); -static int bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, - yasm_output_value_func output_value, - /*@null@*/ yasm_output_reloc_func output_reloc); - -/* Standard bytecode callback structures */ - -static const yasm_bytecode_callback bc_data_callback = { - bc_data_destroy, - bc_data_print, - bc_data_finalize, - bc_data_resolve, - bc_data_tobytes -}; - -static const yasm_bytecode_callback bc_leb128_callback = { - bc_leb128_destroy, - bc_leb128_print, - bc_leb128_finalize, - bc_leb128_resolve, - bc_leb128_tobytes -}; - -static const yasm_bytecode_callback bc_reserve_callback = { - bc_reserve_destroy, - bc_reserve_print, - bc_reserve_finalize, - bc_reserve_resolve, - bc_reserve_tobytes -}; - -static const yasm_bytecode_callback bc_incbin_callback = { - bc_incbin_destroy, - bc_incbin_print, - bc_incbin_finalize, - bc_incbin_resolve, - bc_incbin_tobytes -}; - -static const yasm_bytecode_callback bc_align_callback = { - bc_align_destroy, - bc_align_print, - bc_align_finalize, - bc_align_resolve, - bc_align_tobytes -}; - -static const yasm_bytecode_callback bc_org_callback = { - bc_org_destroy, - bc_org_print, - bc_org_finalize, - bc_org_resolve, - bc_org_tobytes -}; - -static const yasm_bytecode_callback bc_insn_callback = { - bc_insn_destroy, - bc_insn_print, - bc_insn_finalize, - bc_insn_resolve, - bc_insn_tobytes -}; - -/* Static structures for when NULL is passed to conversion functions. */ -/* for Convert*ToBytes() */ -unsigned char bytes_static[16]; - - -yasm_immval * -yasm_imm_create_expr(yasm_expr *e) -{ - yasm_immval *im = yasm_xmalloc(sizeof(yasm_immval)); - - if (yasm_value_finalize_expr(&im->val, e)) - yasm_error_set(YASM_ERROR_TOO_COMPLEX, - N_("immediate expression too complex")); - im->len = 0; - im->sign = 0; - - return im; -} - -const yasm_expr * -yasm_ea_get_disp(const yasm_effaddr *ea) -{ - return ea->disp.abs; -} - -void -yasm_ea_set_len(yasm_effaddr *ptr, unsigned int len) -{ - if (!ptr) - return; - - /* Currently don't warn if length truncated, as this is called only from - * an explicit override, where we expect the user knows what they're doing. - */ - - ptr->disp_len = (unsigned char)len; -} - -void -yasm_ea_set_nosplit(yasm_effaddr *ptr, unsigned int nosplit) -{ - if (!ptr) - return; - - ptr->nosplit = (unsigned char)nosplit; -} - -void -yasm_ea_set_strong(yasm_effaddr *ptr, unsigned int strong) -{ - if (!ptr) - return; - - ptr->strong = (unsigned char)strong; -} - -void -yasm_ea_set_segreg(yasm_effaddr *ea, unsigned long segreg) -{ - if (!ea) - return; - - if (segreg != 0 && ea->segreg != 0) - yasm_warn_set(YASM_WARN_GENERAL, - N_("multiple segment overrides, using leftmost")); - - ea->segreg = segreg; -} - -/*@-nullstate@*/ -void -yasm_ea_destroy(yasm_effaddr *ea) -{ - ea->callback->destroy(ea); - yasm_value_delete(&ea->disp); - yasm_xfree(ea); -} -/*@=nullstate@*/ - -/*@-nullstate@*/ -void -yasm_ea_print(const yasm_effaddr *ea, FILE *f, int indent_level) -{ - fprintf(f, "%*sDisp:\n", indent_level, ""); - yasm_value_print(&ea->disp, f, indent_level+1); - fprintf(f, "%*sLen=%u\n", indent_level, "", (unsigned int)ea->disp_len); - fprintf(f, "%*sNoSplit=%u\n", indent_level, "", (unsigned int)ea->nosplit); - ea->callback->print(ea, f, indent_level); -} -/*@=nullstate@*/ - void yasm_bc_set_multiple(yasm_bytecode *bc, yasm_expr *e) { @@ -394,1010 +93,6 @@ yasm_bc_create_common(const yasm_bytecode_callback *callback, void *contents, return bc; } -static void -bc_data_destroy(void *contents) -{ - bytecode_data *bc_data = (bytecode_data *)contents; - yasm_dvs_destroy(&bc_data->datahead); - yasm_xfree(contents); -} - -static void -bc_data_print(const void *contents, FILE *f, int indent_level) -{ - const bytecode_data *bc_data = (const bytecode_data *)contents; - fprintf(f, "%*s_Data_\n", indent_level, ""); - fprintf(f, "%*sElements:\n", indent_level+1, ""); - yasm_dvs_print(&bc_data->datahead, f, indent_level+2); -} - -static void -bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc) -{ - bytecode_data *bc_data = (bytecode_data *)bc->contents; - yasm_dataval *dv; - - /* Convert values from simple expr to value. */ - STAILQ_FOREACH(dv, &bc_data->datahead, link) { - if (dv->type == DV_VALUE) { - if (yasm_value_finalize(&dv->data.val)) - yasm_error_set(YASM_ERROR_TOO_COMPLEX, - N_("data expression too complex")); - } - } -} - -static yasm_bc_resolve_flags -bc_data_resolve(yasm_bytecode *bc, int save, - yasm_calc_bc_dist_func calc_bc_dist) -{ - bytecode_data *bc_data = (bytecode_data *)bc->contents; - yasm_dataval *dv; - - /* Count up element sizes, rounding up string length. */ - STAILQ_FOREACH(dv, &bc_data->datahead, link) { - switch (dv->type) { - case DV_EMPTY: - break; - case DV_VALUE: - bc->len += bc_data->size; - break; - case DV_RAW: - bc->len += dv->data.raw.len; - break; - } - } - - return YASM_BC_RESOLVE_MIN_LEN; -} - -static int -bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, - yasm_output_value_func output_value, - /*@unused@*/ yasm_output_reloc_func output_reloc) -{ - bytecode_data *bc_data = (bytecode_data *)bc->contents; - yasm_dataval *dv; - unsigned char *bufp_orig = *bufp; - - STAILQ_FOREACH(dv, &bc_data->datahead, link) { - switch (dv->type) { - case DV_EMPTY: - break; - case DV_VALUE: - if (output_value(&dv->data.val, *bufp, bc_data->size, - (size_t)(bc_data->size*8), 0, - (unsigned long)(*bufp-bufp_orig), bc, 1, d)) - return 1; - *bufp += bc_data->size; - break; - case DV_RAW: - memcpy(*bufp, dv->data.raw.contents, dv->data.raw.len); - *bufp += dv->data.raw.len; - break; - } - } - - return 0; -} - -yasm_bytecode * -yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size, - int append_zero, yasm_arch *arch, unsigned long line) -{ - bytecode_data *data = yasm_xmalloc(sizeof(bytecode_data)); - yasm_bytecode *bc = yasm_bc_create_common(&bc_data_callback, data, line); - yasm_dataval *dv, *dv2, *dvo; - yasm_intnum *intn; - unsigned long len = 0, rlen, i; - - - yasm_dvs_initialize(&data->datahead); - data->size = size; - - /* Prescan input data for length, etc. Careful: this needs to be - * precisely paired with the second loop. - */ - STAILQ_FOREACH(dv, datahead, link) { - switch (dv->type) { - case DV_EMPTY: - break; - case DV_VALUE: - if ((arch || size == 1) && dv->data.val.abs && - yasm_expr_get_intnum(&dv->data.val.abs, NULL)) - len += size; - else { - if (len > 0) { - /* Create bytecode for all previous len */ - dvo = yasm_dv_create_raw(yasm_xmalloc(len), len); - STAILQ_INSERT_TAIL(&data->datahead, dvo, link); - len = 0; - } - - /* Create bytecode for this value */ - dvo = yasm_xmalloc(sizeof(yasm_dataval)); - STAILQ_INSERT_TAIL(&data->datahead, dvo, link); - } - break; - case DV_RAW: - rlen = dv->data.raw.len; - /* find count, rounding up to nearest multiple of size */ - rlen = (rlen + size - 1) / size; - len += rlen*size; - break; - } - if (append_zero) - len++; - } - - /* Create final dataval for any trailing length */ - if (len > 0) { - dvo = yasm_dv_create_raw(yasm_xmalloc(len), len); - STAILQ_INSERT_TAIL(&data->datahead, dvo, link); - } - - /* Second iteration: copy data and delete input datavals. */ - dv = STAILQ_FIRST(datahead); - dvo = STAILQ_FIRST(&data->datahead); - len = 0; - while (dv) { - switch (dv->type) { - case DV_EMPTY: - break; - case DV_VALUE: - if ((arch || size == 1) && dv->data.val.abs && - (intn = yasm_expr_get_intnum(&dv->data.val.abs, NULL))) { - if (size == 1) - yasm_intnum_get_sized(intn, - &dvo->data.raw.contents[len], - 1, 8, 0, 0, 1); - else - yasm_arch_intnum_tobytes(arch, intn, - &dvo->data.raw.contents[len], - size, size*8, 0, bc, 1); - yasm_value_delete(&dv->data.val); - len += size; - } else { - dvo->type = DV_VALUE; - dvo->data.val = dv->data.val; /* structure copy */ - dvo = STAILQ_NEXT(dvo, link); - len = 0; - } - break; - case DV_RAW: - rlen = dv->data.raw.len; - memcpy(&dvo->data.raw.contents[len], dv->data.raw.contents, - rlen); - yasm_xfree(dv->data.raw.contents); - len += rlen; - /* pad with 0's to nearest multiple of size */ - rlen %= size; - if (rlen > 0) { - rlen = size-rlen; - for (i=0; idata.raw.contents[len++] = 0; - } - break; - } - if (append_zero) - dvo->data.raw.contents[len++] = 0; - dv2 = STAILQ_NEXT(dv, link); - yasm_xfree(dv); - dv = dv2; - } - - return bc; -} - -static void -bc_leb128_destroy(void *contents) -{ - bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)contents; - yasm_dvs_destroy(&bc_leb128->datahead); - yasm_xfree(contents); -} - -static void -bc_leb128_print(const void *contents, FILE *f, int indent_level) -{ - const bytecode_leb128 *bc_leb128 = (const bytecode_leb128 *)contents; - fprintf(f, "%*s_Data_\n", indent_level, ""); - fprintf(f, "%*sSign=%u\n", indent_level+1, "", - (unsigned int)bc_leb128->sign); - fprintf(f, "%*sElements:\n", indent_level+1, ""); - yasm_dvs_print(&bc_leb128->datahead, f, indent_level+2); -} - -static void -bc_leb128_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc) -{ - bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)bc->contents; - yasm_dataval *dv; - /*@dependent@*/ /*@null@*/ yasm_intnum *intn; - - /* Only constant expressions are allowed. - * Because of this, go ahead and calculate length. - */ - bc_leb128->len = 0; - STAILQ_FOREACH(dv, &bc_leb128->datahead, link) { - switch (dv->type) { - case DV_EMPTY: - break; - case DV_VALUE: - intn = yasm_expr_get_intnum(&dv->data.val.abs, NULL); - if (!intn) { - yasm_error_set(YASM_ERROR_NOT_CONSTANT, - N_("LEB128 requires constant values")); - return; - } - /* Warn for negative values in unsigned environment. - * This could be an error instead: the likelihood this is - * desired is very low! - */ - if (yasm_intnum_sign(intn) == -1 && !bc_leb128->sign) - yasm_warn_set(YASM_WARN_GENERAL, - N_("negative value in unsigned LEB128")); - bc_leb128->len += - yasm_intnum_size_leb128(intn, bc_leb128->sign); - break; - case DV_RAW: - yasm_error_set(YASM_ERROR_VALUE, - N_("LEB128 does not allow string constants")); - return; - } - } -} - -static yasm_bc_resolve_flags -bc_leb128_resolve(yasm_bytecode *bc, int save, - yasm_calc_bc_dist_func calc_bc_dist) -{ - bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)bc->contents; - bc->len += bc_leb128->len; - return YASM_BC_RESOLVE_MIN_LEN; -} - -static int -bc_leb128_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, - yasm_output_value_func output_value, - /*@unused@*/ yasm_output_reloc_func output_reloc) -{ - bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)bc->contents; - yasm_dataval *dv; - /*@dependent@*/ /*@null@*/ yasm_intnum *intn; - - STAILQ_FOREACH(dv, &bc_leb128->datahead, link) { - switch (dv->type) { - case DV_EMPTY: - break; - case DV_VALUE: - intn = yasm_expr_get_intnum(&dv->data.val.abs, NULL); - if (!intn) - yasm_internal_error(N_("non-constant in leb128_tobytes")); - *bufp += yasm_intnum_get_leb128(intn, *bufp, bc_leb128->sign); - break; - case DV_RAW: - yasm_internal_error(N_("raw in leb128_tobytes")); - } - } - - return 0; -} - -yasm_bytecode * -yasm_bc_create_leb128(yasm_datavalhead *datahead, int sign, unsigned long line) -{ - bytecode_leb128 *leb128 = yasm_xmalloc(sizeof(bytecode_leb128)); - - leb128->datahead = *datahead; - leb128->sign = sign; - - return yasm_bc_create_common(&bc_leb128_callback, leb128, line); -} - -static void -bc_reserve_destroy(void *contents) -{ - bytecode_reserve *reserve = (bytecode_reserve *)contents; - yasm_expr_destroy(reserve->numitems); - yasm_xfree(contents); -} - -static void -bc_reserve_print(const void *contents, FILE *f, int indent_level) -{ - const bytecode_reserve *reserve = (const bytecode_reserve *)contents; - fprintf(f, "%*s_Reserve_\n", indent_level, ""); - fprintf(f, "%*sNum Items=", indent_level, ""); - yasm_expr_print(reserve->numitems, f); - fprintf(f, "\n%*sItem Size=%u\n", indent_level, "", - (unsigned int)reserve->itemsize); -} - -static void -bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc) -{ - bytecode_reserve *reserve = (bytecode_reserve *)bc->contents; - yasm_value val; - - if (yasm_value_finalize_expr(&val, reserve->numitems)) - yasm_error_set(YASM_ERROR_TOO_COMPLEX, - N_("reserve expression too complex")); - else if (val.rel) - yasm_error_set(YASM_ERROR_NOT_ABSOLUTE, - N_("reserve expression not absolute")); - else if (val.abs && yasm_expr__contains(val.abs, YASM_EXPR_FLOAT)) - yasm_error_set(YASM_ERROR_VALUE, - N_("expression must not contain floating point value")); - reserve->numitems = val.abs; -} - -static yasm_bc_resolve_flags -bc_reserve_resolve(yasm_bytecode *bc, int save, - yasm_calc_bc_dist_func calc_bc_dist) -{ - bytecode_reserve *reserve = (bytecode_reserve *)bc->contents; - yasm_bc_resolve_flags retval = YASM_BC_RESOLVE_MIN_LEN; - /*@null@*/ yasm_expr *temp; - yasm_expr **tempp; - /*@dependent@*/ /*@null@*/ const yasm_intnum *num; - - if (!reserve->numitems) - return YASM_BC_RESOLVE_MIN_LEN; - - if (save) { - temp = NULL; - tempp = &reserve->numitems; - } else { - temp = yasm_expr_copy(reserve->numitems); - assert(temp != NULL); - tempp = &temp; - } - num = yasm_expr_get_intnum(tempp, calc_bc_dist); - if (!num) { - /* For reserve, just say non-constant quantity instead of allowing - * the circular reference error to filter through. - */ - yasm_error_set(YASM_ERROR_NOT_CONSTANT, - N_("attempt to reserve non-constant quantity of space")); - retval = YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN; - } else - bc->len += yasm_intnum_get_uint(num)*reserve->itemsize; - yasm_expr_destroy(temp); - return retval; -} - -static int -bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, - yasm_output_value_func output_value, - /*@unused@*/ yasm_output_reloc_func output_reloc) -{ - yasm_internal_error(N_("bc_reserve_tobytes called")); - /*@notreached@*/ - return 1; -} - -yasm_bytecode * -yasm_bc_create_reserve(yasm_expr *numitems, unsigned int itemsize, - unsigned long line) -{ - bytecode_reserve *reserve = yasm_xmalloc(sizeof(bytecode_reserve)); - - /*@-mustfree@*/ - reserve->numitems = numitems; - /*@=mustfree@*/ - reserve->itemsize = (unsigned char)itemsize; - - return yasm_bc_create_common(&bc_reserve_callback, reserve, line); -} - -static void -bc_incbin_destroy(void *contents) -{ - bytecode_incbin *incbin = (bytecode_incbin *)contents; - yasm_xfree(incbin->filename); - yasm_expr_destroy(incbin->start); - yasm_expr_destroy(incbin->maxlen); - yasm_xfree(contents); -} - -static void -bc_incbin_print(const void *contents, FILE *f, int indent_level) -{ - const bytecode_incbin *incbin = (const bytecode_incbin *)contents; - fprintf(f, "%*s_IncBin_\n", indent_level, ""); - fprintf(f, "%*sFilename=`%s'\n", indent_level, "", - incbin->filename); - fprintf(f, "%*sStart=", indent_level, ""); - if (!incbin->start) - fprintf(f, "nil (0)"); - else - yasm_expr_print(incbin->start, f); - fprintf(f, "%*sMax Len=", indent_level, ""); - if (!incbin->maxlen) - fprintf(f, "nil (unlimited)"); - else - yasm_expr_print(incbin->maxlen, f); - fprintf(f, "\n"); -} - -static void -bc_incbin_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc) -{ - bytecode_incbin *incbin = (bytecode_incbin *)bc->contents; - yasm_value val; - - if (yasm_value_finalize_expr(&val, incbin->start)) - yasm_error_set(YASM_ERROR_TOO_COMPLEX, - N_("start expression too complex")); - else if (val.rel) - yasm_error_set(YASM_ERROR_NOT_ABSOLUTE, - N_("start expression not absolute")); - incbin->start = val.abs; - - if (yasm_value_finalize_expr(&val, incbin->maxlen)) - yasm_error_set(YASM_ERROR_TOO_COMPLEX, - N_("maximum length expression too complex")); - else if (val.rel) - yasm_error_set(YASM_ERROR_NOT_ABSOLUTE, - N_("maximum length expression not absolute")); - incbin->maxlen = val.abs; -} - -static yasm_bc_resolve_flags -bc_incbin_resolve(yasm_bytecode *bc, int save, - yasm_calc_bc_dist_func calc_bc_dist) -{ - bytecode_incbin *incbin = (bytecode_incbin *)bc->contents; - FILE *f; - /*@null@*/ yasm_expr *temp; - yasm_expr **tempp; - /*@dependent@*/ /*@null@*/ const yasm_intnum *num; - unsigned long start = 0, maxlen = 0xFFFFFFFFUL, flen; - - /* Try to convert start to integer value */ - if (incbin->start) { - if (save) { - temp = NULL; - tempp = &incbin->start; - } else { - temp = yasm_expr_copy(incbin->start); - assert(temp != NULL); - tempp = &temp; - } - num = yasm_expr_get_intnum(tempp, calc_bc_dist); - if (num) - start = yasm_intnum_get_uint(num); - yasm_expr_destroy(temp); - if (!num) - return YASM_BC_RESOLVE_UNKNOWN_LEN; - } - - /* Try to convert maxlen to integer value */ - if (incbin->maxlen) { - if (save) { - temp = NULL; - tempp = &incbin->maxlen; - } else { - temp = yasm_expr_copy(incbin->maxlen); - assert(temp != NULL); - tempp = &temp; - } - num = yasm_expr_get_intnum(tempp, calc_bc_dist); - if (num) - maxlen = yasm_intnum_get_uint(num); - yasm_expr_destroy(temp); - if (!num) - return YASM_BC_RESOLVE_UNKNOWN_LEN; - } - - /* FIXME: Search include path for filename. Save full path back into - * filename if save is true. - */ - - /* Open file and determine its length */ - f = fopen(incbin->filename, "rb"); - if (!f) { - yasm_error_set(YASM_ERROR_IO, - N_("`incbin': unable to open file `%s'"), - incbin->filename); - return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN; - } - if (fseek(f, 0L, SEEK_END) < 0) { - yasm_error_set(YASM_ERROR_IO, - N_("`incbin': unable to seek on file `%s'"), - incbin->filename); - return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN; - } - flen = (unsigned long)ftell(f); - fclose(f); - - /* Compute length of incbin from start, maxlen, and len */ - if (start > flen) { - yasm_warn_set(YASM_WARN_GENERAL, - N_("`incbin': start past end of file `%s'"), - incbin->filename); - start = flen; - } - flen -= start; - if (incbin->maxlen) - if (maxlen < flen) - flen = maxlen; - bc->len += flen; - return YASM_BC_RESOLVE_MIN_LEN; -} - -static int -bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, - yasm_output_value_func output_value, - /*@unused@*/ yasm_output_reloc_func output_reloc) -{ - bytecode_incbin *incbin = (bytecode_incbin *)bc->contents; - FILE *f; - /*@dependent@*/ /*@null@*/ const yasm_intnum *num; - unsigned long start = 0; - - /* Convert start to integer value */ - if (incbin->start) { - num = yasm_expr_get_intnum(&incbin->start, NULL); - if (!num) - yasm_internal_error( - N_("could not determine start in bc_tobytes_incbin")); - start = yasm_intnum_get_uint(num); - } - - /* Open file */ - f = fopen(incbin->filename, "rb"); - if (!f) { - yasm_error_set(YASM_ERROR_IO, N_("`incbin': unable to open file `%s'"), - incbin->filename); - return 1; - } - - /* Seek to start of data */ - if (fseek(f, (long)start, SEEK_SET) < 0) { - yasm_error_set(YASM_ERROR_IO, - N_("`incbin': unable to seek on file `%s'"), - incbin->filename); - fclose(f); - return 1; - } - - /* Read len bytes */ - if (fread(*bufp, 1, (size_t)bc->len, f) < (size_t)bc->len) { - yasm_error_set(YASM_ERROR_IO, - N_("`incbin': unable to read %lu bytes from file `%s'"), - bc->len, incbin->filename); - fclose(f); - return 1; - } - - *bufp += bc->len; - fclose(f); - return 0; -} - -yasm_bytecode * -yasm_bc_create_incbin(char *filename, yasm_expr *start, yasm_expr *maxlen, - unsigned long line) -{ - bytecode_incbin *incbin = yasm_xmalloc(sizeof(bytecode_incbin)); - - /*@-mustfree@*/ - incbin->filename = filename; - incbin->start = start; - incbin->maxlen = maxlen; - /*@=mustfree@*/ - - return yasm_bc_create_common(&bc_incbin_callback, incbin, line); -} - -static void -bc_align_destroy(void *contents) -{ - bytecode_align *align = (bytecode_align *)contents; - if (align->boundary) - yasm_expr_destroy(align->boundary); - if (align->fill) - yasm_expr_destroy(align->fill); - if (align->maxskip) - yasm_expr_destroy(align->maxskip); - yasm_xfree(contents); -} - -static void -bc_align_print(const void *contents, FILE *f, int indent_level) -{ - const bytecode_align *align = (const bytecode_align *)contents; - fprintf(f, "%*s_Align_\n", indent_level, ""); - fprintf(f, "%*sBoundary=", indent_level, ""); - yasm_expr_print(align->boundary, f); - fprintf(f, "\n%*sFill=", indent_level, ""); - yasm_expr_print(align->fill, f); - fprintf(f, "\n%*sMax Skip=", indent_level, ""); - yasm_expr_print(align->maxskip, f); - fprintf(f, "\n"); -} - -static void -bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc) -{ - bytecode_align *align = (bytecode_align *)bc->contents; - if (!yasm_expr_get_intnum(&align->boundary, NULL)) - yasm_error_set(YASM_ERROR_NOT_CONSTANT, - N_("align boundary must be a constant")); - if (align->fill && !yasm_expr_get_intnum(&align->fill, NULL)) - yasm_error_set(YASM_ERROR_NOT_CONSTANT, - N_("align fill must be a constant")); - if (align->maxskip && !yasm_expr_get_intnum(&align->maxskip, NULL)) - yasm_error_set(YASM_ERROR_NOT_CONSTANT, - N_("align maximum skip must be a constant")); -} - -static yasm_bc_resolve_flags -bc_align_resolve(yasm_bytecode *bc, int save, - yasm_calc_bc_dist_func calc_bc_dist) -{ - bytecode_align *align = (bytecode_align *)bc->contents; - unsigned long end; - unsigned long boundary = - yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, NULL)); - - if (boundary == 0) { - bc->len = 0; - return YASM_BC_RESOLVE_MIN_LEN; - } - - end = bc->offset; - if (bc->offset & (boundary-1)) - end = (bc->offset & ~(boundary-1)) + boundary; - - bc->len = end - bc->offset; - - if (align->maxskip) { - unsigned long maxskip = - yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, NULL)); - if ((end - bc->offset) > maxskip) - bc->len = 0; - } - return YASM_BC_RESOLVE_MIN_LEN; -} - -static int -bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, - yasm_output_value_func output_value, - /*@unused@*/ yasm_output_reloc_func output_reloc) -{ - bytecode_align *align = (bytecode_align *)bc->contents; - unsigned long len; - unsigned long boundary = - yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, NULL)); - - if (boundary == 0) - return 0; - else { - unsigned long end = bc->offset; - if (bc->offset & (boundary-1)) - end = (bc->offset & ~(boundary-1)) + boundary; - len = end - bc->offset; - if (len == 0) - return 0; - if (align->maxskip) { - unsigned long maxskip = - yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, - NULL)); - if (len > maxskip) - return 0; - } - } - - if (align->fill) { - unsigned long v; - v = yasm_intnum_get_uint(yasm_expr_get_intnum(&align->fill, NULL)); - memset(*bufp, (int)v, len); - *bufp += len; - } else if (align->code_fill) { - unsigned long maxlen = 15; - while (!align->code_fill[maxlen] && maxlen>0) - maxlen--; - if (maxlen == 0) { - yasm_error_set(YASM_ERROR_GENERAL, - N_("could not find any code alignment size")); - return 1; - } - - /* Fill with maximum code fill as much as possible */ - while (len > maxlen) { - memcpy(*bufp, align->code_fill[maxlen], maxlen); - *bufp += maxlen; - len -= maxlen; - } - - if (!align->code_fill[len]) { - yasm_error_set(YASM_ERROR_VALUE, - N_("invalid alignment size %d"), len); - return 1; - } - /* Handle rest of code fill */ - memcpy(*bufp, align->code_fill[len], len); - *bufp += len; - } else { - /* Just fill with 0 */ - memset(*bufp, 0, len); - *bufp += len; - } - return 0; -} - -yasm_bytecode * -yasm_bc_create_align(yasm_expr *boundary, yasm_expr *fill, - yasm_expr *maxskip, const unsigned char **code_fill, - unsigned long line) -{ - bytecode_align *align = yasm_xmalloc(sizeof(bytecode_align)); - - align->boundary = boundary; - align->fill = fill; - align->maxskip = maxskip; - align->code_fill = code_fill; - - return yasm_bc_create_common(&bc_align_callback, align, line); -} - -static void -bc_org_destroy(void *contents) -{ - yasm_xfree(contents); -} - -static void -bc_org_print(const void *contents, FILE *f, int indent_level) -{ - const bytecode_org *org = (const bytecode_org *)contents; - fprintf(f, "%*s_Org_\n", indent_level, ""); - fprintf(f, "%*sStart=%lu\n", indent_level, "", org->start); -} - -static void -bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc) -{ -} - -static yasm_bc_resolve_flags -bc_org_resolve(yasm_bytecode *bc, int save, - yasm_calc_bc_dist_func calc_bc_dist) -{ - bytecode_org *org = (bytecode_org *)bc->contents; - - /* Check for overrun */ - if (bc->offset > org->start) { - yasm_error_set(YASM_ERROR_GENERAL, - N_("ORG overlap with already existing data")); - return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN; - } - - /* Generate space to start offset */ - bc->len = org->start - bc->offset; - return YASM_BC_RESOLVE_MIN_LEN; -} - -static int -bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, - yasm_output_value_func output_value, - /*@unused@*/ yasm_output_reloc_func output_reloc) -{ - bytecode_org *org = (bytecode_org *)bc->contents; - unsigned long len, i; - - /* Sanity check for overrun */ - if (bc->offset > org->start) { - yasm_error_set(YASM_ERROR_GENERAL, - N_("ORG overlap with already existing data")); - return 1; - } - len = org->start - bc->offset; - for (i=0; istart = start; - - return yasm_bc_create_common(&bc_org_callback, org, line); -} - -static void -bc_insn_destroy(void *contents) -{ - bytecode_insn *insn = (bytecode_insn *)contents; - if (insn->num_operands > 0) - yasm_ops_delete(&insn->operands, 0); - if (insn->num_prefixes > 0) { - int i; - for (i=0; inum_prefixes; i++) - yasm_xfree(insn->prefixes[i]); - yasm_xfree(insn->prefixes); - } - if (insn->num_segregs > 0) - yasm_xfree(insn->segregs); - yasm_xfree(contents); -} - -static void -bc_insn_print(const void *contents, FILE *f, int indent_level) -{ -} - -static void -bc_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc) -{ - bytecode_insn *insn = (bytecode_insn *)bc->contents; - int i; - yasm_insn_operand *op; - yasm_error_class eclass; - char *str, *xrefstr; - unsigned long xrefline; - - /* Simplify the operands' expressions first. */ - for (i = 0, op = yasm_ops_first(&insn->operands); - op && inum_operands; op = yasm_operand_next(op), i++) { - /* Check operand type */ - switch (op->type) { - case YASM_INSN__OPERAND_MEMORY: - /* Don't get over-ambitious here; some archs' memory expr - * parser are sensitive to the presence of *1, etc, so don't - * simplify reg*1 identities. - */ - if (op->data.ea) - op->data.ea->disp.abs = - yasm_expr__level_tree(op->data.ea->disp.abs, 1, 1, 0, - NULL, NULL, NULL, NULL); - if (yasm_error_occurred()) { - /* Add a pointer to where it was used to the error */ - yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr); - if (xrefstr) { - yasm_error_set_xref(xrefline, "%s", xrefstr); - yasm_xfree(xrefstr); - } - if (str) { - yasm_error_set(eclass, "%s in memory expression", str); - yasm_xfree(str); - } - return; - } - break; - case YASM_INSN__OPERAND_IMM: - op->data.val = - yasm_expr__level_tree(op->data.val, 1, 1, 1, NULL, NULL, - NULL, NULL); - if (yasm_error_occurred()) { - /* Add a pointer to where it was used to the error */ - yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr); - if (xrefstr) { - yasm_error_set_xref(xrefline, "%s", xrefstr); - yasm_xfree(xrefstr); - } - if (str) { - yasm_error_set(eclass, "%s in immediate expression", - str); - yasm_xfree(str); - } - return; - } - break; - default: - break; - } - } - - yasm_arch_finalize_insn(insn->arch, bc, prev_bc, insn->insn_data, - insn->num_operands, &insn->operands, - insn->num_prefixes, insn->prefixes, - insn->num_segregs, insn->segregs); -} - -static yasm_bc_resolve_flags -bc_insn_resolve(yasm_bytecode *bc, int save, - yasm_calc_bc_dist_func calc_bc_dist) -{ - yasm_internal_error(N_("bc_insn_resolve() is not implemented")); - /*@notreached@*/ - return YASM_BC_RESOLVE_ERROR; -} - -static int -bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, - yasm_output_value_func output_value, - /*@unused@*/ yasm_output_reloc_func output_reloc) -{ - yasm_internal_error(N_("bc_insn_tobytes() is not implemented")); - /*@notreached@*/ - return 1; -} - -yasm_bytecode * -yasm_bc_create_insn(yasm_arch *arch, const unsigned long insn_data[4], - int num_operands, /*@null@*/ yasm_insn_operands *operands, - unsigned long line) -{ - bytecode_insn *insn = yasm_xmalloc(sizeof(bytecode_insn)); - - insn->arch = arch; - insn->insn_data[0] = insn_data[0]; - insn->insn_data[1] = insn_data[1]; - insn->insn_data[2] = insn_data[2]; - insn->insn_data[3] = insn_data[3]; - insn->num_operands = num_operands; - if (operands) - insn->operands = *operands; /* structure copy */ - else - yasm_ops_initialize(&insn->operands); - insn->num_prefixes = 0; - insn->prefixes = NULL; - insn->num_segregs = 0; - insn->segregs = NULL; - - return yasm_bc_create_common(&bc_insn_callback, insn, line); -} - -yasm_bytecode * -yasm_bc_create_empty_insn(yasm_arch *arch, unsigned long line) -{ - bytecode_insn *insn = yasm_xmalloc(sizeof(bytecode_insn)); - - insn->arch = arch; - insn->insn_data[0] = 0; - insn->insn_data[1] = 0; - insn->insn_data[2] = 0; - insn->insn_data[3] = 0; - insn->num_operands = 0; - yasm_ops_initialize(&insn->operands); - insn->num_prefixes = 0; - insn->prefixes = NULL; - insn->num_segregs = 0; - insn->segregs = NULL; - - return yasm_bc_create_common(&bc_insn_callback, insn, line); -} - -void -yasm_bc_insn_add_prefix(yasm_bytecode *bc, const unsigned long prefix_data[4]) -{ - bytecode_insn *insn = (bytecode_insn *)bc->contents; - - assert(bc->callback == bc_insn_callback); - - insn->prefixes = - yasm_xrealloc(insn->prefixes, - (insn->num_prefixes+1)*sizeof(unsigned long *)); - insn->prefixes[insn->num_prefixes] = - yasm_xmalloc(4*sizeof(unsigned long)); - insn->prefixes[insn->num_prefixes][0] = prefix_data[0]; - insn->prefixes[insn->num_prefixes][1] = prefix_data[1]; - insn->prefixes[insn->num_prefixes][2] = prefix_data[2]; - insn->prefixes[insn->num_prefixes][3] = prefix_data[3]; - insn->num_prefixes++; -} - -void -yasm_bc_insn_add_seg_prefix(yasm_bytecode *bc, unsigned long segreg) -{ - bytecode_insn *insn = (bytecode_insn *)bc->contents; - - assert(bc->callback == bc_insn_callback); - - insn->segregs = - yasm_xrealloc(insn->segregs, - (insn->num_segregs+1)*sizeof(unsigned long)); - insn->segregs[insn->num_segregs] = segreg; - insn->num_segregs++; -} - yasm_section * yasm_bc_get_section(yasm_bytecode *bc) { @@ -1577,7 +272,7 @@ yasm_bc_tobytes(yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize, datasize = bc->len / (*multiple); /* special case for reserve bytecodes */ - if (bc->callback == &bc_reserve_callback) { + if (bc->callback->reserve) { *bufsize = datasize; *gap = 1; return NULL; /* we didn't allocate a buffer */ @@ -1606,95 +301,3 @@ yasm_bc_tobytes(yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize, N_("written length does not match optimized length")); return mybuf; } - -yasm_dataval * -yasm_dv_create_expr(yasm_expr *e) -{ - yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval)); - - retval->type = DV_VALUE; - yasm_value_initialize(&retval->data.val, e); - - return retval; -} - -yasm_dataval * -yasm_dv_create_raw(unsigned char *contents, unsigned long len) -{ - yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval)); - - retval->type = DV_RAW; - retval->data.raw.contents = contents; - retval->data.raw.len = len; - - return retval; -} - -void -yasm_dvs_destroy(yasm_datavalhead *headp) -{ - yasm_dataval *cur, *next; - - cur = STAILQ_FIRST(headp); - while (cur) { - next = STAILQ_NEXT(cur, link); - switch (cur->type) { - case DV_VALUE: - yasm_value_delete(&cur->data.val); - break; - case DV_RAW: - yasm_xfree(cur->data.raw.contents); - break; - default: - break; - } - yasm_xfree(cur); - cur = next; - } - STAILQ_INIT(headp); -} - -yasm_dataval * -yasm_dvs_append(yasm_datavalhead *headp, yasm_dataval *dv) -{ - if (dv) { - STAILQ_INSERT_TAIL(headp, dv, link); - return dv; - } - return (yasm_dataval *)NULL; -} - -void -yasm_dvs_print(const yasm_datavalhead *head, FILE *f, int indent_level) -{ - yasm_dataval *cur; - unsigned long i; - - STAILQ_FOREACH(cur, head, link) { - switch (cur->type) { - case DV_EMPTY: - fprintf(f, "%*sEmpty\n", indent_level, ""); - break; - case DV_VALUE: - fprintf(f, "%*sValue:\n", indent_level, ""); - yasm_value_print(&cur->data.val, f, indent_level+1); - break; - case DV_RAW: - fprintf(f, "%*sLength=%lu\n", indent_level, "", - cur->data.raw.len); - fprintf(f, "%*sBytes=[", indent_level, ""); - for (i=0; idata.raw.len; i++) - fprintf(f, "0x%02x, ", cur->data.raw.contents[i]); - fprintf(f, "]\n"); - break; - } - } -} - -/* Non-macro yasm_dvs_initialize() for non-YASM_LIB_INTERNAL users. */ -#undef yasm_dvs_initialize -void -yasm_dvs_initialize(yasm_datavalhead *headp) -{ - STAILQ_INIT(headp); -} diff --git a/modules/arch/lc3b/lc3bbc.c b/modules/arch/lc3b/lc3bbc.c index a4f64001..ba2517b3 100644 --- a/modules/arch/lc3b/lc3bbc.c +++ b/modules/arch/lc3b/lc3bbc.c @@ -52,7 +52,8 @@ static const yasm_bytecode_callback lc3b_bc_callback_insn = { lc3b_bc_insn_print, yasm_bc_finalize_common, lc3b_bc_insn_resolve, - lc3b_bc_insn_tobytes + lc3b_bc_insn_tobytes, + 0 }; diff --git a/modules/arch/x86/x86bc.c b/modules/arch/x86/x86bc.c index dff2666e..4e2068d6 100644 --- a/modules/arch/x86/x86bc.c +++ b/modules/arch/x86/x86bc.c @@ -83,7 +83,8 @@ static const yasm_bytecode_callback x86_bc_callback_insn = { x86_bc_insn_print, yasm_bc_finalize_common, x86_bc_insn_resolve, - x86_bc_insn_tobytes + x86_bc_insn_tobytes, + 0 }; static const yasm_bytecode_callback x86_bc_callback_jmp = { @@ -91,7 +92,8 @@ static const yasm_bytecode_callback x86_bc_callback_jmp = { x86_bc_jmp_print, yasm_bc_finalize_common, x86_bc_jmp_resolve, - x86_bc_jmp_tobytes + x86_bc_jmp_tobytes, + 0 }; static const yasm_bytecode_callback x86_bc_callback_jmpfar = { @@ -99,7 +101,8 @@ static const yasm_bytecode_callback x86_bc_callback_jmpfar = { x86_bc_jmpfar_print, yasm_bc_finalize_common, x86_bc_jmpfar_resolve, - x86_bc_jmpfar_tobytes + x86_bc_jmpfar_tobytes, + 0 }; int diff --git a/modules/dbgfmts/codeview/cv-symline.c b/modules/dbgfmts/codeview/cv-symline.c index aac2b29c..96bda2c6 100644 --- a/modules/dbgfmts/codeview/cv-symline.c +++ b/modules/dbgfmts/codeview/cv-symline.c @@ -208,7 +208,8 @@ static const yasm_bytecode_callback cv8_symhead_bc_callback = { cv8_symhead_bc_print, yasm_bc_finalize_common, cv8_symhead_bc_resolve, - cv8_symhead_bc_tobytes + cv8_symhead_bc_tobytes, + 0 }; static const yasm_bytecode_callback cv8_fileinfo_bc_callback = { @@ -216,7 +217,8 @@ static const yasm_bytecode_callback cv8_fileinfo_bc_callback = { cv8_fileinfo_bc_print, yasm_bc_finalize_common, cv8_fileinfo_bc_resolve, - cv8_fileinfo_bc_tobytes + cv8_fileinfo_bc_tobytes, + 0 }; static const yasm_bytecode_callback cv8_lineinfo_bc_callback = { @@ -224,7 +226,8 @@ static const yasm_bytecode_callback cv8_lineinfo_bc_callback = { cv8_lineinfo_bc_print, yasm_bc_finalize_common, cv8_lineinfo_bc_resolve, - cv8_lineinfo_bc_tobytes + cv8_lineinfo_bc_tobytes, + 0 }; static const yasm_bytecode_callback cv_sym_bc_callback = { @@ -232,7 +235,8 @@ static const yasm_bytecode_callback cv_sym_bc_callback = { cv_sym_bc_print, yasm_bc_finalize_common, cv_sym_bc_resolve, - cv_sym_bc_tobytes + cv_sym_bc_tobytes, + 0 }; static cv8_symhead *cv8_add_symhead(yasm_dbgfmt_cv *dbgfmt_cv, diff --git a/modules/dbgfmts/codeview/cv-type.c b/modules/dbgfmts/codeview/cv-type.c index 8951b392..51cb897b 100644 --- a/modules/dbgfmts/codeview/cv-type.c +++ b/modules/dbgfmts/codeview/cv-type.c @@ -496,7 +496,8 @@ static const yasm_bytecode_callback cv_type_bc_callback = { cv_type_bc_print, yasm_bc_finalize_common, cv_type_bc_resolve, - cv_type_bc_tobytes + cv_type_bc_tobytes, + 0 }; static cv_type *cv_type_create(yasm_dbgfmt_cv *dbgfmt_cv, unsigned long indx); diff --git a/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c b/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c index e91f005e..dfddc492 100644 --- a/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c +++ b/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c @@ -59,7 +59,8 @@ static const yasm_bytecode_callback dwarf2_head_bc_callback = { dwarf2_head_bc_print, yasm_bc_finalize_common, dwarf2_head_bc_resolve, - dwarf2_head_bc_tobytes + dwarf2_head_bc_tobytes, + 0 }; /* Section data callback function prototypes */ diff --git a/modules/dbgfmts/dwarf2/dwarf2-info.c b/modules/dbgfmts/dwarf2/dwarf2-info.c index 1f7133a1..c2692fe5 100644 --- a/modules/dbgfmts/dwarf2/dwarf2-info.c +++ b/modules/dbgfmts/dwarf2/dwarf2-info.c @@ -222,7 +222,8 @@ static const yasm_bytecode_callback dwarf2_abbrev_bc_callback = { dwarf2_abbrev_bc_print, yasm_bc_finalize_common, dwarf2_abbrev_bc_resolve, - dwarf2_abbrev_bc_tobytes + dwarf2_abbrev_bc_tobytes, + 0 }; diff --git a/modules/dbgfmts/dwarf2/dwarf2-line.c b/modules/dbgfmts/dwarf2/dwarf2-line.c index a0eb95e4..5be6581e 100644 --- a/modules/dbgfmts/dwarf2/dwarf2-line.c +++ b/modules/dbgfmts/dwarf2/dwarf2-line.c @@ -153,7 +153,8 @@ static const yasm_bytecode_callback dwarf2_spp_bc_callback = { dwarf2_spp_bc_print, yasm_bc_finalize_common, dwarf2_spp_bc_resolve, - dwarf2_spp_bc_tobytes + dwarf2_spp_bc_tobytes, + 0 }; static const yasm_bytecode_callback dwarf2_line_op_bc_callback = { @@ -161,7 +162,8 @@ static const yasm_bytecode_callback dwarf2_line_op_bc_callback = { dwarf2_line_op_bc_print, yasm_bc_finalize_common, dwarf2_line_op_bc_resolve, - dwarf2_line_op_bc_tobytes + dwarf2_line_op_bc_tobytes, + 0 }; diff --git a/modules/dbgfmts/stabs/stabs-dbgfmt.c b/modules/dbgfmts/stabs/stabs-dbgfmt.c index 1a8bf37e..30d2c8df 100644 --- a/modules/dbgfmts/stabs/stabs-dbgfmt.c +++ b/modules/dbgfmts/stabs/stabs-dbgfmt.c @@ -146,7 +146,8 @@ static const yasm_bytecode_callback stabs_bc_str_callback = { stabs_bc_str_print, yasm_bc_finalize_common, stabs_bc_str_resolve, - stabs_bc_str_tobytes + stabs_bc_str_tobytes, + 0 }; static const yasm_bytecode_callback stabs_bc_stab_callback = { @@ -154,7 +155,8 @@ static const yasm_bytecode_callback stabs_bc_stab_callback = { stabs_bc_stab_print, yasm_bc_finalize_common, stabs_bc_stab_resolve, - stabs_bc_stab_tobytes + stabs_bc_stab_tobytes, + 0 }; yasm_dbgfmt_module yasm_stabs_LTX_dbgfmt; diff --git a/tools/python-yasm/bytecode.pxi b/tools/python-yasm/bytecode.pxi index 7a14ef1c..d1c07919 100644 --- a/tools/python-yasm/bytecode.pxi +++ b/tools/python-yasm/bytecode.pxi @@ -121,6 +121,7 @@ cdef extern from "libyasm/bc-int.h": int (*tobytes) (yasm_bytecode *bc, unsigned char **bufp, void *d, yasm_output_value_func output_value, yasm_output_reloc_func output_reloc) + int reserve cdef struct yasm_bytecode: yasm_bytecode_callback *callback -- 2.40.0