mirror of
https://github.com/yasm/yasm
synced 2026-08-26 22:26:05 -04:00
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:
parent
58921419c2
commit
fe09480565
9 changed files with 81 additions and 79 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
3
tests/win32-relocovfl.asm
Normal file
3
tests/win32-relocovfl.asm
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
extern foo
|
||||
section .text
|
||||
times 64*1024 dd foo
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue