From 29227125f05302cc3e084f2e799411c78b0258e0 Mon Sep 17 00:00:00 2001 From: Marat Dukhan Date: Thu, 19 Sep 2013 19:19:52 -0400 Subject: [PATCH] coff: Better handling of section redefinition 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 Signed-off-by: Cyrill Gorcunov --- output/outcoff.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/output/outcoff.c b/output/outcoff.c index b404347b..d0fcb775 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; -- 2.11.4.GIT