Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sd-boot/sd-stub fails to build with clang-18's lld due to overlapping sections #31637

Closed
mrc0mmand opened this issue Mar 5, 2024 · 0 comments
Labels
bug 🐛 Programming errors, that need preferential fixing sd-boot/sd-stub/bootctl

Comments

@mrc0mmand
Copy link
Member

mrc0mmand commented Mar 5, 2024

Spotted in #31633, but can be easily reproduced on the latest Fedora Rawhide as well:

$ podman run --pull always -it --rm fedora:rawhide
# dnf install -y git-core dnf-plugins-core lld
# dnf builddep -y systemd
# git clone https://github.com/systemd/systemd --depth=1
# cd systemd
# CC=clang CXX=clang++ CC_LD=lld CXX_LD=lld meson setup build -Dbootloader=enabled
# ninja -C build systemd-boot
ninja: Entering directory `build'
[37/38] Generating src/boot/efi/linuxx64.efi.stub with a custom command
FAILED: src/boot/efi/linuxx64.efi.stub 
/systemd/tools/elf2efi.py --version-major=256 --version-minor=0 --efi-major=1 --efi-minor=1 --subsystem=10 --minimum-sections=15 --copy-sections=.sbat,.sdmagic,.osrel src/boot/efi/linuxx64.elf.stub src/boot/efi/linuxx64.efi.stub
Traceback (most recent call last):
  File "/systemd/tools/elf2efi.py", line 698, in <module>
    main()
  File "/systemd/tools/elf2efi.py", line 694, in main
    elf2efi(parser.parse_args())
  File "/systemd/tools/elf2efi.py", line 599, in elf2efi
    sections = convert_sections(elf, opt)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/systemd/tools/elf2efi.py", line 330, in convert_sections
    raise RuntimeError("Overlapping PE sections.")
RuntimeError: Overlapping PE sections.
[38/38] Generating src/boot/efi/systemd-bootx64.efi with a custom command
FAILED: src/boot/efi/systemd-bootx64.efi 
/systemd/tools/elf2efi.py --version-major=256 --version-minor=0 --efi-major=1 --efi-minor=1 --subsystem=10 --minimum-sections=0 --copy-sections=.sbat,.sdmagic,.osrel src/boot/efi/systemd-bootx64.elf src/boot/efi/systemd-bootx64.efi
Traceback (most recent call last):
  File "/systemd/tools/elf2efi.py", line 698, in <module>
    main()
  File "/systemd/tools/elf2efi.py", line 694, in main
    elf2efi(parser.parse_args())
  File "/systemd/tools/elf2efi.py", line 599, in elf2efi
    sections = convert_sections(elf, opt)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/systemd/tools/elf2efi.py", line 330, in convert_sections
    raise RuntimeError("Overlapping PE sections.")
RuntimeError: Overlapping PE sections.
ninja: build stopped: subcommand failed.
# readelf -lS build/src/boot/efi/systemd-bootx64.elf
There are 31 section headers, starting at offset 0x5a0d0:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .note.gnu.bu[...] NOTE             0000000000000238  00000238
       0000000000000018  0000000000000000   A       0     0     4
  [ 2] .dynsym           DYNSYM           0000000000000250  00000250
       0000000000000018  0000000000000018   A       4     1     8
  [ 3] .gnu.hash         GNU_HASH         0000000000000268  00000268
       000000000000001c  0000000000000000   A       2     0     8
  [ 4] .dynstr           STRTAB           0000000000000284  00000284
       0000000000000001  0000000000000000   A       0     0     1
  [ 5] .rela.dyn         RELA             0000000000000288  00000288
       0000000000000618  0000000000000018   A       2     0     8
  [ 6] .rodata           PROGBITS         00000000000008a0  000008a0
       0000000000003fe8  0000000000000000 AMS       0     0     16
  [ 7] .text             PROGBITS         0000000000005000  00005000
       00000000000221e1  0000000000000000  AX       0     0     16
  [ 8] .data.rel.ro      PROGBITS         0000000000028000  00028000
       0000000000000300  0000000000000000  WA       0     0     16
  [ 9] .dynamic          DYNAMIC          0000000000028300  00028300
       00000000000000c0  0000000000000010  WA       4     0     8
  [10] .got              PROGBITS         00000000000283c0  000283c0
       0000000000000000  0000000000000000  WA       0     0     8
  [11] .relro_padding    NOBITS           00000000000283c0  000283c0
       0000000000000c40  0000000000000000  WA       0     0     1
  [12] .data             PROGBITS         00000000000293c0  000283c0
       0000000000000024  0000000000000000  WA       0     0     16
  [13] .bss              NOBITS           00000000000293e8  000283e4
       0000000000000070  0000000000000000  WA       0     0     8
  [14] .sdmagic          PROGBITS         0000000000000000  000283e4
       0000000000000036  0000000000000000   S       0     0     1
  [15] .osrel            PROGBITS         0000000000000000  0002841a
       0000000000000055  0000000000000000   S       0     0     1
  [16] .sbat             PROGBITS         0000000000000000  0002846f
       00000000000000ee  0000000000000000   S       0     0     1
  [17] .debug_loclists   PROGBITS         0000000000000000  0002855d
       0000000000000033  0000000000000000           0     0     1
  [18] .debug_abbrev     PROGBITS         0000000000000000  00028590
       0000000000002074  0000000000000000           0     0     1
  [19] .debug_info       PROGBITS         0000000000000000  0002a604
       000000000000f910  0000000000000000           0     0     1
  [20] .debug_rnglists   PROGBITS         0000000000000000  00039f14
       00000000000000c4  0000000000000000           0     0     1
  [21] .debug_str_o[...] PROGBITS         0000000000000000  00039fd8
       000000000000315c  0000000000000000           0     0     1
  [22] .debug_str        PROGBITS         0000000000000000  0003d134
       000000000000532e  0000000000000001  MS       0     0     1
  [23] .debug_addr       PROGBITS         0000000000000000  00042462
       0000000000002c10  0000000000000000           0     0     1
  [24] .comment          PROGBITS         0000000000000000  00045072
       0000000000000044  0000000000000001  MS       0     0     1
  [25] .debug_frame      PROGBITS         0000000000000000  000450b8
       0000000000003aa0  0000000000000000           0     0     8
  [26] .debug_line       PROGBITS         0000000000000000  00048b58
       000000000000d121  0000000000000000           0     0     1
  [27] .debug_line_str   PROGBITS         0000000000000000  00055c79
       00000000000004d3  0000000000000001  MS       0     0     1
  [28] .symtab           SYMTAB           0000000000000000  00056150
       00000000000025e0  0000000000000018          30   404     8
  [29] .shstrtab         STRTAB           0000000000000000  00058730
       0000000000000141  0000000000000000           0     0     1
  [30] .strtab           STRTAB           0000000000000000  00058871
       0000000000001858  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  D (mbind), l (large), p (processor specific)

Elf file type is DYN (Position-Independent Executable file)
Entry point 0x5000
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                 0x00000000000001f8 0x00000000000001f8  R      0x8
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000004888 0x0000000000004888  R      0x1000
  LOAD           0x0000000000005000 0x0000000000005000 0x0000000000005000
                 0x00000000000221e1 0x00000000000221e1  R E    0x1000
  LOAD           0x0000000000028000 0x0000000000028000 0x0000000000028000
                 0x00000000000003c0 0x0000000000001000  RW     0x1000
  LOAD           0x00000000000283c0 0x00000000000293c0 0x00000000000293c0
                 0x0000000000000024 0x0000000000000098  RW     0x1000
  DYNAMIC        0x0000000000028300 0x0000000000028300 0x0000000000028300
                 0x00000000000000c0 0x00000000000000c0  RW     0x8
  GNU_RELRO      0x0000000000028000 0x0000000000028000 0x0000000000028000
                 0x00000000000003c0 0x0000000000001000  R      0x1
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x0
  NOTE           0x0000000000000238 0x0000000000000238 0x0000000000000238
                 0x0000000000000018 0x0000000000000018  R      0x4

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .note.gnu.build-id .dynsym .gnu.hash .dynstr .rela.dyn .rodata 
   02     .text 
   03     .data.rel.ro .dynamic .relro_padding 
   04     .data .bss 
   05     .dynamic 
   06     .data.rel.ro .dynamic .relro_padding 
   07     
   08     .note.gnu.build-id 
@mrc0mmand mrc0mmand added sd-boot/sd-stub/bootctl bug 🐛 Programming errors, that need preferential fixing labels Mar 5, 2024
keszybz added a commit to keszybz/systemd that referenced this issue Mar 14, 2024
RuntimeError is documented as "Unspecified run-time error". It doesn't make
much sense for Python. (It originated in Java, where exceptions that can be
thrown by a function are declared in the function signature. All code calling
such a function must either explicitly catch all possible exception types, or
allow them to propagate by listing them in its own exception type list. This is
nice in theory, but in practice very annoying. Especially during development,
when the list of possible exception types is not finalized, we would end up
adding and removing exceptions to functions signatures all the time. Also for
code which is designed to call functions recursively, we would soon end up with
all functions declaring all possible exception types… To avoid this, people
would quite often do fake handling with a block that either prints and ignores
an exception, or has just a comment like "fix me later", or even nothing. This
often lead to people forgetting to adjust this later on and production code
containing such constructs. An escape hatch was opened with RuntimeException and
its subclasses, which do not need to be pre-declared. Various memory-related
exceptions were added as subclasses of RuntimeException. But later on, people
starting using this to not to have to declare all exception types everywhere.)

In Python, exceptions do no have to be pre-declared, and for code which just
encounters a failure, we should raise a specific exception type. The catch-all
class for unexpected input is ValueError.

For systemd#31637:
BadSectionError: Section '.data' @0x28000 overlaps previous section @0x28000+0x300=@0x28300

Also, exception strings should not contain trailing periods, because they are
often embedded in sentences.
keszybz added a commit to keszybz/systemd that referenced this issue Mar 14, 2024
Resolves systemd#31637.

clang-18 does the section setup differently than older versions. There
is a bunch of ordering chagnes, but it also inserts the following:

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
...
  9 .got          00000000  00000000000283c0  00000000000283c0  000283c0  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 10 .relro_padding 00000c40  00000000000283c0  00000000000283c0  000283c0  2**0
                  ALLOC
 11 .data         00000024  00000000000293c0  00000000000293c0  000283c0  2**4
                  CONTENTS, ALLOC, LOAD, DATA
...

This causes a problem for us, because we try to map the .got to .rodata,
and the subsequent .data to .data, and round down the VMA to the nearest
page, which causes the PE sections to overlap.

llvm/llvm-project#66042 adds .relro_padding to make
sure that the RELRO segment is properly write protected and allocated.
For our binaries, the .got section is empty, so I think it we can skip it
safely, and the .relro_padding section is not useful once .got has been
dropped.
keszybz added a commit to keszybz/systemd that referenced this issue Mar 17, 2024
Resolves systemd#31637.

lld-18 does the section setup differently than older versions. There is a bunch
of ordering chagnes, but it also inserts the following:

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
...
  9 .got          00000000  00000000000283c0  00000000000283c0  000283c0  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 10 .relro_padding 00000c40  00000000000283c0  00000000000283c0  000283c0  2**0
                  ALLOC
 11 .data         00000024  00000000000293c0  00000000000293c0  000283c0  2**4
                  CONTENTS, ALLOC, LOAD, DATA
...

This causes a problem for us, because we try to map the .got to .rodata,
and the subsequent .data to .data, and round down the VMA to the nearest
page, which causes the PE sections to overlap.

llvm/llvm-project#66042 adds .relro_padding to make
sure that the RELRO segment is properly write protected and allocated. For our
binaries, the .got section is empty, so we can skip it safely, and the
.relro_padding section is not useful once .got has been dropped.

To make sure that the code does not use the .got section unexpectedly, raise an
error if a (non-empty) .got section is found.
chunyi-wu pushed a commit to chunyi-wu/systemd that referenced this issue Apr 3, 2024
RuntimeError is documented as "Unspecified run-time error". It doesn't make
much sense for Python. (It originated in Java, where exceptions that can be
thrown by a function are declared in the function signature. All code calling
such a function must either explicitly catch all possible exception types, or
allow them to propagate by listing them in its own exception type list. This is
nice in theory, but in practice very annoying. Especially during development,
when the list of possible exception types is not finalized, we would end up
adding and removing exceptions to functions signatures all the time. Also for
code which is designed to call functions recursively, we would soon end up with
all functions declaring all possible exception types… To avoid this, people
would quite often do fake handling with a block that either prints and ignores
an exception, or has just a comment like "fix me later", or even nothing. This
often lead to people forgetting to adjust this later on and production code
containing such constructs. An escape hatch was opened with RuntimeException and
its subclasses, which do not need to be pre-declared. Various memory-related
exceptions were added as subclasses of RuntimeException. But later on, people
starting using this to not to have to declare all exception types everywhere.)

In Python, exceptions do no have to be pre-declared, and for code which just
encounters a failure, we should raise a specific exception type. The catch-all
class for unexpected input is ValueError.

For systemd#31637:
BadSectionError: Section '.data' @0x28000 overlaps previous section @0x28000+0x300=@0x28300

Also, exception strings should not contain trailing periods, because they are
often embedded in sentences.
chunyi-wu pushed a commit to chunyi-wu/systemd that referenced this issue Apr 3, 2024
Resolves systemd#31637.

lld-18 does the section setup differently than older versions. There is a bunch
of ordering chagnes, but it also inserts the following:

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
...
  9 .got          00000000  00000000000283c0  00000000000283c0  000283c0  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 10 .relro_padding 00000c40  00000000000283c0  00000000000283c0  000283c0  2**0
                  ALLOC
 11 .data         00000024  00000000000293c0  00000000000293c0  000283c0  2**4
                  CONTENTS, ALLOC, LOAD, DATA
...

This causes a problem for us, because we try to map the .got to .rodata,
and the subsequent .data to .data, and round down the VMA to the nearest
page, which causes the PE sections to overlap.

llvm/llvm-project#66042 adds .relro_padding to make
sure that the RELRO segment is properly write protected and allocated. For our
binaries, the .got section is empty, so we can skip it safely, and the
.relro_padding section is not useful once .got has been dropped.

We don't expect .got sections, but they are apparently inserted on i386 and
aarch64 builds. Emit a warning until we figure out why they are there.
keszybz added a commit to systemd/systemd-stable that referenced this issue Apr 23, 2024
RuntimeError is documented as "Unspecified run-time error". It doesn't make
much sense for Python. (It originated in Java, where exceptions that can be
thrown by a function are declared in the function signature. All code calling
such a function must either explicitly catch all possible exception types, or
allow them to propagate by listing them in its own exception type list. This is
nice in theory, but in practice very annoying. Especially during development,
when the list of possible exception types is not finalized, we would end up
adding and removing exceptions to functions signatures all the time. Also for
code which is designed to call functions recursively, we would soon end up with
all functions declaring all possible exception types… To avoid this, people
would quite often do fake handling with a block that either prints and ignores
an exception, or has just a comment like "fix me later", or even nothing. This
often lead to people forgetting to adjust this later on and production code
containing such constructs. An escape hatch was opened with RuntimeException and
its subclasses, which do not need to be pre-declared. Various memory-related
exceptions were added as subclasses of RuntimeException. But later on, people
starting using this to not to have to declare all exception types everywhere.)

In Python, exceptions do no have to be pre-declared, and for code which just
encounters a failure, we should raise a specific exception type. The catch-all
class for unexpected input is ValueError.

For systemd/systemd#31637:
BadSectionError: Section '.data' @0x28000 overlaps previous section @0x28000+0x300=@0x28300

Also, exception strings should not contain trailing periods, because they are
often embedded in sentences.

(cherry picked from commit 8a75371)
keszybz added a commit to systemd/systemd-stable that referenced this issue Apr 23, 2024
Resolves systemd/systemd#31637.

lld-18 does the section setup differently than older versions. There is a bunch
of ordering chagnes, but it also inserts the following:

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
...
  9 .got          00000000  00000000000283c0  00000000000283c0  000283c0  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 10 .relro_padding 00000c40  00000000000283c0  00000000000283c0  000283c0  2**0
                  ALLOC
 11 .data         00000024  00000000000293c0  00000000000293c0  000283c0  2**4
                  CONTENTS, ALLOC, LOAD, DATA
...

This causes a problem for us, because we try to map the .got to .rodata,
and the subsequent .data to .data, and round down the VMA to the nearest
page, which causes the PE sections to overlap.

llvm/llvm-project#66042 adds .relro_padding to make
sure that the RELRO segment is properly write protected and allocated. For our
binaries, the .got section is empty, so we can skip it safely, and the
.relro_padding section is not useful once .got has been dropped.

We don't expect .got sections, but they are apparently inserted on i386 and
aarch64 builds. Emit a warning until we figure out why they are there.

(cherry picked from commit 6d03e55)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Programming errors, that need preferential fixing sd-boot/sd-stub/bootctl
Development

No branches or pull requests

1 participant