diff mbox series

[bpf-next,V2,5/5] tools/libbpf: handle issues with bpf ELF objects containing .eh_frames

Message ID 151792886827.16520.13497757653052246816.stgit@firesoul
State Changes Requested, archived
Delegated to: BPF Maintainers
Headers show
Series tools/libbpf improvements and selftests | expand

Commit Message

Jesper Dangaard Brouer Feb. 6, 2018, 2:54 p.m. UTC
If clang >= 4.0.1 is missing the option '-target bpf', it will cause
llc/llvm to create two ELF sections for "Exception Frames", with
section names '.eh_frame' and '.rel.eh_frame'.

The BPF ELF loader library libbpf fails when loading files with these
sections.  The other in-kernel BPF ELF loader in samples/bpf/bpf_load.c,
handle this gracefully. And iproute2 loader also seems to work with these
"eh" sections.

The issue in libbpf is caused by bpf_object__elf_collect() skip the
'.eh_frame' and thus doesn't create an internal data structure
pointing to this ELF section index.  Later when the relocation section
'.rel.eh_frame' is processed, it tries to find the '.eh_frame' via the
ELF section idx, which is that fails (in bpf_object__collect_reloc).

I couldn't find a way to see that the '.rel.eh_frame' was irrelevant
(that is only determined by looking at the section it reference, which
we no longer have info available on).

Thus, my solution is simply to match on the name of the relocation
section, to skip that too.

Note, for samples/bpf/ the '-target bpf' parameter to clang cannot be used
due to incompatibility with asm embedded headers, that some of the samples
include. This is explained in more details by Yonghong Song in bpf_devel_QA.

Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
---
 tools/lib/bpf/libbpf.c |    7 +++++++
 1 file changed, 7 insertions(+)

Comments

Alexei Starovoitov Feb. 6, 2018, 4 p.m. UTC | #1
On Tue, Feb 06, 2018 at 03:54:28PM +0100, Jesper Dangaard Brouer wrote:
> If clang >= 4.0.1 is missing the option '-target bpf', it will cause
> llc/llvm to create two ELF sections for "Exception Frames", with
> section names '.eh_frame' and '.rel.eh_frame'.
> 
> The BPF ELF loader library libbpf fails when loading files with these
> sections.  The other in-kernel BPF ELF loader in samples/bpf/bpf_load.c,
> handle this gracefully. And iproute2 loader also seems to work with these
> "eh" sections.
> 
> The issue in libbpf is caused by bpf_object__elf_collect() skip the
> '.eh_frame' and thus doesn't create an internal data structure
> pointing to this ELF section index.  Later when the relocation section
> '.rel.eh_frame' is processed, it tries to find the '.eh_frame' via the
> ELF section idx, which is that fails (in bpf_object__collect_reloc).
> 
> I couldn't find a way to see that the '.rel.eh_frame' was irrelevant
> (that is only determined by looking at the section it reference, which
> we no longer have info available on).

but does this approach work for all extra sections and relocations emitted
when source is compiled with -g ?
To address this case bpf_load.c does:
  if (shdr.sh_type == SHT_REL) {
          struct bpf_insn *insns;

          /* locate prog sec that need map fixup (relocations) */
          if (get_sec(elf, shdr.sh_info, &ehdr, &shname_prog,
                      &shdr_prog, &data_prog))
                  continue;

          if (shdr_prog.sh_type != SHT_PROGBITS ||
              !(shdr_prog.sh_flags & SHF_EXECINSTR))
                  continue;

why the same approach is not applicable here?

I guess we can apply this workaround as-is but it looks incomplete.

> Thus, my solution is simply to match on the name of the relocation
> section, to skip that too.
> 
> Note, for samples/bpf/ the '-target bpf' parameter to clang cannot be used
> due to incompatibility with asm embedded headers, that some of the samples
> include. This is explained in more details by Yonghong Song in bpf_devel_QA.
> 
> Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
> ---
>  tools/lib/bpf/libbpf.c |    7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index b4eeaa3ebff5..84e8bbe07347 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -822,6 +822,13 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
>  			void *reloc = obj->efile.reloc;
>  			int nr_reloc = obj->efile.nr_reloc + 1;
>  
> +			/* Skip decoding of "eh" exception frames */
> +			if (strcmp(name, ".rel.eh_frame") == 0) {
> +				pr_debug("skip relo section %s(%d) for section(%d)\n",
> +					 name, idx, sh.sh_info);
> +				continue;
> +			}
> +
>  			reloc = realloc(reloc,
>  					sizeof(*obj->efile.reloc) * nr_reloc);
>  			if (!reloc) {
>
Jesper Dangaard Brouer Feb. 6, 2018, 5:03 p.m. UTC | #2
On Tue, 6 Feb 2018 08:00:59 -0800 Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:

> On Tue, Feb 06, 2018 at 03:54:28PM +0100, Jesper Dangaard Brouer wrote:
> > If clang >= 4.0.1 is missing the option '-target bpf', it will cause
> > llc/llvm to create two ELF sections for "Exception Frames", with
> > section names '.eh_frame' and '.rel.eh_frame'.
> > 
> > The BPF ELF loader library libbpf fails when loading files with these
> > sections.  The other in-kernel BPF ELF loader in samples/bpf/bpf_load.c,
> > handle this gracefully. And iproute2 loader also seems to work with these
> > "eh" sections.
> > 
> > The issue in libbpf is caused by bpf_object__elf_collect() skip the
> > '.eh_frame' and thus doesn't create an internal data structure
> > pointing to this ELF section index.  Later when the relocation section
> > '.rel.eh_frame' is processed, it tries to find the '.eh_frame' via the
> > ELF section idx, which is that fails (in bpf_object__collect_reloc).
> > 
> > I couldn't find a way to see that the '.rel.eh_frame' was irrelevant
> > (that is only determined by looking at the section it reference, which
> > we no longer have info available on).  
> 
> but does this approach work for all extra sections and relocations emitted
> when source is compiled with -g ?

No, but I plan to follow up and do a more complete solution later. This
is a workaround to get the Suricata use-case working and also that
samples/bpf/ can be loaded.

> To address this case bpf_load.c does:
>   if (shdr.sh_type == SHT_REL) {
>           struct bpf_insn *insns;
> 
>           /* locate prog sec that need map fixup (relocations) */
>           if (get_sec(elf, shdr.sh_info, &ehdr, &shname_prog,
>                       &shdr_prog, &data_prog))
>                   continue;
> 
>           if (shdr_prog.sh_type != SHT_PROGBITS ||
>               !(shdr_prog.sh_flags & SHF_EXECINSTR))
>                   continue;
> 
> why the same approach is not applicable here?

As described above bpf_object__elf_collect() skip the "real" section
that the relo-section want to lookup (based on the same kind of
check), but libbpf is now missing the section idx in its internal
structures... and thus the relo lookup of the idx fails. (bpf_load.c
does the lookup in the ELF obj directly, thus it does not have this
problem).


> I guess we can apply this workaround as-is but it looks incomplete.

Yes, it is a workaround to move forward... it requires a larger change
to libbpf, so it stores idx'es of skipped sections.
Daniel Borkmann Feb. 6, 2018, 7:05 p.m. UTC | #3
On 02/06/2018 06:03 PM, Jesper Dangaard Brouer wrote:
> On Tue, 6 Feb 2018 08:00:59 -0800 Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
>> On Tue, Feb 06, 2018 at 03:54:28PM +0100, Jesper Dangaard Brouer wrote:
>>> If clang >= 4.0.1 is missing the option '-target bpf', it will cause
>>> llc/llvm to create two ELF sections for "Exception Frames", with
>>> section names '.eh_frame' and '.rel.eh_frame'.
>>>
>>> The BPF ELF loader library libbpf fails when loading files with these
>>> sections.  The other in-kernel BPF ELF loader in samples/bpf/bpf_load.c,
>>> handle this gracefully. And iproute2 loader also seems to work with these
>>> "eh" sections.
>>>
>>> The issue in libbpf is caused by bpf_object__elf_collect() skip the
>>> '.eh_frame' and thus doesn't create an internal data structure
>>> pointing to this ELF section index.  Later when the relocation section
>>> '.rel.eh_frame' is processed, it tries to find the '.eh_frame' via the
>>> ELF section idx, which is that fails (in bpf_object__collect_reloc).
>>>
>>> I couldn't find a way to see that the '.rel.eh_frame' was irrelevant
>>> (that is only determined by looking at the section it reference, which
>>> we no longer have info available on).  
>>
>> but does this approach work for all extra sections and relocations emitted
>> when source is compiled with -g ?
> 
> No, but I plan to follow up and do a more complete solution later. This
> is a workaround to get the Suricata use-case working and also that
> samples/bpf/ can be loaded.

Aside from a needed fix in any case, is there a specifc reason why Suricata
cannot rely on 'clang -target bpf'? Is it asm inline headers in your case?

>> To address this case bpf_load.c does:
>>   if (shdr.sh_type == SHT_REL) {
>>           struct bpf_insn *insns;
>>
>>           /* locate prog sec that need map fixup (relocations) */
>>           if (get_sec(elf, shdr.sh_info, &ehdr, &shname_prog,
>>                       &shdr_prog, &data_prog))
>>                   continue;
>>
>>           if (shdr_prog.sh_type != SHT_PROGBITS ||
>>               !(shdr_prog.sh_flags & SHF_EXECINSTR))
>>                   continue;
>>
>> why the same approach is not applicable here?
> 
> As described above bpf_object__elf_collect() skip the "real" section
> that the relo-section want to lookup (based on the same kind of
> check), but libbpf is now missing the section idx in its internal
> structures... and thus the relo lookup of the idx fails. (bpf_load.c
> does the lookup in the ELF obj directly, thus it does not have this
> problem).

Out of curiosity, I just double checked iproute2 loader (examples/bpf/):

$ clang -O2 -g -emit-llvm -c bpf_cyclic.c -o - | llc -march=bpf -mcpu=probe -filetype=obj -o bpf_cyclic.o
$ readelf -a bpf_cyclic.o | grep "\["
  [Nr] Name              Type             Address           Offset
  [ 0]                   NULL             0000000000000000  00000000
  [ 1] .strtab           STRTAB           0000000000000000  000016b0
  [ 2] .text             PROGBITS         0000000000000000  00000040
  [ 3] 0xabccba/0        PROGBITS         0000000000000000  00000040
  [ 4] .rel0xabccba/0    REL              0000000000000000  00001120
  [ 5] classifier        PROGBITS         0000000000000000  000000e8
  [ 6] .relclassifier    REL              0000000000000000  00001130
  [ 7] maps              PROGBITS         0000000000000000  00000118
  [ 8] license           PROGBITS         0000000000000000  0000013c
  [ 9] .debug_str        PROGBITS         0000000000000000  00000140
  [10] .debug_loc        PROGBITS         0000000000000000  000003d5
  [11] .rel.debug_loc    REL              0000000000000000  00001140
  [12] .debug_abbrev     PROGBITS         0000000000000000  0000045a
  [13] .debug_info       PROGBITS         0000000000000000  0000055c
  [14] .rel.debug_info   REL              0000000000000000  000011c0
  [15] .debug_ranges     PROGBITS         0000000000000000  0000088c
  [16] .rel.debug_ranges REL              0000000000000000  000015d0
  [17] .debug_macinfo    PROGBITS         0000000000000000  000008ec
  [18] .debug_pubnames   PROGBITS         0000000000000000  000008ed
  [19] .rel.debug_pubnam REL              0000000000000000  00001650
  [20] .debug_pubtypes   PROGBITS         0000000000000000  00000954
  [21] .rel.debug_pubtyp REL              0000000000000000  00001660
  [22] .eh_frame         PROGBITS         0000000000000000  000009c0
  [23] .rel.eh_frame     REL              0000000000000000  00001670
  [24] .debug_line       PROGBITS         0000000000000000  00000a10
  [25] .rel.debug_line   REL              0000000000000000  00001690
  [26] .symtab           SYMTAB           0000000000000000  00000b08
# tc qdisc add dev lo clsact
# tc filter add dev lo ingress bpf da obj bpf_cyclic.o
# tc filter show dev lo ingress
filter protocol all pref 49152 bpf chain 0
filter protocol all pref 49152 bpf chain 0 handle 0x1 bpf_cyclic.o:[classifier] direct-action not_in_hw id 6 tag 736a8a004dead229

So no problems. What it does internally is pretty similar to what Alexei
described; for programs, they need to have ELF section header type of
SHT_PROGBITS and section header flags must match on SHF_EXECINSTR in
the relocation parsing.

Now, picking out two, and looking at the flags:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
[...]
  [ 5] classifier        PROGBITS         0000000000000000  000000e8
       0000000000000030  0000000000000000  AX       0     0     8
[...]
  [22] .eh_frame         PROGBITS         0000000000000000  000009c0
       0000000000000050  0000000000000000   A       0     0     8
[...]
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

So .eh_frame doesn't even have SHF_EXECINSTR set. Why it cannot test on
this? Doing strcmp(name, ".rel.eh_frame") == 0 test is indeed a bit
fragile in the sense that we would also need to strcmp() all the others
listed above since libbpf could trip over them just as well. When you
check the SHT_REL sections, the target section index sits in GElf_Shdr's
.sh_info, so the only thing that would need to be done in this case is
to look up the ELF section header with index from .sh_info, get the
GElf_Shdr section header and check for a match on SHT_PROGBITS/SHF_EXECINSTR,
otherwise skip that SHT_REL section. A direct lookup of the index in
the obj would not require any complex section/index tracking or larger
rework in libbpf, hmm, what am I missing?

>> I guess we can apply this workaround as-is but it looks incomplete.
> 
> Yes, it is a workaround to move forward... it requires a larger change
> to libbpf, so it stores idx'es of skipped sections.

Thanks,
Daniel
Jesper Dangaard Brouer Feb. 7, 2018, 12:40 p.m. UTC | #4
On Tue, 6 Feb 2018 20:05:43 +0100 Daniel Borkmann <daniel@iogearbox.net> wrote:

> On 02/06/2018 06:03 PM, Jesper Dangaard Brouer wrote:
[...]
> > [...] I plan to follow up and do a more complete solution later. This
> > is a workaround to get the Suricata use-case working and also that
> > samples/bpf/ can be loaded.  
> 
> Aside from a needed fix in any case, is there a specifc reason why Suricata
> cannot rely on 'clang -target bpf'? Is it asm inline headers in your case?

Below is the error I get when using 'clang' with '-target bpf'

$ dirs
~/git/suricata/src/ebpf

$ clang -Wall -Iinclude -O2 -D__KERNEL__  -target bpf -emit-llvm -c xdp_filter.c -o - | llc -march=bpf -filetype=obj -o xdp_filter.bpf
In file included from xdp_filter.c:19:
In file included from /usr/bin/../lib64/clang/4.0.1/include/stdint.h:63:
In file included from /usr/include/stdint.h:26:
In file included from /usr/include/bits/libc-header-start.h:33:
In file included from /usr/include/features.h:434:
/usr/include/gnu/stubs.h:7:11: fatal error: 'gnu/stubs-32.h' file not found
# include <gnu/stubs-32.h>
          ^~~~~~~~~~~~~~~~

I'll leave it up to Eric Leblond to figure out that he need to change
in the eBPF programs to make it compile with '-target bpf'.  Maybe you
can offer him some guidance here?

Direct link to code:
 https://github.com/OISF/suricata/blob/master/ebpf/xdp_filter.c
Daniel Borkmann Feb. 7, 2018, 1:19 p.m. UTC | #5
On 02/07/2018 01:40 PM, Jesper Dangaard Brouer wrote:
> On Tue, 6 Feb 2018 20:05:43 +0100 Daniel Borkmann <daniel@iogearbox.net> wrote:
>> On 02/06/2018 06:03 PM, Jesper Dangaard Brouer wrote:
> [...]
>>> [...] I plan to follow up and do a more complete solution later. This
>>> is a workaround to get the Suricata use-case working and also that
>>> samples/bpf/ can be loaded.  
>>
>> Aside from a needed fix in any case, is there a specifc reason why Suricata
>> cannot rely on 'clang -target bpf'? Is it asm inline headers in your case?
> 
> Below is the error I get when using 'clang' with '-target bpf'
> 
> $ dirs
> ~/git/suricata/src/ebpf
> 
> $ clang -Wall -Iinclude -O2 -D__KERNEL__  -target bpf -emit-llvm -c xdp_filter.c -o - | llc -march=bpf -filetype=obj -o xdp_filter.bpf
> In file included from xdp_filter.c:19:
> In file included from /usr/bin/../lib64/clang/4.0.1/include/stdint.h:63:
> In file included from /usr/include/stdint.h:26:
> In file included from /usr/include/bits/libc-header-start.h:33:
> In file included from /usr/include/features.h:434:
> /usr/include/gnu/stubs.h:7:11: fatal error: 'gnu/stubs-32.h' file not found
> # include <gnu/stubs-32.h>
>           ^~~~~~~~~~~~~~~~
> 
> I'll leave it up to Eric Leblond to figure out that he need to change
> in the eBPF programs to make it compile with '-target bpf'.  Maybe you
> can offer him some guidance here?
> 
> Direct link to code:
>  https://github.com/OISF/suricata/blob/master/ebpf/xdp_filter.c

Sure, you just need glibc-devel.i686, see:

$ clang -Wall -Iinclude -O2 -D__KERNEL__ -target bpf -emit-llvm -c xdp_filter.c -o - | llc -march=bpf -filetype=obj -o xdp_filter.bpf
  In file included from xdp_filter.c:19:
  In file included from /home/darkstar/llvm/build/lib/clang/7.0.0/include/stdint.h:63:
  In file included from /usr/include/stdint.h:25:
  In file included from /usr/include/features.h:392:
  /usr/include/gnu/stubs.h:7:11: fatal error: 'gnu/stubs-32.h' file not found
  # include <gnu/stubs-32.h>
            ^~~~~~~~~~~~~~~~
  1 error generated.
# yum install glibc-devel.i686
  [...]
$ clang -Wall -Iinclude -O2 -D__KERNEL__ -target bpf -emit-llvm -c xdp_filter.c -o - | llc -march=bpf -filetype=obj -o xdp_filter.bpf
$

Alternatively, you could do something like done in selftests to provide a
dummy, see commit 1c2dd16add7e ("selftests/bpf: get rid of -D__x86_64__").

Cheers,
Daniel
Jesper Dangaard Brouer Feb. 7, 2018, 2:58 p.m. UTC | #6
On Wed, 7 Feb 2018 14:19:00 +0100
Daniel Borkmann <daniel@iogearbox.net> wrote:

> On 02/07/2018 01:40 PM, Jesper Dangaard Brouer wrote:
> > On Tue, 6 Feb 2018 20:05:43 +0100 Daniel Borkmann <daniel@iogearbox.net> wrote:  
> >> On 02/06/2018 06:03 PM, Jesper Dangaard Brouer wrote:  
> > [...]  
> >>> [...] I plan to follow up and do a more complete solution later. This
> >>> is a workaround to get the Suricata use-case working and also that
> >>> samples/bpf/ can be loaded.    
> >>
> >> Aside from a needed fix in any case, is there a specifc reason why Suricata
> >> cannot rely on 'clang -target bpf'? Is it asm inline headers in your case?  
> > 
> > Below is the error I get when using 'clang' with '-target bpf'
> > 
> > $ dirs
> > ~/git/suricata/src/ebpf
> > 
> > $ clang -Wall -Iinclude -O2 -D__KERNEL__  -target bpf -emit-llvm -c xdp_filter.c -o - | llc -march=bpf -filetype=obj -o xdp_filter.bpf
> > In file included from xdp_filter.c:19:
> > In file included from /usr/bin/../lib64/clang/4.0.1/include/stdint.h:63:
> > In file included from /usr/include/stdint.h:26:
> > In file included from /usr/include/bits/libc-header-start.h:33:
> > In file included from /usr/include/features.h:434:
> > /usr/include/gnu/stubs.h:7:11: fatal error: 'gnu/stubs-32.h' file not found
> > # include <gnu/stubs-32.h>
> >           ^~~~~~~~~~~~~~~~
> > 
> > I'll leave it up to Eric Leblond to figure out that he need to change
> > in the eBPF programs to make it compile with '-target bpf'.  Maybe you
> > can offer him some guidance here?
> > 
> > Direct link to code:
> >  https://github.com/OISF/suricata/blob/master/ebpf/xdp_filter.c  
> 
> Sure, you just need glibc-devel.i686, see:
> 
> $ clang -Wall -Iinclude -O2 -D__KERNEL__ -target bpf -emit-llvm -c xdp_filter.c -o - | llc -march=bpf -filetype=obj -o xdp_filter.bpf
>   In file included from xdp_filter.c:19:
>   In file included from /home/darkstar/llvm/build/lib/clang/7.0.0/include/stdint.h:63:
>   In file included from /usr/include/stdint.h:25:
>   In file included from /usr/include/features.h:392:
>   /usr/include/gnu/stubs.h:7:11: fatal error: 'gnu/stubs-32.h' file not found
>   # include <gnu/stubs-32.h>
>             ^~~~~~~~~~~~~~~~
>   1 error generated.
> # yum install glibc-devel.i686
>   [...]
> $ clang -Wall -Iinclude -O2 -D__KERNEL__ -target bpf -emit-llvm -c xdp_filter.c -o - | llc -march=bpf -filetype=obj -o xdp_filter.bpf

> $

Could you please explain why if makes a difference to install glibc-devel.i686 ?


How will people compiling suricata figure out the new dependency, that
on their 64-bit (x86_64) distro's they also need to install the 32-bit
(i686) variant of glibc-devel ?

> Alternatively, you could do something like done in selftests to provide a
> dummy, see commit 1c2dd16add7e ("selftests/bpf: get rid of -D__x86_64__").

That is a funny way to workaround the problem (having an empty
<gnu/stubs.h> file in include path), but it might be a better solution
to avoid frustrations for people compiling suricata.


An alternative solution is to NOT:
 #include <stdint.h>
 #include <string.h>

And then change:
 uint64_t -> __u64
 uint32_t -> __u32
 uint16_t -> __u16
 uint8_t  -> __u8
Daniel Borkmann Feb. 7, 2018, 4:18 p.m. UTC | #7
On 02/07/2018 03:58 PM, Jesper Dangaard Brouer wrote:
> On Wed, 7 Feb 2018 14:19:00 +0100
> Daniel Borkmann <daniel@iogearbox.net> wrote:
>> On 02/07/2018 01:40 PM, Jesper Dangaard Brouer wrote:
>>> On Tue, 6 Feb 2018 20:05:43 +0100 Daniel Borkmann <daniel@iogearbox.net> wrote:  
>>>> On 02/06/2018 06:03 PM, Jesper Dangaard Brouer wrote:  
>>> [...]  
>>>>> [...] I plan to follow up and do a more complete solution later. This
>>>>> is a workaround to get the Suricata use-case working and also that
>>>>> samples/bpf/ can be loaded.    
>>>>
>>>> Aside from a needed fix in any case, is there a specifc reason why Suricata
>>>> cannot rely on 'clang -target bpf'? Is it asm inline headers in your case?  
>>>
>>> Below is the error I get when using 'clang' with '-target bpf'
>>>
>>> $ dirs
>>> ~/git/suricata/src/ebpf
>>>
>>> $ clang -Wall -Iinclude -O2 -D__KERNEL__  -target bpf -emit-llvm -c xdp_filter.c -o - | llc -march=bpf -filetype=obj -o xdp_filter.bpf
>>> In file included from xdp_filter.c:19:
>>> In file included from /usr/bin/../lib64/clang/4.0.1/include/stdint.h:63:
>>> In file included from /usr/include/stdint.h:26:
>>> In file included from /usr/include/bits/libc-header-start.h:33:
>>> In file included from /usr/include/features.h:434:
>>> /usr/include/gnu/stubs.h:7:11: fatal error: 'gnu/stubs-32.h' file not found
>>> # include <gnu/stubs-32.h>
>>>           ^~~~~~~~~~~~~~~~
>>>
>>> I'll leave it up to Eric Leblond to figure out that he need to change
>>> in the eBPF programs to make it compile with '-target bpf'.  Maybe you
>>> can offer him some guidance here?
>>>
>>> Direct link to code:
>>>  https://github.com/OISF/suricata/blob/master/ebpf/xdp_filter.c  
>>
>> Sure, you just need glibc-devel.i686, see:
>>
>> $ clang -Wall -Iinclude -O2 -D__KERNEL__ -target bpf -emit-llvm -c xdp_filter.c -o - | llc -march=bpf -filetype=obj -o xdp_filter.bpf
>>   In file included from xdp_filter.c:19:
>>   In file included from /home/darkstar/llvm/build/lib/clang/7.0.0/include/stdint.h:63:
>>   In file included from /usr/include/stdint.h:25:
>>   In file included from /usr/include/features.h:392:
>>   /usr/include/gnu/stubs.h:7:11: fatal error: 'gnu/stubs-32.h' file not found
>>   # include <gnu/stubs-32.h>
>>             ^~~~~~~~~~~~~~~~
>>   1 error generated.
>> # yum install glibc-devel.i686
>>   [...]
>> $ clang -Wall -Iinclude -O2 -D__KERNEL__ -target bpf -emit-llvm -c xdp_filter.c -o - | llc -march=bpf -filetype=obj -o xdp_filter.bpf
> 
>> $
> 
> Could you please explain why if makes a difference to install glibc-devel.i686 ?

Well, see what /usr/include/gnu/stubs.h is doing, on x86_64 it's:

  #if !defined __x86_64__
  # include <gnu/stubs-32.h>
  #endif
  #if defined __x86_64__ && defined __LP64__
  # include <gnu/stubs-64.h>
  #endif
  #if defined __x86_64__ && defined __ILP32__
  # include <gnu/stubs-x32.h>
  #endif

If you do clang -target bpf, then clang will have '__bpf__' defined instead
of '__x86_64__' hence the gnu/stubs-32.h include attempt, and the workaround
used in selftests with -D__x86_64__. But the -D__x86_64__ is not portable, so
yeah, either dummy stubs if you need to include the headers or also other the
workaround you mention below.

[...]
>> Alternatively, you could do something like done in selftests to provide a
>> dummy, see commit 1c2dd16add7e ("selftests/bpf: get rid of -D__x86_64__").
> 
> That is a funny way to workaround the problem (having an empty
> <gnu/stubs.h> file in include path), but it might be a better solution
> to avoid frustrations for people compiling suricata.
> 
> An alternative solution is to NOT:
>  #include <stdint.h>
>  #include <string.h>
> 
> And then change:
>  uint64_t -> __u64
>  uint32_t -> __u32
>  uint16_t -> __u16
>  uint8_t  -> __u8
diff mbox series

Patch

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index b4eeaa3ebff5..84e8bbe07347 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -822,6 +822,13 @@  static int bpf_object__elf_collect(struct bpf_object *obj)
 			void *reloc = obj->efile.reloc;
 			int nr_reloc = obj->efile.nr_reloc + 1;
 
+			/* Skip decoding of "eh" exception frames */
+			if (strcmp(name, ".rel.eh_frame") == 0) {
+				pr_debug("skip relo section %s(%d) for section(%d)\n",
+					 name, idx, sh.sh_info);
+				continue;
+			}
+
 			reloc = realloc(reloc,
 					sizeof(*obj->efile.reloc) * nr_reloc);
 			if (!reloc) {