btf.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
  2. /* Copyright (C) 2019 Facebook */
  3. #include <errno.h>
  4. #include <fcntl.h>
  5. #include <linux/err.h>
  6. #include <stdbool.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include <linux/btf.h>
  11. #include <sys/types.h>
  12. #include <sys/stat.h>
  13. #include <bpf/bpf.h>
  14. #include <bpf/btf.h>
  15. #include <bpf/hashmap.h>
  16. #include <bpf/libbpf.h>
  17. #include "json_writer.h"
  18. #include "main.h"
  19. static const char * const btf_kind_str[NR_BTF_KINDS] = {
  20. [BTF_KIND_UNKN] = "UNKNOWN",
  21. [BTF_KIND_INT] = "INT",
  22. [BTF_KIND_PTR] = "PTR",
  23. [BTF_KIND_ARRAY] = "ARRAY",
  24. [BTF_KIND_STRUCT] = "STRUCT",
  25. [BTF_KIND_UNION] = "UNION",
  26. [BTF_KIND_ENUM] = "ENUM",
  27. [BTF_KIND_FWD] = "FWD",
  28. [BTF_KIND_TYPEDEF] = "TYPEDEF",
  29. [BTF_KIND_VOLATILE] = "VOLATILE",
  30. [BTF_KIND_CONST] = "CONST",
  31. [BTF_KIND_RESTRICT] = "RESTRICT",
  32. [BTF_KIND_FUNC] = "FUNC",
  33. [BTF_KIND_FUNC_PROTO] = "FUNC_PROTO",
  34. [BTF_KIND_VAR] = "VAR",
  35. [BTF_KIND_DATASEC] = "DATASEC",
  36. [BTF_KIND_FLOAT] = "FLOAT",
  37. [BTF_KIND_DECL_TAG] = "DECL_TAG",
  38. [BTF_KIND_TYPE_TAG] = "TYPE_TAG",
  39. [BTF_KIND_ENUM64] = "ENUM64",
  40. };
  41. static const char *btf_int_enc_str(__u8 encoding)
  42. {
  43. switch (encoding) {
  44. case 0:
  45. return "(none)";
  46. case BTF_INT_SIGNED:
  47. return "SIGNED";
  48. case BTF_INT_CHAR:
  49. return "CHAR";
  50. case BTF_INT_BOOL:
  51. return "BOOL";
  52. default:
  53. return "UNKN";
  54. }
  55. }
  56. static const char *btf_var_linkage_str(__u32 linkage)
  57. {
  58. switch (linkage) {
  59. case BTF_VAR_STATIC:
  60. return "static";
  61. case BTF_VAR_GLOBAL_ALLOCATED:
  62. return "global";
  63. case BTF_VAR_GLOBAL_EXTERN:
  64. return "extern";
  65. default:
  66. return "(unknown)";
  67. }
  68. }
  69. static const char *btf_func_linkage_str(const struct btf_type *t)
  70. {
  71. switch (btf_vlen(t)) {
  72. case BTF_FUNC_STATIC:
  73. return "static";
  74. case BTF_FUNC_GLOBAL:
  75. return "global";
  76. case BTF_FUNC_EXTERN:
  77. return "extern";
  78. default:
  79. return "(unknown)";
  80. }
  81. }
  82. static const char *btf_str(const struct btf *btf, __u32 off)
  83. {
  84. if (!off)
  85. return "(anon)";
  86. return btf__name_by_offset(btf, off) ? : "(invalid)";
  87. }
  88. static int btf_kind_safe(int kind)
  89. {
  90. return kind <= BTF_KIND_MAX ? kind : BTF_KIND_UNKN;
  91. }
  92. static int dump_btf_type(const struct btf *btf, __u32 id,
  93. const struct btf_type *t)
  94. {
  95. json_writer_t *w = json_wtr;
  96. int kind = btf_kind(t);
  97. if (json_output) {
  98. jsonw_start_object(w);
  99. jsonw_uint_field(w, "id", id);
  100. jsonw_string_field(w, "kind", btf_kind_str[btf_kind_safe(kind)]);
  101. jsonw_string_field(w, "name", btf_str(btf, t->name_off));
  102. } else {
  103. printf("[%u] %s '%s'", id, btf_kind_str[btf_kind_safe(kind)],
  104. btf_str(btf, t->name_off));
  105. }
  106. switch (kind) {
  107. case BTF_KIND_INT: {
  108. __u32 v = *(__u32 *)(t + 1);
  109. const char *enc;
  110. enc = btf_int_enc_str(BTF_INT_ENCODING(v));
  111. if (json_output) {
  112. jsonw_uint_field(w, "size", t->size);
  113. jsonw_uint_field(w, "bits_offset", BTF_INT_OFFSET(v));
  114. jsonw_uint_field(w, "nr_bits", BTF_INT_BITS(v));
  115. jsonw_string_field(w, "encoding", enc);
  116. } else {
  117. printf(" size=%u bits_offset=%u nr_bits=%u encoding=%s",
  118. t->size, BTF_INT_OFFSET(v), BTF_INT_BITS(v),
  119. enc);
  120. }
  121. break;
  122. }
  123. case BTF_KIND_PTR:
  124. case BTF_KIND_CONST:
  125. case BTF_KIND_VOLATILE:
  126. case BTF_KIND_RESTRICT:
  127. case BTF_KIND_TYPEDEF:
  128. case BTF_KIND_TYPE_TAG:
  129. if (json_output)
  130. jsonw_uint_field(w, "type_id", t->type);
  131. else
  132. printf(" type_id=%u", t->type);
  133. break;
  134. case BTF_KIND_ARRAY: {
  135. const struct btf_array *arr = (const void *)(t + 1);
  136. if (json_output) {
  137. jsonw_uint_field(w, "type_id", arr->type);
  138. jsonw_uint_field(w, "index_type_id", arr->index_type);
  139. jsonw_uint_field(w, "nr_elems", arr->nelems);
  140. } else {
  141. printf(" type_id=%u index_type_id=%u nr_elems=%u",
  142. arr->type, arr->index_type, arr->nelems);
  143. }
  144. break;
  145. }
  146. case BTF_KIND_STRUCT:
  147. case BTF_KIND_UNION: {
  148. const struct btf_member *m = (const void *)(t + 1);
  149. __u16 vlen = BTF_INFO_VLEN(t->info);
  150. int i;
  151. if (json_output) {
  152. jsonw_uint_field(w, "size", t->size);
  153. jsonw_uint_field(w, "vlen", vlen);
  154. jsonw_name(w, "members");
  155. jsonw_start_array(w);
  156. } else {
  157. printf(" size=%u vlen=%u", t->size, vlen);
  158. }
  159. for (i = 0; i < vlen; i++, m++) {
  160. const char *name = btf_str(btf, m->name_off);
  161. __u32 bit_off, bit_sz;
  162. if (BTF_INFO_KFLAG(t->info)) {
  163. bit_off = BTF_MEMBER_BIT_OFFSET(m->offset);
  164. bit_sz = BTF_MEMBER_BITFIELD_SIZE(m->offset);
  165. } else {
  166. bit_off = m->offset;
  167. bit_sz = 0;
  168. }
  169. if (json_output) {
  170. jsonw_start_object(w);
  171. jsonw_string_field(w, "name", name);
  172. jsonw_uint_field(w, "type_id", m->type);
  173. jsonw_uint_field(w, "bits_offset", bit_off);
  174. if (bit_sz) {
  175. jsonw_uint_field(w, "bitfield_size",
  176. bit_sz);
  177. }
  178. jsonw_end_object(w);
  179. } else {
  180. printf("\n\t'%s' type_id=%u bits_offset=%u",
  181. name, m->type, bit_off);
  182. if (bit_sz)
  183. printf(" bitfield_size=%u", bit_sz);
  184. }
  185. }
  186. if (json_output)
  187. jsonw_end_array(w);
  188. break;
  189. }
  190. case BTF_KIND_ENUM: {
  191. const struct btf_enum *v = (const void *)(t + 1);
  192. __u16 vlen = BTF_INFO_VLEN(t->info);
  193. const char *encoding;
  194. int i;
  195. encoding = btf_kflag(t) ? "SIGNED" : "UNSIGNED";
  196. if (json_output) {
  197. jsonw_string_field(w, "encoding", encoding);
  198. jsonw_uint_field(w, "size", t->size);
  199. jsonw_uint_field(w, "vlen", vlen);
  200. jsonw_name(w, "values");
  201. jsonw_start_array(w);
  202. } else {
  203. printf(" encoding=%s size=%u vlen=%u", encoding, t->size, vlen);
  204. }
  205. for (i = 0; i < vlen; i++, v++) {
  206. const char *name = btf_str(btf, v->name_off);
  207. if (json_output) {
  208. jsonw_start_object(w);
  209. jsonw_string_field(w, "name", name);
  210. if (btf_kflag(t))
  211. jsonw_int_field(w, "val", v->val);
  212. else
  213. jsonw_uint_field(w, "val", v->val);
  214. jsonw_end_object(w);
  215. } else {
  216. if (btf_kflag(t))
  217. printf("\n\t'%s' val=%d", name, v->val);
  218. else
  219. printf("\n\t'%s' val=%u", name, v->val);
  220. }
  221. }
  222. if (json_output)
  223. jsonw_end_array(w);
  224. break;
  225. }
  226. case BTF_KIND_ENUM64: {
  227. const struct btf_enum64 *v = btf_enum64(t);
  228. __u16 vlen = btf_vlen(t);
  229. const char *encoding;
  230. int i;
  231. encoding = btf_kflag(t) ? "SIGNED" : "UNSIGNED";
  232. if (json_output) {
  233. jsonw_string_field(w, "encoding", encoding);
  234. jsonw_uint_field(w, "size", t->size);
  235. jsonw_uint_field(w, "vlen", vlen);
  236. jsonw_name(w, "values");
  237. jsonw_start_array(w);
  238. } else {
  239. printf(" encoding=%s size=%u vlen=%u", encoding, t->size, vlen);
  240. }
  241. for (i = 0; i < vlen; i++, v++) {
  242. const char *name = btf_str(btf, v->name_off);
  243. __u64 val = ((__u64)v->val_hi32 << 32) | v->val_lo32;
  244. if (json_output) {
  245. jsonw_start_object(w);
  246. jsonw_string_field(w, "name", name);
  247. if (btf_kflag(t))
  248. jsonw_int_field(w, "val", val);
  249. else
  250. jsonw_uint_field(w, "val", val);
  251. jsonw_end_object(w);
  252. } else {
  253. if (btf_kflag(t))
  254. printf("\n\t'%s' val=%lldLL", name,
  255. (unsigned long long)val);
  256. else
  257. printf("\n\t'%s' val=%lluULL", name,
  258. (unsigned long long)val);
  259. }
  260. }
  261. if (json_output)
  262. jsonw_end_array(w);
  263. break;
  264. }
  265. case BTF_KIND_FWD: {
  266. const char *fwd_kind = BTF_INFO_KFLAG(t->info) ? "union"
  267. : "struct";
  268. if (json_output)
  269. jsonw_string_field(w, "fwd_kind", fwd_kind);
  270. else
  271. printf(" fwd_kind=%s", fwd_kind);
  272. break;
  273. }
  274. case BTF_KIND_FUNC: {
  275. const char *linkage = btf_func_linkage_str(t);
  276. if (json_output) {
  277. jsonw_uint_field(w, "type_id", t->type);
  278. jsonw_string_field(w, "linkage", linkage);
  279. } else {
  280. printf(" type_id=%u linkage=%s", t->type, linkage);
  281. }
  282. break;
  283. }
  284. case BTF_KIND_FUNC_PROTO: {
  285. const struct btf_param *p = (const void *)(t + 1);
  286. __u16 vlen = BTF_INFO_VLEN(t->info);
  287. int i;
  288. if (json_output) {
  289. jsonw_uint_field(w, "ret_type_id", t->type);
  290. jsonw_uint_field(w, "vlen", vlen);
  291. jsonw_name(w, "params");
  292. jsonw_start_array(w);
  293. } else {
  294. printf(" ret_type_id=%u vlen=%u", t->type, vlen);
  295. }
  296. for (i = 0; i < vlen; i++, p++) {
  297. const char *name = btf_str(btf, p->name_off);
  298. if (json_output) {
  299. jsonw_start_object(w);
  300. jsonw_string_field(w, "name", name);
  301. jsonw_uint_field(w, "type_id", p->type);
  302. jsonw_end_object(w);
  303. } else {
  304. printf("\n\t'%s' type_id=%u", name, p->type);
  305. }
  306. }
  307. if (json_output)
  308. jsonw_end_array(w);
  309. break;
  310. }
  311. case BTF_KIND_VAR: {
  312. const struct btf_var *v = (const void *)(t + 1);
  313. const char *linkage;
  314. linkage = btf_var_linkage_str(v->linkage);
  315. if (json_output) {
  316. jsonw_uint_field(w, "type_id", t->type);
  317. jsonw_string_field(w, "linkage", linkage);
  318. } else {
  319. printf(" type_id=%u, linkage=%s", t->type, linkage);
  320. }
  321. break;
  322. }
  323. case BTF_KIND_DATASEC: {
  324. const struct btf_var_secinfo *v = (const void *)(t + 1);
  325. const struct btf_type *vt;
  326. __u16 vlen = BTF_INFO_VLEN(t->info);
  327. int i;
  328. if (json_output) {
  329. jsonw_uint_field(w, "size", t->size);
  330. jsonw_uint_field(w, "vlen", vlen);
  331. jsonw_name(w, "vars");
  332. jsonw_start_array(w);
  333. } else {
  334. printf(" size=%u vlen=%u", t->size, vlen);
  335. }
  336. for (i = 0; i < vlen; i++, v++) {
  337. if (json_output) {
  338. jsonw_start_object(w);
  339. jsonw_uint_field(w, "type_id", v->type);
  340. jsonw_uint_field(w, "offset", v->offset);
  341. jsonw_uint_field(w, "size", v->size);
  342. jsonw_end_object(w);
  343. } else {
  344. printf("\n\ttype_id=%u offset=%u size=%u",
  345. v->type, v->offset, v->size);
  346. if (v->type < btf__type_cnt(btf)) {
  347. vt = btf__type_by_id(btf, v->type);
  348. printf(" (%s '%s')",
  349. btf_kind_str[btf_kind_safe(btf_kind(vt))],
  350. btf_str(btf, vt->name_off));
  351. }
  352. }
  353. }
  354. if (json_output)
  355. jsonw_end_array(w);
  356. break;
  357. }
  358. case BTF_KIND_FLOAT: {
  359. if (json_output)
  360. jsonw_uint_field(w, "size", t->size);
  361. else
  362. printf(" size=%u", t->size);
  363. break;
  364. }
  365. case BTF_KIND_DECL_TAG: {
  366. const struct btf_decl_tag *tag = (const void *)(t + 1);
  367. if (json_output) {
  368. jsonw_uint_field(w, "type_id", t->type);
  369. jsonw_int_field(w, "component_idx", tag->component_idx);
  370. } else {
  371. printf(" type_id=%u component_idx=%d", t->type, tag->component_idx);
  372. }
  373. break;
  374. }
  375. default:
  376. break;
  377. }
  378. if (json_output)
  379. jsonw_end_object(json_wtr);
  380. else
  381. printf("\n");
  382. return 0;
  383. }
  384. static int dump_btf_raw(const struct btf *btf,
  385. __u32 *root_type_ids, int root_type_cnt)
  386. {
  387. const struct btf_type *t;
  388. int i;
  389. if (json_output) {
  390. jsonw_start_object(json_wtr);
  391. jsonw_name(json_wtr, "types");
  392. jsonw_start_array(json_wtr);
  393. }
  394. if (root_type_cnt) {
  395. for (i = 0; i < root_type_cnt; i++) {
  396. t = btf__type_by_id(btf, root_type_ids[i]);
  397. dump_btf_type(btf, root_type_ids[i], t);
  398. }
  399. } else {
  400. const struct btf *base;
  401. int cnt = btf__type_cnt(btf);
  402. int start_id = 1;
  403. base = btf__base_btf(btf);
  404. if (base)
  405. start_id = btf__type_cnt(base);
  406. for (i = start_id; i < cnt; i++) {
  407. t = btf__type_by_id(btf, i);
  408. dump_btf_type(btf, i, t);
  409. }
  410. }
  411. if (json_output) {
  412. jsonw_end_array(json_wtr);
  413. jsonw_end_object(json_wtr);
  414. }
  415. return 0;
  416. }
  417. static void __printf(2, 0) btf_dump_printf(void *ctx,
  418. const char *fmt, va_list args)
  419. {
  420. vfprintf(stdout, fmt, args);
  421. }
  422. static int dump_btf_c(const struct btf *btf,
  423. __u32 *root_type_ids, int root_type_cnt)
  424. {
  425. struct btf_dump *d;
  426. int err = 0, i;
  427. d = btf_dump__new(btf, btf_dump_printf, NULL, NULL);
  428. err = libbpf_get_error(d);
  429. if (err)
  430. return err;
  431. printf("#ifndef __VMLINUX_H__\n");
  432. printf("#define __VMLINUX_H__\n");
  433. printf("\n");
  434. printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n");
  435. printf("#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)\n");
  436. printf("#endif\n\n");
  437. if (root_type_cnt) {
  438. for (i = 0; i < root_type_cnt; i++) {
  439. err = btf_dump__dump_type(d, root_type_ids[i]);
  440. if (err)
  441. goto done;
  442. }
  443. } else {
  444. int cnt = btf__type_cnt(btf);
  445. for (i = 1; i < cnt; i++) {
  446. err = btf_dump__dump_type(d, i);
  447. if (err)
  448. goto done;
  449. }
  450. }
  451. printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n");
  452. printf("#pragma clang attribute pop\n");
  453. printf("#endif\n");
  454. printf("\n");
  455. printf("#endif /* __VMLINUX_H__ */\n");
  456. done:
  457. btf_dump__free(d);
  458. return err;
  459. }
  460. static const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux";
  461. static struct btf *get_vmlinux_btf_from_sysfs(void)
  462. {
  463. struct btf *base;
  464. base = btf__parse(sysfs_vmlinux, NULL);
  465. if (libbpf_get_error(base)) {
  466. p_err("failed to parse vmlinux BTF at '%s': %ld\n",
  467. sysfs_vmlinux, libbpf_get_error(base));
  468. base = NULL;
  469. }
  470. return base;
  471. }
  472. #define BTF_NAME_BUFF_LEN 64
  473. static bool btf_is_kernel_module(__u32 btf_id)
  474. {
  475. struct bpf_btf_info btf_info = {};
  476. char btf_name[BTF_NAME_BUFF_LEN];
  477. int btf_fd;
  478. __u32 len;
  479. int err;
  480. btf_fd = bpf_btf_get_fd_by_id(btf_id);
  481. if (btf_fd < 0) {
  482. p_err("can't get BTF object by id (%u): %s", btf_id, strerror(errno));
  483. return false;
  484. }
  485. len = sizeof(btf_info);
  486. btf_info.name = ptr_to_u64(btf_name);
  487. btf_info.name_len = sizeof(btf_name);
  488. err = bpf_obj_get_info_by_fd(btf_fd, &btf_info, &len);
  489. close(btf_fd);
  490. if (err) {
  491. p_err("can't get BTF (ID %u) object info: %s", btf_id, strerror(errno));
  492. return false;
  493. }
  494. return btf_info.kernel_btf && strncmp(btf_name, "vmlinux", sizeof(btf_name)) != 0;
  495. }
  496. static int do_dump(int argc, char **argv)
  497. {
  498. struct btf *btf = NULL, *base = NULL;
  499. __u32 root_type_ids[2];
  500. int root_type_cnt = 0;
  501. bool dump_c = false;
  502. __u32 btf_id = -1;
  503. const char *src;
  504. int fd = -1;
  505. int err;
  506. if (!REQ_ARGS(2)) {
  507. usage();
  508. return -1;
  509. }
  510. src = GET_ARG();
  511. if (is_prefix(src, "map")) {
  512. struct bpf_map_info info = {};
  513. __u32 len = sizeof(info);
  514. if (!REQ_ARGS(2)) {
  515. usage();
  516. return -1;
  517. }
  518. fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
  519. if (fd < 0)
  520. return -1;
  521. btf_id = info.btf_id;
  522. if (argc && is_prefix(*argv, "key")) {
  523. root_type_ids[root_type_cnt++] = info.btf_key_type_id;
  524. NEXT_ARG();
  525. } else if (argc && is_prefix(*argv, "value")) {
  526. root_type_ids[root_type_cnt++] = info.btf_value_type_id;
  527. NEXT_ARG();
  528. } else if (argc && is_prefix(*argv, "all")) {
  529. NEXT_ARG();
  530. } else if (argc && is_prefix(*argv, "kv")) {
  531. root_type_ids[root_type_cnt++] = info.btf_key_type_id;
  532. root_type_ids[root_type_cnt++] = info.btf_value_type_id;
  533. NEXT_ARG();
  534. } else {
  535. root_type_ids[root_type_cnt++] = info.btf_key_type_id;
  536. root_type_ids[root_type_cnt++] = info.btf_value_type_id;
  537. }
  538. } else if (is_prefix(src, "prog")) {
  539. struct bpf_prog_info info = {};
  540. __u32 len = sizeof(info);
  541. if (!REQ_ARGS(2)) {
  542. usage();
  543. return -1;
  544. }
  545. fd = prog_parse_fd(&argc, &argv);
  546. if (fd < 0)
  547. return -1;
  548. err = bpf_obj_get_info_by_fd(fd, &info, &len);
  549. if (err) {
  550. p_err("can't get prog info: %s", strerror(errno));
  551. goto done;
  552. }
  553. btf_id = info.btf_id;
  554. } else if (is_prefix(src, "id")) {
  555. char *endptr;
  556. btf_id = strtoul(*argv, &endptr, 0);
  557. if (*endptr) {
  558. p_err("can't parse %s as ID", *argv);
  559. return -1;
  560. }
  561. NEXT_ARG();
  562. } else if (is_prefix(src, "file")) {
  563. const char sysfs_prefix[] = "/sys/kernel/btf/";
  564. if (!base_btf &&
  565. strncmp(*argv, sysfs_prefix, sizeof(sysfs_prefix) - 1) == 0 &&
  566. strcmp(*argv, sysfs_vmlinux) != 0)
  567. base = get_vmlinux_btf_from_sysfs();
  568. btf = btf__parse_split(*argv, base ?: base_btf);
  569. err = libbpf_get_error(btf);
  570. if (!btf) {
  571. p_err("failed to load BTF from %s: %s",
  572. *argv, strerror(errno));
  573. goto done;
  574. }
  575. NEXT_ARG();
  576. } else {
  577. err = -1;
  578. p_err("unrecognized BTF source specifier: '%s'", src);
  579. goto done;
  580. }
  581. while (argc) {
  582. if (is_prefix(*argv, "format")) {
  583. NEXT_ARG();
  584. if (argc < 1) {
  585. p_err("expecting value for 'format' option\n");
  586. err = -EINVAL;
  587. goto done;
  588. }
  589. if (strcmp(*argv, "c") == 0) {
  590. dump_c = true;
  591. } else if (strcmp(*argv, "raw") == 0) {
  592. dump_c = false;
  593. } else {
  594. p_err("unrecognized format specifier: '%s', possible values: raw, c",
  595. *argv);
  596. err = -EINVAL;
  597. goto done;
  598. }
  599. NEXT_ARG();
  600. } else {
  601. p_err("unrecognized option: '%s'", *argv);
  602. err = -EINVAL;
  603. goto done;
  604. }
  605. }
  606. if (!btf) {
  607. if (!base_btf && btf_is_kernel_module(btf_id)) {
  608. p_info("Warning: valid base BTF was not specified with -B option, falling back to standard base BTF (%s)",
  609. sysfs_vmlinux);
  610. base_btf = get_vmlinux_btf_from_sysfs();
  611. }
  612. btf = btf__load_from_kernel_by_id_split(btf_id, base_btf);
  613. err = libbpf_get_error(btf);
  614. if (!btf) {
  615. p_err("get btf by id (%u): %s", btf_id, strerror(errno));
  616. goto done;
  617. }
  618. }
  619. if (dump_c) {
  620. if (json_output) {
  621. p_err("JSON output for C-syntax dump is not supported");
  622. err = -ENOTSUP;
  623. goto done;
  624. }
  625. err = dump_btf_c(btf, root_type_ids, root_type_cnt);
  626. } else {
  627. err = dump_btf_raw(btf, root_type_ids, root_type_cnt);
  628. }
  629. done:
  630. close(fd);
  631. btf__free(btf);
  632. btf__free(base);
  633. return err;
  634. }
  635. static int btf_parse_fd(int *argc, char ***argv)
  636. {
  637. unsigned int id;
  638. char *endptr;
  639. int fd;
  640. if (!is_prefix(*argv[0], "id")) {
  641. p_err("expected 'id', got: '%s'?", **argv);
  642. return -1;
  643. }
  644. NEXT_ARGP();
  645. id = strtoul(**argv, &endptr, 0);
  646. if (*endptr) {
  647. p_err("can't parse %s as ID", **argv);
  648. return -1;
  649. }
  650. NEXT_ARGP();
  651. fd = bpf_btf_get_fd_by_id(id);
  652. if (fd < 0)
  653. p_err("can't get BTF object by id (%u): %s",
  654. id, strerror(errno));
  655. return fd;
  656. }
  657. static int
  658. build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type,
  659. void *info, __u32 *len)
  660. {
  661. static const char * const names[] = {
  662. [BPF_OBJ_UNKNOWN] = "unknown",
  663. [BPF_OBJ_PROG] = "prog",
  664. [BPF_OBJ_MAP] = "map",
  665. };
  666. __u32 btf_id, id = 0;
  667. int err;
  668. int fd;
  669. while (true) {
  670. switch (type) {
  671. case BPF_OBJ_PROG:
  672. err = bpf_prog_get_next_id(id, &id);
  673. break;
  674. case BPF_OBJ_MAP:
  675. err = bpf_map_get_next_id(id, &id);
  676. break;
  677. default:
  678. err = -1;
  679. p_err("unexpected object type: %d", type);
  680. goto err_free;
  681. }
  682. if (err) {
  683. if (errno == ENOENT) {
  684. err = 0;
  685. break;
  686. }
  687. p_err("can't get next %s: %s%s", names[type],
  688. strerror(errno),
  689. errno == EINVAL ? " -- kernel too old?" : "");
  690. goto err_free;
  691. }
  692. switch (type) {
  693. case BPF_OBJ_PROG:
  694. fd = bpf_prog_get_fd_by_id(id);
  695. break;
  696. case BPF_OBJ_MAP:
  697. fd = bpf_map_get_fd_by_id(id);
  698. break;
  699. default:
  700. err = -1;
  701. p_err("unexpected object type: %d", type);
  702. goto err_free;
  703. }
  704. if (fd < 0) {
  705. if (errno == ENOENT)
  706. continue;
  707. p_err("can't get %s by id (%u): %s", names[type], id,
  708. strerror(errno));
  709. err = -1;
  710. goto err_free;
  711. }
  712. memset(info, 0, *len);
  713. err = bpf_obj_get_info_by_fd(fd, info, len);
  714. close(fd);
  715. if (err) {
  716. p_err("can't get %s info: %s", names[type],
  717. strerror(errno));
  718. goto err_free;
  719. }
  720. switch (type) {
  721. case BPF_OBJ_PROG:
  722. btf_id = ((struct bpf_prog_info *)info)->btf_id;
  723. break;
  724. case BPF_OBJ_MAP:
  725. btf_id = ((struct bpf_map_info *)info)->btf_id;
  726. break;
  727. default:
  728. err = -1;
  729. p_err("unexpected object type: %d", type);
  730. goto err_free;
  731. }
  732. if (!btf_id)
  733. continue;
  734. err = hashmap__append(tab, u32_as_hash_field(btf_id),
  735. u32_as_hash_field(id));
  736. if (err) {
  737. p_err("failed to append entry to hashmap for BTF ID %u, object ID %u: %s",
  738. btf_id, id, strerror(-err));
  739. goto err_free;
  740. }
  741. }
  742. return 0;
  743. err_free:
  744. hashmap__free(tab);
  745. return err;
  746. }
  747. static int
  748. build_btf_tables(struct hashmap *btf_prog_table,
  749. struct hashmap *btf_map_table)
  750. {
  751. struct bpf_prog_info prog_info;
  752. __u32 prog_len = sizeof(prog_info);
  753. struct bpf_map_info map_info;
  754. __u32 map_len = sizeof(map_info);
  755. int err = 0;
  756. err = build_btf_type_table(btf_prog_table, BPF_OBJ_PROG, &prog_info,
  757. &prog_len);
  758. if (err)
  759. return err;
  760. err = build_btf_type_table(btf_map_table, BPF_OBJ_MAP, &map_info,
  761. &map_len);
  762. if (err) {
  763. hashmap__free(btf_prog_table);
  764. return err;
  765. }
  766. return 0;
  767. }
  768. static void
  769. show_btf_plain(struct bpf_btf_info *info, int fd,
  770. struct hashmap *btf_prog_table,
  771. struct hashmap *btf_map_table)
  772. {
  773. struct hashmap_entry *entry;
  774. const char *name = u64_to_ptr(info->name);
  775. int n;
  776. printf("%u: ", info->id);
  777. if (info->kernel_btf)
  778. printf("name [%s] ", name);
  779. else if (name && name[0])
  780. printf("name %s ", name);
  781. else
  782. printf("name <anon> ");
  783. printf("size %uB", info->btf_size);
  784. n = 0;
  785. hashmap__for_each_key_entry(btf_prog_table, entry,
  786. u32_as_hash_field(info->id)) {
  787. printf("%s%u", n++ == 0 ? " prog_ids " : ",",
  788. hash_field_as_u32(entry->value));
  789. }
  790. n = 0;
  791. hashmap__for_each_key_entry(btf_map_table, entry,
  792. u32_as_hash_field(info->id)) {
  793. printf("%s%u", n++ == 0 ? " map_ids " : ",",
  794. hash_field_as_u32(entry->value));
  795. }
  796. emit_obj_refs_plain(refs_table, info->id, "\n\tpids ");
  797. printf("\n");
  798. }
  799. static void
  800. show_btf_json(struct bpf_btf_info *info, int fd,
  801. struct hashmap *btf_prog_table,
  802. struct hashmap *btf_map_table)
  803. {
  804. struct hashmap_entry *entry;
  805. const char *name = u64_to_ptr(info->name);
  806. jsonw_start_object(json_wtr); /* btf object */
  807. jsonw_uint_field(json_wtr, "id", info->id);
  808. jsonw_uint_field(json_wtr, "size", info->btf_size);
  809. jsonw_name(json_wtr, "prog_ids");
  810. jsonw_start_array(json_wtr); /* prog_ids */
  811. hashmap__for_each_key_entry(btf_prog_table, entry,
  812. u32_as_hash_field(info->id)) {
  813. jsonw_uint(json_wtr, hash_field_as_u32(entry->value));
  814. }
  815. jsonw_end_array(json_wtr); /* prog_ids */
  816. jsonw_name(json_wtr, "map_ids");
  817. jsonw_start_array(json_wtr); /* map_ids */
  818. hashmap__for_each_key_entry(btf_map_table, entry,
  819. u32_as_hash_field(info->id)) {
  820. jsonw_uint(json_wtr, hash_field_as_u32(entry->value));
  821. }
  822. jsonw_end_array(json_wtr); /* map_ids */
  823. emit_obj_refs_json(refs_table, info->id, json_wtr); /* pids */
  824. jsonw_bool_field(json_wtr, "kernel", info->kernel_btf);
  825. if (name && name[0])
  826. jsonw_string_field(json_wtr, "name", name);
  827. jsonw_end_object(json_wtr); /* btf object */
  828. }
  829. static int
  830. show_btf(int fd, struct hashmap *btf_prog_table,
  831. struct hashmap *btf_map_table)
  832. {
  833. struct bpf_btf_info info;
  834. __u32 len = sizeof(info);
  835. char name[64];
  836. int err;
  837. memset(&info, 0, sizeof(info));
  838. err = bpf_obj_get_info_by_fd(fd, &info, &len);
  839. if (err) {
  840. p_err("can't get BTF object info: %s", strerror(errno));
  841. return -1;
  842. }
  843. /* if kernel support emitting BTF object name, pass name pointer */
  844. if (info.name_len) {
  845. memset(&info, 0, sizeof(info));
  846. info.name_len = sizeof(name);
  847. info.name = ptr_to_u64(name);
  848. len = sizeof(info);
  849. err = bpf_obj_get_info_by_fd(fd, &info, &len);
  850. if (err) {
  851. p_err("can't get BTF object info: %s", strerror(errno));
  852. return -1;
  853. }
  854. }
  855. if (json_output)
  856. show_btf_json(&info, fd, btf_prog_table, btf_map_table);
  857. else
  858. show_btf_plain(&info, fd, btf_prog_table, btf_map_table);
  859. return 0;
  860. }
  861. static int do_show(int argc, char **argv)
  862. {
  863. struct hashmap *btf_prog_table;
  864. struct hashmap *btf_map_table;
  865. int err, fd = -1;
  866. __u32 id = 0;
  867. if (argc == 2) {
  868. fd = btf_parse_fd(&argc, &argv);
  869. if (fd < 0)
  870. return -1;
  871. }
  872. if (argc) {
  873. if (fd >= 0)
  874. close(fd);
  875. return BAD_ARG();
  876. }
  877. btf_prog_table = hashmap__new(hash_fn_for_key_as_id,
  878. equal_fn_for_key_as_id, NULL);
  879. btf_map_table = hashmap__new(hash_fn_for_key_as_id,
  880. equal_fn_for_key_as_id, NULL);
  881. if (IS_ERR(btf_prog_table) || IS_ERR(btf_map_table)) {
  882. hashmap__free(btf_prog_table);
  883. hashmap__free(btf_map_table);
  884. if (fd >= 0)
  885. close(fd);
  886. p_err("failed to create hashmap for object references");
  887. return -1;
  888. }
  889. err = build_btf_tables(btf_prog_table, btf_map_table);
  890. if (err) {
  891. if (fd >= 0)
  892. close(fd);
  893. return err;
  894. }
  895. build_obj_refs_table(&refs_table, BPF_OBJ_BTF);
  896. if (fd >= 0) {
  897. err = show_btf(fd, btf_prog_table, btf_map_table);
  898. close(fd);
  899. goto exit_free;
  900. }
  901. if (json_output)
  902. jsonw_start_array(json_wtr); /* root array */
  903. while (true) {
  904. err = bpf_btf_get_next_id(id, &id);
  905. if (err) {
  906. if (errno == ENOENT) {
  907. err = 0;
  908. break;
  909. }
  910. p_err("can't get next BTF object: %s%s",
  911. strerror(errno),
  912. errno == EINVAL ? " -- kernel too old?" : "");
  913. err = -1;
  914. break;
  915. }
  916. fd = bpf_btf_get_fd_by_id(id);
  917. if (fd < 0) {
  918. if (errno == ENOENT)
  919. continue;
  920. p_err("can't get BTF object by id (%u): %s",
  921. id, strerror(errno));
  922. err = -1;
  923. break;
  924. }
  925. err = show_btf(fd, btf_prog_table, btf_map_table);
  926. close(fd);
  927. if (err)
  928. break;
  929. }
  930. if (json_output)
  931. jsonw_end_array(json_wtr); /* root array */
  932. exit_free:
  933. hashmap__free(btf_prog_table);
  934. hashmap__free(btf_map_table);
  935. delete_obj_refs_table(refs_table);
  936. return err;
  937. }
  938. static int do_help(int argc, char **argv)
  939. {
  940. if (json_output) {
  941. jsonw_null(json_wtr);
  942. return 0;
  943. }
  944. fprintf(stderr,
  945. "Usage: %1$s %2$s { show | list } [id BTF_ID]\n"
  946. " %1$s %2$s dump BTF_SRC [format FORMAT]\n"
  947. " %1$s %2$s help\n"
  948. "\n"
  949. " BTF_SRC := { id BTF_ID | prog PROG | map MAP [{key | value | kv | all}] | file FILE }\n"
  950. " FORMAT := { raw | c }\n"
  951. " " HELP_SPEC_MAP "\n"
  952. " " HELP_SPEC_PROGRAM "\n"
  953. " " HELP_SPEC_OPTIONS " |\n"
  954. " {-B|--base-btf} }\n"
  955. "",
  956. bin_name, "btf");
  957. return 0;
  958. }
  959. static const struct cmd cmds[] = {
  960. { "show", do_show },
  961. { "list", do_show },
  962. { "help", do_help },
  963. { "dump", do_dump },
  964. { 0 }
  965. };
  966. int do_btf(int argc, char **argv)
  967. {
  968. return cmd_select(cmds, argc, argv, do_help);
  969. }