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", *(unsigned long *)data); 30 else 31 jsonw_printf(jw, "%u", *(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, "%lu", *(__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, "%ld", *(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_do_type(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 317 switch (BTF_INFO_KIND(t->info)) { 318 case BTF_KIND_INT: 319 return btf_dumper_int(t, bit_offset, data, d->jw, 320 d->is_plain_text); 321 case BTF_KIND_STRUCT: 322 case BTF_KIND_UNION: 323 return btf_dumper_struct(d, type_id, data); 324 case BTF_KIND_ARRAY: 325 return btf_dumper_array(d, type_id, data); 326 case BTF_KIND_ENUM: 327 btf_dumper_enum(data, d->jw); 328 return 0; 329 case BTF_KIND_PTR: 330 btf_dumper_ptr(data, d->jw, d->is_plain_text); 331 return 0; 332 case BTF_KIND_UNKN: 333 jsonw_printf(d->jw, "(unknown)"); 334 return 0; 335 case BTF_KIND_FWD: 336 /* map key or value can't be forward */ 337 jsonw_printf(d->jw, "(fwd-kind-invalid)"); 338 return -EINVAL; 339 case BTF_KIND_TYPEDEF: 340 case BTF_KIND_VOLATILE: 341 case BTF_KIND_CONST: 342 case BTF_KIND_RESTRICT: 343 return btf_dumper_modifier(d, type_id, bit_offset, data); 344 default: 345 jsonw_printf(d->jw, "(unsupported-kind"); 346 return -EINVAL; 347 } 348 } 349 350 int btf_dumper_type(const struct btf_dumper *d, __u32 type_id, 351 const void *data) 352 { 353 return btf_dumper_do_type(d, type_id, 0, data); 354 } 355 356 #define BTF_PRINT_ARG(...) \ 357 do { \ 358 pos += snprintf(func_sig + pos, size - pos, \ 359 __VA_ARGS__); \ 360 if (pos >= size) \ 361 return -1; \ 362 } while (0) 363 #define BTF_PRINT_TYPE(type) \ 364 do { \ 365 pos = __btf_dumper_type_only(btf, type, func_sig, \ 366 pos, size); \ 367 if (pos == -1) \ 368 return -1; \ 369 } while (0) 370 371 static int btf_dump_func(const struct btf *btf, char *func_sig, 372 const struct btf_type *func_proto, 373 const struct btf_type *func, int pos, int size); 374 375 static int __btf_dumper_type_only(const struct btf *btf, __u32 type_id, 376 char *func_sig, int pos, int size) 377 { 378 const struct btf_type *proto_type; 379 const struct btf_array *array; 380 const struct btf_type *t; 381 382 if (!type_id) { 383 BTF_PRINT_ARG("void "); 384 return pos; 385 } 386 387 t = btf__type_by_id(btf, type_id); 388 389 switch (BTF_INFO_KIND(t->info)) { 390 case BTF_KIND_INT: 391 case BTF_KIND_TYPEDEF: 392 BTF_PRINT_ARG("%s ", btf__name_by_offset(btf, t->name_off)); 393 break; 394 case BTF_KIND_STRUCT: 395 BTF_PRINT_ARG("struct %s ", 396 btf__name_by_offset(btf, t->name_off)); 397 break; 398 case BTF_KIND_UNION: 399 BTF_PRINT_ARG("union %s ", 400 btf__name_by_offset(btf, t->name_off)); 401 break; 402 case BTF_KIND_ENUM: 403 BTF_PRINT_ARG("enum %s ", 404 btf__name_by_offset(btf, t->name_off)); 405 break; 406 case BTF_KIND_ARRAY: 407 array = (struct btf_array *)(t + 1); 408 BTF_PRINT_TYPE(array->type); 409 BTF_PRINT_ARG("[%d]", array->nelems); 410 break; 411 case BTF_KIND_PTR: 412 BTF_PRINT_TYPE(t->type); 413 BTF_PRINT_ARG("* "); 414 break; 415 case BTF_KIND_FWD: 416 BTF_PRINT_ARG("%s %s ", 417 BTF_INFO_KFLAG(t->info) ? "union" : "struct", 418 btf__name_by_offset(btf, t->name_off)); 419 break; 420 case BTF_KIND_VOLATILE: 421 BTF_PRINT_ARG("volatile "); 422 BTF_PRINT_TYPE(t->type); 423 break; 424 case BTF_KIND_CONST: 425 BTF_PRINT_ARG("const "); 426 BTF_PRINT_TYPE(t->type); 427 break; 428 case BTF_KIND_RESTRICT: 429 BTF_PRINT_ARG("restrict "); 430 BTF_PRINT_TYPE(t->type); 431 break; 432 case BTF_KIND_FUNC_PROTO: 433 pos = btf_dump_func(btf, func_sig, t, NULL, pos, size); 434 if (pos == -1) 435 return -1; 436 break; 437 case BTF_KIND_FUNC: 438 proto_type = btf__type_by_id(btf, t->type); 439 pos = btf_dump_func(btf, func_sig, proto_type, t, pos, size); 440 if (pos == -1) 441 return -1; 442 break; 443 case BTF_KIND_UNKN: 444 default: 445 return -1; 446 } 447 448 return pos; 449 } 450 451 static int btf_dump_func(const struct btf *btf, char *func_sig, 452 const struct btf_type *func_proto, 453 const struct btf_type *func, int pos, int size) 454 { 455 int i, vlen; 456 457 BTF_PRINT_TYPE(func_proto->type); 458 if (func) 459 BTF_PRINT_ARG("%s(", btf__name_by_offset(btf, func->name_off)); 460 else 461 BTF_PRINT_ARG("("); 462 vlen = BTF_INFO_VLEN(func_proto->info); 463 for (i = 0; i < vlen; i++) { 464 struct btf_param *arg = &((struct btf_param *)(func_proto + 1))[i]; 465 466 if (i) 467 BTF_PRINT_ARG(", "); 468 if (arg->type) { 469 BTF_PRINT_TYPE(arg->type); 470 BTF_PRINT_ARG("%s", 471 btf__name_by_offset(btf, arg->name_off)); 472 } else { 473 BTF_PRINT_ARG("..."); 474 } 475 } 476 BTF_PRINT_ARG(")"); 477 478 return pos; 479 } 480 481 void btf_dumper_type_only(const struct btf *btf, __u32 type_id, char *func_sig, 482 int size) 483 { 484 int err; 485 486 func_sig[0] = '\0'; 487 if (!btf) 488 return; 489 490 err = __btf_dumper_type_only(btf, type_id, func_sig, 0, size); 491 if (err < 0) 492 func_sig[0] = '\0'; 493 } 494 495 static const char *ltrim(const char *s) 496 { 497 while (isspace(*s)) 498 s++; 499 500 return s; 501 } 502 503 void btf_dump_linfo_plain(const struct btf *btf, 504 const struct bpf_line_info *linfo, 505 const char *prefix, bool linum) 506 { 507 const char *line = btf__name_by_offset(btf, linfo->line_off); 508 509 if (!line) 510 return; 511 line = ltrim(line); 512 513 if (!prefix) 514 prefix = ""; 515 516 if (linum) { 517 const char *file = btf__name_by_offset(btf, linfo->file_name_off); 518 519 /* More forgiving on file because linum option is 520 * expected to provide more info than the already 521 * available src line. 522 */ 523 if (!file) 524 file = ""; 525 526 printf("%s%s [file:%s line_num:%u line_col:%u]\n", 527 prefix, line, file, 528 BPF_LINE_INFO_LINE_NUM(linfo->line_col), 529 BPF_LINE_INFO_LINE_COL(linfo->line_col)); 530 } else { 531 printf("%s%s\n", prefix, line); 532 } 533 } 534 535 void btf_dump_linfo_json(const struct btf *btf, 536 const struct bpf_line_info *linfo, bool linum) 537 { 538 const char *line = btf__name_by_offset(btf, linfo->line_off); 539 540 if (line) 541 jsonw_string_field(json_wtr, "src", ltrim(line)); 542 543 if (linum) { 544 const char *file = btf__name_by_offset(btf, linfo->file_name_off); 545 546 if (file) 547 jsonw_string_field(json_wtr, "file", file); 548 549 if (BPF_LINE_INFO_LINE_NUM(linfo->line_col)) 550 jsonw_int_field(json_wtr, "line_num", 551 BPF_LINE_INFO_LINE_NUM(linfo->line_col)); 552 553 if (BPF_LINE_INFO_LINE_COL(linfo->line_col)) 554 jsonw_int_field(json_wtr, "line_col", 555 BPF_LINE_INFO_LINE_COL(linfo->line_col)); 556 } 557 } 558