sh_addralign inconsistent with sh_addr
authorAlan Modra <amodra@gmail.com>
Wed, 4 Mar 2020 04:56:00 +0000 (15:26 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 4 Mar 2020 05:01:03 +0000 (15:31 +1030)
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.

bfd/ChangeLog
bfd/elf.c

index 6ed228d713b05e1da9b1455a31a03c3785dffb14..821978cf6a8d1b573793774ab513ca1ecbaf3e77 100644 (file)
@@ -1,3 +1,8 @@
+2020-03-04  Alan Modra  <amodra@gmail.com>
+
+       * elf.c (elf_fake_sections): Ensure sh_addralign is such that
+       sh_addr mod sh_addalign is zero.
+
 2020-03-04  Alan Modra  <amodra@gmail.com>
 
        * format.c (bfd_check_format_matches): Call cleanup on error exit.
index fcd84d2d17bce0d2abb2a48a12857c4a2a532fbb..c4d6718aaa0ea540d4b4724008f4faa6ae4d6250 100644 (file)
--- 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.  */