]> granicus.if.org Git - yasm/commitdiff
Add ability for GAS input to set section alignment in the same way GAS does:
authorPeter Johnson <peter@tortall.net>
Mon, 7 Nov 2005 06:53:52 +0000 (06:53 -0000)
committerPeter Johnson <peter@tortall.net>
Mon, 7 Nov 2005 06:53:52 +0000 (06:53 -0000)
if the first thing in the section is a .align, that specifies the section
alignment.

* objfmt.h (yasm_objfmt_module): Add section_align() function.
(yasm_objfmt_section_align): Add wrapper for module section_align().
* xdf-objfmt.c, elf-objfmt.c, bin-objfmt.c, dbg-objfmt.c, coff-objfmt.c:
Implement.

* gas-bison.y (gas_parser_align): Call new yasm_objfmt_section_align() rather
than creating an align bytecode if .align is the first bytecode in the
section.

* gassectalign.asm: New test for this.

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

libyasm/objfmt.h
modules/objfmts/bin/bin-objfmt.c
modules/objfmts/coff/coff-objfmt.c
modules/objfmts/dbg/dbg-objfmt.c
modules/objfmts/elf/elf-objfmt.c
modules/objfmts/xdf/xdf-objfmt.c
modules/parsers/gas/gas-bison.y
modules/parsers/gas/tests/Makefile.inc
modules/parsers/gas/tests/gassectalign.asm [new file with mode: 0644]
modules/parsers/gas/tests/gassectalign.errwarn [new file with mode: 0644]
modules/parsers/gas/tests/gassectalign.hex [new file with mode: 0644]

index 0bdd64832e80f422c89ee9a1281f3f2b0ce862cd..34cf80f0f2a4102fc787d60efa477c5f88c5f84a 100644 (file)
@@ -107,6 +107,12 @@ typedef struct yasm_objfmt_module {
                          /*@null@*/ yasm_valparamhead *objext_valparams,
                          unsigned long line);
 
+    /** Module-level implementation of yasm_objfmt_section_align().
+     * Call yasm_objfmt_section_align() instead of calling this function.
+     */
+    void (*section_align)(yasm_objfmt *objfmt, yasm_section *sect,
+                         unsigned long align, unsigned long line);
+
     /** Module-level implementation of yasm_objfmt_extern_declare().
      * Call yasm_objfmt_extern_declare() instead of calling this function.
      */
@@ -179,6 +185,15 @@ void yasm_objfmt_destroy(/*@only@*/ yasm_objfmt *objfmt);
     (yasm_objfmt *objfmt, yasm_valparamhead *valparams,
      /*@null@*/ yasm_valparamhead *objext_valparams, unsigned long line);
 
+/** Set alignment for a section.
+ * \param objfmt       object format
+ * \param sect         section
+ * \param align                desired alignment (must be power of two)
+ * \param line         virtual line (from yasm_linemap)
+ */
+void yasm_objfmt_section_align(yasm_objfmt *objfmt, yasm_section *sect,
+                              unsigned long align, unsigned long line);
+
 /** Declare an "extern" (importing from another module) symbol.  Should
  * call yasm_symtab_declare().
  * \param objfmt               object format
@@ -246,6 +261,9 @@ int yasm_objfmt_directive(yasm_objfmt *objfmt, const char *name,
 #define yasm_objfmt_section_switch(objfmt, vpms, oe_vpms, line) \
     ((yasm_objfmt_base *)objfmt)->module->section_switch(objfmt, vpms, \
                                                         oe_vpms, line)
+#define yasm_objfmt_section_align(objfmt, sect, align, line) \
+    ((yasm_objfmt_base *)objfmt)->module->section_align(objfmt, sect, \
+                                                       align, line)
 #define yasm_objfmt_extern_declare(objfmt, name, oe_vpms, line) \
     ((yasm_objfmt_base *)objfmt)->module->extern_declare(objfmt, name, \
                                                         oe_vpms, line)
index 8c8f4182fb717c53b68599ba1cae828e287a7313..e8102612f2834cd8497943df04161523e204cd31 100644 (file)
@@ -445,6 +445,27 @@ bin_objfmt_section_switch(yasm_objfmt *objfmt, yasm_valparamhead *valparams,
     } else
        return NULL;
 }
+static void
+bin_objfmt_section_align(yasm_objfmt *objfmt, yasm_section *sect,
+                        unsigned long align, unsigned long line)
+{
+    /*@only@*/ unsigned long *oldalign;
+
+    if (strcmp(yasm_section_get_name(sect), ".text") == 0) {
+       yasm__error(line, N_("cannot specify an alignment to the `%s' section"),
+                   ".text");
+       return;
+    }
+
+    oldalign = yasm_section_get_data(sect, &bin_section_data_callback);
+    if (oldalign)
+       *oldalign = align;
+    else {
+       unsigned long *data = yasm_xmalloc(sizeof(unsigned long));
+       *data = align;
+       yasm_section_add_data(sect, &bin_section_data_callback, data);
+    }
+}
 
 static void
 bin_section_data_destroy(/*@only@*/ void *d)
@@ -568,6 +589,7 @@ yasm_objfmt_module yasm_bin_LTX_objfmt = {
     bin_objfmt_output,
     bin_objfmt_destroy,
     bin_objfmt_section_switch,
+    bin_objfmt_section_align,
     bin_objfmt_extern_declare,
     bin_objfmt_global_declare,
     bin_objfmt_common_declare,
index 49b8578d31043b370dc8de31eeb14f712581e2fa..8702a03c1a7c645776a09391942e962b65220a7b 100644 (file)
@@ -1240,6 +1240,37 @@ coff_objfmt_section_switch(yasm_objfmt *objfmt, yasm_valparamhead *valparams,
     return retval;
 }
 
+static void
+coff_objfmt_section_align(yasm_objfmt *objfmt, yasm_section *sect,
+                         unsigned long align, unsigned long line)
+{
+    yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)objfmt;
+    /*@dependent@*/ /*@null@*/ coff_section_data *csd;
+
+    csd = yasm_section_get_data(sect, &coff_section_data_cb);
+    if (!csd)
+       yasm_internal_error(N_("NULL coff section data in section_align"));
+
+    if (!objfmt_coff->win32) {
+       yasm__warning(YASM_WARN_GENERAL, line,
+                     N_("COFF does not support section alignment"));
+       return;
+    }
+
+    /* Check to see if alignment is supported size */
+    if (align > 8192) {
+       yasm__error(line, N_("Win32 does not support alignments > 8192"));
+       return;
+    }
+
+    /* Convert alignment into flags setting */
+    csd->flags &= ~COFF_STYP_ALIGN_MASK;
+    while (align != 0) {
+       csd->flags += 1<<COFF_STYP_ALIGN_SHIFT;
+       align >>= 1;
+    }
+}
+
 static void
 coff_section_data_destroy(void *data)
 {
@@ -1430,6 +1461,7 @@ yasm_objfmt_module yasm_coff_LTX_objfmt = {
     coff_objfmt_output,
     coff_objfmt_destroy,
     coff_objfmt_section_switch,
+    coff_objfmt_section_align,
     coff_objfmt_extern_declare,
     coff_objfmt_global_declare,
     coff_objfmt_common_declare,
@@ -1449,6 +1481,7 @@ yasm_objfmt_module yasm_win32_LTX_objfmt = {
     coff_objfmt_output,
     coff_objfmt_destroy,
     coff_objfmt_section_switch,
+    coff_objfmt_section_align,
     coff_objfmt_extern_declare,
     coff_objfmt_global_declare,
     coff_objfmt_common_declare,
@@ -1468,6 +1501,7 @@ yasm_objfmt_module yasm_win64_LTX_objfmt = {
     coff_objfmt_output,
     coff_objfmt_destroy,
     coff_objfmt_section_switch,
+    coff_objfmt_section_align,
     coff_objfmt_extern_declare,
     coff_objfmt_global_declare,
     coff_objfmt_common_declare,
index 0aef687c1a5e1e6a1809819df39c17595effe9fc..80f40119735d96e8eb22f5b91793c6e0d91e60a7 100644 (file)
@@ -133,6 +133,15 @@ dbg_objfmt_section_switch(yasm_objfmt *objfmt, yasm_valparamhead *valparams,
     }
 }
 
+static void
+dbg_objfmt_section_align(yasm_objfmt *objfmt, yasm_section *sect,
+                        unsigned long align, unsigned long line)
+{
+    yasm_objfmt_dbg *objfmt_dbg = (yasm_objfmt_dbg *)objfmt;
+    fprintf(objfmt_dbg->dbgfile, "section_align(\"%s\", %lu, %lu)\n",
+           yasm_section_get_name(sect), align, line);
+}
+
 static yasm_symrec *
 dbg_objfmt_extern_declare(yasm_objfmt *objfmt, const char *name,
                          /*@unused@*/ /*@null@*/
@@ -225,6 +234,7 @@ yasm_objfmt_module yasm_dbg_LTX_objfmt = {
     dbg_objfmt_output,
     dbg_objfmt_destroy,
     dbg_objfmt_section_switch,
+    dbg_objfmt_section_align,
     dbg_objfmt_extern_declare,
     dbg_objfmt_global_declare,
     dbg_objfmt_common_declare,
index 0f6cb79cd5986f8c0a31c2e6d74b08606eb60526..5aaec99e568075fa97a42250bc7d96cc9af0af66 100644 (file)
@@ -913,6 +913,20 @@ elf_objfmt_section_switch(yasm_objfmt *objfmt, yasm_valparamhead *valparams,
     return retval;
 }
 
+static void
+elf_objfmt_section_align(/*@unused@*/ yasm_objfmt *objfmt, yasm_section *sect,
+                        unsigned long align, unsigned long line)
+{
+    /*@dependent@*/ /*@null@*/ elf_secthead *esd;
+
+    esd = yasm_section_get_data(sect, &elf_section_data);
+
+    if (!esd)
+       yasm_internal_error(N_("NULL elf section data in section_align"));
+
+    elf_secthead_set_align(esd, yasm_intnum_create_uint(align));
+}
+
 static yasm_symrec *
 elf_objfmt_extern_declare(yasm_objfmt *objfmt, const char *name, /*@unused@*/
                          /*@null@*/ yasm_valparamhead *objext_valparams,
@@ -1133,6 +1147,7 @@ yasm_objfmt_module yasm_elf_LTX_objfmt = {
     elf_objfmt_output,
     elf_objfmt_destroy,
     elf_objfmt_section_switch,
+    elf_objfmt_section_align,
     elf_objfmt_extern_declare,
     elf_objfmt_global_declare,
     elf_objfmt_common_declare,
@@ -1151,6 +1166,7 @@ yasm_objfmt_module yasm_elf32_LTX_objfmt = {
     elf_objfmt_output,
     elf_objfmt_destroy,
     elf_objfmt_section_switch,
+    elf_objfmt_section_align,
     elf_objfmt_extern_declare,
     elf_objfmt_global_declare,
     elf_objfmt_common_declare,
@@ -1169,6 +1185,7 @@ yasm_objfmt_module yasm_elf64_LTX_objfmt = {
     elf_objfmt_output,
     elf_objfmt_destroy,
     elf_objfmt_section_switch,
+    elf_objfmt_section_align,
     elf_objfmt_extern_declare,
     elf_objfmt_global_declare,
     elf_objfmt_common_declare,
index d7ff9b77459207863b2324b9216f1e367fb6da5f..7e932ed3fb026e07c82569008e7ad67604e6f350 100644 (file)
@@ -776,6 +776,24 @@ xdf_objfmt_section_switch(yasm_objfmt *objfmt, yasm_valparamhead *valparams,
                      N_("section flags ignored on section redeclaration"));
     return retval;
 }
+static void
+xdf_objfmt_section_align(yasm_objfmt *objfmt, yasm_section *sect,
+                        unsigned long align, unsigned long line)
+{
+    /*@dependent@*/ /*@null@*/ xdf_section_data *xsd;
+
+    xsd = yasm_section_get_data(sect, &xdf_section_data_cb);
+    if (!xsd)
+       yasm_internal_error(N_("NULL xdf section data in section_align"));
+
+    /* Check to see if alignment is supported size */
+    if (align > 4096) {
+       yasm__error(line, N_("XDF does not support alignments > 4096"));
+       return;
+    }
+
+    xsd->align = align;
+}
 
 static void
 xdf_section_data_destroy(void *data)
@@ -891,6 +909,7 @@ yasm_objfmt_module yasm_xdf_LTX_objfmt = {
     xdf_objfmt_output,
     xdf_objfmt_destroy,
     xdf_objfmt_section_switch,
+    xdf_objfmt_section_align,
     xdf_objfmt_extern_declare,
     xdf_objfmt_global_declare,
     xdf_objfmt_common_declare,
index c547f29589e350a05131f04e4068ca0488a43c93..c9298db99502e7b799517a4278597149e8f0eeab 100644 (file)
@@ -841,6 +841,31 @@ gas_parser_align(yasm_parser_gas *parser_gas, yasm_valparamhead *valparams,
                                    yasm_expr_int(yasm_intnum_create_uint(1)),
                                    yasm_expr_expr(boundval), cur_line);
 
+    /* If .align is the first bytecode in the section, it's really specifying
+     * section alignment.
+     */
+    if (parser_gas->prev_bc
+       == yasm_section_bcs_first(parser_gas->cur_section)) {
+       yasm_intnum *boundintn = yasm_expr_get_intnum(&boundval, NULL);
+       unsigned long boundint;
+       if (!boundintn) {
+           yasm__error(cur_line, N_("section alignment not constnat"));
+           return NULL;
+       }
+       boundint = yasm_intnum_get_uint(boundintn);
+
+       /* Alignments must be a power of two. */
+       if ((boundint & (boundint - 1)) != 0) {
+           yasm__error(cur_line,
+                       N_("section alignment is not a power of two"));
+           return NULL;
+       }
+
+       yasm_objfmt_section_align(parser_gas->objfmt, parser_gas->cur_section,
+                                 boundint, cur_line);
+       return NULL;
+    }
+
     return yasm_bc_create_align(boundval, fillval, maxskipval,
                                parser_gas->code_section ?
                                    yasm_arch_get_fill(parser_gas->arch) : NULL,
index e357c98b90fc498af176bd4178b363e3043476a8..5c940d8e7fd16cd21b30d65bc911bf8fe6c88955 100644 (file)
@@ -18,6 +18,9 @@ EXTRA_DIST += modules/parsers/gas/tests/gas-instlabel.hex
 EXTRA_DIST += modules/parsers/gas/tests/gas-semi.asm
 EXTRA_DIST += modules/parsers/gas/tests/gas-semi.errwarn
 EXTRA_DIST += modules/parsers/gas/tests/gas-semi.hex
+EXTRA_DIST += modules/parsers/gas/tests/gassectalign.asm
+EXTRA_DIST += modules/parsers/gas/tests/gassectalign.errwarn
+EXTRA_DIST += modules/parsers/gas/tests/gassectalign.hex
 EXTRA_DIST += modules/parsers/gas/tests/jmpcall.asm
 EXTRA_DIST += modules/parsers/gas/tests/jmpcall.errwarn
 EXTRA_DIST += modules/parsers/gas/tests/jmpcall.hex
diff --git a/modules/parsers/gas/tests/gassectalign.asm b/modules/parsers/gas/tests/gassectalign.asm
new file mode 100644 (file)
index 0000000..b11bffe
--- /dev/null
@@ -0,0 +1,6 @@
+.text
+.align 8
+.data
+.align 16
+.bss
+.align 32
diff --git a/modules/parsers/gas/tests/gassectalign.errwarn b/modules/parsers/gas/tests/gassectalign.errwarn
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/modules/parsers/gas/tests/gassectalign.hex b/modules/parsers/gas/tests/gassectalign.hex
new file mode 100644 (file)
index 0000000..2740266
--- /dev/null
@@ -0,0 +1,472 @@
+7f 
+45 
+4c 
+46 
+01 
+01 
+01 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+01 
+00 
+03 
+00 
+01 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+c0 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+34 
+00 
+00 
+00 
+00 
+00 
+28 
+00 
+07 
+00 
+01 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+2e 
+74 
+65 
+78 
+74 
+00 
+2e 
+64 
+61 
+74 
+61 
+00 
+2e 
+62 
+73 
+73 
+00 
+2e 
+73 
+74 
+72 
+74 
+61 
+62 
+00 
+2e 
+73 
+79 
+6d 
+74 
+61 
+62 
+00 
+2e 
+73 
+68 
+73 
+74 
+72 
+74 
+61 
+62 
+00 
+00 
+2d 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+01 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+04 
+00 
+f1 
+ff 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+03 
+00 
+06 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+03 
+00 
+05 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+03 
+00 
+04 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+22 
+00 
+00 
+00 
+03 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+40 
+00 
+00 
+00 
+2c 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+12 
+00 
+00 
+00 
+03 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+6c 
+00 
+00 
+00 
+03 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+1a 
+00 
+00 
+00 
+02 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+70 
+00 
+00 
+00 
+50 
+00 
+00 
+00 
+02 
+00 
+00 
+00 
+05 
+00 
+00 
+00 
+04 
+00 
+00 
+00 
+10 
+00 
+00 
+00 
+01 
+00 
+00 
+00 
+01 
+00 
+00 
+00 
+06 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+38 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+08 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+07 
+00 
+00 
+00 
+01 
+00 
+00 
+00 
+03 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+40 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+10 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+0d 
+00 
+00 
+00 
+08 
+00 
+00 
+00 
+03 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+00 
+20 
+00 
+00 
+00 
+00 
+00 
+00 
+00