coff: Better handling of section redefinition
authorMarat Dukhan <maratek@gmail.com>
Thu, 19 Sep 2013 23:19:52 +0000 (19:19 -0400)
committerCyrill Gorcunov <gorcunov@gmail.com>
Thu, 3 Oct 2013 12:55:50 +0000 (16:55 +0400)
Currently, if we try to define an already defined section and specify
section flags, NASM will output "warning: section attributes ignored
on redeclaration of section %SECTIONNAME%".

The patch modifies this behaviour:

1. If the previous section definition differs only in alignment flags,
   no warning is generated

2. If the new definition implies larger alignment, it overrides the
   previous section alignment

3. If the new definition specifies any section alignment, the content of
   the section will be aligned on the new boundary (i.e. the effect is the
   same as if there was ALIGN macro)

Signed-off-by: Marat Dukhan <maratek@gmail.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
output/outcoff.c

index b404347..d0fcb77 100644 (file)
@@ -442,9 +442,42 @@ static int32_t coff_section_names(char *name, int pass, int *bits)
         sects[i]->flags &= align_and;
         sects[i]->flags |= align_or;
     } else if (pass == 1) {
-        if (flags)
-            nasm_error(ERR_WARNING, "section attributes ignored on"
-                  " redeclaration of section `%s'", name);
+        /* Check if any flags are specified */
+        if (flags) {
+            unsigned int align_flags = flags & IMAGE_SCN_ALIGN_MASK;
+
+            /* Warn if non-alignment flags differ */
+            if ((flags ^ sects[i]->flags) & ~IMAGE_SCN_ALIGN_MASK) {
+                nasm_error(ERR_WARNING, "section attributes ignored on"
+                    " redeclaration of section `%s'", name);
+            }
+            /* Check if alignment might be needed */
+            if (align_flags > IMAGE_SCN_ALIGN_1BYTES) {
+                unsigned int sect_align_flags = sects[i]->flags & IMAGE_SCN_ALIGN_MASK;
+
+                /* Compute the actual alignment */
+                unsigned int align = 1u << ((align_flags - IMAGE_SCN_ALIGN_1BYTES) >> 20);
+
+                /* Update section header as needed */
+                if (align_flags > sect_align_flags) {
+                    sects[i]->flags = (sects[i]->flags & ~IMAGE_SCN_ALIGN_MASK) | align_flags;
+                }
+                /* Check if not already aligned */
+                if (sects[i]->len % align) {
+                    unsigned int padding = (align - sects[i]->len) % align;
+                    /* We need to write at most 8095 bytes */
+                    char buffer[8095];
+                    if (sects[i]->flags & IMAGE_SCN_CNT_CODE) {
+                        /* Fill with INT 3 instructions */
+                        memset(buffer, 0xCC, padding);
+                    } else {
+                        memset(buffer, 0x00, padding);
+                    }
+                    saa_wbytes(sects[i]->data, buffer, padding);
+                    sects[i]->len += padding;
+                }
+            }
+        }
     }
 
     return sects[i]->index;