Fix major bug related to multiple handling. Unfortunately this slows down

bytecode multiple output significantly, but this way handles generating
relocations correctly (otherwise extern foo; times 5 dd foo doesn't work!).

* bytecode.h (yasm_bc_tobytes): Remove multiple output parameter.
(yasm_bc_get_multiple): New.
* bytecode.c (yasm_bc_tobytes): Update to iterate through multiple here.
(yasm_bc_get_multiple): New.
* xdf-objfmt.c, elf-objfmt.c, bin-objfmt.c, coff-objfmt.c: Don't iterate
through multiple here.
* nasm-listfmt.c: Use yasm_bc_get_multiple() to get multiple instead of
yasm_bc_tobytes().

* bytecode.pxi: Update.

* tests/win32-relocovfl.asm: Tests both this and [1534] but generates too
huge of a file (3MB) to be put into the automated tests.

svn path=/trunk/yasm/; revision=1536
This commit is contained in:
Peter Johnson 2006-05-11 07:00:33 +00:00
parent 58921419c2
commit fe09480565
9 changed files with 81 additions and 79 deletions

View file

@ -240,64 +240,72 @@ yasm_bc_resolve(yasm_bytecode *bc, int save,
/*@null@*/ /*@only@*/ unsigned char *
yasm_bc_tobytes(yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize,
/*@out@*/ unsigned long *multiple, /*@out@*/ int *gap,
void *d, yasm_output_value_func output_value,
/*@out@*/ int *gap, void *d,
yasm_output_value_func output_value,
/*@null@*/ yasm_output_reloc_func output_reloc)
/*@sets *buf@*/
{
/*@only@*/ /*@null@*/ unsigned char *mybuf = NULL;
unsigned char *origbuf, *destbuf;
/*@dependent@*/ /*@null@*/ const yasm_intnum *num;
unsigned long datasize;
unsigned long datasize, multiple, i;
int error = 0;
if (bc->multiple) {
num = yasm_expr_get_intnum(&bc->multiple, NULL);
if (!num)
yasm_internal_error(
N_("could not determine multiple in bc_tobytes"));
if (yasm_intnum_sign(num) < 0) {
yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
*bufsize = 0;
return NULL;
}
*multiple = yasm_intnum_get_uint(num);
if (*multiple == 0) {
*bufsize = 0;
return NULL;
}
} else
*multiple = 1;
datasize = bc->len / (*multiple);
if (yasm_bc_get_multiple(bc, &multiple, NULL) || multiple == 0) {
*bufsize = 0;
return NULL;
}
/* special case for reserve bytecodes */
if (bc->callback->reserve) {
*bufsize = datasize;
*bufsize = bc->len;
*gap = 1;
return NULL; /* we didn't allocate a buffer */
}
*gap = 0;
if (*bufsize < datasize) {
if (*bufsize < bc->len) {
mybuf = yasm_xmalloc(bc->len);
origbuf = mybuf;
destbuf = mybuf;
} else {
origbuf = buf;
} else
destbuf = buf;
}
*bufsize = datasize;
*bufsize = bc->len;
datasize = bc->len / multiple;
if (!bc->callback)
yasm_internal_error(N_("got empty bytecode in bc_tobytes"));
else
else for (i=0; i<multiple; i++) {
origbuf = destbuf;
error = bc->callback->tobytes(bc, &destbuf, d, output_value,
output_reloc);
if (!error && ((unsigned long)(destbuf - origbuf) != datasize))
yasm_internal_error(
N_("written length does not match optimized length"));
if (!error && ((unsigned long)(destbuf - origbuf) != datasize))
yasm_internal_error(
N_("written length does not match optimized length"));
}
return mybuf;
}
int
yasm_bc_get_multiple(yasm_bytecode *bc, unsigned long *multiple,
yasm_calc_bc_dist_func calc_bc_dist)
{
/*@dependent@*/ /*@null@*/ const yasm_intnum *num;
*multiple = 1;
if (bc->multiple) {
num = yasm_expr_get_intnum(&bc->multiple, calc_bc_dist);
if (!num) {
yasm_error_set(YASM_ERROR_VALUE,
N_("could not determine multiple"));
return 1;
}
if (yasm_intnum_sign(num) < 0) {
yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
return 1;
}
*multiple = yasm_intnum_get_uint(num);
}
return 0;
}

View file

@ -339,8 +339,6 @@ yasm_bc_resolve_flags yasm_bc_resolve(yasm_bytecode *bc, int save,
* \param buf byte representation destination buffer
* \param bufsize size of buf (in bytes) prior to call; size of the
* generated data after call
* \param multiple number of times the data should be duplicated when
* written to the object file [output]
* \param gap if nonzero, indicates the data does not really need to
* exist in the object file; if nonzero, contents of buf
* are undefined [output]
@ -358,11 +356,19 @@ yasm_bc_resolve_flags yasm_bc_resolve(yasm_bytecode *bc, int save,
*/
/*@null@*/ /*@only@*/ unsigned char *yasm_bc_tobytes
(yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize,
/*@out@*/ unsigned long *multiple, /*@out@*/ int *gap, void *d,
yasm_output_value_func output_value,
/*@out@*/ int *gap, void *d, yasm_output_value_func output_value,
/*@null@*/ yasm_output_reloc_func output_reloc)
/*@sets *buf@*/;
/** Get the bytecode multiple value as an unsigned long integer.
* \param bc bytecode
* \param multiple multiple value (output)
* \param calc_bc_dist bytecode distance calculation function (optional)
* \return 1 on error (set with yasm_error_set), 0 on success.
*/
int yasm_bc_get_multiple(yasm_bytecode *bc, /*@out@*/ unsigned long *multiple,
/*@null@*/ yasm_calc_bc_dist_func calc_bc_dist);
/** Create a new data value from an expression.
* \param expn expression
* \return Newly allocated data value.

View file

@ -214,9 +214,10 @@ nasm_listfmt_output(yasm_listfmt *listfmt, FILE *f, yasm_linemap *linemap,
/* convert bytecode into bytes, recording relocs along the
* way
*/
bigbuf = yasm_bc_tobytes(bc, buf, &size, &multiple, &gap,
&info, nasm_listfmt_output_value,
NULL);
bigbuf = yasm_bc_tobytes(bc, buf, &size, &gap, &info,
nasm_listfmt_output_value, NULL);
yasm_bc_get_multiple(bc, &multiple, NULL);
size /= multiple;
/* output bytes with reloc information */
origp = bigbuf ? bigbuf : buf;

View file

@ -187,13 +187,11 @@ bin_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
/*@null@*/ bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;
/*@null@*/ /*@only@*/ unsigned char *bigbuf;
unsigned long size = REGULAR_OUTBUF_SIZE;
unsigned long multiple;
unsigned long i;
int gap;
assert(info != NULL);
bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &multiple, &gap, info,
bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &gap, info,
bin_objfmt_output_value, NULL);
/* Don't bother doing anything else if size ended up being 0. */
@ -210,16 +208,15 @@ bin_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
N_("uninitialized space declared in code/data section: zeroing"));
/* Write out in chunks */
memset(info->buf, 0, REGULAR_OUTBUF_SIZE);
left = multiple*size;
left = size;
while (left > REGULAR_OUTBUF_SIZE) {
fwrite(info->buf, REGULAR_OUTBUF_SIZE, 1, info->f);
left -= REGULAR_OUTBUF_SIZE;
}
fwrite(info->buf, left, 1, info->f);
} else {
/* Output multiple copies of buf (or bigbuf if non-NULL) to file */
for (i=0; i<multiple; i++)
fwrite(bigbuf ? bigbuf : info->buf, (size_t)size, 1, info->f);
/* Output buf (or bigbuf if non-NULL) to file */
fwrite(bigbuf ? bigbuf : info->buf, (size_t)size, 1, info->f);
}
/* If bigbuf was allocated, free it */

View file

@ -692,13 +692,11 @@ coff_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
/*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;
/*@null@*/ /*@only@*/ unsigned char *bigbuf;
unsigned long size = REGULAR_OUTBUF_SIZE;
unsigned long multiple;
unsigned long i;
int gap;
assert(info != NULL);
bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &multiple, &gap, info,
bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &gap, info,
coff_objfmt_output_value, NULL);
/* Don't bother doing anything else if size ended up being 0. */
@ -708,7 +706,7 @@ coff_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
return 0;
}
info->csd->size += multiple*size;
info->csd->size += size;
/* Warn that gaps are converted to 0 and write out the 0's. */
if (gap) {
@ -717,16 +715,15 @@ coff_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
N_("uninitialized space declared in code/data section: zeroing"));
/* Write out in chunks */
memset(info->buf, 0, REGULAR_OUTBUF_SIZE);
left = multiple*size;
left = size;
while (left > REGULAR_OUTBUF_SIZE) {
fwrite(info->buf, REGULAR_OUTBUF_SIZE, 1, info->f);
left -= REGULAR_OUTBUF_SIZE;
}
fwrite(info->buf, left, 1, info->f);
} else {
/* Output multiple copies of buf (or bigbuf if non-NULL) to file */
for (i=0; i<multiple; i++)
fwrite(bigbuf ? bigbuf : info->buf, (size_t)size, 1, info->f);
/* Output buf (or bigbuf if non-NULL) to file */
fwrite(bigbuf ? bigbuf : info->buf, (size_t)size, 1, info->f);
}
/* If bigbuf was allocated, free it */

View file

@ -406,14 +406,12 @@ elf_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
unsigned char buf[256];
/*@null@*/ /*@only@*/ unsigned char *bigbuf;
unsigned long size = 256;
unsigned long multiple;
unsigned long i;
int gap;
if (info == NULL)
yasm_internal_error("null info struct");
bigbuf = yasm_bc_tobytes(bc, buf, &size, &multiple, &gap, info,
bigbuf = yasm_bc_tobytes(bc, buf, &size, &gap, info,
elf_objfmt_output_value, elf_objfmt_output_reloc);
/* Don't bother doing anything else if size ended up being 0. */
@ -424,13 +422,8 @@ elf_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
}
else {
yasm_intnum *bcsize = yasm_intnum_create_uint(size);
yasm_intnum *mult = yasm_intnum_create_uint(multiple);
yasm_intnum_calc(bcsize, YASM_EXPR_MUL, mult);
elf_secthead_add_size(info->shead, bcsize);
yasm_intnum_destroy(bcsize);
yasm_intnum_destroy(mult);
}
/* Warn that gaps are converted to 0 and write out the 0's. */
@ -440,16 +433,15 @@ elf_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
N_("uninitialized space declared in code/data section: zeroing"));
/* Write out in chunks */
memset(buf, 0, 256);
left = multiple*size;
left = size;
while (left > 256) {
fwrite(buf, 256, 1, info->f);
left -= 256;
}
fwrite(buf, left, 1, info->f);
} else {
/* Output multiple copies of buf (or bigbuf if non-NULL) to file */
for (i=0; i<multiple; i++)
fwrite(bigbuf ? bigbuf : buf, (size_t)size, 1, info->f);
/* Output buf (or bigbuf if non-NULL) to file */
fwrite(bigbuf ? bigbuf : buf, (size_t)size, 1, info->f);
}
/* If bigbuf was allocated, free it */

View file

@ -253,13 +253,11 @@ xdf_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
/*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d;
/*@null@*/ /*@only@*/ unsigned char *bigbuf;
unsigned long size = REGULAR_OUTBUF_SIZE;
unsigned long multiple;
unsigned long i;
int gap;
assert(info != NULL);
bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &multiple, &gap, info,
bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &gap, info,
xdf_objfmt_output_value, NULL);
/* Don't bother doing anything else if size ended up being 0. */
@ -269,7 +267,7 @@ xdf_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
return 0;
}
info->xsd->size += multiple*size;
info->xsd->size += size;
/* Warn that gaps are converted to 0 and write out the 0's. */
if (gap) {
@ -278,16 +276,15 @@ xdf_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
N_("uninitialized space: zeroing"));
/* Write out in chunks */
memset(info->buf, 0, REGULAR_OUTBUF_SIZE);
left = multiple*size;
left = size;
while (left > REGULAR_OUTBUF_SIZE) {
fwrite(info->buf, REGULAR_OUTBUF_SIZE, 1, info->f);
left -= REGULAR_OUTBUF_SIZE;
}
fwrite(info->buf, left, 1, info->f);
} else {
/* Output multiple copies of buf (or bigbuf if non-NULL) to file */
for (i=0; i<multiple; i++)
fwrite(bigbuf ? bigbuf : info->buf, (size_t)size, 1, info->f);
/* Output buf (or bigbuf if non-NULL) to file */
fwrite(bigbuf ? bigbuf : info->buf, (size_t)size, 1, info->f);
}
/* If bigbuf was allocated, free it */

View file

@ -0,0 +1,3 @@
extern foo
section .text
times 64*1024 dd foo

View file

@ -96,10 +96,11 @@ cdef extern from "libyasm/bytecode.h":
cdef yasm_bc_resolve_flags yasm_bc_resolve(yasm_bytecode *bc, int save,
yasm_calc_bc_dist_func calc_bc_dist)
cdef unsigned char* yasm_bc_tobytes(yasm_bytecode *bc,
unsigned char *buf, unsigned long *bufsize,
unsigned long *multiple, int *gap, void *d,
unsigned char *buf, unsigned long *bufsize, int *gap, void *d,
yasm_output_value_func output_value,
yasm_output_reloc_func output_reloc)
cdef int yasm_bc_get_multiple(yasm_bytecode *bc, unsigned long *multiple,
yasm_calc_bc_dist_func calc_bc_dist)
cdef yasm_dataval* yasm_dv_create_expr(yasm_expr *expn)
cdef yasm_dataval* yasm_dv_create_string(char *contents, size_t len)