Prevent spurious "Circular reference detected" errors by refining the return

value for bc_resolve() to enum-defined flags.

svn path=/trunk/yasm/; revision=623
0.3
Peter Johnson 23 years ago
parent 4fed536d3c
commit ac2743de63
  1. 5
      libyasm/arch.h
  2. 30
      libyasm/bytecode.c
  3. 17
      libyasm/bytecode.h
  4. 4
      modules/arch/x86/x86-int.h
  5. 41
      modules/arch/x86/x86bc.c
  6. 4
      modules/objfmts/Makefile.inc
  7. 7
      modules/objfmts/bin/tests/Makefile.inc
  8. 15
      modules/objfmts/bin/tests/reserve-err.asm
  9. 4
      modules/objfmts/bin/tests/reserve-err.errwarn
  10. 18
      modules/optimizers/basic/basic-optimizer.c
  11. 5
      src/arch.h
  12. 4
      src/arch/x86/x86-int.h
  13. 41
      src/arch/x86/x86bc.c
  14. 30
      src/bytecode.c
  15. 17
      src/bytecode.h
  16. 4
      src/objfmts/Makefile.inc
  17. 7
      src/objfmts/bin/tests/Makefile.inc
  18. 15
      src/objfmts/bin/tests/reserve-err.asm
  19. 4
      src/objfmts/bin/tests/reserve-err.errwarn
  20. 18
      src/optimizers/basic/basic-optimizer.c

@ -40,8 +40,9 @@ struct arch {
void (*bc_print) (FILE *f, const bytecode *bc);
/* See bytecode.h comments on bc_resolve() */
int (*bc_resolve) (bytecode *bc, int save, const section *sect,
resolve_label_func resolve_label);
bc_resolve_flags (*bc_resolve) (bytecode *bc, int save,
const section *sect,
resolve_label_func resolve_label);
/* See bytecode.h comments on bc_tobytes() */
int (*bc_tobytes) (bytecode *bc, unsigned char **bufp,
const section *sect, void *d,

@ -293,7 +293,7 @@ bc_print(FILE *f, const bytecode *bc)
fprintf(f, "%*sOffset=%lx\n", indent_level, "", bc->offset);
}
static int
static bc_resolve_flags
bc_resolve_data(bytecode_data *bc_data, unsigned long *len)
{
dataval *dv;
@ -316,15 +316,15 @@ bc_resolve_data(bytecode_data *bc_data, unsigned long *len)
}
}
return 1;
return BC_RESOLVE_MIN_LEN;
}
static int
static bc_resolve_flags
bc_resolve_reserve(bytecode_reserve *reserve, unsigned long *len, int save,
unsigned long line, const section *sect,
resolve_label_func resolve_label)
{
int retval = 1;
bc_resolve_flags retval = BC_RESOLVE_MIN_LEN;
/*@null@*/ expr *temp;
expr **tempp;
/*@dependent@*/ /*@null@*/ const intnum *num;
@ -343,14 +343,14 @@ bc_resolve_reserve(bytecode_reserve *reserve, unsigned long *len, int save,
if (expr_contains(temp, EXPR_FLOAT))
ErrorAt(line,
_("expression must not contain floating point value"));
retval = -1;
retval = BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
} else
*len += intnum_get_uint(num)*reserve->itemsize;
expr_delete(temp);
return retval;
}
static int
static bc_resolve_flags
bc_resolve_incbin(bytecode_incbin *incbin, unsigned long *len, int save,
unsigned long line, const section *sect,
resolve_label_func resolve_label)
@ -377,7 +377,7 @@ bc_resolve_incbin(bytecode_incbin *incbin, unsigned long *len, int save,
start = intnum_get_uint(num);
expr_delete(temp);
if (!num)
return -1;
return BC_RESOLVE_UNKNOWN_LEN;
}
/* Try to convert maxlen to integer value */
@ -396,7 +396,7 @@ bc_resolve_incbin(bytecode_incbin *incbin, unsigned long *len, int save,
maxlen = intnum_get_uint(num);
expr_delete(temp);
if (!num)
return -1;
return BC_RESOLVE_UNKNOWN_LEN;
}
/* FIXME: Search include path for filename. Save full path back into
@ -408,12 +408,12 @@ bc_resolve_incbin(bytecode_incbin *incbin, unsigned long *len, int save,
if (!f) {
ErrorAt(line, _("`incbin': unable to open file `%s'"),
incbin->filename);
return -1;
return BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
}
if (fseek(f, 0L, SEEK_END) < 0) {
ErrorAt(line, _("`incbin': unable to seek on file `%s'"),
incbin->filename);
return -1;
return BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
}
flen = (unsigned long)ftell(f);
fclose(f);
@ -429,14 +429,14 @@ bc_resolve_incbin(bytecode_incbin *incbin, unsigned long *len, int save,
if (maxlen < flen)
flen = maxlen;
*len += flen;
return 1;
return BC_RESOLVE_MIN_LEN;
}
int
bc_resolve_flags
bc_resolve(bytecode *bc, int save, const section *sect,
resolve_label_func resolve_label)
{
int retval = 1;
bc_resolve_flags retval = BC_RESOLVE_MIN_LEN;
bytecode_data *bc_data;
bytecode_reserve *reserve;
bytecode_incbin *incbin;
@ -487,14 +487,14 @@ bc_resolve(bytecode *bc, int save, const section *sect,
if (expr_contains(temp, EXPR_FLOAT))
ErrorAt(bc->line,
_("expression must not contain floating point value"));
retval = -1;
retval = BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
} else
bc->len *= intnum_get_uint(num);
expr_delete(temp);
}
/* If we got an error somewhere along the line, clear out any calc len */
if (retval < 0)
if (retval & BC_RESOLVE_UNKNOWN_LEN)
bc->len = 0;
return retval;

@ -58,10 +58,19 @@ void bc_delete(/*@only@*/ /*@null@*/ bytecode *bc);
void bc_print(FILE *f, const bytecode *bc);
/* Return value flags for bc_resolve() */
typedef enum {
BC_RESOLVE_NONE = 0, /* Ok, but length is not minimum */
BC_RESOLVE_ERROR = 1<<0, /* Error found, output */
BC_RESOLVE_MIN_LEN = 1<<1, /* Length is minimum possible */
BC_RESOLVE_UNKNOWN_LEN = 1<<2 /* Length indeterminate */
} bc_resolve_flags;
/* Resolves labels in bytecode, and calculates its length.
* Tries to minimize the length as much as possible.
* Returns whether the length is the minimum possible (1=yes, 0=no).
* Returns -1 if the length was indeterminate.
* Returns whether the length is the minimum possible, indeterminate, and
* if there was an error recognized and output during execution (see above
* for return flags).
* Note: sometimes it's impossible to determine if a length is the minimum
* possible. In this case, this function returns that the length is NOT
* the minimum.
@ -72,8 +81,8 @@ void bc_print(FILE *f, const bytecode *bc);
* resolve_label except temporarily to try to minimize the length).
* When save is nonzero, all fields in bc may be modified by this function.
*/
int bc_resolve(bytecode *bc, int save, const section *sect,
resolve_label_func resolve_label);
bc_resolve_flags bc_resolve(bytecode *bc, int save, const section *sect,
resolve_label_func resolve_label);
/* Converts the bytecode bc into its byte representation.
* Inputs:

@ -96,8 +96,8 @@ typedef struct x86_jmprel {
void x86_bc_delete(bytecode *bc);
void x86_bc_print(FILE *f, const bytecode *bc);
int x86_bc_resolve(bytecode *bc, int save, const section *sect,
resolve_label_func resolve_label);
bc_resolve_flags x86_bc_resolve(bytecode *bc, int save, const section *sect,
resolve_label_func resolve_label);
int x86_bc_tobytes(bytecode *bc, unsigned char **bufp, const section *sect,
void *d, output_expr_func output_expr);

@ -462,7 +462,7 @@ x86_bc_print(FILE *f, const bytecode *bc)
}
}
static int
static bc_resolve_flags
x86_bc_resolve_insn(x86_insn *insn, unsigned long *len, int save,
const section *sect, resolve_label_func resolve_label)
{
@ -470,7 +470,7 @@ x86_bc_resolve_insn(x86_insn *insn, unsigned long *len, int save,
effaddr *ea = insn->ea;
x86_effaddr_data *ead = ea_get_data(ea);
immval *imm = insn->imm;
int retval = 1; /* may turn into 0 at some point */
bc_resolve_flags retval = BC_RESOLVE_MIN_LEN;
if (ea) {
/* Create temp copy of disp, etc. */
@ -496,14 +496,15 @@ x86_bc_resolve_insn(x86_insn *insn, unsigned long *len, int save,
&ead_t.sib, &ead_t.valid_sib,
&ead_t.need_sib)) {
expr_delete(temp);
return -1; /* failed, don't bother checking rest of insn */
/* failed, don't bother checking rest of insn */
return BC_RESOLVE_UNKNOWN_LEN;
}
expr_delete(temp);
if (displen != 1) {
/* Fits into a word/dword, or unknown. */
retval = 0; /* may not be smallest size */
retval = BC_RESOLVE_NONE; /* may not be smallest size */
/* Handle unknown case, make displen word-sized */
if (displen == 0xff)
@ -553,7 +554,7 @@ x86_bc_resolve_insn(x86_insn *insn, unsigned long *len, int save,
insn->imm = (immval *)NULL;
}
} else
retval = 0; /* we could still get ,1 */
retval = BC_RESOLVE_NONE; /* we could still get ,1 */
/* Not really necessary, but saves confusion over it. */
if (save)
@ -574,12 +575,12 @@ x86_bc_resolve_insn(x86_insn *insn, unsigned long *len, int save,
return retval;
}
static int
static bc_resolve_flags
x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
const bytecode *bc, const section *sect,
resolve_label_func resolve_label)
{
int retval = 1;
bc_resolve_flags retval = BC_RESOLVE_MIN_LEN;
/*@null@*/ expr *temp;
/*@dependent@*/ /*@null@*/ const intnum *num;
unsigned long target;
@ -605,7 +606,7 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
if (!num) {
ErrorAt(bc->line,
_("short jump target external or out of segment"));
return -1;
return BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
} else {
target = intnum_get_uint(num);
rel = (long)(target -
@ -613,12 +614,12 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
/* does a short form exist? */
if (jmprel->shortop.opcode_len == 0) {
ErrorAt(bc->line, _("short jump does not exist"));
return -1;
return BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
}
/* short displacement must fit in -128 <= rel <= +127 */
if (rel < -128 || rel > 127) {
ErrorAt(bc->line, _("short jump out of range"));
return -1;
return BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
}
}
}
@ -629,7 +630,7 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
if (save) {
if (jmprel->nearop.opcode_len == 0) {
ErrorAt(bc->line, _("near jump does not exist"));
return -1;
return BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
}
}
break;
@ -656,7 +657,7 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
*/
jrshort = 0;
if (jmprel->shortop.opcode_len != 0)
retval = 0;
retval = BC_RESOLVE_NONE;
} else {
/* Doesn't fit into short, and there's no near opcode.
* Error out if saving, otherwise just make it a short
@ -665,7 +666,7 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
*/
if (save) {
ErrorAt(bc->line, _("short jump out of range"));
return -1;
return BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
}
jrshort = 1;
}
@ -676,13 +677,13 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
*/
if (jmprel->nearop.opcode_len != 0) {
if (jmprel->shortop.opcode_len != 0)
retval = 0;
retval = BC_RESOLVE_NONE;
jrshort = 0;
} else {
if (save) {
ErrorAt(bc->line,
_("short jump target or out of segment"));
return -1;
return BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
}
jrshort = 1;
}
@ -695,14 +696,14 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
if (save)
jmprel->op_sel = JR_SHORT;
if (jmprel->shortop.opcode_len == 0)
return -1; /* uh-oh, that size not available */
return BC_RESOLVE_UNKNOWN_LEN; /* uh-oh, that size not available */
*len += jmprel->shortop.opcode_len + 1;
} else {
if (save)
jmprel->op_sel = JR_NEAR;
if (jmprel->nearop.opcode_len == 0)
return -1; /* uh-oh, that size not available */
return BC_RESOLVE_UNKNOWN_LEN; /* uh-oh, that size not available */
*len += jmprel->nearop.opcode_len;
*len += (opersize == 32) ? 4 : 2;
@ -716,7 +717,7 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
return retval;
}
int
bc_resolve_flags
x86_bc_resolve(bytecode *bc, int save, const section *sect,
resolve_label_func resolve_label)
{
@ -735,7 +736,9 @@ x86_bc_resolve(bytecode *bc, int save, const section *sect,
default:
break;
}
return 0;
InternalError(_("Didn't handle bytecode type in x86 arch"));
/*@notreached@*/
return BC_RESOLVE_UNKNOWN_LEN;
}
static int

@ -2,9 +2,11 @@
EXTRA_DIST += \
src/objfmts/dbg/Makefile.inc \
src/objfmts/bin/Makefile.inc
src/objfmts/bin/Makefile.inc \
src/objfmts/elf/Makefile.inc
YASMOBJFMTFILES =
include src/objfmts/dbg/Makefile.inc
include src/objfmts/bin/Makefile.inc
include src/objfmts/elf/Makefile.inc
yasm_SOURCES += $(YASMOBJFMTFILES)

@ -18,7 +18,9 @@ EXTRA_DIST += \
src/objfmts/bin/tests/integer.errwarn \
src/objfmts/bin/tests/reserve.asm \
src/objfmts/bin/tests/reserve.bin.hx \
src/objfmts/bin/tests/reserve.errwarn
src/objfmts/bin/tests/reserve.errwarn \
src/objfmts/bin/tests/reserve-err.asm \
src/objfmts/bin/tests/reserve-err.errwarn
CLEANFILES += \
float-err.ew \
@ -33,4 +35,5 @@ CLEANFILES += \
integer.ew \
reserve \
reserve.ew \
reserve.hx
reserve.hx \
reserve-err.ew

@ -0,0 +1,15 @@
; Test res* family errors
a:
resb -5
resw 1.2
resd -1.2
resq 0xffffffff
rest a
[section .bss]
resb -5
resw 1.2
resd -1.2
resq 0xffffffff
rest a

@ -0,0 +1,4 @@
./src/objfmts/bin/tests/reserve-err.asm:4: expression must not contain floating point value
./src/objfmts/bin/tests/reserve-err.asm:5: expression must not contain floating point value
./src/objfmts/bin/tests/reserve-err.asm:11: expression must not contain floating point value
./src/objfmts/bin/tests/reserve-err.asm:12: expression must not contain floating point value

@ -150,6 +150,7 @@ static int
basic_optimize_bytecode_1(/*@observer@*/ bytecode *bc, void *d)
{
basic_optimize_data *data = (basic_optimize_data *)d;
bc_resolve_flags bcr_retval;
/* Don't even bother if we're in-progress or done. */
if (bc->opt_flags == BCFLAG_INPROGRESS)
@ -169,8 +170,10 @@ basic_optimize_bytecode_1(/*@observer@*/ bytecode *bc, void *d)
* is minimum or not, and just check for indeterminate length (indicative
* of circular reference).
*/
if (bc_resolve(bc, 0, data->sect, basic_optimize_resolve_label) < 0) {
ErrorAt(bc->line, _("Circular reference detected."));
bcr_retval = bc_resolve(bc, 0, data->sect, basic_optimize_resolve_label);
if (bcr_retval & BC_RESOLVE_UNKNOWN_LEN) {
if (!(bcr_retval & BC_RESOLVE_ERROR))
ErrorAt(bc->line, _("Circular reference detected."));
data->saw_unknown = -1;
return 0;
}
@ -181,8 +184,9 @@ basic_optimize_bytecode_1(/*@observer@*/ bytecode *bc, void *d)
}
static int
basic_optimize_section_1(section *sect, /*@unused@*/ /*@null@*/ void *d)
basic_optimize_section_1(section *sect, void *d)
{
int *saw_unknown = (int *)d;
basic_optimize_data data;
unsigned long flags;
int retval;
@ -206,7 +210,7 @@ basic_optimize_section_1(section *sect, /*@unused@*/ /*@null@*/ void *d)
return retval;
if (data.saw_unknown != 0)
return data.saw_unknown;
*saw_unknown = data.saw_unknown;
section_set_opt_flags(sect, SECTFLAG_DONE);
@ -252,6 +256,8 @@ basic_optimize_section_2(section *sect, /*@unused@*/ /*@null@*/ void *d)
static void
basic_optimize(sectionhead *sections)
{
int saw_unknown = 0;
/* Optimization process: (essentially NASM's pass 1)
* Determine the size of all bytecodes.
* Forward references are /not/ resolved (only backward references are
@ -264,7 +270,9 @@ basic_optimize(sectionhead *sections)
* - not strictly top->bottom scanning; we scan through a section and
* hop to other sections as necessary.
*/
if (sections_traverse(sections, NULL, basic_optimize_section_1) < 0)
if (sections_traverse(sections, &saw_unknown,
basic_optimize_section_1) < 0 ||
saw_unknown != 0)
return;
/* Check completion of all sections and save bytecode changes */

@ -40,8 +40,9 @@ struct arch {
void (*bc_print) (FILE *f, const bytecode *bc);
/* See bytecode.h comments on bc_resolve() */
int (*bc_resolve) (bytecode *bc, int save, const section *sect,
resolve_label_func resolve_label);
bc_resolve_flags (*bc_resolve) (bytecode *bc, int save,
const section *sect,
resolve_label_func resolve_label);
/* See bytecode.h comments on bc_tobytes() */
int (*bc_tobytes) (bytecode *bc, unsigned char **bufp,
const section *sect, void *d,

@ -96,8 +96,8 @@ typedef struct x86_jmprel {
void x86_bc_delete(bytecode *bc);
void x86_bc_print(FILE *f, const bytecode *bc);
int x86_bc_resolve(bytecode *bc, int save, const section *sect,
resolve_label_func resolve_label);
bc_resolve_flags x86_bc_resolve(bytecode *bc, int save, const section *sect,
resolve_label_func resolve_label);
int x86_bc_tobytes(bytecode *bc, unsigned char **bufp, const section *sect,
void *d, output_expr_func output_expr);

@ -462,7 +462,7 @@ x86_bc_print(FILE *f, const bytecode *bc)
}
}
static int
static bc_resolve_flags
x86_bc_resolve_insn(x86_insn *insn, unsigned long *len, int save,
const section *sect, resolve_label_func resolve_label)
{
@ -470,7 +470,7 @@ x86_bc_resolve_insn(x86_insn *insn, unsigned long *len, int save,
effaddr *ea = insn->ea;
x86_effaddr_data *ead = ea_get_data(ea);
immval *imm = insn->imm;
int retval = 1; /* may turn into 0 at some point */
bc_resolve_flags retval = BC_RESOLVE_MIN_LEN;
if (ea) {
/* Create temp copy of disp, etc. */
@ -496,14 +496,15 @@ x86_bc_resolve_insn(x86_insn *insn, unsigned long *len, int save,
&ead_t.sib, &ead_t.valid_sib,
&ead_t.need_sib)) {
expr_delete(temp);
return -1; /* failed, don't bother checking rest of insn */
/* failed, don't bother checking rest of insn */
return BC_RESOLVE_UNKNOWN_LEN;
}
expr_delete(temp);
if (displen != 1) {
/* Fits into a word/dword, or unknown. */
retval = 0; /* may not be smallest size */
retval = BC_RESOLVE_NONE; /* may not be smallest size */
/* Handle unknown case, make displen word-sized */
if (displen == 0xff)
@ -553,7 +554,7 @@ x86_bc_resolve_insn(x86_insn *insn, unsigned long *len, int save,
insn->imm = (immval *)NULL;
}
} else
retval = 0; /* we could still get ,1 */
retval = BC_RESOLVE_NONE; /* we could still get ,1 */
/* Not really necessary, but saves confusion over it. */
if (save)
@ -574,12 +575,12 @@ x86_bc_resolve_insn(x86_insn *insn, unsigned long *len, int save,
return retval;
}
static int
static bc_resolve_flags
x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
const bytecode *bc, const section *sect,
resolve_label_func resolve_label)
{
int retval = 1;
bc_resolve_flags retval = BC_RESOLVE_MIN_LEN;
/*@null@*/ expr *temp;
/*@dependent@*/ /*@null@*/ const intnum *num;
unsigned long target;
@ -605,7 +606,7 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
if (!num) {
ErrorAt(bc->line,
_("short jump target external or out of segment"));
return -1;
return BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
} else {
target = intnum_get_uint(num);
rel = (long)(target -
@ -613,12 +614,12 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
/* does a short form exist? */
if (jmprel->shortop.opcode_len == 0) {
ErrorAt(bc->line, _("short jump does not exist"));
return -1;
return BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
}
/* short displacement must fit in -128 <= rel <= +127 */
if (rel < -128 || rel > 127) {
ErrorAt(bc->line, _("short jump out of range"));
return -1;
return BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
}
}
}
@ -629,7 +630,7 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
if (save) {
if (jmprel->nearop.opcode_len == 0) {
ErrorAt(bc->line, _("near jump does not exist"));
return -1;
return BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
}
}
break;
@ -656,7 +657,7 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
*/
jrshort = 0;
if (jmprel->shortop.opcode_len != 0)
retval = 0;
retval = BC_RESOLVE_NONE;
} else {
/* Doesn't fit into short, and there's no near opcode.
* Error out if saving, otherwise just make it a short
@ -665,7 +666,7 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
*/
if (save) {
ErrorAt(bc->line, _("short jump out of range"));
return -1;
return BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
}
jrshort = 1;
}
@ -676,13 +677,13 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
*/
if (jmprel->nearop.opcode_len != 0) {
if (jmprel->shortop.opcode_len != 0)
retval = 0;
retval = BC_RESOLVE_NONE;
jrshort = 0;
} else {
if (save) {
ErrorAt(bc->line,
_("short jump target or out of segment"));
return -1;
return BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
}
jrshort = 1;
}
@ -695,14 +696,14 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
if (save)
jmprel->op_sel = JR_SHORT;
if (jmprel->shortop.opcode_len == 0)
return -1; /* uh-oh, that size not available */
return BC_RESOLVE_UNKNOWN_LEN; /* uh-oh, that size not available */
*len += jmprel->shortop.opcode_len + 1;
} else {
if (save)
jmprel->op_sel = JR_NEAR;
if (jmprel->nearop.opcode_len == 0)
return -1; /* uh-oh, that size not available */
return BC_RESOLVE_UNKNOWN_LEN; /* uh-oh, that size not available */
*len += jmprel->nearop.opcode_len;
*len += (opersize == 32) ? 4 : 2;
@ -716,7 +717,7 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
return retval;
}
int
bc_resolve_flags
x86_bc_resolve(bytecode *bc, int save, const section *sect,
resolve_label_func resolve_label)
{
@ -735,7 +736,9 @@ x86_bc_resolve(bytecode *bc, int save, const section *sect,
default:
break;
}
return 0;
InternalError(_("Didn't handle bytecode type in x86 arch"));
/*@notreached@*/
return BC_RESOLVE_UNKNOWN_LEN;
}
static int

@ -293,7 +293,7 @@ bc_print(FILE *f, const bytecode *bc)
fprintf(f, "%*sOffset=%lx\n", indent_level, "", bc->offset);
}
static int
static bc_resolve_flags
bc_resolve_data(bytecode_data *bc_data, unsigned long *len)
{
dataval *dv;
@ -316,15 +316,15 @@ bc_resolve_data(bytecode_data *bc_data, unsigned long *len)
}
}
return 1;
return BC_RESOLVE_MIN_LEN;
}
static int
static bc_resolve_flags
bc_resolve_reserve(bytecode_reserve *reserve, unsigned long *len, int save,
unsigned long line, const section *sect,
resolve_label_func resolve_label)
{
int retval = 1;
bc_resolve_flags retval = BC_RESOLVE_MIN_LEN;
/*@null@*/ expr *temp;
expr **tempp;
/*@dependent@*/ /*@null@*/ const intnum *num;
@ -343,14 +343,14 @@ bc_resolve_reserve(bytecode_reserve *reserve, unsigned long *len, int save,
if (expr_contains(temp, EXPR_FLOAT))
ErrorAt(line,
_("expression must not contain floating point value"));
retval = -1;
retval = BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
} else
*len += intnum_get_uint(num)*reserve->itemsize;
expr_delete(temp);
return retval;
}
static int
static bc_resolve_flags
bc_resolve_incbin(bytecode_incbin *incbin, unsigned long *len, int save,
unsigned long line, const section *sect,
resolve_label_func resolve_label)
@ -377,7 +377,7 @@ bc_resolve_incbin(bytecode_incbin *incbin, unsigned long *len, int save,
start = intnum_get_uint(num);
expr_delete(temp);
if (!num)
return -1;
return BC_RESOLVE_UNKNOWN_LEN;
}
/* Try to convert maxlen to integer value */
@ -396,7 +396,7 @@ bc_resolve_incbin(bytecode_incbin *incbin, unsigned long *len, int save,
maxlen = intnum_get_uint(num);
expr_delete(temp);
if (!num)
return -1;
return BC_RESOLVE_UNKNOWN_LEN;
}
/* FIXME: Search include path for filename. Save full path back into
@ -408,12 +408,12 @@ bc_resolve_incbin(bytecode_incbin *incbin, unsigned long *len, int save,
if (!f) {
ErrorAt(line, _("`incbin': unable to open file `%s'"),
incbin->filename);
return -1;
return BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
}
if (fseek(f, 0L, SEEK_END) < 0) {
ErrorAt(line, _("`incbin': unable to seek on file `%s'"),
incbin->filename);
return -1;
return BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
}
flen = (unsigned long)ftell(f);
fclose(f);
@ -429,14 +429,14 @@ bc_resolve_incbin(bytecode_incbin *incbin, unsigned long *len, int save,
if (maxlen < flen)
flen = maxlen;
*len += flen;
return 1;
return BC_RESOLVE_MIN_LEN;
}
int
bc_resolve_flags
bc_resolve(bytecode *bc, int save, const section *sect,
resolve_label_func resolve_label)
{
int retval = 1;
bc_resolve_flags retval = BC_RESOLVE_MIN_LEN;
bytecode_data *bc_data;
bytecode_reserve *reserve;
bytecode_incbin *incbin;
@ -487,14 +487,14 @@ bc_resolve(bytecode *bc, int save, const section *sect,
if (expr_contains(temp, EXPR_FLOAT))
ErrorAt(bc->line,
_("expression must not contain floating point value"));
retval = -1;
retval = BC_RESOLVE_ERROR | BC_RESOLVE_UNKNOWN_LEN;
} else
bc->len *= intnum_get_uint(num);
expr_delete(temp);
}
/* If we got an error somewhere along the line, clear out any calc len */
if (retval < 0)
if (retval & BC_RESOLVE_UNKNOWN_LEN)
bc->len = 0;
return retval;

@ -58,10 +58,19 @@ void bc_delete(/*@only@*/ /*@null@*/ bytecode *bc);
void bc_print(FILE *f, const bytecode *bc);
/* Return value flags for bc_resolve() */
typedef enum {
BC_RESOLVE_NONE = 0, /* Ok, but length is not minimum */
BC_RESOLVE_ERROR = 1<<0, /* Error found, output */
BC_RESOLVE_MIN_LEN = 1<<1, /* Length is minimum possible */
BC_RESOLVE_UNKNOWN_LEN = 1<<2 /* Length indeterminate */
} bc_resolve_flags;
/* Resolves labels in bytecode, and calculates its length.
* Tries to minimize the length as much as possible.
* Returns whether the length is the minimum possible (1=yes, 0=no).
* Returns -1 if the length was indeterminate.
* Returns whether the length is the minimum possible, indeterminate, and
* if there was an error recognized and output during execution (see above
* for return flags).
* Note: sometimes it's impossible to determine if a length is the minimum
* possible. In this case, this function returns that the length is NOT
* the minimum.
@ -72,8 +81,8 @@ void bc_print(FILE *f, const bytecode *bc);
* resolve_label except temporarily to try to minimize the length).
* When save is nonzero, all fields in bc may be modified by this function.
*/
int bc_resolve(bytecode *bc, int save, const section *sect,
resolve_label_func resolve_label);
bc_resolve_flags bc_resolve(bytecode *bc, int save, const section *sect,
resolve_label_func resolve_label);
/* Converts the bytecode bc into its byte representation.
* Inputs:

@ -2,9 +2,11 @@
EXTRA_DIST += \
src/objfmts/dbg/Makefile.inc \
src/objfmts/bin/Makefile.inc
src/objfmts/bin/Makefile.inc \
src/objfmts/elf/Makefile.inc
YASMOBJFMTFILES =
include src/objfmts/dbg/Makefile.inc
include src/objfmts/bin/Makefile.inc
include src/objfmts/elf/Makefile.inc
yasm_SOURCES += $(YASMOBJFMTFILES)

@ -18,7 +18,9 @@ EXTRA_DIST += \
src/objfmts/bin/tests/integer.errwarn \
src/objfmts/bin/tests/reserve.asm \
src/objfmts/bin/tests/reserve.bin.hx \
src/objfmts/bin/tests/reserve.errwarn
src/objfmts/bin/tests/reserve.errwarn \
src/objfmts/bin/tests/reserve-err.asm \
src/objfmts/bin/tests/reserve-err.errwarn
CLEANFILES += \
float-err.ew \
@ -33,4 +35,5 @@ CLEANFILES += \
integer.ew \
reserve \
reserve.ew \
reserve.hx
reserve.hx \
reserve-err.ew

@ -0,0 +1,15 @@
; Test res* family errors
a:
resb -5
resw 1.2
resd -1.2
resq 0xffffffff
rest a
[section .bss]
resb -5
resw 1.2
resd -1.2
resq 0xffffffff
rest a

@ -0,0 +1,4 @@
./src/objfmts/bin/tests/reserve-err.asm:4: expression must not contain floating point value
./src/objfmts/bin/tests/reserve-err.asm:5: expression must not contain floating point value
./src/objfmts/bin/tests/reserve-err.asm:11: expression must not contain floating point value
./src/objfmts/bin/tests/reserve-err.asm:12: expression must not contain floating point value

@ -150,6 +150,7 @@ static int
basic_optimize_bytecode_1(/*@observer@*/ bytecode *bc, void *d)
{
basic_optimize_data *data = (basic_optimize_data *)d;
bc_resolve_flags bcr_retval;
/* Don't even bother if we're in-progress or done. */
if (bc->opt_flags == BCFLAG_INPROGRESS)
@ -169,8 +170,10 @@ basic_optimize_bytecode_1(/*@observer@*/ bytecode *bc, void *d)
* is minimum or not, and just check for indeterminate length (indicative
* of circular reference).
*/
if (bc_resolve(bc, 0, data->sect, basic_optimize_resolve_label) < 0) {
ErrorAt(bc->line, _("Circular reference detected."));
bcr_retval = bc_resolve(bc, 0, data->sect, basic_optimize_resolve_label);
if (bcr_retval & BC_RESOLVE_UNKNOWN_LEN) {
if (!(bcr_retval & BC_RESOLVE_ERROR))
ErrorAt(bc->line, _("Circular reference detected."));
data->saw_unknown = -1;
return 0;
}
@ -181,8 +184,9 @@ basic_optimize_bytecode_1(/*@observer@*/ bytecode *bc, void *d)
}
static int
basic_optimize_section_1(section *sect, /*@unused@*/ /*@null@*/ void *d)
basic_optimize_section_1(section *sect, void *d)
{
int *saw_unknown = (int *)d;
basic_optimize_data data;
unsigned long flags;
int retval;
@ -206,7 +210,7 @@ basic_optimize_section_1(section *sect, /*@unused@*/ /*@null@*/ void *d)
return retval;
if (data.saw_unknown != 0)
return data.saw_unknown;
*saw_unknown = data.saw_unknown;
section_set_opt_flags(sect, SECTFLAG_DONE);
@ -252,6 +256,8 @@ basic_optimize_section_2(section *sect, /*@unused@*/ /*@null@*/ void *d)
static void
basic_optimize(sectionhead *sections)
{
int saw_unknown = 0;
/* Optimization process: (essentially NASM's pass 1)
* Determine the size of all bytecodes.
* Forward references are /not/ resolved (only backward references are
@ -264,7 +270,9 @@ basic_optimize(sectionhead *sections)
* - not strictly top->bottom scanning; we scan through a section and
* hop to other sections as necessary.
*/
if (sections_traverse(sections, NULL, basic_optimize_section_1) < 0)
if (sections_traverse(sections, &saw_unknown,
basic_optimize_section_1) < 0 ||
saw_unknown != 0)
return;
/* Check completion of all sections and save bytecode changes */

Loading…
Cancel
Save