public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [ld] section address : ALIGN(align) and the maximum of input section alignments
@ 2020-02-26  5:23 Fangrui Song
  2020-02-26  6:31 ` Fangrui Song
  0 siblings, 1 reply; 11+ messages in thread
From: Fangrui Song @ 2020-02-26  5:23 UTC (permalink / raw)
  To: binutils

https://sourceware.org/binutils/docs/ld/Output-Section-Description.html
I have observed some strange rules while playing with the output section address and ALIGN.

cat > a.s <<e
  .globl _start; _start: ret
  .section .data.rel.ro,"aw"; .balign 8; .byte 0
  .data; .byte 0
  .section .data2,"aw"; .balign 8; .byte 0
  .section .data3,"aw"; .balign 32; .byte 0
  .bss; .balign 32; .byte 0
e

cat > a.x <<e
  SECTIONS {
    .text 0x10000 : { *(.text) }
    /* sh_addr is aligned to 16. */
    .data.rel.ro . : ALIGN(16) { *(.data.rel.ro) }

    .data 0x20000 : { *(.data) }
    /* The output section address is set without ALIGN. sh_addr is set to Dot, ignoring alignment. */
    /* sh_addralign is the maximum of input section alignments, 8. */
    .data2 . : { *(.data2) }
    /* sh_addr is aligned to 32. */
    .data3 : ALIGN(16) { *(.data3) }
    /* sh_addr is aligned to 16, ???????????? */
    .bss . : ALIGN(16) { *(.bss) }
  }
e

as a.s -o a.o
ld.bfd -T a.x a.o -o a

% readelf -WS a

Section Headers:
   [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
   [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
   [ 1] .text             PROGBITS        0000000000010000 001000 000001 00  AX  0   0  1
   [ 2] .data.rel.ro      PROGBITS        0000000000010010 001010 000001 00  WA  0   0 16
   [ 3] .data             PROGBITS        0000000000020000 002000 000001 00  WA  0   0  1
   [ 4] .data2            PROGBITS        0000000000020008 002008 000001 00  WA  0   0  8
   [ 5] .data3            PROGBITS        0000000000020020 002020 000001 00  WA  0   0 32
   [ 6] .bss              NOBITS          0000000000020030 002021 000011 00  WA  0   0 32
...


Why doesn't `.bss . : ALIGN(16)` respect the maximum of input section alignments (32)?

(I have verified that .bss being SHT_NOBITS is unrelated.)

The rule of sh_addr computation appears to be:

* ADDR is unset, ALIGN is unset => max_input_alignment
* ADDR is unset, ALIGN is set => max(ALIGN, max_input_alignment)
* ADDR is set, ALIGN is unset => max_input_alignment
* ADDR is set, ALIGN is set => ALIGN

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [ld] section address : ALIGN(align) and the maximum of input section alignments
  2020-02-26  5:23 [ld] section address : ALIGN(align) and the maximum of input section alignments Fangrui Song
@ 2020-02-26  6:31 ` Fangrui Song
  2020-03-03  5:46   ` Fangrui Song
  2020-03-03 22:39   ` Alan Modra
  0 siblings, 2 replies; 11+ messages in thread
From: Fangrui Song @ 2020-02-26  6:31 UTC (permalink / raw)
  To: Alan Modra; +Cc: binutils

On 2020-02-25, Fangrui Song wrote:
>https://sourceware.org/binutils/docs/ld/Output-Section-Description.html
>I have observed some strange rules while playing with the output section address and ALIGN.
>
>cat > a.s <<e
> .globl _start; _start: ret
> .section .data.rel.ro,"aw"; .balign 8; .byte 0
> .data; .byte 0
> .section .data2,"aw"; .balign 8; .byte 0
> .section .data3,"aw"; .balign 32; .byte 0
> .bss; .balign 32; .byte 0
>e
>
>cat > a.x <<e
> SECTIONS {
>   .text 0x10000 : { *(.text) }
>   /* sh_addr is aligned to 16. */
>   .data.rel.ro . : ALIGN(16) { *(.data.rel.ro) }
>
>   .data 0x20000 : { *(.data) }
>   /* The output section address is set without ALIGN. sh_addr is set to Dot, ignoring alignment. */
>   /* sh_addralign is the maximum of input section alignments, 8. */
>   .data2 . : { *(.data2) }
>   /* sh_addr is aligned to 32. */
>   .data3 : ALIGN(16) { *(.data3) }
>   /* sh_addr is aligned to 16, ???????????? */
>   .bss . : ALIGN(16) { *(.bss) }
> }
>e
>
>as a.s -o a.o
>ld.bfd -T a.x a.o -o a
>
>% readelf -WS a
>
>Section Headers:
>  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
>  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
>  [ 1] .text             PROGBITS        0000000000010000 001000 000001 00  AX  0   0  1
>  [ 2] .data.rel.ro      PROGBITS        0000000000010010 001010 000001 00  WA  0   0 16
>  [ 3] .data             PROGBITS        0000000000020000 002000 000001 00  WA  0   0  1
>  [ 4] .data2            PROGBITS        0000000000020008 002008 000001 00  WA  0   0  8
>  [ 5] .data3            PROGBITS        0000000000020020 002020 000001 00  WA  0   0 32
>  [ 6] .bss              NOBITS          0000000000020030 002021 000011 00  WA  0   0 32
>...
>
>
>Why doesn't `.bss . : ALIGN(16)` respect the maximum of input section alignments (32)?
>
>(I have verified that .bss being SHT_NOBITS is unrelated.)
>
>The rule of sh_addr computation appears to be:
>
>* ADDR is unset, ALIGN is unset => max_input_alignment
>* ADDR is unset, ALIGN is set => max(ALIGN, max_input_alignment)
>* ADDR is set, ALIGN is unset => max_input_alignment
>* ADDR is set, ALIGN is set => ALIGN

When ADDR is set, ALIGN is used while max_input_alignment is ignored.

ld/ldlang.c:5582

                 if (os->addr_tree == NULL) {
                     ...
		    newdot = os->region->current;
                     // maximum of ALIGN and input section alignments
		    section_alignment = os->bfd_section->alignment_power;
		  }
		else
                   // ALIGN
		  section_alignment = exp_get_power (os->section_alignment, "section alignment");

Alan, is the `else` branch supposed to use `section_alignment = os->bfd_section->alignment_power;` as well?

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [ld] section address : ALIGN(align) and the maximum of input section alignments
  2020-02-26  6:31 ` Fangrui Song
@ 2020-03-03  5:46   ` Fangrui Song
  2020-03-03 22:39   ` Alan Modra
  1 sibling, 0 replies; 11+ messages in thread
From: Fangrui Song @ 2020-03-03  5:46 UTC (permalink / raw)
  To: Alan Modra; +Cc: binutils

On Tue, Feb 25, 2020 at 10:30 PM Fangrui Song <i@maskray.me> wrote:
>
> On 2020-02-25, Fangrui Song wrote:
> >https://sourceware.org/binutils/docs/ld/Output-Section-Description.html
> >I have observed some strange rules while playing with the output section address and ALIGN.
> >
> >cat > a.s <<e
> > .globl _start; _start: ret
> > .section .data.rel.ro,"aw"; .balign 8; .byte 0
> > .data; .byte 0
> > .section .data2,"aw"; .balign 8; .byte 0
> > .section .data3,"aw"; .balign 32; .byte 0
> > .bss; .balign 32; .byte 0
> >e
> >
> >cat > a.x <<e
> > SECTIONS {
> >   .text 0x10000 : { *(.text) }
> >   /* sh_addr is aligned to 16. */
> >   .data.rel.ro . : ALIGN(16) { *(.data.rel.ro) }
> >
> >   .data 0x20000 : { *(.data) }
> >   /* The output section address is set without ALIGN. sh_addr is set to Dot, ignoring alignment. */
> >   /* sh_addralign is the maximum of input section alignments, 8. */
> >   .data2 . : { *(.data2) }
> >   /* sh_addr is aligned to 32. */
> >   .data3 : ALIGN(16) { *(.data3) }
> >   /* sh_addr is aligned to 16, ???????????? */
> >   .bss . : ALIGN(16) { *(.bss) }
> > }
> >e
> >
> >as a.s -o a.o
> >ld.bfd -T a.x a.o -o a
> >
> >% readelf -WS a
> >
> >Section Headers:
> >  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
> >  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
> >  [ 1] .text             PROGBITS        0000000000010000 001000 000001 00  AX  0   0  1
> >  [ 2] .data.rel.ro      PROGBITS        0000000000010010 001010 000001 00  WA  0   0 16
> >  [ 3] .data             PROGBITS        0000000000020000 002000 000001 00  WA  0   0  1
> >  [ 4] .data2            PROGBITS        0000000000020008 002008 000001 00  WA  0   0  8
> >  [ 5] .data3            PROGBITS        0000000000020020 002020 000001 00  WA  0   0 32
> >  [ 6] .bss              NOBITS          0000000000020030 002021 000011 00  WA  0   0 32
> >...
> >
> >
> >Why doesn't `.bss . : ALIGN(16)` respect the maximum of input section alignments (32)?
> >
> >(I have verified that .bss being SHT_NOBITS is unrelated.)
> >
> >The rule of sh_addr computation appears to be:
> >
> >* ADDR is unset, ALIGN is unset => max_input_alignment
> >* ADDR is unset, ALIGN is set => max(ALIGN, max_input_alignment)
> >* ADDR is set, ALIGN is unset => max_input_alignment
> >* ADDR is set, ALIGN is set => ALIGN
>
> When ADDR is set, ALIGN is used while max_input_alignment is ignored.
>
> ld/ldlang.c:5582
>
>                  if (os->addr_tree == NULL) {
>                      ...
>                     newdot = os->region->current;
>                      // maximum of ALIGN and input section alignments
>                     section_alignment = os->bfd_section->alignment_power;
>                   }
>                 else
>                    // ALIGN
>                   section_alignment = exp_get_power (os->section_alignment, "section alignment");
>
> Alan, is the `else` branch supposed to use `section_alignment = os->bfd_section->alignment_power;` as well?

Ping :)

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [ld] section address : ALIGN(align) and the maximum of input section alignments
  2020-02-26  6:31 ` Fangrui Song
  2020-03-03  5:46   ` Fangrui Song
@ 2020-03-03 22:39   ` Alan Modra
  2020-03-04  0:03     ` Fangrui Song
       [not found]     ` <BY5PR07MB7316674DD98011D2AD812A63CBE40@BY5PR07MB7316.namprd07.prod.outlook.com>
  1 sibling, 2 replies; 11+ messages in thread
From: Alan Modra @ 2020-03-03 22:39 UTC (permalink / raw)
  To: Fangrui Song; +Cc: binutils

On Tue, Feb 25, 2020 at 10:30:03PM -0800, Fangrui Song wrote:
> > Why doesn't `.bss . : ALIGN(16)` respect the maximum of input section alignments (32)?
> > 
> > (I have verified that .bss being SHT_NOBITS is unrelated.)
> > 
> > The rule of sh_addr computation appears to be:
> > 
> > * ADDR is unset, ALIGN is unset => max_input_alignment
> > * ADDR is unset, ALIGN is set => max(ALIGN, max_input_alignment)
> > * ADDR is set, ALIGN is unset => max_input_alignment
> > * ADDR is set, ALIGN is set => ALIGN
> 
> When ADDR is set, ALIGN is used while max_input_alignment is ignored.
> 
> ld/ldlang.c:5582
> 
>                 if (os->addr_tree == NULL) {
>                     ...
> 		    newdot = os->region->current;
>                     // maximum of ALIGN and input section alignments
> 		    section_alignment = os->bfd_section->alignment_power;
> 		  }
> 		else
>                   // ALIGN
> 		  section_alignment = exp_get_power (os->section_alignment, "section alignment");
> 
> Alan, is the `else` branch supposed to use `section_alignment = os->bfd_section->alignment_power;` as well?

No.  When you specify the address of an output section that is the
address it should have.  Except that specifying both an address and
alignment aligns the address given.  Specifying both is somewhat
contradictory and it would probably have been better if we didn't
support ALIGN here.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [ld] section address : ALIGN(align) and the maximum of input section alignments
  2020-03-03 22:39   ` Alan Modra
@ 2020-03-04  0:03     ` Fangrui Song
       [not found]     ` <BY5PR07MB7316674DD98011D2AD812A63CBE40@BY5PR07MB7316.namprd07.prod.outlook.com>
  1 sibling, 0 replies; 11+ messages in thread
From: Fangrui Song @ 2020-03-04  0:03 UTC (permalink / raw)
  To: Alan Modra; +Cc: binutils

On Tue, Mar 3, 2020 at 2:39 PM Alan Modra <amodra@gmail.com> wrote:
>
> On Tue, Feb 25, 2020 at 10:30:03PM -0800, Fangrui Song wrote:
> > > Why doesn't `.bss . : ALIGN(16)` respect the maximum of input section alignments (32)?
> > >
> > > (I have verified that .bss being SHT_NOBITS is unrelated.)
> > >
> > > The rule of sh_addr computation appears to be:
> > >
> > > * ADDR is unset, ALIGN is unset => max_input_alignment
> > > * ADDR is unset, ALIGN is set => max(ALIGN, max_input_alignment)
> > > * ADDR is set, ALIGN is unset => max_input_alignment
> > > * ADDR is set, ALIGN is set => ALIGN
> >
> > When ADDR is set, ALIGN is used while max_input_alignment is ignored.
> >
> > ld/ldlang.c:5582
> >
> >                 if (os->addr_tree == NULL) {
> >                     ...
> >                   newdot = os->region->current;
> >                     // maximum of ALIGN and input section alignments
> >                   section_alignment = os->bfd_section->alignment_power;
> >                 }
> >               else
> >                   // ALIGN
> >                 section_alignment = exp_get_power (os->section_alignment, "section alignment");
> >
> > Alan, is the `else` branch supposed to use `section_alignment = os->bfd_section->alignment_power;` as well?
>
> No.  When you specify the address of an output section that is the
> address it should have.  Except that specifying both an address and
> alignment aligns the address given.  Specifying both is somewhat
> contradictory and it would probably have been better if we didn't
> support ALIGN here.

Thanks. For the example below, do you agree with the comments in a.x below?

% cat a.s
.globl _start; _start: ret
.section .data.rel.ro,"aw"; .balign 8; .byte 0
.data; .byte 0
.section .data2,"aw"; .balign 8; .byte 0
.section .data3,"aw"; .balign 32; .byte 0
.bss; .balign 32; .byte 0
% as a.s -o a.o

% cat a.x
SECTIONS {
  .text 0x10000 : { *(.text) }
  /* sh_addr is 0x10010. Specifying both address and ALIGN should be
disallowed. */
  .data.rel.ro . : ALIGN(16) { *(.data.rel.ro) }

  .data 0x20000 : { *(.data) }
  /* sh_addr is 0x20001. Should there be a warning that sh_addralign
is 8? Even --warn-section-align does not warn. */
  .data2 . : { *(.data2) }
  /* sh_addr is 0x20020. The input section alignment wins. */
  .data3 : ALIGN(16) { *(.data3) }
  /* sh_addr is 0x20030. Specifying both address and ALIGN should be
disallowed. */
  .bss . : ALIGN(16) { *(.bss) }
}

% ld.bfd -T a.x a.s -o a

If specifying both Output Section Address and ALIGN is disallowed,
there should be no "changing start of section" warning when
--warn-section-align is not specified. Is my understanding correct?

BTW, I filed a bug about duplicate "changing start of section"
warnings https://sourceware.org/bugzilla/show_bug.cgi?id=25570

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [ld] section address : ALIGN(align) and the maximum of input section alignments
       [not found]     ` <BY5PR07MB7316674DD98011D2AD812A63CBE40@BY5PR07MB7316.namprd07.prod.outlook.com>
@ 2020-03-04  5:56       ` Alan Modra
  2020-03-04  6:40         ` Fangrui Song
  0 siblings, 1 reply; 11+ messages in thread
From: Alan Modra @ 2020-03-04  5:56 UTC (permalink / raw)
  To: Fangrui Song; +Cc: binutils

On Tue, Mar 03, 2020 at 03:58:12PM -0800, Fangrui Song wrote:
> Thanks. For the example below, do you agree with the comments in a.x below?
> 
> % cat a.s
> .globl _start; _start: ret
> .section .data.rel.ro,"aw"; .balign 8; .byte 0
> .data; .byte 0
> .section .data2,"aw"; .balign 8; .byte 0
> .section .data3,"aw"; .balign 32; .byte 0
> .bss; .balign 32; .byte 0
> % as a.s -o a.o
> 
> % cat a.x
> SECTIONS {
>   .text 0x10000 : { *(.text) }
>   /* sh_addr is 0x10010. Specifying both address and ALIGN should be
> disallowed. */
>   .data.rel.ro . : ALIGN(16) { *(.data.rel.ro) }
> 
>   .data 0x20000 : { *(.data) }
>   /* sh_addr is 0x20001. Should there be a warning that sh_addralign
> is 8? Even --warn-section-align does not warn. */

That is a bug.

The ELF gABI says in part of sh_addralign:  "The value of sh_addr must
be congruent to 0, modulo the value of sh_addralign."

	* elf.c (elf_fake_sections): Ensure sh_addralign is such that
	sh_addr mod sh_addalign is zero.

diff --git a/bfd/elf.c b/bfd/elf.c
index fcd84d2d17..c4d6718aaa 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -3192,6 +3192,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
   unsigned int sh_type;
   const char *name = asect->name;
   bfd_boolean delay_st_name_p = FALSE;
+  bfd_vma mask;
 
   if (arg->failed)
     {
@@ -3291,7 +3292,10 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
       arg->failed = TRUE;
       return;
     }
-  this_hdr->sh_addralign = (bfd_vma) 1 << asect->alignment_power;
+  /* Set sh_addralign to the highest power of two given by alignment
+     consistent with the section VMA.  Linker scripts can force VMA.  */
+  mask = ((bfd_vma) 1 << asect->alignment_power) | this_hdr->sh_addr;
+  this_hdr->sh_addralign = mask & -mask;
   /* The sh_entsize and sh_info fields may have been set already by
      copy_private_section_data.  */
 

>   .data2 . : { *(.data2) }
>   /* sh_addr is 0x20020. The input section alignment wins. */
>   .data3 : ALIGN(16) { *(.data3) }
>   /* sh_addr is 0x20030. Specifying both address and ALIGN should be
> disallowed. */
>   .bss . : ALIGN(16) { *(.bss) }
> }
> 
> % ld.bfd -T a.x a.s -o a
> 
> If specifying both Output Section Address and ALIGN is disallowed,
> there should be no "changing start of section" warning when
> --warn-section-align is not specified. Is my understanding correct?
> 
> BTW, I filed a bug about duplicate "changing start of section"
> warnings https://sourceware.org/bugzilla/show_bug.cgi?id=25570

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [ld] section address : ALIGN(align) and the maximum of input section alignments
  2020-03-04  5:56       ` Alan Modra
@ 2020-03-04  6:40         ` Fangrui Song
  2020-03-04  8:04           ` Alan Modra
  0 siblings, 1 reply; 11+ messages in thread
From: Fangrui Song @ 2020-03-04  6:40 UTC (permalink / raw)
  To: Alan Modra; +Cc: binutils, smithp352

On Tue, Mar 3, 2020 at 9:56 PM Alan Modra <amodra@gmail.com> wrote:
>
> On Tue, Mar 03, 2020 at 03:58:12PM -0800, Fangrui Song wrote:
> > Thanks. For the example below, do you agree with the comments in a.x below?
> >
> > % cat a.s
> > .globl _start; _start: ret
> > .section .data.rel.ro,"aw"; .balign 8; .byte 0
> > .data; .byte 0
> > .section .data2,"aw"; .balign 8; .byte 0
> > .section .data3,"aw"; .balign 32; .byte 0
> > .bss; .balign 32; .byte 0
> > % as a.s -o a.o
> >
> > % cat a.x
> > SECTIONS {
> >   .text 0x10000 : { *(.text) }
> >   /* sh_addr is 0x10010. Specifying both address and ALIGN should be
> > disallowed. */
> >   .data.rel.ro . : ALIGN(16) { *(.data.rel.ro) }
> >
> >   .data 0x20000 : { *(.data) }
> >   /* sh_addr is 0x20001. Should there be a warning that sh_addralign
> > is 8? Even --warn-section-align does not warn. */
>
> That is a bug.
>
> The ELF gABI says in part of sh_addralign:  "The value of sh_addr must
> be congruent to 0, modulo the value of sh_addralign."
>
>         * elf.c (elf_fake_sections): Ensure sh_addralign is such that
>         sh_addr mod sh_addalign is zero.
>
> diff --git a/bfd/elf.c b/bfd/elf.c
> index fcd84d2d17..c4d6718aaa 100644
> --- a/bfd/elf.c
> +++ b/bfd/elf.c
> @@ -3192,6 +3192,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
>    unsigned int sh_type;
>    const char *name = asect->name;
>    bfd_boolean delay_st_name_p = FALSE;
> +  bfd_vma mask;
>
>    if (arg->failed)
>      {
> @@ -3291,7 +3292,10 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
>        arg->failed = TRUE;
>        return;
>      }
> -  this_hdr->sh_addralign = (bfd_vma) 1 << asect->alignment_power;
> +  /* Set sh_addralign to the highest power of two given by alignment
> +     consistent with the section VMA.  Linker scripts can force VMA.  */
> +  mask = ((bfd_vma) 1 << asect->alignment_power) | this_hdr->sh_addr;
> +  this_hdr->sh_addralign = mask & -mask;
>    /* The sh_entsize and sh_info fields may have been set already by
>       copy_private_section_data.  */
>
>
> >   .data2 . : { *(.data2) }
> >   /* sh_addr is 0x20020. The input section alignment wins. */
> >   .data3 : ALIGN(16) { *(.data3) }
> >   /* sh_addr is 0x20030. Specifying both address and ALIGN should be
> > disallowed. */
> >   .bss . : ALIGN(16) { *(.bss) }
> > }
> >
> > % ld.bfd -T a.x a.s -o a
> >
> > If specifying both Output Section Address and ALIGN is disallowed,
> > there should be no "changing start of section" warning when
> > --warn-section-align is not specified. Is my understanding correct?
> >
> > BTW, I filed a bug about duplicate "changing start of section"
> > warnings https://sourceware.org/bugzilla/show_bug.cgi?id=25570

The implementation is complex. For users to understand, I think it
will be helpful to have something more detailed in
https://sourceware.org/binutils/docs/ld/Output-Section-Address.html#Output-Section-Address

If my understanding is correct
https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=233bf4f847b136705247e2f7f11bae41c72448a4
 makes the output section address override sh_addralign computed from
the maximum of input section alignments. So, generally the rules are:

* The max of ALIGN and (the maximum of input section alignments) is taken.
* The output section address overrides the above. If sh_addr %
alignment != 0, set sh_addralign to the largest alignment that makes
sh_addr%alignment=0
  In this case, should the linker emit a warning?
* ALIGN and the output section address cannot be specified at the same
time. This is considered a linker script "undefined behavior". Users
should not rely on a particular result.

--warn-section-align may be out of place. It can be noisy for normal
output section descriptions like    .foo : ALIGN(16) { ... }  without
a preceding dot advancing to a multiple of 16.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [ld] section address : ALIGN(align) and the maximum of input section alignments
  2020-03-04  6:40         ` Fangrui Song
@ 2020-03-04  8:04           ` Alan Modra
  2020-03-05  6:41             ` Fangrui Song
  0 siblings, 1 reply; 11+ messages in thread
From: Alan Modra @ 2020-03-04  8:04 UTC (permalink / raw)
  To: Fangrui Song; +Cc: binutils, smithp352

On Tue, Mar 03, 2020 at 10:39:45PM -0800, Fangrui Song wrote:
> The implementation is complex. For users to understand, I think it
> will be helpful to have something more detailed in
> https://sourceware.org/binutils/docs/ld/Output-Section-Address.html#Output-Section-Address
> 
> If my understanding is correct
> https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=233bf4f847b136705247e2f7f11bae41c72448a4
>  makes the output section address override sh_addralign computed from
> the maximum of input section alignments.

Right.

> So, generally the rules are:
> * The max of ALIGN and (the maximum of input section alignments) is taken.
> * The output section address overrides the above. If sh_addr %
> alignment != 0, set sh_addralign to the largest alignment that makes
> sh_addr%alignment=0
>   In this case, should the linker emit a warning?

I don't think so.  The input sections are still aligned within the
output section to their required alignment.

> * ALIGN and the output section address cannot be specified at the same
> time. This is considered a linker script "undefined behavior". Users
> should not rely on a particular result.

I'm not going to make that change for ld.bfd.  I said it probably
would have been better if ALIGN for output section statements hadn't
been invented, but once there are users for a script feature it can't
be removed without a good reason.

> --warn-section-align may be out of place. It can be noisy for normal
> output section descriptions like    .foo : ALIGN(16) { ... }  without
> a preceding dot advancing to a multiple of 16.

It's even more noisy when relaxation is enabled..

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [ld] section address : ALIGN(align) and the maximum of input section alignments
  2020-03-04  8:04           ` Alan Modra
@ 2020-03-05  6:41             ` Fangrui Song
  2020-03-05 11:21               ` Alan Modra
  0 siblings, 1 reply; 11+ messages in thread
From: Fangrui Song @ 2020-03-05  6:41 UTC (permalink / raw)
  To: Alan Modra; +Cc: binutils, smithp352

For convenience, I will use some notations:

max_input_align: maximum of input section alignments.
addr_tree: output section address

On 2020-03-04, Alan Modra wrote:
>On Tue, Mar 03, 2020 at 10:39:45PM -0800, Fangrui Song wrote:
>> The implementation is complex. For users to understand, I think it
>> will be helpful to have something more detailed in
>> https://sourceware.org/binutils/docs/ld/Output-Section-Address.html#Output-Section-Address
>>
>> If my understanding is correct
>> https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=233bf4f847b136705247e2f7f11bae41c72448a4
>>  makes the output section address override sh_addralign computed from
>> the maximum of input section alignments.
>
>Right.
>
>> So, generally the rules are:
>> * The max of ALIGN and (the maximum of input section alignments) is taken.
>> * The output section address overrides the above. If sh_addr %
>> alignment != 0, set sh_addralign to the largest alignment that makes
>> sh_addr%alignment=0
>>   In this case, should the linker emit a warning?
>
>I don't think so.  The input sections are still aligned within the
>output section to their required alignment.
>
>> * ALIGN and the output section address cannot be specified at the same
>> time. This is considered a linker script "undefined behavior". Users
>> should not rely on a particular result.
>
>I'm not going to make that change for ld.bfd.  I said it probably
>would have been better if ALIGN for output section statements hadn't
>been invented, but once there are users for a script feature it can't
>be removed without a good reason.

I take ALIGN as a way to overalign an output section.
When ALIGN < max_input_align, do we agree that sh_addralign = max(ALIGN, max_input_align) = max_input_align ?

When both addr_tree and ALIGN are specified (what I called "undefined behavior"), and addr_tree is misaligned,
sh_addralign can be decreased from max(ALIGN,max_input_align) to
(addr_tree|max(ALIGN,max_input_align)) & -(addr_tree|max(ALIGN,max_input_align))

Commit 233bf4f847b136705247e2f7f11bae41c72448a4 is made so that
"The value of sh_addr must be congruent to 0, modulo the value of sh_addralign."
is obeyed.

Another view is that the user intentionally breaks the ELF rule. We can keep
sh_addralign as max(ALIGN,max_input_align) and emit a warning along the line of:

   warning: address (0x10010) of section .foo is not a multiple of alignment (32)

>> --warn-section-align may be out of place. It can be noisy for normal
>> output section descriptions like    .foo : ALIGN(16) { ... }  without
>> a preceding dot advancing to a multiple of 16.

   /* Without this assignment, the ALIGN(16) below will likely report a warning */
   . = ALIGN(16);
   
   .foo : ALIGN(16) { ... } 

Does this suggest that --warn-section-align is not very useful?
Keep reading.

>It's even more noisy when relaxation is enabled..

https://sourceware.org/ml/binutils/2020-03/msg00107.html does not fix
the --warn-section-align version of PR25570.

# My original example.
cat > a.s <<e
   .globl _start; _start: ret
   .section .data.rel.ro,"aw"; .balign 8; .byte 0
   .data; .byte 0
   .section .data2,"aw"; .balign 8; .byte 0
   .bss; .balign 32; .byte 0
e
as a.s -o a.o

% ./ld-new a.o -o a --warn-section-align            
./ld-new: warning: start of section .got changed by 7
./ld-new: warning: start of section .got.plt changed by 7
./ld-new: warning: start of section .data2 changed by 6
./ld-new: warning: start of section .bss changed by 23
./ld-new: warning: start of section .data.rel.ro changed by 4088
./ld-new: warning: start of section .got changed by 4088
./ld-new: warning: start of section .got.plt changed by 4088
./ld-new: warning: start of section .data2 changed by 4096
./ld-new: warning: start of section .bss changed by 4096
./ld-new: warning: start of section .rela.dyn changed by 56
./ld-new: warning: start of section .rela.plt changed by 56
./ld-new: warning: start of section .data.rel.ro changed by -4088
./ld-new: warning: start of section .got changed by -4088
./ld-new: warning: start of section .got.plt changed by -4088
./ld-new: warning: start of section .data2 changed by -4096
./ld-new: warning: start of section .bss changed by -4096
./ld-new: warning: start of section .data.rel.ro changed by 4088
./ld-new: warning: start of section .got changed by 4088
./ld-new: warning: start of section .got.plt changed by 4088
./ld-new: warning: start of section .data2 changed by 4096
./ld-new: warning: start of section .bss changed by 4096

This also demonstrates how annoying --warn-section-align can be.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [ld] section address : ALIGN(align) and the maximum of input section alignments
  2020-03-05  6:41             ` Fangrui Song
@ 2020-03-05 11:21               ` Alan Modra
  2020-03-10 19:00                 ` Fangrui Song
  0 siblings, 1 reply; 11+ messages in thread
From: Alan Modra @ 2020-03-05 11:21 UTC (permalink / raw)
  To: Fangrui Song; +Cc: binutils, smithp352

On Wed, Mar 04, 2020 at 10:41:28PM -0800, Fangrui Song wrote:
> For convenience, I will use some notations:
> 
> max_input_align: maximum of input section alignments.
> addr_tree: output section address
> 
> On 2020-03-04, Alan Modra wrote:
> > On Tue, Mar 03, 2020 at 10:39:45PM -0800, Fangrui Song wrote:
> > > The implementation is complex. For users to understand, I think it
> > > will be helpful to have something more detailed in
> > > https://sourceware.org/binutils/docs/ld/Output-Section-Address.html#Output-Section-Address
> > > 
> > > If my understanding is correct
> > > https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=233bf4f847b136705247e2f7f11bae41c72448a4
> > >  makes the output section address override sh_addralign computed from
> > > the maximum of input section alignments.
> > 
> > Right.
> > 
> > > So, generally the rules are:
> > > * The max of ALIGN and (the maximum of input section alignments) is taken.
> > > * The output section address overrides the above. If sh_addr %
> > > alignment != 0, set sh_addralign to the largest alignment that makes
> > > sh_addr%alignment=0
> > >   In this case, should the linker emit a warning?
> > 
> > I don't think so.  The input sections are still aligned within the
> > output section to their required alignment.
> > 
> > > * ALIGN and the output section address cannot be specified at the same
> > > time. This is considered a linker script "undefined behavior". Users
> > > should not rely on a particular result.
> > 
> > I'm not going to make that change for ld.bfd.  I said it probably
> > would have been better if ALIGN for output section statements hadn't
> > been invented, but once there are users for a script feature it can't
> > be removed without a good reason.
> 
> I take ALIGN as a way to overalign an output section.
> When ALIGN < max_input_align, do we agree that sh_addralign = max(ALIGN, max_input_align) = max_input_align ?
> 
> When both addr_tree and ALIGN are specified (what I called "undefined behavior"), and addr_tree is misaligned,
> sh_addralign can be decreased from max(ALIGN,max_input_align) to
> (addr_tree|max(ALIGN,max_input_align)) & -(addr_tree|max(ALIGN,max_input_align))
> 
> Commit 233bf4f847b136705247e2f7f11bae41c72448a4 is made so that
> "The value of sh_addr must be congruent to 0, modulo the value of sh_addralign."
> is obeyed.
> 
> Another view is that the user intentionally breaks the ELF rule. We can keep
> sh_addralign as max(ALIGN,max_input_align) and emit a warning along the line of:
> 
>   warning: address (0x10010) of section .foo is not a multiple of alignment (32)

I'm not going to do that for BFD ld.  The user chose an address for an
output section, and all input sections are placed in that section
according to their alignment.  No warning needed, just a change in
sh_addralign calculation.   I'll note that ld could quite correctly
set sh_addralign to 0 or 1 for any final linked executable.

> > > --warn-section-align may be out of place. It can be noisy for normal
> > > output section descriptions like    .foo : ALIGN(16) { ... }  without
> > > a preceding dot advancing to a multiple of 16.
> 
>   /* Without this assignment, the ALIGN(16) below will likely report a warning */
>   . = ALIGN(16);
>      .foo : ALIGN(16) { ... }
> 
> Does this suggest that --warn-section-align is not very useful?
> Keep reading.
> 
> > It's even more noisy when relaxation is enabled..
> 
> https://sourceware.org/ml/binutils/2020-03/msg00107.html does not fix
> the --warn-section-align version of PR25570.
> 
> # My original example.
> cat > a.s <<e
>   .globl _start; _start: ret
>   .section .data.rel.ro,"aw"; .balign 8; .byte 0
>   .data; .byte 0
>   .section .data2,"aw"; .balign 8; .byte 0
>   .bss; .balign 32; .byte 0
> e
> as a.s -o a.o
> 
> % ./ld-new a.o -o a --warn-section-align            ./ld-new: warning: start
> of section .got changed by 7
> ./ld-new: warning: start of section .got.plt changed by 7
> ./ld-new: warning: start of section .data2 changed by 6
> ./ld-new: warning: start of section .bss changed by 23
> ./ld-new: warning: start of section .data.rel.ro changed by 4088
> ./ld-new: warning: start of section .got changed by 4088
> ./ld-new: warning: start of section .got.plt changed by 4088
> ./ld-new: warning: start of section .data2 changed by 4096
> ./ld-new: warning: start of section .bss changed by 4096
> ./ld-new: warning: start of section .rela.dyn changed by 56
> ./ld-new: warning: start of section .rela.plt changed by 56
> ./ld-new: warning: start of section .data.rel.ro changed by -4088
> ./ld-new: warning: start of section .got changed by -4088
> ./ld-new: warning: start of section .got.plt changed by -4088
> ./ld-new: warning: start of section .data2 changed by -4096
> ./ld-new: warning: start of section .bss changed by -4096
> ./ld-new: warning: start of section .data.rel.ro changed by 4088
> ./ld-new: warning: start of section .got changed by 4088
> ./ld-new: warning: start of section .got.plt changed by 4088
> ./ld-new: warning: start of section .data2 changed by 4096
> ./ld-new: warning: start of section .bss changed by 4096
> 
> This also demonstrates how annoying --warn-section-align can be.

	PR 25570
	* ldlang.c (lang_size_sections_1): Don't report changes on
	second and subsequent iterations that make no change in
	alignment from that already reported.

diff --git a/ld/ldlang.c b/ld/ldlang.c
index 6ffa7af575..63f9d182ea 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -5597,7 +5597,13 @@ lang_size_sections_1
 		    if (lang_sizing_iteration == 1)
 		      diff = dotdelta;
 		    else if (lang_sizing_iteration > 1)
-		      diff = newdot - os->bfd_section->vma;
+		      {
+			/* Only report adjustments that would change
+			   alignment from what we have already reported.  */
+			diff = newdot - os->bfd_section->vma;
+			if (!(diff & (((bfd_vma) 1 << section_alignment) - 1)))
+			  diff = 0;
+		      }
 		    if (diff != 0
 			&& (config.warn_section_align
 			    || os->addr_tree != NULL))


-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [ld] section address : ALIGN(align) and the maximum of input section alignments
  2020-03-05 11:21               ` Alan Modra
@ 2020-03-10 19:00                 ` Fangrui Song
  0 siblings, 0 replies; 11+ messages in thread
From: Fangrui Song @ 2020-03-10 19:00 UTC (permalink / raw)
  To: Alan Modra; +Cc: binutils, smithp352

On 2020-03-05, Alan Modra wrote:
>On Wed, Mar 04, 2020 at 10:41:28PM -0800, Fangrui Song wrote:
>> For convenience, I will use some notations:
>>
>> max_input_align: maximum of input section alignments.
>> addr_tree: output section address
>>
>> On 2020-03-04, Alan Modra wrote:
>> > On Tue, Mar 03, 2020 at 10:39:45PM -0800, Fangrui Song wrote:
>> > > The implementation is complex. For users to understand, I think it
>> > > will be helpful to have something more detailed in
>> > > https://sourceware.org/binutils/docs/ld/Output-Section-Address.html#Output-Section-Address
>> > >
>> > > If my understanding is correct
>> > > https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=233bf4f847b136705247e2f7f11bae41c72448a4
>> > >  makes the output section address override sh_addralign computed from
>> > > the maximum of input section alignments.
>> >
>> > Right.
>> >
>> > > So, generally the rules are:
>> > > * The max of ALIGN and (the maximum of input section alignments) is taken.
>> > > * The output section address overrides the above. If sh_addr %
>> > > alignment != 0, set sh_addralign to the largest alignment that makes
>> > > sh_addr%alignment=0
>> > >   In this case, should the linker emit a warning?
>> >
>> > I don't think so.  The input sections are still aligned within the
>> > output section to their required alignment.
>> >
>> > > * ALIGN and the output section address cannot be specified at the same
>> > > time. This is considered a linker script "undefined behavior". Users
>> > > should not rely on a particular result.
>> >
>> > I'm not going to make that change for ld.bfd.  I said it probably
>> > would have been better if ALIGN for output section statements hadn't
>> > been invented, but once there are users for a script feature it can't
>> > be removed without a good reason.
>>
>> I take ALIGN as a way to overalign an output section.
>> When ALIGN < max_input_align, do we agree that sh_addralign = max(ALIGN, max_input_align) = max_input_align ?
>>
>> When both addr_tree and ALIGN are specified (what I called "undefined behavior"), and addr_tree is misaligned,
>> sh_addralign can be decreased from max(ALIGN,max_input_align) to
>> (addr_tree|max(ALIGN,max_input_align)) & -(addr_tree|max(ALIGN,max_input_align))
>>
>> Commit 233bf4f847b136705247e2f7f11bae41c72448a4 is made so that
>> "The value of sh_addr must be congruent to 0, modulo the value of sh_addralign."
>> is obeyed.
>>
>> Another view is that the user intentionally breaks the ELF rule. We can keep
>> sh_addralign as max(ALIGN,max_input_align) and emit a warning along the line of:
>>
>>   warning: address (0x10010) of section .foo is not a multiple of alignment (32)
>
>I'm not going to do that for BFD ld.  The user chose an address for an
>output section, and all input sections are placed in that section
>according to their alignment.  No warning needed, just a change in
>sh_addralign calculation.   I'll note that ld could quite correctly
>set sh_addralign to 0 or 1 for any final linked executable.

Hi, Alan,

https://reviews.llvm.org/D75724 includes the output section
address/alignment changes I intended for lld.

The comment https://reviews.llvm.org/D75724#1915342 includes useful user feedback:

> If anything, I think the GNU linkers should warn about violating input sh_addralign requirements if they're going to have that behavior.
>
> But it seems likely that the most common use of explicit alignments is
> exactly when setting the minimum alignment of the output section is
> the intent and that being increased by input sh_addralign requirements
> is normal and expected, and not a case like mine.

>> > > --warn-section-align may be out of place. It can be noisy for normal
>> > > output section descriptions like    .foo : ALIGN(16) { ... }  without
>> > > a preceding dot advancing to a multiple of 16.
>>
>>   /* Without this assignment, the ALIGN(16) below will likely report a warning */
>>   . = ALIGN(16);
>>      .foo : ALIGN(16) { ... }
>>
>> Does this suggest that --warn-section-align is not very useful?
>> Keep reading.
>>
>> > It's even more noisy when relaxation is enabled..
>>
>> https://sourceware.org/ml/binutils/2020-03/msg00107.html does not fix
>> the --warn-section-align version of PR25570.
>>
>> # My original example.
>> cat > a.s <<e
>>   .globl _start; _start: ret
>>   .section .data.rel.ro,"aw"; .balign 8; .byte 0
>>   .data; .byte 0
>>   .section .data2,"aw"; .balign 8; .byte 0
>>   .bss; .balign 32; .byte 0
>> e
>> as a.s -o a.o
>>
>> % ./ld-new a.o -o a --warn-section-align            ./ld-new: warning: start
>> of section .got changed by 7
>> ./ld-new: warning: start of section .got.plt changed by 7
>> ./ld-new: warning: start of section .data2 changed by 6
>> ./ld-new: warning: start of section .bss changed by 23
>> ./ld-new: warning: start of section .data.rel.ro changed by 4088
>> ./ld-new: warning: start of section .got changed by 4088
>> ./ld-new: warning: start of section .got.plt changed by 4088
>> ./ld-new: warning: start of section .data2 changed by 4096
>> ./ld-new: warning: start of section .bss changed by 4096
>> ./ld-new: warning: start of section .rela.dyn changed by 56
>> ./ld-new: warning: start of section .rela.plt changed by 56
>> ./ld-new: warning: start of section .data.rel.ro changed by -4088
>> ./ld-new: warning: start of section .got changed by -4088
>> ./ld-new: warning: start of section .got.plt changed by -4088
>> ./ld-new: warning: start of section .data2 changed by -4096
>> ./ld-new: warning: start of section .bss changed by -4096
>> ./ld-new: warning: start of section .data.rel.ro changed by 4088
>> ./ld-new: warning: start of section .got changed by 4088
>> ./ld-new: warning: start of section .got.plt changed by 4088
>> ./ld-new: warning: start of section .data2 changed by 4096
>> ./ld-new: warning: start of section .bss changed by 4096
>>
>> This also demonstrates how annoying --warn-section-align can be.
>
>	PR 25570
>	* ldlang.c (lang_size_sections_1): Don't report changes on
>	second and subsequent iterations that make no change in
>	alignment from that already reported.
>
>diff --git a/ld/ldlang.c b/ld/ldlang.c
>index 6ffa7af575..63f9d182ea 100644
>--- a/ld/ldlang.c
>+++ b/ld/ldlang.c
>@@ -5597,7 +5597,13 @@ lang_size_sections_1
> 		    if (lang_sizing_iteration == 1)
> 		      diff = dotdelta;
> 		    else if (lang_sizing_iteration > 1)
>-		      diff = newdot - os->bfd_section->vma;
>+		      {
>+			/* Only report adjustments that would change
>+			   alignment from what we have already reported.  */
>+			diff = newdot - os->bfd_section->vma;
>+			if (!(diff & (((bfd_vma) 1 << section_alignment) - 1)))
>+			  diff = 0;
>+		      }
> 		    if (diff != 0
> 			&& (config.warn_section_align
> 			    || os->addr_tree != NULL))
>
>
>-- 
>Alan Modra
>Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2020-03-10 19:00 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-26  5:23 [ld] section address : ALIGN(align) and the maximum of input section alignments Fangrui Song
2020-02-26  6:31 ` Fangrui Song
2020-03-03  5:46   ` Fangrui Song
2020-03-03 22:39   ` Alan Modra
2020-03-04  0:03     ` Fangrui Song
     [not found]     ` <BY5PR07MB7316674DD98011D2AD812A63CBE40@BY5PR07MB7316.namprd07.prod.outlook.com>
2020-03-04  5:56       ` Alan Modra
2020-03-04  6:40         ` Fangrui Song
2020-03-04  8:04           ` Alan Modra
2020-03-05  6:41             ` Fangrui Song
2020-03-05 11:21               ` Alan Modra
2020-03-10 19:00                 ` Fangrui Song

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).