• Andrii Nakryiko's avatar
    libbpf: Add BPF-side of USDT support · d72e2968
    Andrii Nakryiko authored
    Add BPF-side implementation of libbpf-provided USDT support. This
    consists of single header library, usdt.bpf.h, which is meant to be used
    from user's BPF-side source code. This header is added to the list of
    installed libbpf header, along bpf_helpers.h and others.
    
    BPF-side implementation consists of two BPF maps:
      - spec map, which contains "a USDT spec" which encodes information
        necessary to be able to fetch USDT arguments and other information
        (argument count, user-provided cookie value, etc) at runtime;
      - IP-to-spec-ID map, which is only used on kernels that don't support
        BPF cookie feature. It allows to lookup spec ID based on the place
        in user application that triggers USDT program.
    
    These maps have default sizes, 256 and 1024, which are chosen
    conservatively to not waste a lot of space, but handling a lot of common
    cases. But there could be cases when user application needs to either
    trace a lot of different USDTs, or USDTs are heavily inlined and their
    arguments are located in a lot of differing locations. For such cases it
    might be necessary to size those maps up, which libbpf allows to do by
    overriding BPF_USDT_MAX_SPEC_CNT and BPF_USDT_MAX_IP_CNT macros.
    
    It is an important aspect to keep in mind. Single USDT (user-space
    equivalent of kernel tracepoint) can have multiple USDT "call sites".
    That is, single logical USDT is triggered from multiple places in user
    application. This can happen due to function inlining. Each such inlined
    instance of USDT invocation can have its own unique USDT argument
    specification (instructions about the location of the value of each of
    USDT arguments). So while USDT looks very similar to usual uprobe or
    kernel tracepoint, under the hood it's actually a collection of uprobes,
    each potentially needing different spec to know how to fetch arguments.
    
    User-visible API consists of three helper functions:
      - bpf_usdt_arg_cnt(), which returns number of arguments of current USDT;
      - bpf_usdt_arg(), which reads value of specified USDT argument (by
        it's zero-indexed position) and returns it as 64-bit value;
      - bpf_usdt_cookie(), which functions like BPF cookie for USDT
        programs; this is necessary as libbpf doesn't allow specifying actual
        BPF cookie and utilizes it internally for USDT support implementation.
    
    Each bpf_usdt_xxx() APIs expect struct pt_regs * context, passed into
    BPF program. On kernels that don't support BPF cookie it is used to
    fetch absolute IP address of the underlying uprobe.
    
    usdt.bpf.h also provides BPF_USDT() macro, which functions like
    BPF_PROG() and BPF_KPROBE() and allows much more user-friendly way to
    get access to USDT arguments, if USDT definition is static and known to
    the user. It is expected that majority of use cases won't have to use
    bpf_usdt_arg_cnt() and bpf_usdt_arg() directly and BPF_USDT() will cover
    all their needs.
    
    Last, usdt.bpf.h is utilizing BPF CO-RE for one single purpose: to
    detect kernel support for BPF cookie. If BPF CO-RE dependency is
    undesirable, user application can redefine BPF_USDT_HAS_BPF_COOKIE to
    either a boolean constant (or equivalently zero and non-zero), or even
    point it to its own .rodata variable that can be specified from user's
    application user-space code. It is important that
    BPF_USDT_HAS_BPF_COOKIE is known to BPF verifier as static value (thus
    .rodata and not just .data), as otherwise BPF code will still contain
    bpf_get_attach_cookie() BPF helper call and will fail validation at
    runtime, if not dead-code eliminated.
    Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
    Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    Reviewed-by: default avatarAlan Maguire <alan.maguire@oracle.com>
    Link: https://lore.kernel.org/bpf/20220404234202.331384-2-andrii@kernel.org
    d72e2968
Makefile 9.74 KB