summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarat Dukhan <maratek@gmail.com>2013-09-19 19:19:52 -0400
committerCyrill Gorcunov <gorcunov@gmail.com>2013-10-03 16:55:50 +0400
commit29227125f05302cc3e084f2e799411c78b0258e0 (patch)
tree5a0f5f36c3bdb0d911b4dd3fee3fac734c25f078
parente81b2ee85ca0f06705181dca615f13b50fcb3c35 (diff)
downloadnasm-2.10.xx.tar.gz
coff: Better handling of section redefinitionnasm-2.10.xx
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>
-rw-r--r--output/outcoff.c39
1 files 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;