root/tools/lib/bpf/bpf_prog_linfo.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dissect_jited_func
  2. bpf_prog_linfo__free
  3. bpf_prog_linfo__new
  4. bpf_prog_linfo__lfind_addr_func
  5. bpf_prog_linfo__lfind

   1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
   2 /* Copyright (c) 2018 Facebook */
   3 
   4 #include <string.h>
   5 #include <stdlib.h>
   6 #include <linux/err.h>
   7 #include <linux/bpf.h>
   8 #include "libbpf.h"
   9 #include "libbpf_internal.h"
  10 
  11 struct bpf_prog_linfo {
  12         void *raw_linfo;
  13         void *raw_jited_linfo;
  14         __u32 *nr_jited_linfo_per_func;
  15         __u32 *jited_linfo_func_idx;
  16         __u32 nr_linfo;
  17         __u32 nr_jited_func;
  18         __u32 rec_size;
  19         __u32 jited_rec_size;
  20 };
  21 
  22 static int dissect_jited_func(struct bpf_prog_linfo *prog_linfo,
  23                               const __u64 *ksym_func, const __u32 *ksym_len)
  24 {
  25         __u32 nr_jited_func, nr_linfo;
  26         const void *raw_jited_linfo;
  27         const __u64 *jited_linfo;
  28         __u64 last_jited_linfo;
  29         /*
  30          * Index to raw_jited_linfo:
  31          *      i: Index for searching the next ksym_func
  32          * prev_i: Index to the last found ksym_func
  33          */
  34         __u32 i, prev_i;
  35         __u32 f; /* Index to ksym_func */
  36 
  37         raw_jited_linfo = prog_linfo->raw_jited_linfo;
  38         jited_linfo = raw_jited_linfo;
  39         if (ksym_func[0] != *jited_linfo)
  40                 goto errout;
  41 
  42         prog_linfo->jited_linfo_func_idx[0] = 0;
  43         nr_jited_func = prog_linfo->nr_jited_func;
  44         nr_linfo = prog_linfo->nr_linfo;
  45 
  46         for (prev_i = 0, i = 1, f = 1;
  47              i < nr_linfo && f < nr_jited_func;
  48              i++) {
  49                 raw_jited_linfo += prog_linfo->jited_rec_size;
  50                 last_jited_linfo = *jited_linfo;
  51                 jited_linfo = raw_jited_linfo;
  52 
  53                 if (ksym_func[f] == *jited_linfo) {
  54                         prog_linfo->jited_linfo_func_idx[f] = i;
  55 
  56                         /* Sanity check */
  57                         if (last_jited_linfo - ksym_func[f - 1] + 1 >
  58                             ksym_len[f - 1])
  59                                 goto errout;
  60 
  61                         prog_linfo->nr_jited_linfo_per_func[f - 1] =
  62                                 i - prev_i;
  63                         prev_i = i;
  64 
  65                         /*
  66                          * The ksym_func[f] is found in jited_linfo.
  67                          * Look for the next one.
  68                          */
  69                         f++;
  70                 } else if (*jited_linfo <= last_jited_linfo) {
  71                         /* Ensure the addr is increasing _within_ a func */
  72                         goto errout;
  73                 }
  74         }
  75 
  76         if (f != nr_jited_func)
  77                 goto errout;
  78 
  79         prog_linfo->nr_jited_linfo_per_func[nr_jited_func - 1] =
  80                 nr_linfo - prev_i;
  81 
  82         return 0;
  83 
  84 errout:
  85         return -EINVAL;
  86 }
  87 
  88 void bpf_prog_linfo__free(struct bpf_prog_linfo *prog_linfo)
  89 {
  90         if (!prog_linfo)
  91                 return;
  92 
  93         free(prog_linfo->raw_linfo);
  94         free(prog_linfo->raw_jited_linfo);
  95         free(prog_linfo->nr_jited_linfo_per_func);
  96         free(prog_linfo->jited_linfo_func_idx);
  97         free(prog_linfo);
  98 }
  99 
 100 struct bpf_prog_linfo *bpf_prog_linfo__new(const struct bpf_prog_info *info)
 101 {
 102         struct bpf_prog_linfo *prog_linfo;
 103         __u32 nr_linfo, nr_jited_func;
 104         __u64 data_sz;
 105 
 106         nr_linfo = info->nr_line_info;
 107 
 108         if (!nr_linfo)
 109                 return NULL;
 110 
 111         /*
 112          * The min size that bpf_prog_linfo has to access for
 113          * searching purpose.
 114          */
 115         if (info->line_info_rec_size <
 116             offsetof(struct bpf_line_info, file_name_off))
 117                 return NULL;
 118 
 119         prog_linfo = calloc(1, sizeof(*prog_linfo));
 120         if (!prog_linfo)
 121                 return NULL;
 122 
 123         /* Copy xlated line_info */
 124         prog_linfo->nr_linfo = nr_linfo;
 125         prog_linfo->rec_size = info->line_info_rec_size;
 126         data_sz = (__u64)nr_linfo * prog_linfo->rec_size;
 127         prog_linfo->raw_linfo = malloc(data_sz);
 128         if (!prog_linfo->raw_linfo)
 129                 goto err_free;
 130         memcpy(prog_linfo->raw_linfo, (void *)(long)info->line_info, data_sz);
 131 
 132         nr_jited_func = info->nr_jited_ksyms;
 133         if (!nr_jited_func ||
 134             !info->jited_line_info ||
 135             info->nr_jited_line_info != nr_linfo ||
 136             info->jited_line_info_rec_size < sizeof(__u64) ||
 137             info->nr_jited_func_lens != nr_jited_func ||
 138             !info->jited_ksyms ||
 139             !info->jited_func_lens)
 140                 /* Not enough info to provide jited_line_info */
 141                 return prog_linfo;
 142 
 143         /* Copy jited_line_info */
 144         prog_linfo->nr_jited_func = nr_jited_func;
 145         prog_linfo->jited_rec_size = info->jited_line_info_rec_size;
 146         data_sz = (__u64)nr_linfo * prog_linfo->jited_rec_size;
 147         prog_linfo->raw_jited_linfo = malloc(data_sz);
 148         if (!prog_linfo->raw_jited_linfo)
 149                 goto err_free;
 150         memcpy(prog_linfo->raw_jited_linfo,
 151                (void *)(long)info->jited_line_info, data_sz);
 152 
 153         /* Number of jited_line_info per jited func */
 154         prog_linfo->nr_jited_linfo_per_func = malloc(nr_jited_func *
 155                                                      sizeof(__u32));
 156         if (!prog_linfo->nr_jited_linfo_per_func)
 157                 goto err_free;
 158 
 159         /*
 160          * For each jited func,
 161          * the start idx to the "linfo" and "jited_linfo" array,
 162          */
 163         prog_linfo->jited_linfo_func_idx = malloc(nr_jited_func *
 164                                                   sizeof(__u32));
 165         if (!prog_linfo->jited_linfo_func_idx)
 166                 goto err_free;
 167 
 168         if (dissect_jited_func(prog_linfo,
 169                                (__u64 *)(long)info->jited_ksyms,
 170                                (__u32 *)(long)info->jited_func_lens))
 171                 goto err_free;
 172 
 173         return prog_linfo;
 174 
 175 err_free:
 176         bpf_prog_linfo__free(prog_linfo);
 177         return NULL;
 178 }
 179 
 180 const struct bpf_line_info *
 181 bpf_prog_linfo__lfind_addr_func(const struct bpf_prog_linfo *prog_linfo,
 182                                 __u64 addr, __u32 func_idx, __u32 nr_skip)
 183 {
 184         __u32 jited_rec_size, rec_size, nr_linfo, start, i;
 185         const void *raw_jited_linfo, *raw_linfo;
 186         const __u64 *jited_linfo;
 187 
 188         if (func_idx >= prog_linfo->nr_jited_func)
 189                 return NULL;
 190 
 191         nr_linfo = prog_linfo->nr_jited_linfo_per_func[func_idx];
 192         if (nr_skip >= nr_linfo)
 193                 return NULL;
 194 
 195         start = prog_linfo->jited_linfo_func_idx[func_idx] + nr_skip;
 196         jited_rec_size = prog_linfo->jited_rec_size;
 197         raw_jited_linfo = prog_linfo->raw_jited_linfo +
 198                 (start * jited_rec_size);
 199         jited_linfo = raw_jited_linfo;
 200         if (addr < *jited_linfo)
 201                 return NULL;
 202 
 203         nr_linfo -= nr_skip;
 204         rec_size = prog_linfo->rec_size;
 205         raw_linfo = prog_linfo->raw_linfo + (start * rec_size);
 206         for (i = 0; i < nr_linfo; i++) {
 207                 if (addr < *jited_linfo)
 208                         break;
 209 
 210                 raw_linfo += rec_size;
 211                 raw_jited_linfo += jited_rec_size;
 212                 jited_linfo = raw_jited_linfo;
 213         }
 214 
 215         return raw_linfo - rec_size;
 216 }
 217 
 218 const struct bpf_line_info *
 219 bpf_prog_linfo__lfind(const struct bpf_prog_linfo *prog_linfo,
 220                       __u32 insn_off, __u32 nr_skip)
 221 {
 222         const struct bpf_line_info *linfo;
 223         __u32 rec_size, nr_linfo, i;
 224         const void *raw_linfo;
 225 
 226         nr_linfo = prog_linfo->nr_linfo;
 227         if (nr_skip >= nr_linfo)
 228                 return NULL;
 229 
 230         rec_size = prog_linfo->rec_size;
 231         raw_linfo = prog_linfo->raw_linfo + (nr_skip * rec_size);
 232         linfo = raw_linfo;
 233         if (insn_off < linfo->insn_off)
 234                 return NULL;
 235 
 236         nr_linfo -= nr_skip;
 237         for (i = 0; i < nr_linfo; i++) {
 238                 if (insn_off < linfo->insn_off)
 239                         break;
 240 
 241                 raw_linfo += rec_size;
 242                 linfo = raw_linfo;
 243         }
 244 
 245         return raw_linfo - rec_size;
 246 }

/* [<][>][^][v][top][bottom][index][help] */