diff -rup binutils.orig/binutils/doc/binutils.texi binutils-2.35.2/binutils/doc/binutils.texi --- binutils.orig/binutils/doc/binutils.texi 2024-04-03 11:32:37.507595411 +0100 +++ binutils-2.35.2/binutils/doc/binutils.texi 2024-04-03 11:32:53.188615675 +0100 @@ -1643,6 +1643,10 @@ above. If @var{sectionpattern} does not input file, a warning will be issued, unless @option{--no-change-warnings} is used. +Note - changing the VMA of sections in a fully linked binary can be +dangerous since there may be code that expects the sections to be +located at their old address. + @item --change-warnings @itemx --adjust-warnings If @option{--change-section-address} or @option{--change-section-lma} or @@ -1671,7 +1675,14 @@ ELF format files. @item --set-section-alignment @var{sectionpattern}=@var{align} Set the alignment for any sections matching @var{sectionpattern}. @var{align} specifies the alignment in bytes and must be a power of -two, i.e. 1, 2, 4, 8@dots{}. +two, i.e. 1, 2, 4, 8@dots{}. + +Note - setting a section's alignment will not automatically align its +LMA or VMA addresses. If those need to be changed as well then the +@option{--change-section-lma} and/or @option{--change-section-vma} +options should be used. Also note that changing VMAs can cause +problems in fully linked binaries where there may be code that expects +the contents of the sections to be located at their old address. @item --add-section @var{sectionname}=@var{filename} Add a new section named @var{sectionname} while copying the file. The @@ -2029,11 +2040,21 @@ for dlls. [This option is specific to PE targets.] @item --section-alignment @var{num} -Sets the section alignment field in the PE header. Sections in memory -will always begin at addresses which are a multiple of this number. -Defaults to 0x1000. [This option is specific to PE targets.] +Sets the section alignment field in the PE header - if one is present +in the binary. Sections in memory will always begin at addresses +which are a multiple of this number. Defaults to 0x1000. + +Note - this option will also set the alignment field in each section's +flags. + +Note - if a section's LMA or VMA addresses are no longer aligned, and +those addresses have not been set via the @option{--set-section-lma} or +@option{--set-section-vma} options, and the file has been fully +relocated then a warning message will be issued. It will then be up +to the user to decide if the LMA and VMA need updating. + @item --stack @var{reserve} @itemx --stack @var{reserve},@var{commit} Specify the number of bytes of memory to reserve (and optionally commit) diff -rup binutils.orig/binutils/objcopy.c binutils-2.35.2/binutils/objcopy.c --- binutils.orig/binutils/objcopy.c 2024-04-03 11:32:37.862595870 +0100 +++ binutils-2.35.2/binutils/objcopy.c 2024-04-03 11:32:53.189615676 +0100 @@ -3954,6 +3954,50 @@ setup_bfd_headers (bfd *ibfd, bfd *obfd) return; } +static inline signed int +power_of_two (bfd_vma val) +{ + signed int result = 0; + + if (val == 0) + return 0; + + while ((val & 1) == 0) + { + val >>= 1; + ++result; + } + + if (val != 1) + /* Number has more than one 1, i.e. wasn't a power of 2. */ + return -1; + + return result; +} + +static unsigned int +image_scn_align (unsigned int alignment) +{ + switch (alignment) + { + case 8192: return IMAGE_SCN_ALIGN_8192BYTES; + case 4096: return IMAGE_SCN_ALIGN_4096BYTES; + case 2048: return IMAGE_SCN_ALIGN_2048BYTES; + case 1024: return IMAGE_SCN_ALIGN_1024BYTES; + case 512: return IMAGE_SCN_ALIGN_512BYTES; + case 256: return IMAGE_SCN_ALIGN_256BYTES; + case 128: return IMAGE_SCN_ALIGN_128BYTES; + case 64: return IMAGE_SCN_ALIGN_64BYTES; + case 32: return IMAGE_SCN_ALIGN_32BYTES; + case 16: return IMAGE_SCN_ALIGN_16BYTES; + case 8: return IMAGE_SCN_ALIGN_8BYTES; + case 4: return IMAGE_SCN_ALIGN_4BYTES; + case 2: return IMAGE_SCN_ALIGN_2BYTES; + case 1: return IMAGE_SCN_ALIGN_1BYTES; + default: return 0; + } +} + /* Create a section in OBFD with the same name and attributes as ISECTION in IBFD. */ @@ -4058,6 +4102,8 @@ setup_section (bfd *ibfd, sec_ptr isecti goto loser; } + bfd_boolean vma_set_by_user = FALSE; + vma = bfd_section_vma (isection); p = find_section_list (bfd_section_name (isection), FALSE, SECTION_CONTEXT_ALTER_VMA | SECTION_CONTEXT_SET_VMA); @@ -4067,6 +4113,7 @@ setup_section (bfd *ibfd, sec_ptr isecti vma = p->vma_val; else vma += p->vma_val; + vma_set_by_user = TRUE; } else vma += change_section_address; @@ -4077,6 +4124,8 @@ setup_section (bfd *ibfd, sec_ptr isecti goto loser; } + bfd_boolean lma_set_by_user = FALSE; + lma = isection->lma; p = find_section_list (bfd_section_name (isection), FALSE, SECTION_CONTEXT_ALTER_LMA | SECTION_CONTEXT_SET_LMA); @@ -4086,6 +4135,7 @@ setup_section (bfd *ibfd, sec_ptr isecti lma += p->lma_val; else lma = p->lma_val; + lma_set_by_user = TRUE; } else lma += change_section_address; @@ -4096,6 +4146,24 @@ setup_section (bfd *ibfd, sec_ptr isecti SECTION_CONTEXT_SET_ALIGNMENT); if (p != NULL) alignment = p->alignment; + else if (pe_section_alignment != (bfd_vma) -1 + && bfd_get_flavour (obfd) == bfd_target_coff_flavour) + { + alignment = power_of_two (pe_section_alignment); + + if (coff_section_data (ibfd, isection)) + { + struct pei_section_tdata * pei_data = pei_section_data (ibfd, isection); + + if (pei_data != NULL) + { + /* Set the alignment flag of the input section, which will + be copied to the output section later on. */ + pei_data->pe_flags &= ~IMAGE_SCN_ALIGN_POWER_BIT_MASK; + pei_data->pe_flags |= image_scn_align (pe_section_alignment); + } + } + } else alignment = bfd_section_alignment (isection); @@ -4107,6 +4175,32 @@ setup_section (bfd *ibfd, sec_ptr isecti goto loser; } + /* If the output section's VMA is not aligned + and the alignment has changed + and the VMA was not set by the user + and the section does not have relocations associated with it + then warn the user. */ + if (osection->vma & ((1 << alignment) - 1) + && alignment != bfd_section_alignment (isection) + && change_section_address == 0 + && ! vma_set_by_user + && bfd_get_reloc_upper_bound (ibfd, isection) < 1) + { + non_fatal (_("output section %s's alignment does not match its VMA"), name); + } + + /* Similar check for a non-aligned LMA. + FIXME: Since this is only an LMA, maybe it does not matter if + it is not aligned ? */ + if (osection->lma & ((1 << alignment) - 1) + && alignment != bfd_section_alignment (isection) + && change_section_address == 0 + && ! lma_set_by_user + && bfd_get_reloc_upper_bound (ibfd, isection) < 1) + { + non_fatal (_("output section %s's alignment does not match its LMA"), name); + } + /* Copy merge entity size. */ osection->entsize = isection->entsize; @@ -5530,15 +5624,8 @@ copy_main (int argc, char *argv[]) fatal (_("bad format for --set-section-alignment: numeric argument needed")); /* Convert integer alignment into a power-of-two alignment. */ - palign = 0; - while ((align & 1) == 0) - { - align >>= 1; - ++palign; - } - - if (align != 1) - /* Number has more than on 1, i.e. wasn't a power of 2. */ + palign = power_of_two (align); + if (palign == -1) fatal (_("bad format for --set-section-alignment: alignment is not a power of two")); /* Add the alignment setting to the section list. */ @@ -5751,6 +5838,11 @@ copy_main (int argc, char *argv[]) case OPTION_PE_SECTION_ALIGNMENT: pe_section_alignment = parse_vma (optarg, "--section-alignment"); + if (power_of_two (pe_section_alignment) == -1) + { + non_fatal (_("--section-alignment argument is not a power of two: %s - ignoring"), optarg); + pe_section_alignment = (bfd_vma) -1; + } break; case OPTION_SUBSYSTEM: diff -rup binutils.orig/binutils/testsuite/binutils-all/objcopy.exp binutils-2.35.2/binutils/testsuite/binutils-all/objcopy.exp --- binutils.orig/binutils/testsuite/binutils-all/objcopy.exp 2024-04-03 11:32:37.781595765 +0100 +++ binutils-2.35.2/binutils/testsuite/binutils-all/objcopy.exp 2024-04-03 11:33:00.878625614 +0100 @@ -1342,6 +1342,7 @@ objcopy_remove_relocations_from_executab run_dump_test "pr23633" run_dump_test "set-section-alignment" +run_dump_test "section-alignment" setup_xfail "hppa*-*-*" setup_xfail "sh-*-coff*" --- /dev/null 2024-06-27 08:39:51.717818400 +0100 +++ binutils-2.35.2/binutils/testsuite/binutils-all/section-alignment.d 2024-06-27 15:43:00.626529058 +0100 @@ -0,0 +1,9 @@ +#source: pr23633.s +#PROG: objcopy +#objcopy: --section-alignment=512 +#objdump: -P sections +#target: [is_pecoff_format] + +#... +.* Align: 512.* +#pass --- binutils.orig/binutils/objcopy.c 2024-07-25 15:30:49.380323472 +0100 +++ binutils-2.35.2/binutils/objcopy.c 2024-07-25 15:33:35.779466989 +0100 @@ -4147,6 +4147,7 @@ setup_section (bfd *ibfd, sec_ptr isecti if (p != NULL) alignment = p->alignment; else if (pe_section_alignment != (bfd_vma) -1 + && bfd_get_flavour (ibfd) == bfd_target_coff_flavour && bfd_get_flavour (obfd) == bfd_target_coff_flavour) { alignment = power_of_two (pe_section_alignment); --- binutils.orig/bfd/coffcode.h 2024-08-12 09:44:06.041128327 +0100 +++ binutils-2.35.2/bfd/coffcode.h 2024-08-12 11:13:58.209619284 +0100 @@ -2942,7 +2942,7 @@ coff_compute_section_file_positions (bfd #endif #ifdef COFF_IMAGE_WITH_PE - int page_size; + unsigned int page_size; if (coff_data (abfd)->link_info || (pe_data (abfd) && pe_data (abfd)->pe_opthdr.FileAlignment)) @@ -2953,22 +2953,12 @@ coff_compute_section_file_positions (bfd This repairs 'ld -r' for arm-wince-pe target. */ if (page_size == 0) page_size = 1; - - /* PR 17512: file: 0ac816d3. */ - if (page_size < 0) - { - bfd_set_error (bfd_error_file_too_big); - _bfd_error_handler - /* xgettext:c-format */ - (_("%pB: page size is too large (0x%x)"), abfd, page_size); - return FALSE; - } } else page_size = PE_DEF_FILE_ALIGNMENT; #else #ifdef COFF_PAGE_SIZE - int page_size = COFF_PAGE_SIZE; + unsigned int page_size = COFF_PAGE_SIZE; #endif #endif @@ -3050,10 +3040,11 @@ coff_compute_section_file_positions (bfd bfd_size_type amt; #ifdef COFF_PAGE_SIZE - /* Clear D_PAGED if section alignment is smaller than - COFF_PAGE_SIZE. */ - if (pe_data (abfd)->pe_opthdr.SectionAlignment < COFF_PAGE_SIZE) - abfd->flags &= ~D_PAGED; + /* Clear D_PAGED if section / file alignment aren't suitable for + paging at COFF_PAGE_SIZE granularity. */ + if (pe_data (abfd)->pe_opthdr.SectionAlignment < COFF_PAGE_SIZE + || page_size < COFF_PAGE_SIZE) + abfd->flags &= ~D_PAGED; #endif count = 0; @@ -3173,7 +3164,11 @@ coff_compute_section_file_positions (bfd padding the previous section up if necessary. */ old_sofar = sofar; +#ifdef COFF_IMAGE_WITH_PE + sofar = BFD_ALIGN (sofar, page_size); +#else sofar = BFD_ALIGN (sofar, 1 << current->alignment_power); +#endif #ifdef RS6000COFF_C /* Make sure the file offset and the vma of .text/.data are at the @@ -3210,7 +3205,6 @@ coff_compute_section_file_positions (bfd if (previous != NULL) previous->size += sofar - old_sofar; } - #endif /* In demand paged files the low order bits of the file offset @@ -3221,7 +3215,7 @@ coff_compute_section_file_positions (bfd sofar += (current->vma - (bfd_vma) sofar) % page_size; #endif current->filepos = sofar; - + #ifdef COFF_IMAGE_WITH_PE /* Set the padded size. */ current->size = (current->size + page_size - 1) & -page_size; @@ -3244,7 +3238,11 @@ coff_compute_section_file_positions (bfd else { old_sofar = sofar; +#ifdef COFF_IMAGE_WITH_PE + sofar = BFD_ALIGN (sofar, page_size); +#else sofar = BFD_ALIGN (sofar, 1 << current->alignment_power); +#endif align_adjust = sofar != old_sofar; current->size += sofar - old_sofar; } --- binutils.orig/binutils/testsuite/binutils-all/aarch64/pei-aarch64-little.d 2024-08-14 13:10:49.565104090 +0100 +++ binutils-2.35.2/binutils/testsuite/binutils-all/aarch64/pei-aarch64-little.d 2024-08-14 13:15:44.378037490 +0100 @@ -12,5 +12,5 @@ start address 0x0000000000000000 Sections: Idx Name Size VMA LMA File off Algn - 0 \.text 00000030 0[^ ]+ 0[^ ]+ 0[^ ]+ 2\*\*12 + 0 \.text 00000030 0[^ ]+ 0[^ ]+ 0[^ ]+ 2\*\*2 CONTENTS, ALLOC, LOAD, READONLY, CODE