root/tools/bpf/bpftool/btf_dumper.c

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

DEFINITIONS

This source file includes following definitions.
  1. btf_dumper_ptr
  2. btf_dumper_modifier
  3. btf_dumper_enum
  4. btf_dumper_array
  5. btf_int128_print
  6. btf_int128_shift
  7. btf_dumper_bitfield
  8. btf_dumper_int_bits
  9. btf_dumper_int
  10. btf_dumper_struct
  11. btf_dumper_var
  12. btf_dumper_datasec
  13. btf_dumper_do_type
  14. btf_dumper_type
  15. __btf_dumper_type_only
  16. btf_dump_func
  17. btf_dumper_type_only
  18. ltrim
  19. btf_dump_linfo_plain
  20. btf_dump_linfo_json

   1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
   2 /* Copyright (c) 2018 Facebook */
   3 
   4 #include <ctype.h>
   5 #include <stdio.h> /* for (FILE *) used by json_writer */
   6 #include <string.h>
   7 #include <asm/byteorder.h>
   8 #include <linux/bitops.h>
   9 #include <linux/btf.h>
  10 #include <linux/err.h>
  11 
  12 #include "btf.h"
  13 #include "json_writer.h"
  14 #include "main.h"
  15 
  16 #define BITS_PER_BYTE_MASK (BITS_PER_BYTE - 1)
  17 #define BITS_PER_BYTE_MASKED(bits) ((bits) & BITS_PER_BYTE_MASK)
  18 #define BITS_ROUNDDOWN_BYTES(bits) ((bits) >> 3)
  19 #define BITS_ROUNDUP_BYTES(bits) \
  20         (BITS_ROUNDDOWN_BYTES(bits) + !!BITS_PER_BYTE_MASKED(bits))
  21 
  22 static int btf_dumper_do_type(const struct btf_dumper *d, __u32 type_id,
  23                               __u8 bit_offset, const void *data);
  24 
  25 static void btf_dumper_ptr(const void *data, json_writer_t *jw,
  26                            bool is_plain_text)
  27 {
  28         if (is_plain_text)
  29                 jsonw_printf(jw, "%p", *(void **)data);
  30         else
  31                 jsonw_printf(jw, "%lu", *(unsigned long *)data);
  32 }
  33 
  34 static int btf_dumper_modifier(const struct btf_dumper *d, __u32 type_id,
  35                                __u8 bit_offset, const void *data)
  36 {
  37         int actual_type_id;
  38 
  39         actual_type_id = btf__resolve_type(d->btf, type_id);
  40         if (actual_type_id < 0)
  41                 return actual_type_id;
  42 
  43         return btf_dumper_do_type(d, actual_type_id, bit_offset, data);
  44 }
  45 
  46 static void btf_dumper_enum(const void *data, json_writer_t *jw)
  47 {
  48         jsonw_printf(jw, "%d", *(int *)data);
  49 }
  50 
  51 static int btf_dumper_array(const struct btf_dumper *d, __u32 type_id,
  52                             const void *data)
  53 {
  54         const struct btf_type *t = btf__type_by_id(d->btf, type_id);
  55         struct btf_array *arr = (struct btf_array *)(t + 1);
  56         long long elem_size;
  57         int ret = 0;
  58         __u32 i;
  59 
  60         elem_size = btf__resolve_size(d->btf, arr->type);
  61         if (elem_size < 0)
  62                 return elem_size;
  63 
  64         jsonw_start_array(d->jw);
  65         for (i = 0; i < arr->nelems; i++) {
  66                 ret = btf_dumper_do_type(d, arr->type, 0,
  67                                          data + i * elem_size);
  68                 if (ret)
  69                         break;
  70         }
  71 
  72         jsonw_end_array(d->jw);
  73         return ret;
  74 }
  75 
  76 static void btf_int128_print(json_writer_t *jw, const void *data,
  77                              bool is_plain_text)
  78 {
  79         /* data points to a __int128 number.
  80          * Suppose
  81          *     int128_num = *(__int128 *)data;
  82          * The below formulas shows what upper_num and lower_num represents:
  83          *     upper_num = int128_num >> 64;
  84          *     lower_num = int128_num & 0xffffffffFFFFFFFFULL;
  85          */
  86         __u64 upper_num, lower_num;
  87 
  88 #ifdef __BIG_ENDIAN_BITFIELD
  89         upper_num = *(__u64 *)data;
  90         lower_num = *(__u64 *)(data + 8);
  91 #else
  92         upper_num = *(__u64 *)(data + 8);
  93         lower_num = *(__u64 *)data;
  94 #endif
  95 
  96         if (is_plain_text) {
  97                 if (upper_num == 0)
  98                         jsonw_printf(jw, "0x%llx", lower_num);
  99                 else
 100                         jsonw_printf(jw, "0x%llx%016llx", upper_num, lower_num);
 101         } else {
 102                 if (upper_num == 0)
 103                         jsonw_printf(jw, "\"0x%llx\"", lower_num);
 104                 else
 105                         jsonw_printf(jw, "\"0x%llx%016llx\"", upper_num, lower_num);
 106         }
 107 }
 108 
 109 static void btf_int128_shift(__u64 *print_num, u16 left_shift_bits,
 110                              u16 right_shift_bits)
 111 {
 112         __u64 upper_num, lower_num;
 113 
 114 #ifdef __BIG_ENDIAN_BITFIELD
 115         upper_num = print_num[0];
 116         lower_num = print_num[1];
 117 #else
 118         upper_num = print_num[1];
 119         lower_num = print_num[0];
 120 #endif
 121 
 122         /* shake out un-needed bits by shift/or operations */
 123         if (left_shift_bits >= 64) {
 124                 upper_num = lower_num << (left_shift_bits - 64);
 125                 lower_num = 0;
 126         } else {
 127                 upper_num = (upper_num << left_shift_bits) |
 128                             (lower_num >> (64 - left_shift_bits));
 129                 lower_num = lower_num << left_shift_bits;
 130         }
 131 
 132         if (right_shift_bits >= 64) {
 133                 lower_num = upper_num >> (right_shift_bits - 64);
 134                 upper_num = 0;
 135         } else {
 136                 lower_num = (lower_num >> right_shift_bits) |
 137                             (upper_num << (64 - right_shift_bits));
 138                 upper_num = upper_num >> right_shift_bits;
 139         }
 140 
 141 #ifdef __BIG_ENDIAN_BITFIELD
 142         print_num[0] = upper_num;
 143         print_num[1] = lower_num;
 144 #else
 145         print_num[0] = lower_num;
 146         print_num[1] = upper_num;
 147 #endif
 148 }
 149 
 150 static void btf_dumper_bitfield(__u32 nr_bits, __u8 bit_offset,
 151                                 const void *data, json_writer_t *jw,
 152                                 bool is_plain_text)
 153 {
 154         int left_shift_bits, right_shift_bits;
 155         __u64 print_num[2] = {};
 156         int bytes_to_copy;
 157         int bits_to_copy;
 158 
 159         bits_to_copy = bit_offset + nr_bits;
 160         bytes_to_copy = BITS_ROUNDUP_BYTES(bits_to_copy);
 161 
 162         memcpy(print_num, data, bytes_to_copy);
 163 #if defined(__BIG_ENDIAN_BITFIELD)
 164         left_shift_bits = bit_offset;
 165 #elif defined(__LITTLE_ENDIAN_BITFIELD)
 166         left_shift_bits = 128 - bits_to_copy;
 167 #else
 168 #error neither big nor little endian
 169 #endif
 170         right_shift_bits = 128 - nr_bits;
 171 
 172         btf_int128_shift(print_num, left_shift_bits, right_shift_bits);
 173         btf_int128_print(jw, print_num, is_plain_text);
 174 }
 175 
 176 
 177 static void btf_dumper_int_bits(__u32 int_type, __u8 bit_offset,
 178                                 const void *data, json_writer_t *jw,
 179                                 bool is_plain_text)
 180 {
 181         int nr_bits = BTF_INT_BITS(int_type);
 182         int total_bits_offset;
 183 
 184         /* bits_offset is at most 7.
 185          * BTF_INT_OFFSET() cannot exceed 128 bits.
 186          */
 187         total_bits_offset = bit_offset + BTF_INT_OFFSET(int_type);
 188         data += BITS_ROUNDDOWN_BYTES(total_bits_offset);
 189         bit_offset = BITS_PER_BYTE_MASKED(total_bits_offset);
 190         btf_dumper_bitfield(nr_bits, bit_offset, data, jw,
 191                             is_plain_text);
 192 }
 193 
 194 static int btf_dumper_int(const struct btf_type *t, __u8 bit_offset,
 195                           const void *data, json_writer_t *jw,
 196                           bool is_plain_text)
 197 {
 198         __u32 *int_type;
 199         __u32 nr_bits;
 200 
 201         int_type = (__u32 *)(t + 1);
 202         nr_bits = BTF_INT_BITS(*int_type);
 203         /* if this is bit field */
 204         if (bit_offset || BTF_INT_OFFSET(*int_type) ||
 205             BITS_PER_BYTE_MASKED(nr_bits)) {
 206                 btf_dumper_int_bits(*int_type, bit_offset, data, jw,
 207                                     is_plain_text);
 208                 return 0;
 209         }
 210 
 211         if (nr_bits == 128) {
 212                 btf_int128_print(jw, data, is_plain_text);
 213                 return 0;
 214         }
 215 
 216         switch (BTF_INT_ENCODING(*int_type)) {
 217         case 0:
 218                 if (BTF_INT_BITS(*int_type) == 64)
 219                         jsonw_printf(jw, "%llu", *(__u64 *)data);
 220                 else if (BTF_INT_BITS(*int_type) == 32)
 221                         jsonw_printf(jw, "%u", *(__u32 *)data);
 222                 else if (BTF_INT_BITS(*int_type) == 16)
 223                         jsonw_printf(jw, "%hu", *(__u16 *)data);
 224                 else if (BTF_INT_BITS(*int_type) == 8)
 225                         jsonw_printf(jw, "%hhu", *(__u8 *)data);
 226                 else
 227                         btf_dumper_int_bits(*int_type, bit_offset, data, jw,
 228                                             is_plain_text);
 229                 break;
 230         case BTF_INT_SIGNED:
 231                 if (BTF_INT_BITS(*int_type) == 64)
 232                         jsonw_printf(jw, "%lld", *(long long *)data);
 233                 else if (BTF_INT_BITS(*int_type) == 32)
 234                         jsonw_printf(jw, "%d", *(int *)data);
 235                 else if (BTF_INT_BITS(*int_type) == 16)
 236                         jsonw_printf(jw, "%hd", *(short *)data);
 237                 else if (BTF_INT_BITS(*int_type) == 8)
 238                         jsonw_printf(jw, "%hhd", *(char *)data);
 239                 else
 240                         btf_dumper_int_bits(*int_type, bit_offset, data, jw,
 241                                             is_plain_text);
 242                 break;
 243         case BTF_INT_CHAR:
 244                 if (isprint(*(char *)data))
 245                         jsonw_printf(jw, "\"%c\"", *(char *)data);
 246                 else
 247                         if (is_plain_text)
 248                                 jsonw_printf(jw, "0x%hhx", *(char *)data);
 249                         else
 250                                 jsonw_printf(jw, "\"\\u00%02hhx\"",
 251                                              *(char *)data);
 252                 break;
 253         case BTF_INT_BOOL:
 254                 jsonw_bool(jw, *(int *)data);
 255                 break;
 256         default:
 257                 /* shouldn't happen */
 258                 return -EINVAL;
 259         }
 260 
 261         return 0;
 262 }
 263 
 264 static int btf_dumper_struct(const struct btf_dumper *d, __u32 type_id,
 265                              const void *data)
 266 {
 267         const struct btf_type *t;
 268         struct btf_member *m;
 269         const void *data_off;
 270         int kind_flag;
 271         int ret = 0;
 272         int i, vlen;
 273 
 274         t = btf__type_by_id(d->btf, type_id);
 275         if (!t)
 276                 return -EINVAL;
 277 
 278         kind_flag = BTF_INFO_KFLAG(t->info);
 279         vlen = BTF_INFO_VLEN(t->info);
 280         jsonw_start_object(d->jw);
 281         m = (struct btf_member *)(t + 1);
 282 
 283         for (i = 0; i < vlen; i++) {
 284                 __u32 bit_offset = m[i].offset;
 285                 __u32 bitfield_size = 0;
 286 
 287                 if (kind_flag) {
 288                         bitfield_size = BTF_MEMBER_BITFIELD_SIZE(bit_offset);
 289                         bit_offset = BTF_MEMBER_BIT_OFFSET(bit_offset);
 290                 }
 291 
 292                 jsonw_name(d->jw, btf__name_by_offset(d->btf, m[i].name_off));
 293                 data_off = data + BITS_ROUNDDOWN_BYTES(bit_offset);
 294                 if (bitfield_size) {
 295                         btf_dumper_bitfield(bitfield_size,
 296                                             BITS_PER_BYTE_MASKED(bit_offset),
 297                                             data_off, d->jw, d->is_plain_text);
 298                 } else {
 299                         ret = btf_dumper_do_type(d, m[i].type,
 300                                                  BITS_PER_BYTE_MASKED(bit_offset),
 301                                                  data_off);
 302                         if (ret)
 303                                 break;
 304                 }
 305         }
 306 
 307         jsonw_end_object(d->jw);
 308 
 309         return ret;
 310 }
 311 
 312 static int btf_dumper_var(const struct btf_dumper *d, __u32 type_id,
 313                           __u8 bit_offset, const void *data)
 314 {
 315         const struct btf_type *t = btf__type_by_id(d->btf, type_id);
 316         int ret;
 317 
 318         jsonw_start_object(d->jw);
 319         jsonw_name(d->jw, btf__name_by_offset(d->btf, t->name_off));
 320         ret = btf_dumper_do_type(d, t->type, bit_offset, data);
 321         jsonw_end_object(d->jw);
 322 
 323         return ret;
 324 }
 325 
 326 static int btf_dumper_datasec(const struct btf_dumper *d, __u32 type_id,
 327                               const void *data)
 328 {
 329         struct btf_var_secinfo *vsi;
 330         const struct btf_type *t;
 331         int ret = 0, i, vlen;
 332 
 333         t = btf__type_by_id(d->btf, type_id);
 334         if (!t)
 335                 return -EINVAL;
 336 
 337         vlen = BTF_INFO_VLEN(t->info);
 338         vsi = (struct btf_var_secinfo *)(t + 1);
 339 
 340         jsonw_start_object(d->jw);
 341         jsonw_name(d->jw, btf__name_by_offset(d->btf, t->name_off));
 342         jsonw_start_array(d->jw);
 343         for (i = 0; i < vlen; i++) {
 344                 ret = btf_dumper_do_type(d, vsi[i].type, 0, data + vsi[i].offset);
 345                 if (ret)
 346                         break;
 347         }
 348         jsonw_end_array(d->jw);
 349         jsonw_end_object(d->jw);
 350 
 351         return ret;
 352 }
 353 
 354 static int btf_dumper_do_type(const struct btf_dumper *d, __u32 type_id,
 355                               __u8 bit_offset, const void *data)
 356 {
 357         const struct btf_type *t = btf__type_by_id(d->btf, type_id);
 358 
 359         switch (BTF_INFO_KIND(t->info)) {
 360         case BTF_KIND_INT:
 361                 return btf_dumper_int(t, bit_offset, data, d->jw,
 362                                      d->is_plain_text);
 363         case BTF_KIND_STRUCT:
 364         case BTF_KIND_UNION:
 365                 return btf_dumper_struct(d, type_id, data);
 366         case BTF_KIND_ARRAY:
 367                 return btf_dumper_array(d, type_id, data);
 368         case BTF_KIND_ENUM:
 369                 btf_dumper_enum(data, d->jw);
 370                 return 0;
 371         case BTF_KIND_PTR:
 372                 btf_dumper_ptr(data, d->jw, d->is_plain_text);
 373                 return 0;
 374         case BTF_KIND_UNKN:
 375                 jsonw_printf(d->jw, "(unknown)");
 376                 return 0;
 377         case BTF_KIND_FWD:
 378                 /* map key or value can't be forward */
 379                 jsonw_printf(d->jw, "(fwd-kind-invalid)");
 380                 return -EINVAL;
 381         case BTF_KIND_TYPEDEF:
 382         case BTF_KIND_VOLATILE:
 383         case BTF_KIND_CONST:
 384         case BTF_KIND_RESTRICT:
 385                 return btf_dumper_modifier(d, type_id, bit_offset, data);
 386         case BTF_KIND_VAR:
 387                 return btf_dumper_var(d, type_id, bit_offset, data);
 388         case BTF_KIND_DATASEC:
 389                 return btf_dumper_datasec(d, type_id, data);
 390         default:
 391                 jsonw_printf(d->jw, "(unsupported-kind");
 392                 return -EINVAL;
 393         }
 394 }
 395 
 396 int btf_dumper_type(const struct btf_dumper *d, __u32 type_id,
 397                     const void *data)
 398 {
 399         return btf_dumper_do_type(d, type_id, 0, data);
 400 }
 401 
 402 #define BTF_PRINT_ARG(...)                                              \
 403         do {                                                            \
 404                 pos += snprintf(func_sig + pos, size - pos,             \
 405                                 __VA_ARGS__);                           \
 406                 if (pos >= size)                                        \
 407                         return -1;                                      \
 408         } while (0)
 409 #define BTF_PRINT_TYPE(type)                                    \
 410         do {                                                            \
 411                 pos = __btf_dumper_type_only(btf, type, func_sig,       \
 412                                              pos, size);                \
 413                 if (pos == -1)                                          \
 414                         return -1;                                      \
 415         } while (0)
 416 
 417 static int btf_dump_func(const struct btf *btf, char *func_sig,
 418                          const struct btf_type *func_proto,
 419                          const struct btf_type *func, int pos, int size);
 420 
 421 static int __btf_dumper_type_only(const struct btf *btf, __u32 type_id,
 422                                   char *func_sig, int pos, int size)
 423 {
 424         const struct btf_type *proto_type;
 425         const struct btf_array *array;
 426         const struct btf_var *var;
 427         const struct btf_type *t;
 428 
 429         if (!type_id) {
 430                 BTF_PRINT_ARG("void ");
 431                 return pos;
 432         }
 433 
 434         t = btf__type_by_id(btf, type_id);
 435 
 436         switch (BTF_INFO_KIND(t->info)) {
 437         case BTF_KIND_INT:
 438         case BTF_KIND_TYPEDEF:
 439                 BTF_PRINT_ARG("%s ", btf__name_by_offset(btf, t->name_off));
 440                 break;
 441         case BTF_KIND_STRUCT:
 442                 BTF_PRINT_ARG("struct %s ",
 443                               btf__name_by_offset(btf, t->name_off));
 444                 break;
 445         case BTF_KIND_UNION:
 446                 BTF_PRINT_ARG("union %s ",
 447                               btf__name_by_offset(btf, t->name_off));
 448                 break;
 449         case BTF_KIND_ENUM:
 450                 BTF_PRINT_ARG("enum %s ",
 451                               btf__name_by_offset(btf, t->name_off));
 452                 break;
 453         case BTF_KIND_ARRAY:
 454                 array = (struct btf_array *)(t + 1);
 455                 BTF_PRINT_TYPE(array->type);
 456                 BTF_PRINT_ARG("[%d]", array->nelems);
 457                 break;
 458         case BTF_KIND_PTR:
 459                 BTF_PRINT_TYPE(t->type);
 460                 BTF_PRINT_ARG("* ");
 461                 break;
 462         case BTF_KIND_FWD:
 463                 BTF_PRINT_ARG("%s %s ",
 464                               BTF_INFO_KFLAG(t->info) ? "union" : "struct",
 465                               btf__name_by_offset(btf, t->name_off));
 466                 break;
 467         case BTF_KIND_VOLATILE:
 468                 BTF_PRINT_ARG("volatile ");
 469                 BTF_PRINT_TYPE(t->type);
 470                 break;
 471         case BTF_KIND_CONST:
 472                 BTF_PRINT_ARG("const ");
 473                 BTF_PRINT_TYPE(t->type);
 474                 break;
 475         case BTF_KIND_RESTRICT:
 476                 BTF_PRINT_ARG("restrict ");
 477                 BTF_PRINT_TYPE(t->type);
 478                 break;
 479         case BTF_KIND_FUNC_PROTO:
 480                 pos = btf_dump_func(btf, func_sig, t, NULL, pos, size);
 481                 if (pos == -1)
 482                         return -1;
 483                 break;
 484         case BTF_KIND_FUNC:
 485                 proto_type = btf__type_by_id(btf, t->type);
 486                 pos = btf_dump_func(btf, func_sig, proto_type, t, pos, size);
 487                 if (pos == -1)
 488                         return -1;
 489                 break;
 490         case BTF_KIND_VAR:
 491                 var = (struct btf_var *)(t + 1);
 492                 if (var->linkage == BTF_VAR_STATIC)
 493                         BTF_PRINT_ARG("static ");
 494                 BTF_PRINT_TYPE(t->type);
 495                 BTF_PRINT_ARG(" %s",
 496                               btf__name_by_offset(btf, t->name_off));
 497                 break;
 498         case BTF_KIND_DATASEC:
 499                 BTF_PRINT_ARG("section (\"%s\") ",
 500                               btf__name_by_offset(btf, t->name_off));
 501                 break;
 502         case BTF_KIND_UNKN:
 503         default:
 504                 return -1;
 505         }
 506 
 507         return pos;
 508 }
 509 
 510 static int btf_dump_func(const struct btf *btf, char *func_sig,
 511                          const struct btf_type *func_proto,
 512                          const struct btf_type *func, int pos, int size)
 513 {
 514         int i, vlen;
 515 
 516         BTF_PRINT_TYPE(func_proto->type);
 517         if (func)
 518                 BTF_PRINT_ARG("%s(", btf__name_by_offset(btf, func->name_off));
 519         else
 520                 BTF_PRINT_ARG("(");
 521         vlen = BTF_INFO_VLEN(func_proto->info);
 522         for (i = 0; i < vlen; i++) {
 523                 struct btf_param *arg = &((struct btf_param *)(func_proto + 1))[i];
 524 
 525                 if (i)
 526                         BTF_PRINT_ARG(", ");
 527                 if (arg->type) {
 528                         BTF_PRINT_TYPE(arg->type);
 529                         BTF_PRINT_ARG("%s",
 530                                       btf__name_by_offset(btf, arg->name_off));
 531                 } else {
 532                         BTF_PRINT_ARG("...");
 533                 }
 534         }
 535         BTF_PRINT_ARG(")");
 536 
 537         return pos;
 538 }
 539 
 540 void btf_dumper_type_only(const struct btf *btf, __u32 type_id, char *func_sig,
 541                           int size)
 542 {
 543         int err;
 544 
 545         func_sig[0] = '\0';
 546         if (!btf)
 547                 return;
 548 
 549         err = __btf_dumper_type_only(btf, type_id, func_sig, 0, size);
 550         if (err < 0)
 551                 func_sig[0] = '\0';
 552 }
 553 
 554 static const char *ltrim(const char *s)
 555 {
 556         while (isspace(*s))
 557                 s++;
 558 
 559         return s;
 560 }
 561 
 562 void btf_dump_linfo_plain(const struct btf *btf,
 563                           const struct bpf_line_info *linfo,
 564                           const char *prefix, bool linum)
 565 {
 566         const char *line = btf__name_by_offset(btf, linfo->line_off);
 567 
 568         if (!line)
 569                 return;
 570         line = ltrim(line);
 571 
 572         if (!prefix)
 573                 prefix = "";
 574 
 575         if (linum) {
 576                 const char *file = btf__name_by_offset(btf, linfo->file_name_off);
 577 
 578                 /* More forgiving on file because linum option is
 579                  * expected to provide more info than the already
 580                  * available src line.
 581                  */
 582                 if (!file)
 583                         file = "";
 584 
 585                 printf("%s%s [file:%s line_num:%u line_col:%u]\n",
 586                        prefix, line, file,
 587                        BPF_LINE_INFO_LINE_NUM(linfo->line_col),
 588                        BPF_LINE_INFO_LINE_COL(linfo->line_col));
 589         } else {
 590                 printf("%s%s\n", prefix, line);
 591         }
 592 }
 593 
 594 void btf_dump_linfo_json(const struct btf *btf,
 595                          const struct bpf_line_info *linfo, bool linum)
 596 {
 597         const char *line = btf__name_by_offset(btf, linfo->line_off);
 598 
 599         if (line)
 600                 jsonw_string_field(json_wtr, "src", ltrim(line));
 601 
 602         if (linum) {
 603                 const char *file = btf__name_by_offset(btf, linfo->file_name_off);
 604 
 605                 if (file)
 606                         jsonw_string_field(json_wtr, "file", file);
 607 
 608                 if (BPF_LINE_INFO_LINE_NUM(linfo->line_col))
 609                         jsonw_int_field(json_wtr, "line_num",
 610                                         BPF_LINE_INFO_LINE_NUM(linfo->line_col));
 611 
 612                 if (BPF_LINE_INFO_LINE_COL(linfo->line_col))
 613                         jsonw_int_field(json_wtr, "line_col",
 614                                         BPF_LINE_INFO_LINE_COL(linfo->line_col));
 615         }
 616 }

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