BPF List
 help / color / mirror / Atom feed
* bpftool fails on 32-bit hosts when -Wa,--compress-debug-sections is used
@ 2023-12-11 12:49 Sergei Trofimovich
  2023-12-13  0:10 ` Andrii Nakryiko
  0 siblings, 1 reply; 5+ messages in thread
From: Sergei Trofimovich @ 2023-12-11 12:49 UTC (permalink / raw)
  To: bpf

Hi bpf@!

Tl;DR:

BPF programs built with `clang`'s `-g -Wa,--compress-debug-sections`
fail when processed by `bpftool` on section alignment checks as:

    $ cat src/core/bpf/socket_bind/bpf.c
    struct socket_bind_map_t { int value; };
    struct socket_bind_map_t sd_bind_allow __attribute__((section(".maps"), used));

    $ clang-16 -target bpf -fno-stack-protector -c src/core/bpf/socket_bind/bpf.c -o bpf.unstripped.o -g -Wa,--compress-debug-sections
    $ bpftool gen object bpf.o bpf.unstripped.o
    libbpf: ELF section #9 has inconsistent alignment addr=8 != d=4 in bpf.unstripped.o
    Error: failed to link 'bpf.unstripped.o': Invalid argument (22)

This happens only when `bpftool` is a 32-bit ELF binary. 64-bit
`bpftool` seems to work as expected.

More words:

Here is my understanding of the failure. Without the
`-Wa,--compress-debug-sections` option `clang` generates byte-aligned
uncompressed `.debug` sections:

    $ clang -target bpf -fno-stack-protector -c src/core/bpf/socket_bind/bpf.c -o bpf.unstripped.o -g
    $ readelf -SW bpf.unstripped.o
    There are 19 section headers, starting at offset 0x530:
    
    Section Headers:
      [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
      [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
      [ 1] .strtab           STRTAB          0000000000000000 000471 0000b8 00      0   0  1
      [ 2] .text             PROGBITS        0000000000000000 000040 000000 00  AX  0   0  4
      [ 3] .maps             PROGBITS        0000000000000000 000040 000004 00  WA  0   0  4
      [ 4] .debug_abbrev     PROGBITS        0000000000000000 000044 00004c 00      0   0  1
      [ 5] .debug_info       PROGBITS        0000000000000000 000090 00003d 00      0   0  1
      [ 6] .rel.debug_info   REL             0000000000000000 000380 000040 10   I 18   5  8
      [ 7] .debug_str_offsets PROGBITS        0000000000000000 0000cd 000024 00      0   0  1
      [ 8] .rel.debug_str_offsets REL             0000000000000000 0003c0 000070 10   I 18   7  8
      [ 9] .debug_str        PROGBITS        0000000000000000 0000f1 000080 01  MS  0   0  1
      [10] .debug_addr       PROGBITS        0000000000000000 000171 000010 00      0   0  1
      [11] .rel.debug_addr   REL             0000000000000000 000430 000010 10   I 18  10  8
      [12] .BTF              PROGBITS        0000000000000000 000184 000099 00      0   0  4
      [13] .rel.BTF          REL             0000000000000000 000440 000010 10   I 18  12  8
      [14] .debug_line       PROGBITS        0000000000000000 00021d 000043 00      0   0  1
      [15] .rel.debug_line   REL             0000000000000000 000450 000020 10   I 18  14  8
      [16] .debug_line_str   PROGBITS        0000000000000000 000260 000041 01  MS  0   0  1
      [17] .llvm_addrsig     LOOS+0xfff4c03  0000000000000000 000470 000001 00   E 18   0  1
      [18] .symtab           SYMTAB          0000000000000000 0002a8 0000d8 18      1   8  8
    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), p (processor specific)

Note how `.debug_str` has `alignment=1` here. Loading of such a section
has no problems on x86_64 or i686.

But when we add `-Wa,--compress-debug-sections` some debug sections
become aligned 8 bytes (usual `ELF64`) alignment:

    $ clang -target bpf -fno-stack-protector -c src/core/bpf/socket_bind/bpf.c -o bpf.unstripped.o -g -Wa,--compress-debug-sections
    $ LANG=C readelf -SW bpf.unstripped.o
    There are 19 section headers, starting at offset 0x530:

    Section Headers:
      [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
      [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
      [ 1] .strtab           STRTAB          0000000000000000 000471 0000b8 00      0   0  1
      [ 2] .text             PROGBITS        0000000000000000 000040 000000 00  AX  0   0  4
      [ 3] .maps             PROGBITS        0000000000000000 000040 000004 00  WA  0   0  4
      [ 4] .debug_abbrev     PROGBITS        0000000000000000 000044 00004c 00      0   0  1
      [ 5] .debug_info       PROGBITS        0000000000000000 000090 00003d 00      0   0  1
      [ 6] .rel.debug_info   REL             0000000000000000 000380 000040 10   I 18   5  8
      [ 7] .debug_str_offsets PROGBITS        0000000000000000 0000cd 000024 00      0   0  1
      [ 8] .rel.debug_str_offsets REL             0000000000000000 0003c0 000070 10   I 18   7  8
      [ 9] .debug_str        PROGBITS        0000000000000000 0000f1 000086 01 MSC  0   0  8
      [10] .debug_addr       PROGBITS        0000000000000000 000177 000010 00      0   0  1
      [11] .rel.debug_addr   REL             0000000000000000 000430 000010 10   I 18  10  8
      [12] .BTF              PROGBITS        0000000000000000 000188 000099 00      0   0  4
      [13] .rel.BTF          REL             0000000000000000 000440 000010 10   I 18  12  8
      [14] .debug_line       PROGBITS        0000000000000000 000221 000043 00      0   0  1
      [15] .rel.debug_line   REL             0000000000000000 000450 000020 10   I 18  14  8
      [16] .debug_line_str   PROGBITS        0000000000000000 000264 000041 01  MS  0   0  1
      [17] .llvm_addrsig     LOOS+0xfff4c03  0000000000000000 000470 000001 00   E 18   0  1
      [18] .symtab           SYMTAB          0000000000000000 0002a8 0000d8 18      1   8  8
    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), p (processor specific)

Note how `.debug_str` alignment changed from 1-byte to 8-byte alignment.

AFAIU 8-byte alignment of compressed section for `ELF64` files is expected:
compressed sections all have a small header that consistes of a few
64-bit values (compression type, uncompressed size, uncompressed data
alignment).

Thus the binary loads as expected by `x86_64` `bpftool` and fails when
loaded by `i686` `bpftool`.

Should `bpftool` work in this scenario? Or compressed sections are not
supported on 32-bit hosts?

It feels like debugging sections with strings should be easily
decompressable on any host type.

Thanks!

-- 

  Sergei

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

* Re: bpftool fails on 32-bit hosts when -Wa,--compress-debug-sections is used
  2023-12-11 12:49 bpftool fails on 32-bit hosts when -Wa,--compress-debug-sections is used Sergei Trofimovich
@ 2023-12-13  0:10 ` Andrii Nakryiko
  2023-12-19 11:03   ` [PATCH] libbpf: skip DWARF sections in linker sanity check Alyssa Ross
  0 siblings, 1 reply; 5+ messages in thread
From: Andrii Nakryiko @ 2023-12-13  0:10 UTC (permalink / raw)
  To: Sergei Trofimovich; +Cc: bpf

On Mon, Dec 11, 2023 at 4:49 AM Sergei Trofimovich <slyich@gmail.com> wrote:
>
> Hi bpf@!
>
> Tl;DR:
>
> BPF programs built with `clang`'s `-g -Wa,--compress-debug-sections`
> fail when processed by `bpftool` on section alignment checks as:
>
>     $ cat src/core/bpf/socket_bind/bpf.c
>     struct socket_bind_map_t { int value; };
>     struct socket_bind_map_t sd_bind_allow __attribute__((section(".maps"), used));
>
>     $ clang-16 -target bpf -fno-stack-protector -c src/core/bpf/socket_bind/bpf.c -o bpf.unstripped.o -g -Wa,--compress-debug-sections
>     $ bpftool gen object bpf.o bpf.unstripped.o
>     libbpf: ELF section #9 has inconsistent alignment addr=8 != d=4 in bpf.unstripped.o

So we are talking about this check in libbpf's linker:

  if (sec->shdr->sh_addralign != sec->data->d_align)

And it's confusing that it would be ok to have actual data alignment
that doesn't match declared alignment in section header? Is that
expected in ELF in general?


Having said that, I think we can mitigate all this easily by ignoring
DWARF sections. Libbpf linker drops all that while linking, see
is_ignored_sec() check, but when doing a sanity check we still
validate everything for DWARF sections.

So perhaps an easy way out is just to ignore DWARF sections in sanity
checks as well?


>     Error: failed to link 'bpf.unstripped.o': Invalid argument (22)
>
> This happens only when `bpftool` is a 32-bit ELF binary. 64-bit
> `bpftool` seems to work as expected.
>
> More words:
>
> Here is my understanding of the failure. Without the
> `-Wa,--compress-debug-sections` option `clang` generates byte-aligned
> uncompressed `.debug` sections:
>
>     $ clang -target bpf -fno-stack-protector -c src/core/bpf/socket_bind/bpf.c -o bpf.unstripped.o -g
>     $ readelf -SW bpf.unstripped.o
>     There are 19 section headers, starting at offset 0x530:
>
>     Section Headers:
>       [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
>       [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
>       [ 1] .strtab           STRTAB          0000000000000000 000471 0000b8 00      0   0  1
>       [ 2] .text             PROGBITS        0000000000000000 000040 000000 00  AX  0   0  4
>       [ 3] .maps             PROGBITS        0000000000000000 000040 000004 00  WA  0   0  4
>       [ 4] .debug_abbrev     PROGBITS        0000000000000000 000044 00004c 00      0   0  1
>       [ 5] .debug_info       PROGBITS        0000000000000000 000090 00003d 00      0   0  1
>       [ 6] .rel.debug_info   REL             0000000000000000 000380 000040 10   I 18   5  8
>       [ 7] .debug_str_offsets PROGBITS        0000000000000000 0000cd 000024 00      0   0  1
>       [ 8] .rel.debug_str_offsets REL             0000000000000000 0003c0 000070 10   I 18   7  8
>       [ 9] .debug_str        PROGBITS        0000000000000000 0000f1 000080 01  MS  0   0  1
>       [10] .debug_addr       PROGBITS        0000000000000000 000171 000010 00      0   0  1
>       [11] .rel.debug_addr   REL             0000000000000000 000430 000010 10   I 18  10  8
>       [12] .BTF              PROGBITS        0000000000000000 000184 000099 00      0   0  4
>       [13] .rel.BTF          REL             0000000000000000 000440 000010 10   I 18  12  8
>       [14] .debug_line       PROGBITS        0000000000000000 00021d 000043 00      0   0  1
>       [15] .rel.debug_line   REL             0000000000000000 000450 000020 10   I 18  14  8
>       [16] .debug_line_str   PROGBITS        0000000000000000 000260 000041 01  MS  0   0  1
>       [17] .llvm_addrsig     LOOS+0xfff4c03  0000000000000000 000470 000001 00   E 18   0  1
>       [18] .symtab           SYMTAB          0000000000000000 0002a8 0000d8 18      1   8  8
>     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), p (processor specific)
>
> Note how `.debug_str` has `alignment=1` here. Loading of such a section
> has no problems on x86_64 or i686.
>
> But when we add `-Wa,--compress-debug-sections` some debug sections
> become aligned 8 bytes (usual `ELF64`) alignment:
>
>     $ clang -target bpf -fno-stack-protector -c src/core/bpf/socket_bind/bpf.c -o bpf.unstripped.o -g -Wa,--compress-debug-sections
>     $ LANG=C readelf -SW bpf.unstripped.o
>     There are 19 section headers, starting at offset 0x530:
>
>     Section Headers:
>       [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
>       [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
>       [ 1] .strtab           STRTAB          0000000000000000 000471 0000b8 00      0   0  1
>       [ 2] .text             PROGBITS        0000000000000000 000040 000000 00  AX  0   0  4
>       [ 3] .maps             PROGBITS        0000000000000000 000040 000004 00  WA  0   0  4
>       [ 4] .debug_abbrev     PROGBITS        0000000000000000 000044 00004c 00      0   0  1
>       [ 5] .debug_info       PROGBITS        0000000000000000 000090 00003d 00      0   0  1
>       [ 6] .rel.debug_info   REL             0000000000000000 000380 000040 10   I 18   5  8
>       [ 7] .debug_str_offsets PROGBITS        0000000000000000 0000cd 000024 00      0   0  1
>       [ 8] .rel.debug_str_offsets REL             0000000000000000 0003c0 000070 10   I 18   7  8
>       [ 9] .debug_str        PROGBITS        0000000000000000 0000f1 000086 01 MSC  0   0  8
>       [10] .debug_addr       PROGBITS        0000000000000000 000177 000010 00      0   0  1
>       [11] .rel.debug_addr   REL             0000000000000000 000430 000010 10   I 18  10  8
>       [12] .BTF              PROGBITS        0000000000000000 000188 000099 00      0   0  4
>       [13] .rel.BTF          REL             0000000000000000 000440 000010 10   I 18  12  8
>       [14] .debug_line       PROGBITS        0000000000000000 000221 000043 00      0   0  1
>       [15] .rel.debug_line   REL             0000000000000000 000450 000020 10   I 18  14  8
>       [16] .debug_line_str   PROGBITS        0000000000000000 000264 000041 01  MS  0   0  1
>       [17] .llvm_addrsig     LOOS+0xfff4c03  0000000000000000 000470 000001 00   E 18   0  1
>       [18] .symtab           SYMTAB          0000000000000000 0002a8 0000d8 18      1   8  8
>     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), p (processor specific)
>
> Note how `.debug_str` alignment changed from 1-byte to 8-byte alignment.
>
> AFAIU 8-byte alignment of compressed section for `ELF64` files is expected:
> compressed sections all have a small header that consistes of a few
> 64-bit values (compression type, uncompressed size, uncompressed data
> alignment).
>
> Thus the binary loads as expected by `x86_64` `bpftool` and fails when
> loaded by `i686` `bpftool`.
>
> Should `bpftool` work in this scenario? Or compressed sections are not
> supported on 32-bit hosts?
>
> It feels like debugging sections with strings should be easily
> decompressable on any host type.
>
> Thanks!
>
> --
>
>   Sergei
>

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

* [PATCH] libbpf: skip DWARF sections in linker sanity check
  2023-12-13  0:10 ` Andrii Nakryiko
@ 2023-12-19 11:03   ` Alyssa Ross
  2023-12-20 15:28     ` Daniel Borkmann
  2023-12-20 23:40     ` patchwork-bot+netdevbpf
  0 siblings, 2 replies; 5+ messages in thread
From: Alyssa Ross @ 2023-12-19 11:03 UTC (permalink / raw)
  To: bpf, Andrii Nakryiko; +Cc: patches, Sergei Trofimovich

clang can generate (with -g -Wa,--compress-debug-sections) 4-byte
aligned DWARF sections that declare themselves to be 8-byte aligned in
the section header.  Since DWARF sections are dropped during linking
anyway, just skip running the sanity checks on them.

Reported-by: Sergei Trofimovich <slyich@gmail.com>
Suggested-by: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Closes: https://lore.kernel.org/bpf/ZXcFRJVKbKxtEL5t@nz.home/
Signed-off-by: Alyssa Ross <hi@alyssa.is>
---
 tools/lib/bpf/linker.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/lib/bpf/linker.c b/tools/lib/bpf/linker.c
index 52a2901e8bd0..16bca56002ab 100644
--- a/tools/lib/bpf/linker.c
+++ b/tools/lib/bpf/linker.c
@@ -719,6 +719,9 @@ static int linker_sanity_check_elf(struct src_obj *obj)
 			return -EINVAL;
 		}
 
+		if (is_dwarf_sec_name(sec->sec_name))
+			continue;
+
 		if (sec->shdr->sh_addralign && !is_pow_of_2(sec->shdr->sh_addralign)) {
 			pr_warn("ELF section #%zu alignment %llu is non pow-of-2 alignment in %s\n",
 				sec->sec_idx, (long long unsigned)sec->shdr->sh_addralign,

base-commit: 733763285acfe8dffd6e39ad2ed3d1222b32a901
-- 
2.42.0


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

* Re: [PATCH] libbpf: skip DWARF sections in linker sanity check
  2023-12-19 11:03   ` [PATCH] libbpf: skip DWARF sections in linker sanity check Alyssa Ross
@ 2023-12-20 15:28     ` Daniel Borkmann
  2023-12-20 23:40     ` patchwork-bot+netdevbpf
  1 sibling, 0 replies; 5+ messages in thread
From: Daniel Borkmann @ 2023-12-20 15:28 UTC (permalink / raw)
  To: Alyssa Ross, bpf, Andrii Nakryiko; +Cc: patches, Sergei Trofimovich

On 12/19/23 12:03 PM, Alyssa Ross wrote:
> clang can generate (with -g -Wa,--compress-debug-sections) 4-byte
> aligned DWARF sections that declare themselves to be 8-byte aligned in
> the section header.  Since DWARF sections are dropped during linking
> anyway, just skip running the sanity checks on them.
> 
> Reported-by: Sergei Trofimovich <slyich@gmail.com>
> Suggested-by: Andrii Nakryiko <andrii.nakryiko@gmail.com>
> Closes: https://lore.kernel.org/bpf/ZXcFRJVKbKxtEL5t@nz.home/
> Signed-off-by: Alyssa Ross <hi@alyssa.is>

Looks reasonable to skip, thus:

Acked-by: Daniel Borkmann <daniel@iogearbox.net>

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

* Re: [PATCH] libbpf: skip DWARF sections in linker sanity check
  2023-12-19 11:03   ` [PATCH] libbpf: skip DWARF sections in linker sanity check Alyssa Ross
  2023-12-20 15:28     ` Daniel Borkmann
@ 2023-12-20 23:40     ` patchwork-bot+netdevbpf
  1 sibling, 0 replies; 5+ messages in thread
From: patchwork-bot+netdevbpf @ 2023-12-20 23:40 UTC (permalink / raw)
  To: Alyssa Ross; +Cc: bpf, andrii.nakryiko, patches, slyich

Hello:

This patch was applied to bpf/bpf-next.git (master)
by Andrii Nakryiko <andrii@kernel.org>:

On Tue, 19 Dec 2023 12:03:24 +0100 you wrote:
> clang can generate (with -g -Wa,--compress-debug-sections) 4-byte
> aligned DWARF sections that declare themselves to be 8-byte aligned in
> the section header.  Since DWARF sections are dropped during linking
> anyway, just skip running the sanity checks on them.
> 
> Reported-by: Sergei Trofimovich <slyich@gmail.com>
> Suggested-by: Andrii Nakryiko <andrii.nakryiko@gmail.com>
> Closes: https://lore.kernel.org/bpf/ZXcFRJVKbKxtEL5t@nz.home/
> Signed-off-by: Alyssa Ross <hi@alyssa.is>
> 
> [...]

Here is the summary with links:
  - libbpf: skip DWARF sections in linker sanity check
    https://git.kernel.org/bpf/bpf-next/c/a4897b87775c

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



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

end of thread, other threads:[~2023-12-20 23:40 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-12-11 12:49 bpftool fails on 32-bit hosts when -Wa,--compress-debug-sections is used Sergei Trofimovich
2023-12-13  0:10 ` Andrii Nakryiko
2023-12-19 11:03   ` [PATCH] libbpf: skip DWARF sections in linker sanity check Alyssa Ross
2023-12-20 15:28     ` Daniel Borkmann
2023-12-20 23:40     ` patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox