From 4bfff483e51c0a4c00feb3085fc6f882b1e0f315 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Tue, 15 May 2007 07:27:26 +0000 Subject: [PATCH] Move absolute section handling into NASM parser, removing all traces of it from libyasm core. Now absolute sections are tracked locally to the parser and the parser generates EQUs directly for labels in absolute sections. Fixes #106 and #103. svn path=/trunk/yasm/; revision=1842 --- libyasm/bc-reserve.c | 20 +++- libyasm/bytecode.c | 6 + libyasm/bytecode.h | 16 +++ libyasm/section.c | 98 ++-------------- libyasm/section.h | 37 ++---- libyasm/symrec.c | 21 ---- modules/dbgfmts/dwarf2/dwarf2-line.c | 6 + modules/objfmts/coff/coff-objfmt.c | 57 +++------- modules/objfmts/elf/elf-objfmt.c | 14 +-- modules/objfmts/elf/elf-x86-amd64.c | 15 +-- modules/objfmts/elf/elf-x86-x86.c | 15 +-- modules/objfmts/macho/macho-objfmt.c | 38 +------ modules/objfmts/rdf/rdf-objfmt.c | 22 +--- modules/objfmts/xdf/xdf-objfmt.c | 27 +---- modules/parsers/nasm/nasm-parse.c | 130 +++++++++++++++++----- modules/parsers/nasm/nasm-parser.c | 3 + modules/parsers/nasm/nasm-parser.h | 10 ++ modules/parsers/nasm/tests/Makefile.inc | 4 + modules/parsers/nasm/tests/strucalign.asm | 14 +++ modules/parsers/nasm/tests/strucalign.hex | 20 ++++ modules/parsers/nasm/tests/struczero.asm | 7 ++ modules/parsers/nasm/tests/struczero.hex | 5 + 22 files changed, 256 insertions(+), 329 deletions(-) create mode 100644 modules/parsers/nasm/tests/strucalign.asm create mode 100644 modules/parsers/nasm/tests/strucalign.hex create mode 100644 modules/parsers/nasm/tests/struczero.asm create mode 100644 modules/parsers/nasm/tests/struczero.hex diff --git a/libyasm/bc-reserve.c b/libyasm/bc-reserve.c index 8ffa98b9..9acde378 100644 --- a/libyasm/bc-reserve.c +++ b/libyasm/bc-reserve.c @@ -44,7 +44,7 @@ typedef struct bytecode_reserve { /*@only@*/ /*@null@*/ yasm_expr *numitems; /* number of items to reserve */ - unsigned char itemsize; /* size of each item (in bytes) */ + unsigned int itemsize; /* size of each item (in bytes) */ } bytecode_reserve; static void bc_reserve_destroy(void *contents); @@ -83,8 +83,7 @@ bc_reserve_print(const void *contents, FILE *f, int indent_level) 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); + fprintf(f, "\n%*sItem Size=%u\n", indent_level, "", reserve->itemsize); } static void @@ -128,7 +127,20 @@ yasm_bc_create_reserve(yasm_expr *numitems, unsigned int itemsize, /*@-mustfree@*/ reserve->numitems = numitems; /*@=mustfree@*/ - reserve->itemsize = (unsigned char)itemsize; + reserve->itemsize = itemsize; return yasm_bc_create_common(&bc_reserve_callback, reserve, line); } + +const yasm_expr * +yasm_bc_reserve_numitems(yasm_bytecode *bc, unsigned int *itemsize) +{ + bytecode_reserve *reserve; + + if (bc->callback != &bc_reserve_callback) + return NULL; + + reserve = (bytecode_reserve *)bc->contents; + *itemsize = reserve->itemsize; + return reserve->numitems; +} diff --git a/libyasm/bytecode.c b/libyasm/bytecode.c index d785e9b8..41fe3ca2 100644 --- a/libyasm/bytecode.c +++ b/libyasm/bytecode.c @@ -339,3 +339,9 @@ yasm_bc_get_multiple(yasm_bytecode *bc, long *multiple, int calc_bc_dist) } return 0; } + +const yasm_expr * +yasm_bc_get_multiple_expr(const yasm_bytecode *bc) +{ + return bc->multiple; +} diff --git a/libyasm/bytecode.h b/libyasm/bytecode.h index 26995216..86c3c7e5 100644 --- a/libyasm/bytecode.h +++ b/libyasm/bytecode.h @@ -176,6 +176,16 @@ void yasm_bc_set_multiple(yasm_bytecode *bc, /*@keep@*/ yasm_expr *e); (/*@only@*/ yasm_expr *numitems, unsigned int itemsize, unsigned long line); +/** Get the number of items and itemsize for a reserve bytecode. If bc + * is not a reserve bytecode, returns NULL. + * \param bc bytecode + * \param itemsize reserved size (in bytes) for each item (returned) + * \return NULL if bc is not a reserve bytecode, otherwise an expression + * for the number of items to reserve. + */ +/*@null@*/ const yasm_expr *yasm_bc_reserve_numitems + (yasm_bytecode *bc, /*@out@*/ unsigned int *itemsize); + /** Create a bytecode that includes a binary file verbatim. * \param filename path to binary file (kept, do not free) * \param start starting location in file (in bytes) to read data from @@ -388,6 +398,12 @@ int yasm_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val, int yasm_bc_get_multiple(yasm_bytecode *bc, /*@out@*/ long *multiple, int calc_bc_dist); +/** Get the bytecode multiple value as an expression. + * \param bc bytecode + * \return Bytecode multiple, NULL if =1. + */ +const yasm_expr *yasm_bc_get_multiple_expr(const yasm_bytecode *bc); + /** Create a new data value from an expression. * \param expn expression * \return Newly allocated data value. diff --git a/libyasm/section.c b/libyasm/section.c index 6ee8eeae..15549c96 100644 --- a/libyasm/section.c +++ b/libyasm/section.c @@ -61,21 +61,7 @@ struct yasm_section { /*@dependent@*/ yasm_object *object; /* Pointer to parent object */ - enum { SECTION_GENERAL, SECTION_ABSOLUTE } type; - - union { - /* SECTION_GENERAL data */ - struct { - /*@owned@*/ char *name; /* strdup()'ed name (given by user) */ - } general; - /* SECTION_ABSOLUTE data */ - struct { - /* Internally created first symrec in section. Used by - * yasm_expr__level_tree during absolute reference expansion. - */ - /*@dependent@*/ yasm_symrec *first; - } absolute; - } data; + /*@owned@*/ char *name; /* strdup()'ed name (given by user) */ /* associated data; NULL if none */ /*@null@*/ /*@only@*/ yasm__assoc_data *assoc_data; @@ -325,8 +311,7 @@ yasm_object_get_general(yasm_object *object, const char *name, * that name. */ STAILQ_FOREACH(s, &object->sections, link) { - if (s->type == SECTION_GENERAL && - strcmp(s->data.general.name, name) == 0) { + if (strcmp(s->name, name) == 0) { *isnew = 0; return s; } @@ -339,8 +324,7 @@ yasm_object_get_general(yasm_object *object, const char *name, STAILQ_INSERT_TAIL(&object->sections, s, link); s->object = object; - s->type = SECTION_GENERAL; - s->data.general.name = yasm__xstrdup(name); + s->name = yasm__xstrdup(name); s->assoc_data = NULL; if (start) s->start = start; @@ -372,45 +356,6 @@ yasm_object_get_general(yasm_object *object, const char *name, } /*@=onlytrans@*/ -/*@-onlytrans@*/ -yasm_section * -yasm_object_create_absolute(yasm_object *object, yasm_expr *start, - unsigned long line) -{ - yasm_section *s; - yasm_bytecode *bc; - - s = yasm_xcalloc(1, sizeof(yasm_section)); - STAILQ_INSERT_TAIL(&object->sections, s, link); - - s->object = object; - s->type = SECTION_ABSOLUTE; - s->start = start; - - /* Initialize bytecodes with one empty bytecode (acts as "prior" for first - * real bytecode in section. - */ - STAILQ_INIT(&s->bcs); - bc = yasm_bc_create_common(NULL, NULL, 0); - bc->section = s; - bc->offset = 0; - STAILQ_INSERT_TAIL(&s->bcs, bc, link); - - /* Initialize relocs */ - STAILQ_INIT(&s->relocs); - s->destroy_reloc = NULL; - - s->data.absolute.first = - yasm_symtab_define_label(object->symtab, ".absstart", bc, 0, 0); - - s->code = 0; - s->res_only = 1; - s->def = 0; - - return s; -} -/*@=onlytrans@*/ - int yasm_object_directive(yasm_object *object, const char *name, const char *parser, yasm_valparamhead *valparams, @@ -440,12 +385,6 @@ yasm_object_set_source_fn(yasm_object *object, const char *src_filename) object->src_filename = yasm__xstrdup(src_filename); } -int -yasm_section_is_absolute(yasm_section *sect) -{ - return (sect->type == SECTION_ABSOLUTE); -} - int yasm_section_is_code(yasm_section *sect) { @@ -597,8 +536,7 @@ yasm_object_find_general(yasm_object *object, const char *name) yasm_section *cur; STAILQ_FOREACH(cur, &object->sections, link) { - if (cur->type == SECTION_GENERAL && - strcmp(cur->data.general.name, name) == 0) + if (strcmp(cur->name, name) == 0) return cur; } return NULL; @@ -690,17 +628,7 @@ yasm_section_bcs_traverse(yasm_section *sect, const char * yasm_section_get_name(const yasm_section *sect) { - if (sect->type == SECTION_GENERAL) - return sect->data.general.name; - return NULL; -} - -yasm_symrec * -yasm_section_abs_get_sym(const yasm_section *sect) -{ - if (sect->type == SECTION_ABSOLUTE) - return sect->data.absolute.first; - return NULL; + return sect->name; } void @@ -739,9 +667,7 @@ yasm_section_destroy(yasm_section *sect) if (!sect) return; - if (sect->type == SECTION_GENERAL) { - yasm_xfree(sect->data.general.name); - } + yasm_xfree(sect->name); yasm__assoc_data_destroy(sect->assoc_data); yasm_expr_destroy(sect->start); @@ -774,17 +700,7 @@ yasm_section_print(const yasm_section *sect, FILE *f, int indent_level, return; } - fprintf(f, "%*stype=", indent_level, ""); - switch (sect->type) { - case SECTION_GENERAL: - fprintf(f, "general\n%*sname=%s\n", indent_level, "", - sect->data.general.name); - break; - case SECTION_ABSOLUTE: - fprintf(f, "absolute\n"); - break; - } - + fprintf(f, "%*sname=%s\n", indent_level, "", sect->name); fprintf(f, "%*sstart=", indent_level, ""); yasm_expr_print(sect->start, f); fprintf(f, "\n"); diff --git a/libyasm/section.h b/libyasm/section.h index a99a8430..27ccb298 100644 --- a/libyasm/section.h +++ b/libyasm/section.h @@ -57,8 +57,10 @@ struct yasm_object { /*@owned@*/ yasm_objfmt *objfmt; /**< Object format */ /*@owned@*/ yasm_dbgfmt *dbgfmt; /**< Debug format */ - /** Currently active section. Used by some directives. */ - /*@dependent@*/ yasm_section *cur_section; + /** Currently active section. Used by some directives. NULL if no + * section active. + */ + /*@dependent@*/ /*@null@*/ yasm_section *cur_section; #ifdef YASM_LIB_INTERNAL /** Linked list of sections. */ @@ -108,16 +110,6 @@ struct yasm_object { /*@null@*/ /*@only@*/ yasm_expr *start, unsigned long align, int code, int res_only, /*@out@*/ int *isnew, unsigned long line); -/** Create a new absolute section. No checking is performed at creation to - * check for overlaps with other absolute sections. - * \param object object - * \param start starting address (expression) - * \param line virtual line of section declaration - * \return New section. - */ -/*@dependent@*/ yasm_section *yasm_object_create_absolute - (yasm_object *object, /*@keep@*/ yasm_expr *start, unsigned long line); - /** Handle a directive. Passed down to object format, debug format, or * architecture as appropriate. * \param object object @@ -186,12 +178,6 @@ void yasm_object_set_source_fn(yasm_object *object, const char *src_filename); */ void yasm_object_optimize(yasm_object *object, yasm_errwarns *errwarns); -/** Determine if a section is absolute or general. - * \param sect section - * \return Nonzero if section is absolute. - */ -int yasm_section_is_absolute(yasm_section *sect); - /** Determine if a section is flagged to contain code. * \param sect section * \return Nonzero if section is flagged to contain code. @@ -326,17 +312,9 @@ int yasm_section_bcs_traverse /** Get name of a section. * \param sect section - * \return Section name, or NULL if section is absolute. - */ -/*@observer@*/ /*@null@*/ const char *yasm_section_get_name - (const yasm_section *sect); - -/** Get starting symbol of an absolute section. - * \param sect section - * \return Starting symrec, or NULL if section is not absolute. + * \return Section name. */ -/*@dependent@*/ /*@null@*/ yasm_symrec *yasm_section_abs_get_sym - (const yasm_section *sect); +/*@observer@*/ const char *yasm_section_get_name(const yasm_section *sect); /** Change starting address of a section. * \param sect section @@ -348,8 +326,7 @@ void yasm_section_set_start(yasm_section *sect, /*@only@*/ yasm_expr *start, /** Get starting address of a section. * \param sect section - * \return Starting address (may be a complex expression if section is - * absolute). + * \return Starting address. */ /*@observer@*/ const yasm_expr *yasm_section_get_start (const yasm_section *sect); diff --git a/libyasm/symrec.c b/libyasm/symrec.c index 2754fe44..bef0eaa9 100644 --- a/libyasm/symrec.c +++ b/libyasm/symrec.c @@ -375,7 +375,6 @@ static int symtab_parser_finalize_checksym(yasm_symrec *sym, /*@null@*/ void *d) { symtab_finalize_info *info = (symtab_finalize_info *)d; - yasm_section *sect; /* error if a symbol is used but never defined or extern/common declared */ if ((sym->status & YASM_SYM_USED) && !(sym->status & YASM_SYM_DEFINED) && @@ -391,26 +390,6 @@ symtab_parser_finalize_checksym(yasm_symrec *sym, /*@null@*/ void *d) } } - /* Change labels in absolute sections into EQUs with value - * absolute start expr + (label bc - first bc in abs section). - * Don't worry about possible circular references because that will get - * caught in EQU expansion. - */ - if (sym->type == SYM_LABEL && sym->value.precbc - && (sect = yasm_bc_get_section(sym->value.precbc)) - && yasm_section_is_absolute(sect)) { - sym->type = SYM_EQU; - sym->value.expn = yasm_expr_create_tree( - yasm_expr_create(YASM_EXPR_SUB, - yasm_expr_precbc(sym->value.precbc), - yasm_expr_precbc(yasm_section_bcs_first(sect)), - sym->def_line), - YASM_EXPR_ADD, - yasm_expr_copy(yasm_section_get_start(sect)), - sym->def_line); - sym->status |= YASM_SYM_VALUED; - } - return 0; } diff --git a/modules/dbgfmts/dwarf2/dwarf2-line.c b/modules/dbgfmts/dwarf2/dwarf2-line.c index f9875996..c85763cf 100644 --- a/modules/dbgfmts/dwarf2/dwarf2-line.c +++ b/modules/dbgfmts/dwarf2/dwarf2-line.c @@ -873,6 +873,12 @@ yasm_dwarf2__dir_loc(yasm_object *object, yasm_valparamhead *valparams, loc->line = yasm_intnum_get_uint(intn); /* Generate new section data if it doesn't already exist */ + if (!object->cur_section) { + yasm_error_set(YASM_ERROR_SYNTAX, + N_("[%s] can only be used inside of a section"), "loc"); + yasm_xfree(loc); + return; + } dsd = yasm_section_get_data(object->cur_section, &yasm_dwarf2__section_data_cb); if (!dsd) { diff --git a/modules/objfmts/coff/coff-objfmt.c b/modules/objfmts/coff/coff-objfmt.c index 72b2bdc6..b7208fa7 100644 --- a/modules/objfmts/coff/coff-objfmt.c +++ b/modules/objfmts/coff/coff-objfmt.c @@ -383,10 +383,6 @@ coff_objfmt_init_remaining_section(yasm_section *sect, /*@null@*/ void *d) /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d; /*@dependent@*/ /*@null@*/ coff_section_data *csd; - /* Skip absolute sections */ - if (yasm_section_is_absolute(sect)) - return 0; - assert(info != NULL); csd = yasm_section_get_data(sect, &coff_section_data_cb); if (!csd) { @@ -411,10 +407,6 @@ coff_objfmt_set_section_addr(yasm_section *sect, /*@null@*/ void *d) /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d; /*@dependent@*/ /*@null@*/ coff_section_data *csd; - /* Don't output absolute sections */ - if (yasm_section_is_absolute(sect)) - return 0; - assert(info != NULL); csd = yasm_section_get_data(sect, &coff_section_data_cb); assert(csd != NULL); @@ -744,10 +736,6 @@ coff_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d) coff_reloc *reloc; unsigned char *localbuf; - /* Don't output absolute sections into the section table */ - if (yasm_section_is_absolute(sect)) - return 0; - assert(info != NULL); csd = yasm_section_get_data(sect, &coff_section_data_cb); assert(csd != NULL); @@ -849,10 +837,6 @@ coff_objfmt_output_sectstr(yasm_section *sect, /*@null@*/ void *d) const char *name; size_t len; - /* Don't output absolute sections into the section table */ - if (yasm_section_is_absolute(sect)) - return 0; - /* Add to strtab if in win32 format and name > 8 chars */ if (!info->objfmt_coff->win32) return 0; @@ -873,10 +857,6 @@ coff_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d) unsigned char *localbuf; unsigned long align = yasm_section_get_align(sect); - /* Don't output absolute sections into the section table */ - if (yasm_section_is_absolute(sect)) - return 0; - assert(info != NULL); objfmt_coff = info->objfmt_coff; csd = yasm_section_get_data(sect, &coff_section_data_cb); @@ -1011,21 +991,6 @@ coff_objfmt_output_sym(yasm_symrec *sym, /*@null@*/ void *d) nreloc = csectd->nreloc; if (COFF_SET_VMA) value = csectd->addr; - } else if (yasm_section_is_absolute(sect)) { - yasm_expr *abs_start; - - abs_start = yasm_expr_copy(yasm_section_get_start(sect)); - intn = yasm_expr_get_intnum(&abs_start, 1); - if (!intn) { - yasm_error_set(YASM_ERROR_NOT_CONSTANT, - N_("absolute section start not an integer expression")); - yasm_errwarn_propagate(info->errwarns, - abs_start->line); - } else - value = yasm_intnum_get_uint(intn); - yasm_expr_destroy(abs_start); - - scnum = 0xffff; /* -1 = absolute symbol */ } else yasm_internal_error(N_("didn't understand section")); if (precbc) @@ -1807,8 +1772,14 @@ procframe_checkstate(yasm_objfmt_coff *objfmt_coff, const char *dirname) * XXX: There should be a better way to do this. */ static yasm_symrec * -get_curpos(yasm_object *object, unsigned long line) +get_curpos(yasm_object *object, const char *dirname, unsigned long line) { + if (!object->cur_section) { + yasm_error_set(YASM_ERROR_SYNTAX, + N_("[%s] can only be used inside of a section"), + dirname); + return NULL; + } return yasm_symtab_define_curpos(object->symtab, "$", yasm_section_bcs_last(object->cur_section), line); } @@ -1835,7 +1806,7 @@ dir_pushreg(yasm_object *object, yasm_valparamhead *valparams, /* Generate a PUSH_NONVOL unwind code. */ code = yasm_xmalloc(sizeof(coff_unwind_code)); code->proc = objfmt_coff->unwind->proc; - code->loc = get_curpos(object, line); + code->loc = get_curpos(object, "PUSHREG", line); code->opcode = UWOP_PUSH_NONVOL; code->info = (unsigned int)(*reg & 0xF); yasm_value_initialize(&code->off, NULL, 0); @@ -1875,7 +1846,7 @@ dir_setframe(yasm_object *object, yasm_valparamhead *valparams, /* Generate a SET_FPREG unwind code */ code = yasm_xmalloc(sizeof(coff_unwind_code)); code->proc = objfmt_coff->unwind->proc; - code->loc = get_curpos(object, line); + code->loc = get_curpos(object, "SETFRAME", line); code->opcode = UWOP_SET_FPREG; code->info = (unsigned int)(*reg & 0xF); yasm_value_initialize(&code->off, yasm_expr_copy(off), 8); @@ -1910,7 +1881,7 @@ dir_allocstack(yasm_object *object, yasm_valparamhead *valparams, */ code = yasm_xmalloc(sizeof(coff_unwind_code)); code->proc = objfmt_coff->unwind->proc; - code->loc = get_curpos(object, line); + code->loc = get_curpos(object, "ALLOCSTACK", line); code->opcode = UWOP_ALLOC_SMALL; code->info = 0; yasm_value_initialize(&code->off, vp->param, 7); @@ -1957,7 +1928,7 @@ dir_save_common(yasm_object *object, yasm_valparamhead *valparams, */ code = yasm_xmalloc(sizeof(coff_unwind_code)); code->proc = objfmt_coff->unwind->proc; - code->loc = get_curpos(object, line); + code->loc = get_curpos(object, name, line); code->opcode = op; code->info = (unsigned int)(*reg & 0xF); yasm_value_initialize(&code->off, vp->param, 16); @@ -1995,7 +1966,7 @@ dir_pushframe(yasm_object *object, /*@null@*/ yasm_valparamhead *valparams, */ code = yasm_xmalloc(sizeof(coff_unwind_code)); code->proc = objfmt_coff->unwind->proc; - code->loc = get_curpos(object, line); + code->loc = get_curpos(object, "PUSHFRAME", line); code->opcode = UWOP_PUSH_MACHFRAME; code->info = vp && (vp->val || vp->param); yasm_value_initialize(&code->off, NULL, 0); @@ -2011,7 +1982,7 @@ dir_endprolog(yasm_object *object, /*@null@*/ yasm_valparamhead *valparams, return; objfmt_coff->done_prolog = line; - objfmt_coff->unwind->prolog = get_curpos(object, line); + objfmt_coff->unwind->prolog = get_curpos(object, "ENDPROLOG", line); } static void @@ -2047,7 +2018,7 @@ dir_endproc_frame(yasm_object *object, /*@null@*/ yasm_valparamhead *valparams, proc_sym = objfmt_coff->unwind->proc; - curpos = get_curpos(object, line); + curpos = get_curpos(object, "ENDPROC_FRAME", line); /* * Add unwind info to end of .xdata section. diff --git a/modules/objfmts/elf/elf-objfmt.c b/modules/objfmts/elf/elf-objfmt.c index eb4e662c..84a27e3b 100644 --- a/modules/objfmts/elf/elf-objfmt.c +++ b/modules/objfmts/elf/elf-objfmt.c @@ -272,7 +272,7 @@ elf_objfmt_build_symtab(yasm_symrec *sym, /*@null@*/ void *d) /* Locals (except when debugging) do not need to be * in the symbol table, unless they're a section. */ - if (sect && !yasm_section_is_absolute(sect) && + if (sect && strcmp(yasm_symrec_get_name(sym), yasm_section_get_name(sect))==0) is_sect = 1; #if 0 @@ -608,8 +608,8 @@ elf_objfmt_create_dbg_secthead(yasm_section *sect, /*@null@*/ void *d) elf_strtab_entry *name; shead = yasm_section_get_data(sect, &elf_section_data); - if (yasm_section_is_absolute(sect) || shead) - return 0; /* only create new secthead if missing and non-absolute */ + if (shead) + return 0; /* only create new secthead if missing */ sectname = yasm_section_get_name(sect); name = elf_strtab_append_str(info->objfmt_elf->shstrtab, sectname); @@ -644,10 +644,6 @@ elf_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d) char *relname; const char *sectname; - /* Don't output absolute sections into the section table */ - if (yasm_section_is_absolute(sect)) - return 0; - if (info == NULL) yasm_internal_error("null info struct"); shead = yasm_section_get_data(sect, &elf_section_data); @@ -711,10 +707,6 @@ elf_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d) /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d; /*@dependent@*/ /*@null@*/ elf_secthead *shead; - /* Don't output absolute sections into the section table */ - if (yasm_section_is_absolute(sect)) - return 0; - if (info == NULL) yasm_internal_error("null info struct"); shead = yasm_section_get_data(sect, &elf_section_data); diff --git a/modules/objfmts/elf/elf-x86-amd64.c b/modules/objfmts/elf/elf-x86-amd64.c index 0c5ba3c9..c1318d64 100644 --- a/modules/objfmts/elf/elf-x86-amd64.c +++ b/modules/objfmts/elf/elf-x86-amd64.c @@ -65,16 +65,11 @@ elf_x86_amd64_write_symtab_entry(unsigned char *bufp, YASM_WRITE_8(bufp, ELF64_ST_INFO(entry->bind, entry->type)); YASM_WRITE_8(bufp, ELF64_ST_OTHER(entry->vis)); if (entry->sect) { - if (yasm_section_is_absolute(entry->sect)) { - YASM_WRITE_16_L(bufp, SHN_ABS); - } else { - elf_secthead *shead = yasm_section_get_data(entry->sect, - &elf_section_data); - if (!shead) - yasm_internal_error( - N_("symbol references section without data")); - YASM_WRITE_16_L(bufp, shead->index); - } + elf_secthead *shead = + yasm_section_get_data(entry->sect, &elf_section_data); + if (!shead) + yasm_internal_error(N_("symbol references section without data")); + YASM_WRITE_16_L(bufp, shead->index); } else { YASM_WRITE_16_L(bufp, entry->index); } diff --git a/modules/objfmts/elf/elf-x86-x86.c b/modules/objfmts/elf/elf-x86-x86.c index c6b41c0e..00d7a047 100644 --- a/modules/objfmts/elf/elf-x86-x86.c +++ b/modules/objfmts/elf/elf-x86-x86.c @@ -70,16 +70,11 @@ elf_x86_x86_write_symtab_entry(unsigned char *bufp, YASM_WRITE_8(bufp, ELF32_ST_INFO(entry->bind, entry->type)); YASM_WRITE_8(bufp, ELF32_ST_OTHER(entry->vis)); if (entry->sect) { - if (yasm_section_is_absolute(entry->sect)) { - YASM_WRITE_16_L(bufp, SHN_ABS); - } else { - elf_secthead *shead = yasm_section_get_data(entry->sect, - &elf_section_data); - if (!shead) - yasm_internal_error( - N_("symbol references section without data")); - YASM_WRITE_16_L(bufp, shead->index); - } + elf_secthead *shead = + yasm_section_get_data(entry->sect, &elf_section_data); + if (!shead) + yasm_internal_error(N_("symbol references section without data")); + YASM_WRITE_16_L(bufp, shead->index); } else { YASM_WRITE_16_L(bufp, entry->index); } diff --git a/modules/objfmts/macho/macho-objfmt.c b/modules/objfmts/macho/macho-objfmt.c index ad60d89d..70f463ba 100644 --- a/modules/objfmts/macho/macho-objfmt.c +++ b/modules/objfmts/macho/macho-objfmt.c @@ -634,10 +634,6 @@ macho_objfmt_output_section(yasm_section *sect, /*@null@ */ void *d) (macho_objfmt_output_info *) d; /*@dependent@ *//*@null@ */ macho_section_data *msd; - /* FIXME: Don't output absolute sections into the section table */ - if (yasm_section_is_absolute(sect)) - return 0; - assert(info != NULL); msd = yasm_section_get_data(sect, &macho_section_data_cb); assert(msd != NULL); @@ -659,10 +655,6 @@ macho_objfmt_output_relocs(yasm_section *sect, /*@null@*/ void *d) /*@dependent@*/ /*@null@*/ macho_section_data *msd; macho_reloc *reloc; - /* FIXME: Don't output absolute sections into the section table */ - if (yasm_section_is_absolute(sect)) - return 0; - reloc = (macho_reloc *)yasm_section_relocs_first(sect); while (reloc) { unsigned char *localbuf = info->buf; @@ -744,10 +736,6 @@ macho_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d) /*@dependent@*/ /*@null@*/ macho_section_data *msd; unsigned char *localbuf; - /* Don't output absolute sections into the section table */ - if (yasm_section_is_absolute(sect)) - return 0; - assert(info != NULL); objfmt_macho = info->objfmt_macho; msd = yasm_section_get_data(sect, &macho_section_data_cb); @@ -894,26 +882,8 @@ macho_objfmt_output_symtable(yasm_symrec *sym, /*@null@*/ void *d) if (msd) { scnum = msd->scnum; n_type = N_SECT; - } else { - if (yasm_section_is_absolute(sect)) { - yasm_expr *abs_start; - - abs_start = - yasm_expr_copy(yasm_section_get_start(sect)); - intn = yasm_expr_get_intnum(&abs_start, 1); - if (!intn) { - yasm_error_set(YASM_ERROR_NOT_CONSTANT, - N_("absolute section start not an integer expression")); - yasm_errwarn_propagate(info->errwarns, - abs_start->line); - } else - value = yasm_intnum_get_uint(intn); - yasm_expr_destroy(abs_start); - - scnum = -2; /* -2 = absolute symbol */ - } else - yasm_internal_error(N_("didn't understand section")); - } + } else + yasm_internal_error(N_("didn't understand section")); if (precbc) value += yasm_bc_next_offset(precbc); /* all values are subject to correction: base offset is first @@ -1017,10 +987,6 @@ macho_objfmt_calc_sectsize(yasm_section *sect, /*@null@ */ void *d) (macho_objfmt_output_info *) d; /*@dependent@ *//*@null@ */ macho_section_data *msd; - /* FIXME: Don't output absolute sections into the section table */ - if (yasm_section_is_absolute(sect)) - return 0; - assert(info != NULL); msd = yasm_section_get_data(sect, &macho_section_data_cb); assert(msd != NULL); diff --git a/modules/objfmts/rdf/rdf-objfmt.c b/modules/objfmts/rdf/rdf-objfmt.c index f9fc2268..aa583a5b 100644 --- a/modules/objfmts/rdf/rdf-objfmt.c +++ b/modules/objfmts/rdf/rdf-objfmt.c @@ -346,10 +346,6 @@ rdf_objfmt_output_section_mem(yasm_section *sect, /*@null@*/ void *d) /*@dependent@*/ /*@null@*/ rdf_section_data *rsd; unsigned long size; - /* Don't output absolute sections */ - if (yasm_section_is_absolute(sect)) - return 0; - assert(info != NULL); rsd = yasm_section_get_data(sect, &rdf_section_data_cb); assert(rsd != NULL); @@ -392,10 +388,6 @@ rdf_objfmt_output_section_reloc(yasm_section *sect, /*@null@*/ void *d) /*@dependent@*/ /*@null@*/ rdf_section_data *rsd; rdf_reloc *reloc; - /* Don't output absolute sections */ - if (yasm_section_is_absolute(sect)) - return 0; - assert(info != NULL); rsd = yasm_section_get_data(sect, &rdf_section_data_cb); assert(rsd != NULL); @@ -440,10 +432,6 @@ rdf_objfmt_output_section_file(yasm_section *sect, /*@null@*/ void *d) /*@dependent@*/ /*@null@*/ rdf_section_data *rsd; unsigned char *localbuf; - /* Don't output absolute sections */ - if (yasm_section_is_absolute(sect)) - return 0; - assert(info != NULL); rsd = yasm_section_get_data(sect, &rdf_section_data_cb); assert(rsd != NULL); @@ -572,15 +560,9 @@ rdf_objfmt_output_sym(yasm_symrec *sym, /*@null@*/ void *d) /* it's a label: get value and offset. */ csectd = yasm_section_get_data(sect, &rdf_section_data_cb); - if (csectd) { + if (csectd) scnum = csectd->scnum; - } else if (yasm_section_is_absolute(sect)) { - yasm_warn_set(YASM_WARN_GENERAL, - N_("rdf does not support exporting absolutes")); - yasm_errwarn_propagate(info->errwarns, - yasm_symrec_get_decl_line(sym)); - return 0; - } else + else yasm_internal_error(N_("didn't understand section")); value = yasm_bc_next_offset(precbc); } else if (yasm_symrec_get_equ(sym)) { diff --git a/modules/objfmts/xdf/xdf-objfmt.c b/modules/objfmts/xdf/xdf-objfmt.c index 0c924e85..5c23c4ed 100644 --- a/modules/objfmts/xdf/xdf-objfmt.c +++ b/modules/objfmts/xdf/xdf-objfmt.c @@ -291,10 +291,6 @@ xdf_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d) long pos; xdf_reloc *reloc; - /* FIXME: Don't output absolute sections into the section table */ - if (yasm_section_is_absolute(sect)) - return 0; - assert(info != NULL); xsd = yasm_section_get_data(sect, &xdf_section_data_cb); assert(xsd != NULL); @@ -388,10 +384,6 @@ xdf_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d) /*@null@*/ xdf_symrec_data *xsymd; unsigned char *localbuf; - /* Don't output absolute sections into the section table */ - if (yasm_section_is_absolute(sect)) - return 0; - assert(info != NULL); objfmt_xdf = info->objfmt_xdf; xsd = yasm_section_get_data(sect, &xdf_section_data_cb); @@ -489,24 +481,9 @@ xdf_objfmt_output_sym(yasm_symrec *sym, /*@null@*/ void *d) if (sect) { /*@dependent@*/ /*@null@*/ xdf_section_data *csectd; csectd = yasm_section_get_data(sect, &xdf_section_data_cb); - if (csectd) { + if (csectd) scnum = csectd->scnum; - } else if (yasm_section_is_absolute(sect)) { - yasm_expr *abs_start; - - abs_start = yasm_expr_copy(yasm_section_get_start(sect)); - intn = yasm_expr_get_intnum(&abs_start, 1); - if (!intn) { - yasm_error_set(YASM_ERROR_NOT_CONSTANT, - N_("absolute section start not an integer expression")); - yasm_errwarn_propagate(info->errwarns, abs_start->line); - } else - value = yasm_intnum_get_uint(intn); - yasm_expr_destroy(abs_start); - - flags |= XDF_SYM_EQU; - scnum = -2; /* -2 = absolute symbol */ - } else + else yasm_internal_error(N_("didn't understand section")); if (precbc) value += yasm_bc_next_offset(precbc); diff --git a/modules/parsers/nasm/nasm-parse.c b/modules/parsers/nasm/nasm-parse.c index d3ddbb3e..0202eae0 100644 --- a/modules/parsers/nasm/nasm-parse.c +++ b/modules/parsers/nasm/nasm-parse.c @@ -197,11 +197,41 @@ nasm_parser_parse(yasm_parser_nasm *parser_nasm) demand_eol(); } + if (parser_nasm->abspos) { + /* If we're inside an absolute section, just add to the absolute + * position rather than appending bytecodes to a section. + * Only RES* are allowed in an absolute section, so this is easy. + */ + if (bc) { + /*@null@*/ const yasm_expr *numitems, *multiple; + unsigned int itemsize; + numitems = yasm_bc_reserve_numitems(bc, &itemsize); + if (numitems) { + yasm_expr *e; + e = yasm_expr_create(YASM_EXPR_MUL, + yasm_expr_expr(yasm_expr_copy(numitems)), + yasm_expr_int(yasm_intnum_create_uint(itemsize)), + cur_line); + multiple = yasm_bc_get_multiple_expr(bc); + if (multiple) + e = yasm_expr_create_tree(e, YASM_EXPR_MUL, + yasm_expr_copy(multiple), + cur_line); + parser_nasm->abspos = yasm_expr_create_tree( + parser_nasm->abspos, YASM_EXPR_ADD, e, cur_line); + } else + yasm_error_set(YASM_ERROR_SYNTAX, + N_("only RES* allowed within absolute section")); + yasm_bc_destroy(bc); + } + temp_bc = NULL; + } else { + temp_bc = yasm_section_bcs_append(cursect, bc); + if (temp_bc) + parser_nasm->prev_bc = temp_bc; + } yasm_errwarn_propagate(parser_nasm->errwarns, cur_line); - temp_bc = yasm_section_bcs_append(cursect, bc); - if (temp_bc) - parser_nasm->prev_bc = temp_bc; if (parser_nasm->save_input) yasm_linemap_add_source(parser_nasm->linemap, temp_bc, @@ -1024,15 +1054,23 @@ parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type) break; case '$': /* "$" references the current assembly position */ - sym = yasm_symtab_define_curpos(p_symtab, "$", - parser_nasm->prev_bc, cur_line); - e = p_expr_new_ident(yasm_expr_sym(sym)); + if (parser_nasm->abspos) + e = yasm_expr_copy(parser_nasm->abspos); + else { + sym = yasm_symtab_define_curpos(p_symtab, "$", + parser_nasm->prev_bc, cur_line); + e = p_expr_new_ident(yasm_expr_sym(sym)); + } break; case START_SECTION_ID: /* "$$" references the start of the current section */ - sym = yasm_symtab_define_label(p_symtab, "$$", - yasm_section_bcs_first(cursect), 0, cur_line); - e = p_expr_new_ident(yasm_expr_sym(sym)); + if (parser_nasm->absstart) + e = yasm_expr_copy(parser_nasm->absstart); + else { + sym = yasm_symtab_define_label(p_symtab, "$$", + yasm_section_bcs_first(cursect), 0, cur_line); + e = p_expr_new_ident(yasm_expr_sym(sym)); + } break; default: return NULL; @@ -1053,8 +1091,12 @@ define_label(yasm_parser_nasm *parser_nasm, char *name, int local) strcpy(parser_nasm->locallabel_base, name); } - yasm_symtab_define_label(p_symtab, name, parser_nasm->prev_bc, 1, - cur_line); + if (parser_nasm->abspos) + yasm_symtab_define_equ(p_symtab, name, + yasm_expr_copy(parser_nasm->abspos), cur_line); + else + yasm_symtab_define_label(p_symtab, name, parser_nasm->prev_bc, 1, + cur_line); yasm_xfree(name); } @@ -1073,16 +1115,6 @@ fix_directive_symrec(yasm_expr__item *ei, void *d) return 0; } -static void -dir_absolute(yasm_object *object, yasm_valparamhead *valparams, - yasm_valparamhead *objext_valparams, unsigned long line) -{ - yasm_valparam *vp = yasm_vps_first(valparams); - yasm_expr *start = yasm_vp_expr(vp, object->symtab, line); - - object->cur_section = yasm_object_create_absolute(object, start, line); -} - static void dir_align(yasm_object *object, yasm_valparamhead *valparams, yasm_valparamhead *objext_valparams, unsigned long line) @@ -1122,20 +1154,62 @@ nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name, yasm_valparamhead *objext_valparams) { unsigned long line = cur_line; + yasm_valparam *vp; if (!yasm_object_directive(p_object, name, "nasm", valparams, objext_valparams, line)) ; - else if (yasm__strcasecmp(name, "absolute") == 0) - dir_absolute(p_object, valparams, objext_valparams, line); - else if (yasm__strcasecmp(name, "align") == 0) - dir_align(p_object, valparams, objext_valparams, line); - else + else if (yasm__strcasecmp(name, "absolute") == 0) { + vp = yasm_vps_first(valparams); + if (parser_nasm->absstart) + yasm_expr_destroy(parser_nasm->absstart); + if (parser_nasm->abspos) + yasm_expr_destroy(parser_nasm->abspos); + parser_nasm->absstart = yasm_vp_expr(vp, p_object->symtab, line); + parser_nasm->abspos = yasm_expr_copy(parser_nasm->absstart); + cursect = NULL; + parser_nasm->prev_bc = NULL; + } else if (yasm__strcasecmp(name, "align") == 0) { + /* Really, we shouldn't end up with an align directive in an absolute + * section (as it's supposed to be only used for nop fill, but handle + * it gracefully anyway. + */ + if (parser_nasm->abspos) { + yasm_expr *boundval, *e; + vp = yasm_vps_first(valparams); + boundval = yasm_vp_expr(vp, p_object->symtab, line); + e = yasm_expr_create_tree( + yasm_expr_create_tree(yasm_expr_copy(parser_nasm->absstart), + YASM_EXPR_SUB, + yasm_expr_copy(parser_nasm->abspos), + cur_line), + YASM_EXPR_AND, + yasm_expr_create(YASM_EXPR_SUB, yasm_expr_expr(boundval), + yasm_expr_int(yasm_intnum_create_uint(1)), + cur_line), + cur_line); + parser_nasm->abspos = yasm_expr_create_tree( + parser_nasm->abspos, YASM_EXPR_ADD, e, cur_line); + } else + dir_align(p_object, valparams, objext_valparams, line); + } else yasm_error_set(YASM_ERROR_SYNTAX, N_("unrecognized directive `%s'"), name); - /* In case cursect changed or a bytecode was added, update prev_bc. */ - parser_nasm->prev_bc = yasm_section_bcs_last(cursect); + if (parser_nasm->absstart && cursect) { + /* We switched to a new section. Get out of absolute section mode. */ + yasm_expr_destroy(parser_nasm->absstart); + parser_nasm->absstart = NULL; + if (parser_nasm->abspos) { + yasm_expr_destroy(parser_nasm->abspos); + parser_nasm->abspos = NULL; + } + } + + if (cursect) { + /* In case cursect changed or a bytecode was added, update prev_bc. */ + parser_nasm->prev_bc = yasm_section_bcs_last(cursect); + } if (valparams) yasm_vps_delete(valparams); diff --git a/modules/parsers/nasm/nasm-parser.c b/modules/parsers/nasm/nasm-parser.c index 786b6d50..2fa1934b 100644 --- a/modules/parsers/nasm/nasm-parser.c +++ b/modules/parsers/nasm/nasm-parser.c @@ -58,6 +58,9 @@ nasm_parser_do_parse(yasm_object *object, yasm_preproc *pp, FILE *f, parser_nasm.peek_token = NONE; + parser_nasm.absstart = NULL; + parser_nasm.abspos = NULL; + /* initialize scanner structure */ yasm_scanner_initialize(&parser_nasm.s); diff --git a/modules/parsers/nasm/nasm-parser.h b/modules/parsers/nasm/nasm-parser.h index 51bb6b7d..de0824b5 100644 --- a/modules/parsers/nasm/nasm-parser.h +++ b/modules/parsers/nasm/nasm-parser.h @@ -117,6 +117,16 @@ typedef struct yasm_parser_nasm { int peek_token; /* NONE if none */ yystype peek_tokval; char peek_tokch; + + /* Starting point of the absolute section. NULL if not in an absolute + * section. + */ + /*@null@*/ yasm_expr *absstart; + + /* Current location inside an absolute section (including the start). + * NULL if not in an absolute section. + */ + /*@null@*/ yasm_expr *abspos; } yasm_parser_nasm; /* shorter access names to commonly used parser_nasm fields */ diff --git a/modules/parsers/nasm/tests/Makefile.inc b/modules/parsers/nasm/tests/Makefile.inc index 87f8c1ca..552320cc 100644 --- a/modules/parsers/nasm/tests/Makefile.inc +++ b/modules/parsers/nasm/tests/Makefile.inc @@ -24,6 +24,10 @@ EXTRA_DIST += modules/parsers/nasm/tests/orphannowarn.hex EXTRA_DIST += modules/parsers/nasm/tests/prevlocalwarn.asm EXTRA_DIST += modules/parsers/nasm/tests/prevlocalwarn.errwarn EXTRA_DIST += modules/parsers/nasm/tests/prevlocalwarn.hex +EXTRA_DIST += modules/parsers/nasm/tests/strucalign.asm +EXTRA_DIST += modules/parsers/nasm/tests/strucalign.hex +EXTRA_DIST += modules/parsers/nasm/tests/struczero.asm +EXTRA_DIST += modules/parsers/nasm/tests/struczero.hex EXTRA_DIST += modules/parsers/nasm/tests/worphan/Makefile.inc diff --git a/modules/parsers/nasm/tests/strucalign.asm b/modules/parsers/nasm/tests/strucalign.asm new file mode 100644 index 00000000..f3fbd485 --- /dev/null +++ b/modules/parsers/nasm/tests/strucalign.asm @@ -0,0 +1,14 @@ +struc bug +times (64-$) resb 1 +.member: +times (128-($-$$)) resb 1 +.member2: +alignb 256 +.member3: +[align 512] +endstruc +dd bug +dd bug.member +dd bug.member2 +dd bug.member3 +dd bug_size diff --git a/modules/parsers/nasm/tests/strucalign.hex b/modules/parsers/nasm/tests/strucalign.hex new file mode 100644 index 00000000..d3baa2ae --- /dev/null +++ b/modules/parsers/nasm/tests/strucalign.hex @@ -0,0 +1,20 @@ +00 +00 +00 +00 +40 +00 +00 +00 +80 +00 +00 +00 +00 +01 +00 +00 +00 +02 +00 +00 diff --git a/modules/parsers/nasm/tests/struczero.asm b/modules/parsers/nasm/tests/struczero.asm new file mode 100644 index 00000000..26bf13df --- /dev/null +++ b/modules/parsers/nasm/tests/struczero.asm @@ -0,0 +1,7 @@ +struc MYSTRUC +.zero resd 0 +endstruc + +foo: +mov eax, [ecx+MYSTRUC.zero] +ret diff --git a/modules/parsers/nasm/tests/struczero.hex b/modules/parsers/nasm/tests/struczero.hex new file mode 100644 index 00000000..769fb4e7 --- /dev/null +++ b/modules/parsers/nasm/tests/struczero.hex @@ -0,0 +1,5 @@ +67 +66 +8b +01 +c3 -- 2.40.0