]> granicus.if.org Git - yasm/commitdiff
Fix COFF_SET_VMA output (needed to add section start address to addend).
authorPeter Johnson <peter@tortall.net>
Tue, 22 Oct 2002 06:37:24 +0000 (06:37 -0000)
committerPeter Johnson <peter@tortall.net>
Tue, 22 Oct 2002 06:37:24 +0000 (06:37 -0000)
To ensure all section start addresses are known, added a first pre-pass of
sections to calculate each one's address.

svn path=/trunk/yasm/; revision=775

modules/objfmts/coff/coff-objfmt.c
modules/objfmts/coff/tests/cofftest.hex
src/objfmts/coff/coff-objfmt.c
src/objfmts/coff/tests/cofftest.hex

index a15646da7f2c2d03c26470ebb5ae76ddc65a0ad5..8295762c414d527b1b448892bb20f8dbbd347234 100644 (file)
@@ -215,6 +215,29 @@ coff_objfmt_initialize(const char *in_filename,
     STAILQ_INSERT_TAIL(&coff_symtab, entry, link);
 }
 
+static int
+coff_objfmt_set_section_addr(section *sect, /*@null@*/ void *d)
+{
+    /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;
+    /*@dependent@*/ /*@null@*/ coff_section_data *csd;
+    /*@null@*/ bytecode *last;
+
+    /* Don't output absolute sections */
+    if (section_is_absolute(sect))
+       return 0;
+
+    assert(info != NULL);
+    csd = section_get_of_data(sect);
+    assert(csd != NULL);
+
+    csd->addr = info->addr;
+    last = bcs_last(section_get_bytecodes(sect));
+    if (last)
+       info->addr += last->offset + last->len;
+
+    return 0;
+}
+
 static int
 coff_objfmt_output_expr(expr **ep, unsigned char **bufp, unsigned long valsize,
                        unsigned long offset,
@@ -271,6 +294,9 @@ coff_objfmt_output_expr(expr **ep, unsigned char **bufp, unsigned long valsize,
                label_csd = section_get_of_data(label_sect);
                assert(label_csd != NULL);
                reloc->sym = label_csd->sym;
+               if (COFF_SET_VMA)
+                   *ep = expr_new(EXPR_ADD, ExprExpr(*ep),
+                                  ExprInt(intnum_new_uint(label_csd->addr)));
            }
        }
 
@@ -486,6 +512,16 @@ coff_objfmt_output(FILE *f, sectionhead *sections)
     }
 
     /* Section data/relocs */
+    if (COFF_SET_VMA) {
+       /* If we're setting the VMA, we need to do a first section pass to
+        * determine each section's addr value before actually outputting
+        * relocations, as a relocation's section address is added into the
+        * addends in the generated code.
+        */
+       info.addr = 0;
+       if (sections_traverse(sections, &info, coff_objfmt_set_section_addr))
+           return;
+    }
     info.addr = 0;
     if (sections_traverse(sections, &info, coff_objfmt_output_section))
        return;
index 659aeff2fd55f9a37136fe855094931b41afb357..c7223f0f3cc5d2bf49e2049a90dd3c3ccd56798f 100644 (file)
@@ -156,13 +156,13 @@ ec
 5d 
 c3 
 a1 
-0
+8
 00 
 00 
 00 
 40 
 a3 
-0
+8
 00 
 00 
 00 
@@ -173,7 +173,7 @@ ff
 00 
 00 
 a1 
-3
+7
 00 
 00 
 00 
@@ -181,12 +181,12 @@ ff
 30 
 ff 
 35 
-0
+8
 00 
 00 
 00 
 68 
-0
+4
 00 
 00 
 00 
@@ -324,7 +324,7 @@ c3
 64 
 0a 
 00 
-0
+8
 00 
 00 
 00 
@@ -332,7 +332,7 @@ c3
 00 
 00 
 00 
-3
+7
 00 
 00 
 00 
index a15646da7f2c2d03c26470ebb5ae76ddc65a0ad5..8295762c414d527b1b448892bb20f8dbbd347234 100644 (file)
@@ -215,6 +215,29 @@ coff_objfmt_initialize(const char *in_filename,
     STAILQ_INSERT_TAIL(&coff_symtab, entry, link);
 }
 
+static int
+coff_objfmt_set_section_addr(section *sect, /*@null@*/ void *d)
+{
+    /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;
+    /*@dependent@*/ /*@null@*/ coff_section_data *csd;
+    /*@null@*/ bytecode *last;
+
+    /* Don't output absolute sections */
+    if (section_is_absolute(sect))
+       return 0;
+
+    assert(info != NULL);
+    csd = section_get_of_data(sect);
+    assert(csd != NULL);
+
+    csd->addr = info->addr;
+    last = bcs_last(section_get_bytecodes(sect));
+    if (last)
+       info->addr += last->offset + last->len;
+
+    return 0;
+}
+
 static int
 coff_objfmt_output_expr(expr **ep, unsigned char **bufp, unsigned long valsize,
                        unsigned long offset,
@@ -271,6 +294,9 @@ coff_objfmt_output_expr(expr **ep, unsigned char **bufp, unsigned long valsize,
                label_csd = section_get_of_data(label_sect);
                assert(label_csd != NULL);
                reloc->sym = label_csd->sym;
+               if (COFF_SET_VMA)
+                   *ep = expr_new(EXPR_ADD, ExprExpr(*ep),
+                                  ExprInt(intnum_new_uint(label_csd->addr)));
            }
        }
 
@@ -486,6 +512,16 @@ coff_objfmt_output(FILE *f, sectionhead *sections)
     }
 
     /* Section data/relocs */
+    if (COFF_SET_VMA) {
+       /* If we're setting the VMA, we need to do a first section pass to
+        * determine each section's addr value before actually outputting
+        * relocations, as a relocation's section address is added into the
+        * addends in the generated code.
+        */
+       info.addr = 0;
+       if (sections_traverse(sections, &info, coff_objfmt_set_section_addr))
+           return;
+    }
     info.addr = 0;
     if (sections_traverse(sections, &info, coff_objfmt_output_section))
        return;
index 659aeff2fd55f9a37136fe855094931b41afb357..c7223f0f3cc5d2bf49e2049a90dd3c3ccd56798f 100644 (file)
@@ -156,13 +156,13 @@ ec
 5d 
 c3 
 a1 
-0
+8
 00 
 00 
 00 
 40 
 a3 
-0
+8
 00 
 00 
 00 
@@ -173,7 +173,7 @@ ff
 00 
 00 
 a1 
-3
+7
 00 
 00 
 00 
@@ -181,12 +181,12 @@ ff
 30 
 ff 
 35 
-0
+8
 00 
 00 
 00 
 68 
-0
+4
 00 
 00 
 00 
@@ -324,7 +324,7 @@ c3
 64 
 0a 
 00 
-0
+8
 00 
 00 
 00 
@@ -332,7 +332,7 @@ c3
 00 
 00 
 00 
-3
+7
 00 
 00 
 00