On Mon, 6 Mar 2017 16:14:06 -0800
Alexei Starovoitov via iovisor-dev <[email protected]> wrote:

> On Mon, Mar 6, 2017 at 10:29 AM, Jesper Dangaard Brouer
> <[email protected]> wrote:
> > On Mon, 6 Mar 2017 09:11:46 -0800
> > Alexei Starovoitov via iovisor-dev <[email protected]> wrote:
> >  
> >> On Mon, Mar 6, 2017 at 3:53 AM, Jesper Dangaard Brouer
> >> <[email protected]> wrote:  
> >> > Hi All,
> >> >
> >> > I've added a section to my eBPF documentation, about how to read the
> >> > eBPF generated ELF binary, and deduct the size of the compiled program
> >> > (mostly for kernel/samples/bpf).
> >> >
> >> > https://prototype-kernel.readthedocs.io/en/latest/bpf/troubleshooting.html#elf-binary
> >> > https://github.com/netoptimizer/prototype-kernel/commit/079352102cb0ba
> >> >
> >> > Can someone validate what I've saying is true? (commit inlined below
> >> > sign, to make is as easy as possible for people to correct me).
> >> >
> >> > And anything else users can use the readelf output for?
> >> >
> >> > --
> >> > Best regards,
> >> >   Jesper Dangaard Brouer
> >> >   MSc.CS, Principal Kernel Engineer at Red Hat
> >> >   LinkedIn: http://www.linkedin.com/in/brouer
> >> >
> >> > commit 079352102cb0ba12141ecd28c216ec5ac5290192
> >> > Author: Jesper Dangaard Brouer <[email protected]>
> >> > Date:   Fri Feb 24 12:10:45 2017 +0100
> >> >
> >> >     doc: eBPF describe howto read the eBPF generated ELF binary
> >> >
> >> >     Signed-off-by: Jesper Dangaard Brouer <[email protected]>
> >> >
> >> > diff --git a/kernel/Documentation/bpf/troubleshooting.rst 
> >> > b/kernel/Documentation/bpf/troubleshooting.rst
> >> > index b6f3b6fe9501..39ebffae4142 100644
> >> > --- a/kernel/Documentation/bpf/troubleshooting.rst
> >> > +++ b/kernel/Documentation/bpf/troubleshooting.rst
> >> > @@ -15,6 +15,41 @@ see system call `setrlimit(2)`_.
> >> >  The ``bpf_create_map`` call will return errno EPERM (Operation not
> >> >  permitted) when the RLIMIT_MEMLOCK memory size limit is exceeded.
> >> >
> >> > -
> >> >  .. _setrlimit(2): http://man7.org/linux/man-pages/man2/setrlimit.2.html
> >> >
> >> > +ELF binary
> >> > +==========
> >> > +
> >> > +The binary containing the eBPF program, which got generated by the
> >> > +LLVM compiler, is an ELF binary.  For samples/bpf/ this is the file
> >> > +named xxx_kern.o.
> >> > +
> >> > +To answer questions like how big is my eBPF program, it is possible to
> >> > +use a tool like ``readelf``. ::
> >> > +
> >> > + $ readelf -SW xdp_ddos01_blacklist_kern.o
> >> > + There are 8 section headers, starting at offset 0x398:
> >> > +
> >> > + 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 000320 000072 00      
> >> > 0   0  1
> >> > +  [ 2] .text          PROGBITS   0000000000000000 000040 000000 00  AX  
> >> > 0   0  4
> >> > +  [ 3] xdp_prog       PROGBITS   0000000000000000 000040 0001b8 00  AX  
> >> > 0   0  8
> >> > +  [ 4] .relxdp_prog   REL        0000000000000000 000300 000020 10      
> >> > 7   3  8
> >> > +  [ 5] maps           PROGBITS   0000000000000000 0001f8 000028 00  WA  
> >> > 0   0  4
> >> > +  [ 6] license        PROGBITS   0000000000000000 000220 000004 00  WA  
> >> > 0   0  1
> >> > +  [ 7] .symtab        SYMTAB     0000000000000000 000228 0000d8 18      
> >> > 1   5  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)
> >> > +
> >> > +From the output, we can see the programmer choose to name the XDP
> >> > +program section "xdp_prog".  From this line ([ 3]) the size column
> >> > +shows the size 0001b8 in hex, which is easily converted on the cmdline
> >> > +to 440 bytes::
> >> > +
> >> > + $ echo $((0x0001b8))
> >> > + 440  
> >>
> >> hmm. i think instead of clarifying bpf elf output is doing the opposite.
> >> at least i'm completely lost in the above text.
> >> What all of the above suppose to mean?  
> >
> > That what I'm implicit asking you ;-)
> >  
> >> why is it useful to do readelf? and look at hex ?  
> >
> > What other tools exists to help me understand the contents of the LLVM
> > compiled binary _kern.o ?  
> 
> The best is to use
> llvm-objdump -S prog_kern.o

Hmmm, what version of LLVM have the -S option?

$ llvm-objdump -S xdp_ddos01_blacklist_kern.o
llvm-objdump: Unknown command line argument '-S'.  Try: 'llvm-objdump -help'
llvm-objdump: Did you mean '-D'?

$ llvm-objdump --version | egrep 'version|bpf'
  LLVM version 3.8.1
    bpf        - BPF (host endian)
    bpfeb      - BPF (big endian)
    bpfel      - BPF (little endian)

I would really like some command tool, to inspect eBPF-ELF program
with, available in a distro version, in this case Fedora 25.


> it will show section names, asm code and original C code
> if compiled with -g

And the option -g is supplied to the CLANG program (not LLC).


> It's important to mention that .o is a normal elf file,
> but the doc doesn't need to go into elf details.

Okay.


> > Is there an easier way to answer my question:
> > Q: how big is my eBPF program?  
> 
> in llvm-objdump output you'll see something like:
>      139:    85 00 00 00 01 00 00 00     call 1
>      140:    b7 00 00 00 00 00 00 00     r0 = 0
>      141:    95 00 00 00 00 00 00 00     exit
> 
> so this particular program has 141 instructions.
> 
> > I would actually (also) like to know the size of the JIT'ed asm code?  
> 
> that's practically impossible to know in advance, since hardening and
> start address randomization will play a role.
> Or use sysctl net.core.bpf_jit_enable=2
> at load time which gives raw x86 hex.

The sysctl adjusting sounds interesting:

 sysctl net.core.bpf_jit_enable=2

What is below "proglen=335" the JIT'ed asm-code size?

flen=55 proglen=335 pass=4 image=ffffffffa0006820 from=xdp_ddos01_blac pid=13333
JIT code: 00000000: 55 48 89 e5 48 81 ec 28 02 00 00 48 89 9d d8 fd
JIT code: 00000010: ff ff 4c 89 ad e0 fd ff ff 4c 89 b5 e8 fd ff ff
JIT code: 00000020: 4c 89 bd f0 fd ff ff 31 c0 48 89 85 f8 fd ff ff
JIT code: 00000030: bb 02 00 00 00 48 8b 77 08 48 8b 7f 00 48 89 fa
JIT code: 00000040: 48 83 c2 0e 48 39 f2 0f 87 e1 00 00 00 48 0f b6
JIT code: 00000050: 4f 0c 48 0f b6 57 0d 48 c1 e2 08 48 09 ca 48 89
JIT code: 00000060: d1 48 81 e1 ff 00 00 00 41 b8 06 00 00 00 49 39
JIT code: 00000070: c8 0f 87 b7 00 00 00 48 81 fa 88 a8 00 00 74 0e
JIT code: 00000080: b9 0e 00 00 00 48 81 fa 81 00 00 00 75 1a 48 89
JIT code: 00000090: fa 48 83 c2 12 48 39 f2 0f 87 90 00 00 00 b9 12
JIT code: 000000a0: 00 00 00 48 0f b7 57 10 bb 02 00 00 00 48 81 e2
JIT code: 000000b0: ff ff 00 00 48 83 fa 08 75 49 48 01 cf 31 db 48
JIT code: 000000c0: 89 fa 48 83 c2 14 48 39 f2 77 38 8b 7f 0c 89 7d
JIT code: 000000d0: fc 48 89 ee 48 83 c6 fc 48 bf 00 9c 24 5f 07 88
JIT code: 000000e0: ff ff e8 29 cd 13 e1 bb 02 00 00 00 48 83 f8 00
JIT code: 000000f0: 74 11 48 8b 78 00 48 83 c7 01 48 89 78 00 bb 01
JIT code: 00000100: 00 00 00 89 5d f8 48 89 ee 48 83 c6 f8 48 bf c0
JIT code: 00000110: 76 12 13 04 88 ff ff e8 f4 cc 13 e1 48 83 f8 00
JIT code: 00000120: 74 0c 48 8b 78 00 48 83 c7 01 48 89 78 00 48 89
JIT code: 00000130: d8 48 8b 9d d8 fd ff ff 4c 8b ad e0 fd ff ff 4c
JIT code: 00000140: 8b b5 e8 fd ff ff 4c 8b bd f0 fd ff ff c9 c3

$ echo $((0x140))
320
$ echo $((0x140 + 15))
335

Using same example code, thus BPF instructions-size was 440 bytes, so
the JIT'ed code size does get smaller.

-- 
Best regards,
  Jesper Dangaard Brouer
  MSc.CS, Principal Kernel Engineer at Red Hat
  LinkedIn: http://www.linkedin.com/in/brouer



_______________________________________________
iovisor-dev mailing list
[email protected]
https://lists.iovisor.org/mailman/listinfo/iovisor-dev

Reply via email to