changed ld subalign priority

Message ID 20240227081547.8260-1-vladislav.belov@syntacore.com
State New
Headers
Series changed ld subalign priority |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm fail Patch failed to apply
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 fail Patch failed to apply

Commit Message

vb-sc Feb. 27, 2024, 8:15 a.m. UTC
  Hi,

According to the GNU LD documentation:

<<You can force input section alignment within an output section by using
SUBALIGN.  The value specified overrides any alignment given by input
sections, whether larger or smaller.>>

However, let's consider the behaviour of GNU ld

Suppose we have the following test:

$ cat one.c
char a_one __attribute__((__aligned__(8))) __attribute__((section(".mysection"))) = 0;

and the following linker script:

$ cat foo.lds
SECTIONS
{
    . = 0x10024;
    .mysection : SUBALIGN(4) {
        *(.mysection)
    }
  
    .note.gnu.property ALIGN(8) : {
      *(.note.gnu.property)
      *(.comment)
    }
}

We suppose that the section .mysection would be aligned by 4 despite of alignment attribute 8 in source code.
However, after linking object file "one.o" __ with gnu ld linker the symbol .mysection is aligned by 8

$ gcc -c one.c
$ ld -T foo.lds one.o -o foo.out
$ objdump -h foo.out
foo2.out:     file format elf64-x86-64Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .mysection    00000001  0000000000010028  0000000000010028  00001028  2**3
                  CONTENTS, ALLOC, LOAD, DATA
  1 .note.gnu.property 0000004b  0000000000010030  0000000000010030  00001030  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

It seems like this is contrary to documented behavior.

Below you can see the patch fixed this problem.

---
Best regards,
Vladislav

---
 ld/ldlang.c | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)
  

Comments

Nick Clifton Feb. 28, 2024, 4:36 p.m. UTC | #1
Hi Vladislav,

   Thanks for reporting this problem.

   In the future, please could I ask that you use the binutils bug
   reporting system, as this allows us to keep track of problems and
   to reference them in comments:

https://sourceware.org/bugzilla/

> Below you can see the patch fixed this problem.

   Thank you.  I have applied a simplified version of your patch
   and added your example code as a new test in the linker testsuite.

Cheers
   Nick
  

Patch

diff --git a/ld/ldlang.c b/ld/ldlang.c
index df4c43ce9f4..0ab59daccb4 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -5349,17 +5349,22 @@  size_input_section
       bfd_size_type alignment_needed;
 
       /* Align this section first to the input sections requirement,
-	 then to the output section's requirement.  If this alignment
-	 is greater than any seen before, then record it too.  Perform
-	 the alignment by inserting a magic 'padding' statement.  */
-
-      if (output_section_statement->subsection_alignment != NULL)
-	i->alignment_power
-	  = exp_get_power (output_section_statement->subsection_alignment,
-			   "subsection alignment");
+         then to the output section's requirement.  If this alignment
+         is greater than any seen before, then record it too.  Perform
+         the alignment by inserting a magic 'padding' statement. 
+         We can force input section alignment within an output section 
+         by using SUBALIGN. The value specified overrides any alignment 
+         given by input sections, whether larger or smaller.  */
+
+      if (output_section_statement->subsection_alignment != NULL) {
+        i->alignment_power =
+            exp_get_power(output_section_statement->subsection_alignment,
+                          "subsection alignment");
+        o->alignment_power = i->alignment_power;
+      }
 
-      if (o->alignment_power < i->alignment_power)
-	o->alignment_power = i->alignment_power;
+      else if (o->alignment_power < i->alignment_power)
+        o->alignment_power = i->alignment_power;
 
       alignment_needed = align_power (dot, i->alignment_power) - dot;