summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--output/outcoff.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/output/outcoff.c b/output/outcoff.c
index b404347..d0fcb77 100644
--- a/output/outcoff.c
+++ b/output/outcoff.c
@@ -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;