]> granicus.if.org Git - yasm/commitdiff
Fix major bug related to multiple handling. Unfortunately this slows down
authorPeter Johnson <peter@tortall.net>
Thu, 11 May 2006 07:00:33 +0000 (07:00 -0000)
committerPeter Johnson <peter@tortall.net>
Thu, 11 May 2006 07:00:33 +0000 (07:00 -0000)
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

libyasm/bytecode.c
libyasm/bytecode.h
modules/listfmts/nasm/nasm-listfmt.c
modules/objfmts/bin/bin-objfmt.c
modules/objfmts/coff/coff-objfmt.c
modules/objfmts/elf/elf-objfmt.c
modules/objfmts/xdf/xdf-objfmt.c
tests/win32-relocovfl.asm [new file with mode: 0644]
tools/python-yasm/bytecode.pxi

index 2ab884b005c2bc159cf3ad871946257b1a766d3a..7138b3ce6bc21a140606d595217235847b0d6516 100644 (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;
+}
index f8100da147b5c639089a75daa5d44ffb4fc8fb59..621bd0521387ce19e1f5f8c1b6232affc3131dfd 100644 (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.
index 168e9ab5af7d990cf0255f6d6c50c04a2ad23ee8..0f19723474d2bb2502ce996df9cab0a68db5d56b 100644 (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;
index 184656e0f28eb25053f9581ff7ec1b15ba437e66..da84defdfd8088fa4efdb0677c3fcb1103fb9509 100644 (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 */
index 39b7f34cd4164f1c7e39c576c2ce02b29a63e7ab..6a3a995756274cd46aca2f7304cf6595286f3f3f 100644 (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 */
index b7d15fc6694fdf4bf2ebd80778beb7daf2b8e7ff..2beeffbf2b65c2800a8b30529a36c07be30054d6 100644 (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 */
index 5a1b80023e7d1eec4af076877da0ed09e26115ac..56fe213cb8fbfbf29338ff6364f64a097d61bcdb 100644 (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 */
diff --git a/tests/win32-relocovfl.asm b/tests/win32-relocovfl.asm
new file mode 100644 (file)
index 0000000..fc3cddb
--- /dev/null
@@ -0,0 +1,3 @@
+extern foo
+section .text
+times 64*1024 dd foo
index d1c079195b518dafdc689b710dcf1be0ca4dbd4f..1c3e5ab4983d14a77929cab78f10c99a69693153 100644 (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)