From: Peter Johnson Date: Tue, 22 Oct 2002 06:37:24 +0000 (-0000) Subject: Fix COFF_SET_VMA output (needed to add section start address to addend). X-Git-Tag: v0.2.0~79 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=50d92d758e66b361cd8cbfe1e3e098457add3f34;p=yasm Fix COFF_SET_VMA output (needed to add section start address to addend). 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 --- diff --git a/modules/objfmts/coff/coff-objfmt.c b/modules/objfmts/coff/coff-objfmt.c index a15646da..8295762c 100644 --- a/modules/objfmts/coff/coff-objfmt.c +++ b/modules/objfmts/coff/coff-objfmt.c @@ -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; diff --git a/modules/objfmts/coff/tests/cofftest.hex b/modules/objfmts/coff/tests/cofftest.hex index 659aeff2..c7223f0f 100644 --- a/modules/objfmts/coff/tests/cofftest.hex +++ b/modules/objfmts/coff/tests/cofftest.hex @@ -156,13 +156,13 @@ ec 5d c3 a1 -00 +80 00 00 00 40 a3 -04 +84 00 00 00 @@ -173,7 +173,7 @@ ff 00 00 a1 -34 +74 00 00 00 @@ -181,12 +181,12 @@ ff 30 ff 35 -00 +80 00 00 00 68 -0d +4d 00 00 00 @@ -324,7 +324,7 @@ c3 64 0a 00 -04 +84 00 00 00 @@ -332,7 +332,7 @@ c3 00 00 00 -3c +7c 00 00 00 diff --git a/src/objfmts/coff/coff-objfmt.c b/src/objfmts/coff/coff-objfmt.c index a15646da..8295762c 100644 --- a/src/objfmts/coff/coff-objfmt.c +++ b/src/objfmts/coff/coff-objfmt.c @@ -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; diff --git a/src/objfmts/coff/tests/cofftest.hex b/src/objfmts/coff/tests/cofftest.hex index 659aeff2..c7223f0f 100644 --- a/src/objfmts/coff/tests/cofftest.hex +++ b/src/objfmts/coff/tests/cofftest.hex @@ -156,13 +156,13 @@ ec 5d c3 a1 -00 +80 00 00 00 40 a3 -04 +84 00 00 00 @@ -173,7 +173,7 @@ ff 00 00 a1 -34 +74 00 00 00 @@ -181,12 +181,12 @@ ff 30 ff 35 -00 +80 00 00 00 68 -0d +4d 00 00 00 @@ -324,7 +324,7 @@ c3 64 0a 00 -04 +84 00 00 00 @@ -332,7 +332,7 @@ c3 00 00 00 -3c +7c 00 00 00