LCOV - code coverage report
Current view: top level - core - btf.c (source / functions) Coverage Total Hit
Test: lcov.out Lines: 47.1 % 51 24
Test Date: 2025-05-09 22:39:08 Functions: 50.0 % 6 3

            Line data    Source code
       1              : // SPDX-License-Identifier: GPL-2.0-only
       2              : /*
       3              :  * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
       4              :  */
       5              : 
       6              : #include "core/btf.h"
       7              : 
       8              : #include <linux/btf.h>
       9              : 
      10              : #include <bpf/btf.h>
      11              : #include <errno.h>
      12              : #include <limits.h>
      13              : #include <stddef.h>
      14              : #include <stdlib.h>
      15              : 
      16              : #include "core/helper.h"
      17              : #include "core/logger.h"
      18              : 
      19              : static struct btf *_bf_btf = NULL;
      20              : 
      21            3 : int bf_btf_setup(void)
      22              : {
      23            3 :     _bf_btf = btf__load_vmlinux_btf();
      24            3 :     if (!_bf_btf)
      25            1 :         return bf_err_r(errno, "failed to load vmlinux BTF");
      26              : 
      27              :     return 0;
      28              : }
      29              : 
      30            2 : void bf_btf_teardown(void)
      31              : {
      32            2 :     btf__free(_bf_btf);
      33            2 :     _bf_btf = NULL;
      34            2 : }
      35              : 
      36            0 : int bf_btf_get_id(const char *name)
      37              : {
      38              :     int id;
      39              : 
      40            0 :     bf_assert(name);
      41              : 
      42            0 :     id = btf__find_by_name(_bf_btf, name);
      43            0 :     if (id < 0)
      44            0 :         return bf_err_r(errno, "failed to find BTF type for \"%s\"", name);
      45              : 
      46              :     return id;
      47              : }
      48              : 
      49            0 : const char *bf_btf_get_name(int id)
      50              : {
      51              :     const struct btf_type *type;
      52              : 
      53            0 :     type = btf__type_by_id(_bf_btf, id);
      54            0 :     if (!type) {
      55            0 :         bf_warn("can't find BTF type ID %d", id);
      56            0 :         return NULL;
      57              :     }
      58              : 
      59            0 :     return btf__name_by_offset(_bf_btf, type->name_off);
      60              : }
      61              : 
      62            0 : int bf_btf_kernel_has_token(void)
      63              : {
      64              :     int bpf_attr_id;
      65              :     const struct btf_type *bpf_attr_type;
      66              :     const struct btf_member *bpf_attr_members;
      67              : 
      68            0 :     bpf_attr_id = btf__find_by_name_kind(_bf_btf, "bpf_attr", BTF_KIND_UNION);
      69            0 :     if (bpf_attr_id < 0) {
      70            0 :         return bf_err_r(bpf_attr_id,
      71              :                         "can't find structure 'bpf_attr' in kernel BTF");
      72              :     }
      73              : 
      74            0 :     bpf_attr_type = btf__type_by_id(_bf_btf, bpf_attr_id);
      75            0 :     if (!bpf_attr_type)
      76            0 :         return bf_err_r(-EINVAL, "failed to request 'bpf_attr' BTF type");
      77              : 
      78              :     bpf_attr_members = btf_members(bpf_attr_type);
      79              :     // Iterate through union members
      80            0 :     for (unsigned short i = 0; i < btf_vlen(bpf_attr_type); i++) {
      81              :         const struct btf_type *member_type =
      82            0 :             btf__type_by_id(_bf_btf, bpf_attr_members[i].type);
      83              :         const struct btf_member *m_members = btf_members(member_type);
      84              : 
      85              :         // We are looking for an anonymous structure
      86            0 :         if (!btf_is_struct(member_type) || bpf_attr_members[i].name_off != 0)
      87            0 :             continue;
      88              : 
      89            0 :         for (int j = 0; j < btf_vlen(member_type); j++) {
      90              :             const char *member_name =
      91            0 :                 btf__name_by_offset(_bf_btf, m_members[j].name_off);
      92              : 
      93            0 :             if (member_name && bf_streq(member_name, "prog_token_fd"))
      94              :                 return 0;
      95              :         }
      96              :     }
      97              : 
      98              :     return -ENOENT;
      99              : }
     100              : 
     101            6 : int bf_btf_get_field_off(const char *struct_name, const char *field_name)
     102              : {
     103              :     int offset = -1;
     104              :     int struct_id;
     105              :     struct btf_member *member;
     106              :     const struct btf_type *type;
     107              : 
     108            6 :     struct_id = btf__find_by_name_kind(_bf_btf, struct_name, BTF_KIND_STRUCT);
     109            6 :     if (struct_id < 0) {
     110            2 :         return bf_err_r(struct_id, "can't find structure '%s' in kernel BTF",
     111              :                         struct_name);
     112              :     }
     113              : 
     114            4 :     type = btf__type_by_id(_bf_btf, struct_id);
     115            4 :     if (!type)
     116            0 :         return bf_err_r(errno, "can't get btf_type for '%s'", struct_name);
     117              : 
     118            4 :     member = (struct btf_member *)(type + 1);
     119           22 :     for (size_t i = 0; i < BTF_INFO_VLEN(type->info); ++i, ++member) {
     120           21 :         const char *cur_name = btf__name_by_offset(_bf_btf, member->name_off);
     121           21 :         if (!cur_name || !bf_streq(cur_name, field_name))
     122              :             continue;
     123              : 
     124            3 :         if (BTF_INFO_KFLAG(type->info)) {
     125            2 :             offset = BTF_MEMBER_BIT_OFFSET(member->offset);
     126              :         } else {
     127            1 :             if (member->offset > INT_MAX) {
     128            0 :                 return bf_err_r(-E2BIG, "BTF member offset is too big: %u",
     129              :                                 member->offset);
     130              :             }
     131              :             offset = (int)member->offset;
     132              :         }
     133              : 
     134              :         break;
     135              :     }
     136              : 
     137            4 :     if (offset < 0 || offset % 8)
     138            1 :         return -ENOENT;
     139              : 
     140            3 :     return offset / 8;
     141              : }
        

Generated by: LCOV version 2.0-1