gen.c 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
  2. /* Copyright (C) 2019 Facebook */
  3. #ifndef _GNU_SOURCE
  4. #define _GNU_SOURCE
  5. #endif
  6. #include <ctype.h>
  7. #include <errno.h>
  8. #include <fcntl.h>
  9. #include <libgen.h>
  10. #include <linux/err.h>
  11. #include <stdbool.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <unistd.h>
  15. #include <bpf/bpf.h>
  16. #include <bpf/libbpf.h>
  17. #include <bpf/libbpf_internal.h>
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <sys/mman.h>
  21. #include <bpf/btf.h>
  22. #include "json_writer.h"
  23. #include "main.h"
  24. #define MAX_OBJ_NAME_LEN 64
  25. static void sanitize_identifier(char *name)
  26. {
  27. int i;
  28. for (i = 0; name[i]; i++)
  29. if (!isalnum(name[i]) && name[i] != '_')
  30. name[i] = '_';
  31. }
  32. static bool str_has_prefix(const char *str, const char *prefix)
  33. {
  34. return strncmp(str, prefix, strlen(prefix)) == 0;
  35. }
  36. static bool str_has_suffix(const char *str, const char *suffix)
  37. {
  38. size_t i, n1 = strlen(str), n2 = strlen(suffix);
  39. if (n1 < n2)
  40. return false;
  41. for (i = 0; i < n2; i++) {
  42. if (str[n1 - i - 1] != suffix[n2 - i - 1])
  43. return false;
  44. }
  45. return true;
  46. }
  47. static const struct btf_type *
  48. resolve_func_ptr(const struct btf *btf, __u32 id, __u32 *res_id)
  49. {
  50. const struct btf_type *t;
  51. t = skip_mods_and_typedefs(btf, id, NULL);
  52. if (!btf_is_ptr(t))
  53. return NULL;
  54. t = skip_mods_and_typedefs(btf, t->type, res_id);
  55. return btf_is_func_proto(t) ? t : NULL;
  56. }
  57. static void get_obj_name(char *name, const char *file)
  58. {
  59. char file_copy[PATH_MAX];
  60. /* Using basename() POSIX version to be more portable. */
  61. strncpy(file_copy, file, PATH_MAX - 1)[PATH_MAX - 1] = '\0';
  62. strncpy(name, basename(file_copy), MAX_OBJ_NAME_LEN - 1)[MAX_OBJ_NAME_LEN - 1] = '\0';
  63. if (str_has_suffix(name, ".o"))
  64. name[strlen(name) - 2] = '\0';
  65. sanitize_identifier(name);
  66. }
  67. static void get_header_guard(char *guard, const char *obj_name, const char *suffix)
  68. {
  69. int i;
  70. sprintf(guard, "__%s_%s__", obj_name, suffix);
  71. for (i = 0; guard[i]; i++)
  72. guard[i] = toupper(guard[i]);
  73. }
  74. static bool get_map_ident(const struct bpf_map *map, char *buf, size_t buf_sz)
  75. {
  76. static const char *sfxs[] = { ".data", ".rodata", ".bss", ".kconfig" };
  77. const char *name = bpf_map__name(map);
  78. int i, n;
  79. if (!bpf_map__is_internal(map)) {
  80. snprintf(buf, buf_sz, "%s", name);
  81. return true;
  82. }
  83. for (i = 0, n = ARRAY_SIZE(sfxs); i < n; i++) {
  84. const char *sfx = sfxs[i], *p;
  85. p = strstr(name, sfx);
  86. if (p) {
  87. snprintf(buf, buf_sz, "%s", p + 1);
  88. sanitize_identifier(buf);
  89. return true;
  90. }
  91. }
  92. return false;
  93. }
  94. static bool get_datasec_ident(const char *sec_name, char *buf, size_t buf_sz)
  95. {
  96. static const char *pfxs[] = { ".data", ".rodata", ".bss", ".kconfig" };
  97. int i, n;
  98. /* recognize hard coded LLVM section name */
  99. if (strcmp(sec_name, ".addr_space.1") == 0) {
  100. /* this is the name to use in skeleton */
  101. snprintf(buf, buf_sz, "arena");
  102. return true;
  103. }
  104. for (i = 0, n = ARRAY_SIZE(pfxs); i < n; i++) {
  105. const char *pfx = pfxs[i];
  106. if (str_has_prefix(sec_name, pfx)) {
  107. snprintf(buf, buf_sz, "%s", sec_name + 1);
  108. sanitize_identifier(buf);
  109. return true;
  110. }
  111. }
  112. return false;
  113. }
  114. static void codegen_btf_dump_printf(void *ctx, const char *fmt, va_list args)
  115. {
  116. vprintf(fmt, args);
  117. }
  118. static int codegen_datasec_def(struct bpf_object *obj,
  119. struct btf *btf,
  120. struct btf_dump *d,
  121. const struct btf_type *sec,
  122. const char *obj_name)
  123. {
  124. const char *sec_name = btf__name_by_offset(btf, sec->name_off);
  125. const struct btf_var_secinfo *sec_var = btf_var_secinfos(sec);
  126. int i, err, off = 0, pad_cnt = 0, vlen = btf_vlen(sec);
  127. char var_ident[256], sec_ident[256];
  128. bool strip_mods = false;
  129. if (!get_datasec_ident(sec_name, sec_ident, sizeof(sec_ident)))
  130. return 0;
  131. if (strcmp(sec_name, ".kconfig") != 0)
  132. strip_mods = true;
  133. printf(" struct %s__%s {\n", obj_name, sec_ident);
  134. for (i = 0; i < vlen; i++, sec_var++) {
  135. const struct btf_type *var = btf__type_by_id(btf, sec_var->type);
  136. const char *var_name = btf__name_by_offset(btf, var->name_off);
  137. DECLARE_LIBBPF_OPTS(btf_dump_emit_type_decl_opts, opts,
  138. .field_name = var_ident,
  139. .indent_level = 2,
  140. .strip_mods = strip_mods,
  141. );
  142. int need_off = sec_var->offset, align_off, align;
  143. __u32 var_type_id = var->type;
  144. /* static variables are not exposed through BPF skeleton */
  145. if (btf_var(var)->linkage == BTF_VAR_STATIC)
  146. continue;
  147. if (off > need_off) {
  148. p_err("Something is wrong for %s's variable #%d: need offset %d, already at %d.\n",
  149. sec_name, i, need_off, off);
  150. return -EINVAL;
  151. }
  152. align = btf__align_of(btf, var->type);
  153. if (align <= 0) {
  154. p_err("Failed to determine alignment of variable '%s': %d",
  155. var_name, align);
  156. return -EINVAL;
  157. }
  158. /* Assume 32-bit architectures when generating data section
  159. * struct memory layout. Given bpftool can't know which target
  160. * host architecture it's emitting skeleton for, we need to be
  161. * conservative and assume 32-bit one to ensure enough padding
  162. * bytes are generated for pointer and long types. This will
  163. * still work correctly for 64-bit architectures, because in
  164. * the worst case we'll generate unnecessary padding field,
  165. * which on 64-bit architectures is not strictly necessary and
  166. * would be handled by natural 8-byte alignment. But it still
  167. * will be a correct memory layout, based on recorded offsets
  168. * in BTF.
  169. */
  170. if (align > 4)
  171. align = 4;
  172. align_off = (off + align - 1) / align * align;
  173. if (align_off != need_off) {
  174. printf("\t\tchar __pad%d[%d];\n",
  175. pad_cnt, need_off - off);
  176. pad_cnt++;
  177. }
  178. /* sanitize variable name, e.g., for static vars inside
  179. * a function, it's name is '<function name>.<variable name>',
  180. * which we'll turn into a '<function name>_<variable name>'
  181. */
  182. var_ident[0] = '\0';
  183. strncat(var_ident, var_name, sizeof(var_ident) - 1);
  184. sanitize_identifier(var_ident);
  185. printf("\t\t");
  186. err = btf_dump__emit_type_decl(d, var_type_id, &opts);
  187. if (err)
  188. return err;
  189. printf(";\n");
  190. off = sec_var->offset + sec_var->size;
  191. }
  192. printf(" } *%s;\n", sec_ident);
  193. return 0;
  194. }
  195. static const struct btf_type *find_type_for_map(struct btf *btf, const char *map_ident)
  196. {
  197. int n = btf__type_cnt(btf), i;
  198. char sec_ident[256];
  199. for (i = 1; i < n; i++) {
  200. const struct btf_type *t = btf__type_by_id(btf, i);
  201. const char *name;
  202. if (!btf_is_datasec(t))
  203. continue;
  204. name = btf__str_by_offset(btf, t->name_off);
  205. if (!get_datasec_ident(name, sec_ident, sizeof(sec_ident)))
  206. continue;
  207. if (strcmp(sec_ident, map_ident) == 0)
  208. return t;
  209. }
  210. return NULL;
  211. }
  212. static bool is_mmapable_map(const struct bpf_map *map, char *buf, size_t sz)
  213. {
  214. size_t tmp_sz;
  215. if (bpf_map__type(map) == BPF_MAP_TYPE_ARENA && bpf_map__initial_value(map, &tmp_sz)) {
  216. snprintf(buf, sz, "arena");
  217. return true;
  218. }
  219. if (!bpf_map__is_internal(map) || !(bpf_map__map_flags(map) & BPF_F_MMAPABLE))
  220. return false;
  221. if (!get_map_ident(map, buf, sz))
  222. return false;
  223. return true;
  224. }
  225. static int codegen_datasecs(struct bpf_object *obj, const char *obj_name)
  226. {
  227. struct btf *btf = bpf_object__btf(obj);
  228. struct btf_dump *d;
  229. struct bpf_map *map;
  230. const struct btf_type *sec;
  231. char map_ident[256];
  232. int err = 0;
  233. d = btf_dump__new(btf, codegen_btf_dump_printf, NULL, NULL);
  234. if (!d)
  235. return -errno;
  236. bpf_object__for_each_map(map, obj) {
  237. /* only generate definitions for memory-mapped internal maps */
  238. if (!is_mmapable_map(map, map_ident, sizeof(map_ident)))
  239. continue;
  240. sec = find_type_for_map(btf, map_ident);
  241. /* In some cases (e.g., sections like .rodata.cst16 containing
  242. * compiler allocated string constants only) there will be
  243. * special internal maps with no corresponding DATASEC BTF
  244. * type. In such case, generate empty structs for each such
  245. * map. It will still be memory-mapped and its contents
  246. * accessible from user-space through BPF skeleton.
  247. */
  248. if (!sec) {
  249. printf(" struct %s__%s {\n", obj_name, map_ident);
  250. printf(" } *%s;\n", map_ident);
  251. } else {
  252. err = codegen_datasec_def(obj, btf, d, sec, obj_name);
  253. if (err)
  254. goto out;
  255. }
  256. }
  257. out:
  258. btf_dump__free(d);
  259. return err;
  260. }
  261. static bool btf_is_ptr_to_func_proto(const struct btf *btf,
  262. const struct btf_type *v)
  263. {
  264. return btf_is_ptr(v) && btf_is_func_proto(btf__type_by_id(btf, v->type));
  265. }
  266. static int codegen_subskel_datasecs(struct bpf_object *obj, const char *obj_name)
  267. {
  268. struct btf *btf = bpf_object__btf(obj);
  269. struct btf_dump *d;
  270. struct bpf_map *map;
  271. const struct btf_type *sec, *var;
  272. const struct btf_var_secinfo *sec_var;
  273. int i, err = 0, vlen;
  274. char map_ident[256], sec_ident[256];
  275. bool strip_mods = false, needs_typeof = false;
  276. const char *sec_name, *var_name;
  277. __u32 var_type_id;
  278. d = btf_dump__new(btf, codegen_btf_dump_printf, NULL, NULL);
  279. if (!d)
  280. return -errno;
  281. bpf_object__for_each_map(map, obj) {
  282. /* only generate definitions for memory-mapped internal maps */
  283. if (!is_mmapable_map(map, map_ident, sizeof(map_ident)))
  284. continue;
  285. sec = find_type_for_map(btf, map_ident);
  286. if (!sec)
  287. continue;
  288. sec_name = btf__name_by_offset(btf, sec->name_off);
  289. if (!get_datasec_ident(sec_name, sec_ident, sizeof(sec_ident)))
  290. continue;
  291. strip_mods = strcmp(sec_name, ".kconfig") != 0;
  292. printf(" struct %s__%s {\n", obj_name, sec_ident);
  293. sec_var = btf_var_secinfos(sec);
  294. vlen = btf_vlen(sec);
  295. for (i = 0; i < vlen; i++, sec_var++) {
  296. DECLARE_LIBBPF_OPTS(btf_dump_emit_type_decl_opts, opts,
  297. .indent_level = 2,
  298. .strip_mods = strip_mods,
  299. /* we'll print the name separately */
  300. .field_name = "",
  301. );
  302. var = btf__type_by_id(btf, sec_var->type);
  303. var_name = btf__name_by_offset(btf, var->name_off);
  304. var_type_id = var->type;
  305. /* static variables are not exposed through BPF skeleton */
  306. if (btf_var(var)->linkage == BTF_VAR_STATIC)
  307. continue;
  308. /* The datasec member has KIND_VAR but we want the
  309. * underlying type of the variable (e.g. KIND_INT).
  310. */
  311. var = skip_mods_and_typedefs(btf, var->type, NULL);
  312. printf("\t\t");
  313. /* Func and array members require special handling.
  314. * Instead of producing `typename *var`, they produce
  315. * `typeof(typename) *var`. This allows us to keep a
  316. * similar syntax where the identifier is just prefixed
  317. * by *, allowing us to ignore C declaration minutiae.
  318. */
  319. needs_typeof = btf_is_array(var) || btf_is_ptr_to_func_proto(btf, var);
  320. if (needs_typeof)
  321. printf("__typeof__(");
  322. err = btf_dump__emit_type_decl(d, var_type_id, &opts);
  323. if (err)
  324. goto out;
  325. if (needs_typeof)
  326. printf(")");
  327. printf(" *%s;\n", var_name);
  328. }
  329. printf(" } %s;\n", sec_ident);
  330. }
  331. out:
  332. btf_dump__free(d);
  333. return err;
  334. }
  335. static void codegen(const char *template, ...)
  336. {
  337. const char *src, *end;
  338. int skip_tabs = 0, n;
  339. char *s, *dst;
  340. va_list args;
  341. char c;
  342. n = strlen(template);
  343. s = malloc(n + 1);
  344. if (!s)
  345. exit(-1);
  346. src = template;
  347. dst = s;
  348. /* find out "baseline" indentation to skip */
  349. while ((c = *src++)) {
  350. if (c == '\t') {
  351. skip_tabs++;
  352. } else if (c == '\n') {
  353. break;
  354. } else {
  355. p_err("unrecognized character at pos %td in template '%s': '%c'",
  356. src - template - 1, template, c);
  357. free(s);
  358. exit(-1);
  359. }
  360. }
  361. while (*src) {
  362. /* skip baseline indentation tabs */
  363. for (n = skip_tabs; n > 0; n--, src++) {
  364. if (*src != '\t') {
  365. p_err("not enough tabs at pos %td in template '%s'",
  366. src - template - 1, template);
  367. free(s);
  368. exit(-1);
  369. }
  370. }
  371. /* trim trailing whitespace */
  372. end = strchrnul(src, '\n');
  373. for (n = end - src; n > 0 && isspace(src[n - 1]); n--)
  374. ;
  375. memcpy(dst, src, n);
  376. dst += n;
  377. if (*end)
  378. *dst++ = '\n';
  379. src = *end ? end + 1 : end;
  380. }
  381. *dst++ = '\0';
  382. /* print out using adjusted template */
  383. va_start(args, template);
  384. n = vprintf(s, args);
  385. va_end(args);
  386. free(s);
  387. }
  388. static void print_hex(const char *data, int data_sz)
  389. {
  390. int i, len;
  391. for (i = 0, len = 0; i < data_sz; i++) {
  392. int w = data[i] ? 4 : 2;
  393. len += w;
  394. if (len > 78) {
  395. printf("\\\n");
  396. len = w;
  397. }
  398. if (!data[i])
  399. printf("\\0");
  400. else
  401. printf("\\x%02x", (unsigned char)data[i]);
  402. }
  403. }
  404. static size_t bpf_map_mmap_sz(const struct bpf_map *map)
  405. {
  406. long page_sz = sysconf(_SC_PAGE_SIZE);
  407. size_t map_sz;
  408. map_sz = (size_t)roundup(bpf_map__value_size(map), 8) * bpf_map__max_entries(map);
  409. map_sz = roundup(map_sz, page_sz);
  410. return map_sz;
  411. }
  412. /* Emit type size asserts for all top-level fields in memory-mapped internal maps. */
  413. static void codegen_asserts(struct bpf_object *obj, const char *obj_name)
  414. {
  415. struct btf *btf = bpf_object__btf(obj);
  416. struct bpf_map *map;
  417. struct btf_var_secinfo *sec_var;
  418. int i, vlen;
  419. const struct btf_type *sec;
  420. char map_ident[256], var_ident[256];
  421. if (!btf)
  422. return;
  423. codegen("\
  424. \n\
  425. __attribute__((unused)) static void \n\
  426. %1$s__assert(struct %1$s *s __attribute__((unused))) \n\
  427. { \n\
  428. #ifdef __cplusplus \n\
  429. #define _Static_assert static_assert \n\
  430. #endif \n\
  431. ", obj_name);
  432. bpf_object__for_each_map(map, obj) {
  433. if (!is_mmapable_map(map, map_ident, sizeof(map_ident)))
  434. continue;
  435. sec = find_type_for_map(btf, map_ident);
  436. if (!sec) {
  437. /* best effort, couldn't find the type for this map */
  438. continue;
  439. }
  440. sec_var = btf_var_secinfos(sec);
  441. vlen = btf_vlen(sec);
  442. for (i = 0; i < vlen; i++, sec_var++) {
  443. const struct btf_type *var = btf__type_by_id(btf, sec_var->type);
  444. const char *var_name = btf__name_by_offset(btf, var->name_off);
  445. long var_size;
  446. /* static variables are not exposed through BPF skeleton */
  447. if (btf_var(var)->linkage == BTF_VAR_STATIC)
  448. continue;
  449. var_size = btf__resolve_size(btf, var->type);
  450. if (var_size < 0)
  451. continue;
  452. var_ident[0] = '\0';
  453. strncat(var_ident, var_name, sizeof(var_ident) - 1);
  454. sanitize_identifier(var_ident);
  455. printf("\t_Static_assert(sizeof(s->%s->%s) == %ld, \"unexpected size of '%s'\");\n",
  456. map_ident, var_ident, var_size, var_ident);
  457. }
  458. }
  459. codegen("\
  460. \n\
  461. #ifdef __cplusplus \n\
  462. #undef _Static_assert \n\
  463. #endif \n\
  464. } \n\
  465. ");
  466. }
  467. static void codegen_attach_detach(struct bpf_object *obj, const char *obj_name)
  468. {
  469. struct bpf_program *prog;
  470. bpf_object__for_each_program(prog, obj) {
  471. const char *tp_name;
  472. codegen("\
  473. \n\
  474. \n\
  475. static inline int \n\
  476. %1$s__%2$s__attach(struct %1$s *skel) \n\
  477. { \n\
  478. int prog_fd = skel->progs.%2$s.prog_fd; \n\
  479. ", obj_name, bpf_program__name(prog));
  480. switch (bpf_program__type(prog)) {
  481. case BPF_PROG_TYPE_RAW_TRACEPOINT:
  482. tp_name = strchr(bpf_program__section_name(prog), '/') + 1;
  483. printf("\tint fd = skel_raw_tracepoint_open(\"%s\", prog_fd);\n", tp_name);
  484. break;
  485. case BPF_PROG_TYPE_TRACING:
  486. case BPF_PROG_TYPE_LSM:
  487. if (bpf_program__expected_attach_type(prog) == BPF_TRACE_ITER)
  488. printf("\tint fd = skel_link_create(prog_fd, 0, BPF_TRACE_ITER);\n");
  489. else
  490. printf("\tint fd = skel_raw_tracepoint_open(NULL, prog_fd);\n");
  491. break;
  492. default:
  493. printf("\tint fd = ((void)prog_fd, 0); /* auto-attach not supported */\n");
  494. break;
  495. }
  496. codegen("\
  497. \n\
  498. \n\
  499. if (fd > 0) \n\
  500. skel->links.%1$s_fd = fd; \n\
  501. return fd; \n\
  502. } \n\
  503. ", bpf_program__name(prog));
  504. }
  505. codegen("\
  506. \n\
  507. \n\
  508. static inline int \n\
  509. %1$s__attach(struct %1$s *skel) \n\
  510. { \n\
  511. int ret = 0; \n\
  512. \n\
  513. ", obj_name);
  514. bpf_object__for_each_program(prog, obj) {
  515. codegen("\
  516. \n\
  517. ret = ret < 0 ? ret : %1$s__%2$s__attach(skel); \n\
  518. ", obj_name, bpf_program__name(prog));
  519. }
  520. codegen("\
  521. \n\
  522. return ret < 0 ? ret : 0; \n\
  523. } \n\
  524. \n\
  525. static inline void \n\
  526. %1$s__detach(struct %1$s *skel) \n\
  527. { \n\
  528. ", obj_name);
  529. bpf_object__for_each_program(prog, obj) {
  530. codegen("\
  531. \n\
  532. skel_closenz(skel->links.%1$s_fd); \n\
  533. ", bpf_program__name(prog));
  534. }
  535. codegen("\
  536. \n\
  537. } \n\
  538. ");
  539. }
  540. static void codegen_destroy(struct bpf_object *obj, const char *obj_name)
  541. {
  542. struct bpf_program *prog;
  543. struct bpf_map *map;
  544. char ident[256];
  545. codegen("\
  546. \n\
  547. static void \n\
  548. %1$s__destroy(struct %1$s *skel) \n\
  549. { \n\
  550. if (!skel) \n\
  551. return; \n\
  552. %1$s__detach(skel); \n\
  553. ",
  554. obj_name);
  555. bpf_object__for_each_program(prog, obj) {
  556. codegen("\
  557. \n\
  558. skel_closenz(skel->progs.%1$s.prog_fd); \n\
  559. ", bpf_program__name(prog));
  560. }
  561. bpf_object__for_each_map(map, obj) {
  562. if (!get_map_ident(map, ident, sizeof(ident)))
  563. continue;
  564. if (bpf_map__is_internal(map) &&
  565. (bpf_map__map_flags(map) & BPF_F_MMAPABLE))
  566. printf("\tskel_free_map_data(skel->%1$s, skel->maps.%1$s.initial_value, %2$zd);\n",
  567. ident, bpf_map_mmap_sz(map));
  568. codegen("\
  569. \n\
  570. skel_closenz(skel->maps.%1$s.map_fd); \n\
  571. ", ident);
  572. }
  573. codegen("\
  574. \n\
  575. skel_free(skel); \n\
  576. } \n\
  577. ",
  578. obj_name);
  579. }
  580. static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *header_guard)
  581. {
  582. DECLARE_LIBBPF_OPTS(gen_loader_opts, opts);
  583. struct bpf_map *map;
  584. char ident[256];
  585. int err = 0;
  586. err = bpf_object__gen_loader(obj, &opts);
  587. if (err)
  588. return err;
  589. err = bpf_object__load(obj);
  590. if (err) {
  591. p_err("failed to load object file");
  592. goto out;
  593. }
  594. /* If there was no error during load then gen_loader_opts
  595. * are populated with the loader program.
  596. */
  597. /* finish generating 'struct skel' */
  598. codegen("\
  599. \n\
  600. }; \n\
  601. ", obj_name);
  602. codegen_attach_detach(obj, obj_name);
  603. codegen_destroy(obj, obj_name);
  604. codegen("\
  605. \n\
  606. static inline struct %1$s * \n\
  607. %1$s__open(void) \n\
  608. { \n\
  609. struct %1$s *skel; \n\
  610. \n\
  611. skel = skel_alloc(sizeof(*skel)); \n\
  612. if (!skel) \n\
  613. goto cleanup; \n\
  614. skel->ctx.sz = (void *)&skel->links - (void *)skel; \n\
  615. ",
  616. obj_name, opts.data_sz);
  617. bpf_object__for_each_map(map, obj) {
  618. const void *mmap_data = NULL;
  619. size_t mmap_size = 0;
  620. if (!is_mmapable_map(map, ident, sizeof(ident)))
  621. continue;
  622. codegen("\
  623. \n\
  624. { \n\
  625. static const char data[] __attribute__((__aligned__(8))) = \"\\\n\
  626. ");
  627. mmap_data = bpf_map__initial_value(map, &mmap_size);
  628. print_hex(mmap_data, mmap_size);
  629. codegen("\
  630. \n\
  631. \"; \n\
  632. \n\
  633. skel->%1$s = skel_prep_map_data((void *)data, %2$zd,\n\
  634. sizeof(data) - 1);\n\
  635. if (!skel->%1$s) \n\
  636. goto cleanup; \n\
  637. skel->maps.%1$s.initial_value = (__u64) (long) skel->%1$s;\n\
  638. } \n\
  639. ", ident, bpf_map_mmap_sz(map));
  640. }
  641. codegen("\
  642. \n\
  643. return skel; \n\
  644. cleanup: \n\
  645. %1$s__destroy(skel); \n\
  646. return NULL; \n\
  647. } \n\
  648. \n\
  649. static inline int \n\
  650. %1$s__load(struct %1$s *skel) \n\
  651. { \n\
  652. struct bpf_load_and_run_opts opts = {}; \n\
  653. int err; \n\
  654. static const char opts_data[] __attribute__((__aligned__(8))) = \"\\\n\
  655. ",
  656. obj_name);
  657. print_hex(opts.data, opts.data_sz);
  658. codegen("\
  659. \n\
  660. \"; \n\
  661. static const char opts_insn[] __attribute__((__aligned__(8))) = \"\\\n\
  662. ");
  663. print_hex(opts.insns, opts.insns_sz);
  664. codegen("\
  665. \n\
  666. \"; \n\
  667. \n\
  668. opts.ctx = (struct bpf_loader_ctx *)skel; \n\
  669. opts.data_sz = sizeof(opts_data) - 1; \n\
  670. opts.data = (void *)opts_data; \n\
  671. opts.insns_sz = sizeof(opts_insn) - 1; \n\
  672. opts.insns = (void *)opts_insn; \n\
  673. \n\
  674. err = bpf_load_and_run(&opts); \n\
  675. if (err < 0) \n\
  676. return err; \n\
  677. ");
  678. bpf_object__for_each_map(map, obj) {
  679. const char *mmap_flags;
  680. if (!is_mmapable_map(map, ident, sizeof(ident)))
  681. continue;
  682. if (bpf_map__map_flags(map) & BPF_F_RDONLY_PROG)
  683. mmap_flags = "PROT_READ";
  684. else
  685. mmap_flags = "PROT_READ | PROT_WRITE";
  686. codegen("\
  687. \n\
  688. skel->%1$s = skel_finalize_map_data(&skel->maps.%1$s.initial_value, \n\
  689. %2$zd, %3$s, skel->maps.%1$s.map_fd);\n\
  690. if (!skel->%1$s) \n\
  691. return -ENOMEM; \n\
  692. ",
  693. ident, bpf_map_mmap_sz(map), mmap_flags);
  694. }
  695. codegen("\
  696. \n\
  697. return 0; \n\
  698. } \n\
  699. \n\
  700. static inline struct %1$s * \n\
  701. %1$s__open_and_load(void) \n\
  702. { \n\
  703. struct %1$s *skel; \n\
  704. \n\
  705. skel = %1$s__open(); \n\
  706. if (!skel) \n\
  707. return NULL; \n\
  708. if (%1$s__load(skel)) { \n\
  709. %1$s__destroy(skel); \n\
  710. return NULL; \n\
  711. } \n\
  712. return skel; \n\
  713. } \n\
  714. \n\
  715. ", obj_name);
  716. codegen_asserts(obj, obj_name);
  717. codegen("\
  718. \n\
  719. \n\
  720. #endif /* %s */ \n\
  721. ",
  722. header_guard);
  723. err = 0;
  724. out:
  725. return err;
  726. }
  727. static void
  728. codegen_maps_skeleton(struct bpf_object *obj, size_t map_cnt, bool mmaped, bool populate_links)
  729. {
  730. struct bpf_map *map;
  731. char ident[256];
  732. size_t i, map_sz;
  733. if (!map_cnt)
  734. return;
  735. /* for backward compatibility with old libbpf versions that don't
  736. * handle new BPF skeleton with new struct bpf_map_skeleton definition
  737. * that includes link field, avoid specifying new increased size,
  738. * unless we absolutely have to (i.e., if there are struct_ops maps
  739. * present)
  740. */
  741. map_sz = offsetof(struct bpf_map_skeleton, link);
  742. if (populate_links) {
  743. bpf_object__for_each_map(map, obj) {
  744. if (bpf_map__type(map) == BPF_MAP_TYPE_STRUCT_OPS) {
  745. map_sz = sizeof(struct bpf_map_skeleton);
  746. break;
  747. }
  748. }
  749. }
  750. codegen("\
  751. \n\
  752. \n\
  753. /* maps */ \n\
  754. s->map_cnt = %zu; \n\
  755. s->map_skel_sz = %zu; \n\
  756. s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt,\n\
  757. sizeof(*s->maps) > %zu ? sizeof(*s->maps) : %zu);\n\
  758. if (!s->maps) { \n\
  759. err = -ENOMEM; \n\
  760. goto err; \n\
  761. } \n\
  762. ",
  763. map_cnt, map_sz, map_sz, map_sz
  764. );
  765. i = 0;
  766. bpf_object__for_each_map(map, obj) {
  767. if (!get_map_ident(map, ident, sizeof(ident)))
  768. continue;
  769. codegen("\
  770. \n\
  771. \n\
  772. map = (struct bpf_map_skeleton *)((char *)s->maps + %zu * s->map_skel_sz);\n\
  773. map->name = \"%s\"; \n\
  774. map->map = &obj->maps.%s; \n\
  775. ",
  776. i, bpf_map__name(map), ident);
  777. /* memory-mapped internal maps */
  778. if (mmaped && is_mmapable_map(map, ident, sizeof(ident))) {
  779. printf("\tmap->mmaped = (void **)&obj->%s;\n", ident);
  780. }
  781. if (populate_links && bpf_map__type(map) == BPF_MAP_TYPE_STRUCT_OPS) {
  782. codegen("\
  783. \n\
  784. map->link = &obj->links.%s; \n\
  785. ", ident);
  786. }
  787. i++;
  788. }
  789. }
  790. static void
  791. codegen_progs_skeleton(struct bpf_object *obj, size_t prog_cnt, bool populate_links)
  792. {
  793. struct bpf_program *prog;
  794. int i;
  795. if (!prog_cnt)
  796. return;
  797. codegen("\
  798. \n\
  799. \n\
  800. /* programs */ \n\
  801. s->prog_cnt = %zu; \n\
  802. s->prog_skel_sz = sizeof(*s->progs); \n\
  803. s->progs = (struct bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);\n\
  804. if (!s->progs) { \n\
  805. err = -ENOMEM; \n\
  806. goto err; \n\
  807. } \n\
  808. ",
  809. prog_cnt
  810. );
  811. i = 0;
  812. bpf_object__for_each_program(prog, obj) {
  813. codegen("\
  814. \n\
  815. \n\
  816. s->progs[%1$zu].name = \"%2$s\"; \n\
  817. s->progs[%1$zu].prog = &obj->progs.%2$s;\n\
  818. ",
  819. i, bpf_program__name(prog));
  820. if (populate_links) {
  821. codegen("\
  822. \n\
  823. s->progs[%1$zu].link = &obj->links.%2$s;\n\
  824. ",
  825. i, bpf_program__name(prog));
  826. }
  827. i++;
  828. }
  829. }
  830. static int walk_st_ops_shadow_vars(struct btf *btf, const char *ident,
  831. const struct btf_type *map_type, __u32 map_type_id)
  832. {
  833. LIBBPF_OPTS(btf_dump_emit_type_decl_opts, opts, .indent_level = 3);
  834. const struct btf_type *member_type;
  835. __u32 offset, next_offset = 0;
  836. const struct btf_member *m;
  837. struct btf_dump *d = NULL;
  838. const char *member_name;
  839. __u32 member_type_id;
  840. int i, err = 0, n;
  841. int size;
  842. d = btf_dump__new(btf, codegen_btf_dump_printf, NULL, NULL);
  843. if (!d)
  844. return -errno;
  845. n = btf_vlen(map_type);
  846. for (i = 0, m = btf_members(map_type); i < n; i++, m++) {
  847. member_type = skip_mods_and_typedefs(btf, m->type, &member_type_id);
  848. member_name = btf__name_by_offset(btf, m->name_off);
  849. offset = m->offset / 8;
  850. if (next_offset < offset)
  851. printf("\t\t\tchar __padding_%d[%d];\n", i, offset - next_offset);
  852. switch (btf_kind(member_type)) {
  853. case BTF_KIND_INT:
  854. case BTF_KIND_FLOAT:
  855. case BTF_KIND_ENUM:
  856. case BTF_KIND_ENUM64:
  857. /* scalar type */
  858. printf("\t\t\t");
  859. opts.field_name = member_name;
  860. err = btf_dump__emit_type_decl(d, member_type_id, &opts);
  861. if (err) {
  862. p_err("Failed to emit type declaration for %s: %d", member_name, err);
  863. goto out;
  864. }
  865. printf(";\n");
  866. size = btf__resolve_size(btf, member_type_id);
  867. if (size < 0) {
  868. p_err("Failed to resolve size of %s: %d\n", member_name, size);
  869. err = size;
  870. goto out;
  871. }
  872. next_offset = offset + size;
  873. break;
  874. case BTF_KIND_PTR:
  875. if (resolve_func_ptr(btf, m->type, NULL)) {
  876. /* Function pointer */
  877. printf("\t\t\tstruct bpf_program *%s;\n", member_name);
  878. next_offset = offset + sizeof(void *);
  879. break;
  880. }
  881. /* All pointer types are unsupported except for
  882. * function pointers.
  883. */
  884. fallthrough;
  885. default:
  886. /* Unsupported types
  887. *
  888. * Types other than scalar types and function
  889. * pointers are currently not supported in order to
  890. * prevent conflicts in the generated code caused
  891. * by multiple definitions. For instance, if the
  892. * struct type FOO is used in a struct_ops map,
  893. * bpftool has to generate definitions for FOO,
  894. * which may result in conflicts if FOO is defined
  895. * in different skeleton files.
  896. */
  897. size = btf__resolve_size(btf, member_type_id);
  898. if (size < 0) {
  899. p_err("Failed to resolve size of %s: %d\n", member_name, size);
  900. err = size;
  901. goto out;
  902. }
  903. printf("\t\t\tchar __unsupported_%d[%d];\n", i, size);
  904. next_offset = offset + size;
  905. break;
  906. }
  907. }
  908. /* Cannot fail since it must be a struct type */
  909. size = btf__resolve_size(btf, map_type_id);
  910. if (next_offset < (__u32)size)
  911. printf("\t\t\tchar __padding_end[%d];\n", size - next_offset);
  912. out:
  913. btf_dump__free(d);
  914. return err;
  915. }
  916. /* Generate the pointer of the shadow type for a struct_ops map.
  917. *
  918. * This function adds a pointer of the shadow type for a struct_ops map.
  919. * The members of a struct_ops map can be exported through a pointer to a
  920. * shadow type. The user can access these members through the pointer.
  921. *
  922. * A shadow type includes not all members, only members of some types.
  923. * They are scalar types and function pointers. The function pointers are
  924. * translated to the pointer of the struct bpf_program. The scalar types
  925. * are translated to the original type without any modifiers.
  926. *
  927. * Unsupported types will be translated to a char array to occupy the same
  928. * space as the original field, being renamed as __unsupported_*. The user
  929. * should treat these fields as opaque data.
  930. */
  931. static int gen_st_ops_shadow_type(const char *obj_name, struct btf *btf, const char *ident,
  932. const struct bpf_map *map)
  933. {
  934. const struct btf_type *map_type;
  935. const char *type_name;
  936. __u32 map_type_id;
  937. int err;
  938. map_type_id = bpf_map__btf_value_type_id(map);
  939. if (map_type_id == 0)
  940. return -EINVAL;
  941. map_type = btf__type_by_id(btf, map_type_id);
  942. if (!map_type)
  943. return -EINVAL;
  944. type_name = btf__name_by_offset(btf, map_type->name_off);
  945. printf("\t\tstruct %s__%s__%s {\n", obj_name, ident, type_name);
  946. err = walk_st_ops_shadow_vars(btf, ident, map_type, map_type_id);
  947. if (err)
  948. return err;
  949. printf("\t\t} *%s;\n", ident);
  950. return 0;
  951. }
  952. static int gen_st_ops_shadow(const char *obj_name, struct btf *btf, struct bpf_object *obj)
  953. {
  954. int err, st_ops_cnt = 0;
  955. struct bpf_map *map;
  956. char ident[256];
  957. if (!btf)
  958. return 0;
  959. /* Generate the pointers to shadow types of
  960. * struct_ops maps.
  961. */
  962. bpf_object__for_each_map(map, obj) {
  963. if (bpf_map__type(map) != BPF_MAP_TYPE_STRUCT_OPS)
  964. continue;
  965. if (!get_map_ident(map, ident, sizeof(ident)))
  966. continue;
  967. if (st_ops_cnt == 0) /* first struct_ops map */
  968. printf("\tstruct {\n");
  969. st_ops_cnt++;
  970. err = gen_st_ops_shadow_type(obj_name, btf, ident, map);
  971. if (err)
  972. return err;
  973. }
  974. if (st_ops_cnt)
  975. printf("\t} struct_ops;\n");
  976. return 0;
  977. }
  978. /* Generate the code to initialize the pointers of shadow types. */
  979. static void gen_st_ops_shadow_init(struct btf *btf, struct bpf_object *obj)
  980. {
  981. struct bpf_map *map;
  982. char ident[256];
  983. if (!btf)
  984. return;
  985. /* Initialize the pointers to_ops shadow types of
  986. * struct_ops maps.
  987. */
  988. bpf_object__for_each_map(map, obj) {
  989. if (bpf_map__type(map) != BPF_MAP_TYPE_STRUCT_OPS)
  990. continue;
  991. if (!get_map_ident(map, ident, sizeof(ident)))
  992. continue;
  993. codegen("\
  994. \n\
  995. obj->struct_ops.%1$s = (__typeof__(obj->struct_ops.%1$s))\n\
  996. bpf_map__initial_value(obj->maps.%1$s, NULL);\n\
  997. \n\
  998. ", ident);
  999. }
  1000. }
  1001. static int do_skeleton(int argc, char **argv)
  1002. {
  1003. char header_guard[MAX_OBJ_NAME_LEN + sizeof("__SKEL_H__")];
  1004. size_t map_cnt = 0, prog_cnt = 0, attach_map_cnt = 0, file_sz, mmap_sz;
  1005. DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts);
  1006. char obj_name[MAX_OBJ_NAME_LEN] = "", *obj_data;
  1007. struct bpf_object *obj = NULL;
  1008. const char *file;
  1009. char ident[256];
  1010. struct bpf_program *prog;
  1011. int fd, err = -1;
  1012. struct bpf_map *map;
  1013. struct btf *btf;
  1014. struct stat st;
  1015. if (!REQ_ARGS(1)) {
  1016. usage();
  1017. return -1;
  1018. }
  1019. file = GET_ARG();
  1020. while (argc) {
  1021. if (!REQ_ARGS(2))
  1022. return -1;
  1023. if (is_prefix(*argv, "name")) {
  1024. NEXT_ARG();
  1025. if (obj_name[0] != '\0') {
  1026. p_err("object name already specified");
  1027. return -1;
  1028. }
  1029. strncpy(obj_name, *argv, MAX_OBJ_NAME_LEN - 1);
  1030. obj_name[MAX_OBJ_NAME_LEN - 1] = '\0';
  1031. } else {
  1032. p_err("unknown arg %s", *argv);
  1033. return -1;
  1034. }
  1035. NEXT_ARG();
  1036. }
  1037. if (argc) {
  1038. p_err("extra unknown arguments");
  1039. return -1;
  1040. }
  1041. if (stat(file, &st)) {
  1042. p_err("failed to stat() %s: %s", file, strerror(errno));
  1043. return -1;
  1044. }
  1045. file_sz = st.st_size;
  1046. mmap_sz = roundup(file_sz, sysconf(_SC_PAGE_SIZE));
  1047. fd = open(file, O_RDONLY);
  1048. if (fd < 0) {
  1049. p_err("failed to open() %s: %s", file, strerror(errno));
  1050. return -1;
  1051. }
  1052. obj_data = mmap(NULL, mmap_sz, PROT_READ, MAP_PRIVATE, fd, 0);
  1053. if (obj_data == MAP_FAILED) {
  1054. obj_data = NULL;
  1055. p_err("failed to mmap() %s: %s", file, strerror(errno));
  1056. goto out;
  1057. }
  1058. if (obj_name[0] == '\0')
  1059. get_obj_name(obj_name, file);
  1060. opts.object_name = obj_name;
  1061. if (verifier_logs)
  1062. /* log_level1 + log_level2 + stats, but not stable UAPI */
  1063. opts.kernel_log_level = 1 + 2 + 4;
  1064. obj = bpf_object__open_mem(obj_data, file_sz, &opts);
  1065. if (!obj) {
  1066. char err_buf[256];
  1067. err = -errno;
  1068. libbpf_strerror(err, err_buf, sizeof(err_buf));
  1069. p_err("failed to open BPF object file: %s", err_buf);
  1070. goto out;
  1071. }
  1072. bpf_object__for_each_map(map, obj) {
  1073. if (!get_map_ident(map, ident, sizeof(ident))) {
  1074. p_err("ignoring unrecognized internal map '%s'...",
  1075. bpf_map__name(map));
  1076. continue;
  1077. }
  1078. if (bpf_map__type(map) == BPF_MAP_TYPE_STRUCT_OPS)
  1079. attach_map_cnt++;
  1080. map_cnt++;
  1081. }
  1082. bpf_object__for_each_program(prog, obj) {
  1083. prog_cnt++;
  1084. }
  1085. get_header_guard(header_guard, obj_name, "SKEL_H");
  1086. if (use_loader) {
  1087. codegen("\
  1088. \n\
  1089. /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ \n\
  1090. /* THIS FILE IS AUTOGENERATED BY BPFTOOL! */ \n\
  1091. #ifndef %2$s \n\
  1092. #define %2$s \n\
  1093. \n\
  1094. #include <bpf/skel_internal.h> \n\
  1095. \n\
  1096. struct %1$s { \n\
  1097. struct bpf_loader_ctx ctx; \n\
  1098. ",
  1099. obj_name, header_guard
  1100. );
  1101. } else {
  1102. codegen("\
  1103. \n\
  1104. /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ \n\
  1105. \n\
  1106. /* THIS FILE IS AUTOGENERATED BY BPFTOOL! */ \n\
  1107. #ifndef %2$s \n\
  1108. #define %2$s \n\
  1109. \n\
  1110. #include <errno.h> \n\
  1111. #include <stdlib.h> \n\
  1112. #include <bpf/libbpf.h> \n\
  1113. \n\
  1114. #define BPF_SKEL_SUPPORTS_MAP_AUTO_ATTACH 1 \n\
  1115. \n\
  1116. struct %1$s { \n\
  1117. struct bpf_object_skeleton *skeleton; \n\
  1118. struct bpf_object *obj; \n\
  1119. ",
  1120. obj_name, header_guard
  1121. );
  1122. }
  1123. if (map_cnt) {
  1124. printf("\tstruct {\n");
  1125. bpf_object__for_each_map(map, obj) {
  1126. if (!get_map_ident(map, ident, sizeof(ident)))
  1127. continue;
  1128. if (use_loader)
  1129. printf("\t\tstruct bpf_map_desc %s;\n", ident);
  1130. else
  1131. printf("\t\tstruct bpf_map *%s;\n", ident);
  1132. }
  1133. printf("\t} maps;\n");
  1134. }
  1135. btf = bpf_object__btf(obj);
  1136. err = gen_st_ops_shadow(obj_name, btf, obj);
  1137. if (err)
  1138. goto out;
  1139. if (prog_cnt) {
  1140. printf("\tstruct {\n");
  1141. bpf_object__for_each_program(prog, obj) {
  1142. if (use_loader)
  1143. printf("\t\tstruct bpf_prog_desc %s;\n",
  1144. bpf_program__name(prog));
  1145. else
  1146. printf("\t\tstruct bpf_program *%s;\n",
  1147. bpf_program__name(prog));
  1148. }
  1149. printf("\t} progs;\n");
  1150. }
  1151. if (prog_cnt + attach_map_cnt) {
  1152. printf("\tstruct {\n");
  1153. bpf_object__for_each_program(prog, obj) {
  1154. if (use_loader)
  1155. printf("\t\tint %s_fd;\n",
  1156. bpf_program__name(prog));
  1157. else
  1158. printf("\t\tstruct bpf_link *%s;\n",
  1159. bpf_program__name(prog));
  1160. }
  1161. bpf_object__for_each_map(map, obj) {
  1162. if (!get_map_ident(map, ident, sizeof(ident)))
  1163. continue;
  1164. if (bpf_map__type(map) != BPF_MAP_TYPE_STRUCT_OPS)
  1165. continue;
  1166. if (use_loader)
  1167. printf("t\tint %s_fd;\n", ident);
  1168. else
  1169. printf("\t\tstruct bpf_link *%s;\n", ident);
  1170. }
  1171. printf("\t} links;\n");
  1172. }
  1173. if (btf) {
  1174. err = codegen_datasecs(obj, obj_name);
  1175. if (err)
  1176. goto out;
  1177. }
  1178. if (use_loader) {
  1179. err = gen_trace(obj, obj_name, header_guard);
  1180. goto out;
  1181. }
  1182. codegen("\
  1183. \n\
  1184. \n\
  1185. #ifdef __cplusplus \n\
  1186. static inline struct %1$s *open(const struct bpf_object_open_opts *opts = nullptr);\n\
  1187. static inline struct %1$s *open_and_load(); \n\
  1188. static inline int load(struct %1$s *skel); \n\
  1189. static inline int attach(struct %1$s *skel); \n\
  1190. static inline void detach(struct %1$s *skel); \n\
  1191. static inline void destroy(struct %1$s *skel); \n\
  1192. static inline const void *elf_bytes(size_t *sz); \n\
  1193. #endif /* __cplusplus */ \n\
  1194. }; \n\
  1195. \n\
  1196. static void \n\
  1197. %1$s__destroy(struct %1$s *obj) \n\
  1198. { \n\
  1199. if (!obj) \n\
  1200. return; \n\
  1201. if (obj->skeleton) \n\
  1202. bpf_object__destroy_skeleton(obj->skeleton);\n\
  1203. free(obj); \n\
  1204. } \n\
  1205. \n\
  1206. static inline int \n\
  1207. %1$s__create_skeleton(struct %1$s *obj); \n\
  1208. \n\
  1209. static inline struct %1$s * \n\
  1210. %1$s__open_opts(const struct bpf_object_open_opts *opts) \n\
  1211. { \n\
  1212. struct %1$s *obj; \n\
  1213. int err; \n\
  1214. \n\
  1215. obj = (struct %1$s *)calloc(1, sizeof(*obj)); \n\
  1216. if (!obj) { \n\
  1217. errno = ENOMEM; \n\
  1218. return NULL; \n\
  1219. } \n\
  1220. \n\
  1221. err = %1$s__create_skeleton(obj); \n\
  1222. if (err) \n\
  1223. goto err_out; \n\
  1224. \n\
  1225. err = bpf_object__open_skeleton(obj->skeleton, opts);\n\
  1226. if (err) \n\
  1227. goto err_out; \n\
  1228. \n\
  1229. ", obj_name);
  1230. gen_st_ops_shadow_init(btf, obj);
  1231. codegen("\
  1232. \n\
  1233. return obj; \n\
  1234. err_out: \n\
  1235. %1$s__destroy(obj); \n\
  1236. errno = -err; \n\
  1237. return NULL; \n\
  1238. } \n\
  1239. \n\
  1240. static inline struct %1$s * \n\
  1241. %1$s__open(void) \n\
  1242. { \n\
  1243. return %1$s__open_opts(NULL); \n\
  1244. } \n\
  1245. \n\
  1246. static inline int \n\
  1247. %1$s__load(struct %1$s *obj) \n\
  1248. { \n\
  1249. return bpf_object__load_skeleton(obj->skeleton); \n\
  1250. } \n\
  1251. \n\
  1252. static inline struct %1$s * \n\
  1253. %1$s__open_and_load(void) \n\
  1254. { \n\
  1255. struct %1$s *obj; \n\
  1256. int err; \n\
  1257. \n\
  1258. obj = %1$s__open(); \n\
  1259. if (!obj) \n\
  1260. return NULL; \n\
  1261. err = %1$s__load(obj); \n\
  1262. if (err) { \n\
  1263. %1$s__destroy(obj); \n\
  1264. errno = -err; \n\
  1265. return NULL; \n\
  1266. } \n\
  1267. return obj; \n\
  1268. } \n\
  1269. \n\
  1270. static inline int \n\
  1271. %1$s__attach(struct %1$s *obj) \n\
  1272. { \n\
  1273. return bpf_object__attach_skeleton(obj->skeleton); \n\
  1274. } \n\
  1275. \n\
  1276. static inline void \n\
  1277. %1$s__detach(struct %1$s *obj) \n\
  1278. { \n\
  1279. bpf_object__detach_skeleton(obj->skeleton); \n\
  1280. } \n\
  1281. ",
  1282. obj_name
  1283. );
  1284. codegen("\
  1285. \n\
  1286. \n\
  1287. static inline const void *%1$s__elf_bytes(size_t *sz); \n\
  1288. \n\
  1289. static inline int \n\
  1290. %1$s__create_skeleton(struct %1$s *obj) \n\
  1291. { \n\
  1292. struct bpf_object_skeleton *s; \n\
  1293. struct bpf_map_skeleton *map __attribute__((unused));\n\
  1294. int err; \n\
  1295. \n\
  1296. s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));\n\
  1297. if (!s) { \n\
  1298. err = -ENOMEM; \n\
  1299. goto err; \n\
  1300. } \n\
  1301. \n\
  1302. s->sz = sizeof(*s); \n\
  1303. s->name = \"%1$s\"; \n\
  1304. s->obj = &obj->obj; \n\
  1305. ",
  1306. obj_name
  1307. );
  1308. codegen_maps_skeleton(obj, map_cnt, true /*mmaped*/, true /*links*/);
  1309. codegen_progs_skeleton(obj, prog_cnt, true /*populate_links*/);
  1310. codegen("\
  1311. \n\
  1312. \n\
  1313. s->data = %1$s__elf_bytes(&s->data_sz); \n\
  1314. \n\
  1315. obj->skeleton = s; \n\
  1316. return 0; \n\
  1317. err: \n\
  1318. bpf_object__destroy_skeleton(s); \n\
  1319. return err; \n\
  1320. } \n\
  1321. \n\
  1322. static inline const void *%1$s__elf_bytes(size_t *sz) \n\
  1323. { \n\
  1324. static const char data[] __attribute__((__aligned__(8))) = \"\\\n\
  1325. ",
  1326. obj_name
  1327. );
  1328. /* embed contents of BPF object file */
  1329. print_hex(obj_data, file_sz);
  1330. codegen("\
  1331. \n\
  1332. \"; \n\
  1333. \n\
  1334. *sz = sizeof(data) - 1; \n\
  1335. return (const void *)data; \n\
  1336. } \n\
  1337. \n\
  1338. #ifdef __cplusplus \n\
  1339. struct %1$s *%1$s::open(const struct bpf_object_open_opts *opts) { return %1$s__open_opts(opts); }\n\
  1340. struct %1$s *%1$s::open_and_load() { return %1$s__open_and_load(); } \n\
  1341. int %1$s::load(struct %1$s *skel) { return %1$s__load(skel); } \n\
  1342. int %1$s::attach(struct %1$s *skel) { return %1$s__attach(skel); } \n\
  1343. void %1$s::detach(struct %1$s *skel) { %1$s__detach(skel); } \n\
  1344. void %1$s::destroy(struct %1$s *skel) { %1$s__destroy(skel); } \n\
  1345. const void *%1$s::elf_bytes(size_t *sz) { return %1$s__elf_bytes(sz); } \n\
  1346. #endif /* __cplusplus */ \n\
  1347. \n\
  1348. ",
  1349. obj_name);
  1350. codegen_asserts(obj, obj_name);
  1351. codegen("\
  1352. \n\
  1353. \n\
  1354. #endif /* %1$s */ \n\
  1355. ",
  1356. header_guard);
  1357. err = 0;
  1358. out:
  1359. bpf_object__close(obj);
  1360. if (obj_data)
  1361. munmap(obj_data, mmap_sz);
  1362. close(fd);
  1363. return err;
  1364. }
  1365. /* Subskeletons are like skeletons, except they don't own the bpf_object,
  1366. * associated maps, links, etc. Instead, they know about the existence of
  1367. * variables, maps, programs and are able to find their locations
  1368. * _at runtime_ from an already loaded bpf_object.
  1369. *
  1370. * This allows for library-like BPF objects to have userspace counterparts
  1371. * with access to their own items without having to know anything about the
  1372. * final BPF object that the library was linked into.
  1373. */
  1374. static int do_subskeleton(int argc, char **argv)
  1375. {
  1376. char header_guard[MAX_OBJ_NAME_LEN + sizeof("__SUBSKEL_H__")];
  1377. size_t i, len, file_sz, map_cnt = 0, prog_cnt = 0, mmap_sz, var_cnt = 0, var_idx = 0;
  1378. DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts);
  1379. char obj_name[MAX_OBJ_NAME_LEN] = "", *obj_data;
  1380. struct bpf_object *obj = NULL;
  1381. const char *file, *var_name;
  1382. char ident[256];
  1383. int fd, err = -1, map_type_id;
  1384. const struct bpf_map *map;
  1385. struct bpf_program *prog;
  1386. struct btf *btf;
  1387. const struct btf_type *map_type, *var_type;
  1388. const struct btf_var_secinfo *var;
  1389. struct stat st;
  1390. if (!REQ_ARGS(1)) {
  1391. usage();
  1392. return -1;
  1393. }
  1394. file = GET_ARG();
  1395. while (argc) {
  1396. if (!REQ_ARGS(2))
  1397. return -1;
  1398. if (is_prefix(*argv, "name")) {
  1399. NEXT_ARG();
  1400. if (obj_name[0] != '\0') {
  1401. p_err("object name already specified");
  1402. return -1;
  1403. }
  1404. strncpy(obj_name, *argv, MAX_OBJ_NAME_LEN - 1);
  1405. obj_name[MAX_OBJ_NAME_LEN - 1] = '\0';
  1406. } else {
  1407. p_err("unknown arg %s", *argv);
  1408. return -1;
  1409. }
  1410. NEXT_ARG();
  1411. }
  1412. if (argc) {
  1413. p_err("extra unknown arguments");
  1414. return -1;
  1415. }
  1416. if (use_loader) {
  1417. p_err("cannot use loader for subskeletons");
  1418. return -1;
  1419. }
  1420. if (stat(file, &st)) {
  1421. p_err("failed to stat() %s: %s", file, strerror(errno));
  1422. return -1;
  1423. }
  1424. file_sz = st.st_size;
  1425. mmap_sz = roundup(file_sz, sysconf(_SC_PAGE_SIZE));
  1426. fd = open(file, O_RDONLY);
  1427. if (fd < 0) {
  1428. p_err("failed to open() %s: %s", file, strerror(errno));
  1429. return -1;
  1430. }
  1431. obj_data = mmap(NULL, mmap_sz, PROT_READ, MAP_PRIVATE, fd, 0);
  1432. if (obj_data == MAP_FAILED) {
  1433. obj_data = NULL;
  1434. p_err("failed to mmap() %s: %s", file, strerror(errno));
  1435. goto out;
  1436. }
  1437. if (obj_name[0] == '\0')
  1438. get_obj_name(obj_name, file);
  1439. /* The empty object name allows us to use bpf_map__name and produce
  1440. * ELF section names out of it. (".data" instead of "obj.data")
  1441. */
  1442. opts.object_name = "";
  1443. obj = bpf_object__open_mem(obj_data, file_sz, &opts);
  1444. if (!obj) {
  1445. char err_buf[256];
  1446. libbpf_strerror(errno, err_buf, sizeof(err_buf));
  1447. p_err("failed to open BPF object file: %s", err_buf);
  1448. obj = NULL;
  1449. goto out;
  1450. }
  1451. btf = bpf_object__btf(obj);
  1452. if (!btf) {
  1453. err = -1;
  1454. p_err("need btf type information for %s", obj_name);
  1455. goto out;
  1456. }
  1457. bpf_object__for_each_program(prog, obj) {
  1458. prog_cnt++;
  1459. }
  1460. /* First, count how many variables we have to find.
  1461. * We need this in advance so the subskel can allocate the right
  1462. * amount of storage.
  1463. */
  1464. bpf_object__for_each_map(map, obj) {
  1465. if (!get_map_ident(map, ident, sizeof(ident)))
  1466. continue;
  1467. /* Also count all maps that have a name */
  1468. map_cnt++;
  1469. if (!is_mmapable_map(map, ident, sizeof(ident)))
  1470. continue;
  1471. map_type_id = bpf_map__btf_value_type_id(map);
  1472. if (map_type_id <= 0) {
  1473. err = map_type_id;
  1474. goto out;
  1475. }
  1476. map_type = btf__type_by_id(btf, map_type_id);
  1477. var = btf_var_secinfos(map_type);
  1478. len = btf_vlen(map_type);
  1479. for (i = 0; i < len; i++, var++) {
  1480. var_type = btf__type_by_id(btf, var->type);
  1481. if (btf_var(var_type)->linkage == BTF_VAR_STATIC)
  1482. continue;
  1483. var_cnt++;
  1484. }
  1485. }
  1486. get_header_guard(header_guard, obj_name, "SUBSKEL_H");
  1487. codegen("\
  1488. \n\
  1489. /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ \n\
  1490. \n\
  1491. /* THIS FILE IS AUTOGENERATED! */ \n\
  1492. #ifndef %2$s \n\
  1493. #define %2$s \n\
  1494. \n\
  1495. #include <errno.h> \n\
  1496. #include <stdlib.h> \n\
  1497. #include <bpf/libbpf.h> \n\
  1498. \n\
  1499. struct %1$s { \n\
  1500. struct bpf_object *obj; \n\
  1501. struct bpf_object_subskeleton *subskel; \n\
  1502. ", obj_name, header_guard);
  1503. if (map_cnt) {
  1504. printf("\tstruct {\n");
  1505. bpf_object__for_each_map(map, obj) {
  1506. if (!get_map_ident(map, ident, sizeof(ident)))
  1507. continue;
  1508. printf("\t\tstruct bpf_map *%s;\n", ident);
  1509. }
  1510. printf("\t} maps;\n");
  1511. }
  1512. err = gen_st_ops_shadow(obj_name, btf, obj);
  1513. if (err)
  1514. goto out;
  1515. if (prog_cnt) {
  1516. printf("\tstruct {\n");
  1517. bpf_object__for_each_program(prog, obj) {
  1518. printf("\t\tstruct bpf_program *%s;\n",
  1519. bpf_program__name(prog));
  1520. }
  1521. printf("\t} progs;\n");
  1522. }
  1523. err = codegen_subskel_datasecs(obj, obj_name);
  1524. if (err)
  1525. goto out;
  1526. /* emit code that will allocate enough storage for all symbols */
  1527. codegen("\
  1528. \n\
  1529. \n\
  1530. #ifdef __cplusplus \n\
  1531. static inline struct %1$s *open(const struct bpf_object *src);\n\
  1532. static inline void destroy(struct %1$s *skel); \n\
  1533. #endif /* __cplusplus */ \n\
  1534. }; \n\
  1535. \n\
  1536. static inline void \n\
  1537. %1$s__destroy(struct %1$s *skel) \n\
  1538. { \n\
  1539. if (!skel) \n\
  1540. return; \n\
  1541. if (skel->subskel) \n\
  1542. bpf_object__destroy_subskeleton(skel->subskel);\n\
  1543. free(skel); \n\
  1544. } \n\
  1545. \n\
  1546. static inline struct %1$s * \n\
  1547. %1$s__open(const struct bpf_object *src) \n\
  1548. { \n\
  1549. struct %1$s *obj; \n\
  1550. struct bpf_object_subskeleton *s; \n\
  1551. struct bpf_map_skeleton *map __attribute__((unused));\n\
  1552. int err; \n\
  1553. \n\
  1554. obj = (struct %1$s *)calloc(1, sizeof(*obj)); \n\
  1555. if (!obj) { \n\
  1556. err = -ENOMEM; \n\
  1557. goto err; \n\
  1558. } \n\
  1559. s = (struct bpf_object_subskeleton *)calloc(1, sizeof(*s));\n\
  1560. if (!s) { \n\
  1561. err = -ENOMEM; \n\
  1562. goto err; \n\
  1563. } \n\
  1564. s->sz = sizeof(*s); \n\
  1565. s->obj = src; \n\
  1566. s->var_skel_sz = sizeof(*s->vars); \n\
  1567. obj->subskel = s; \n\
  1568. \n\
  1569. /* vars */ \n\
  1570. s->var_cnt = %2$d; \n\
  1571. s->vars = (struct bpf_var_skeleton *)calloc(%2$d, sizeof(*s->vars));\n\
  1572. if (!s->vars) { \n\
  1573. err = -ENOMEM; \n\
  1574. goto err; \n\
  1575. } \n\
  1576. ",
  1577. obj_name, var_cnt
  1578. );
  1579. /* walk through each symbol and emit the runtime representation */
  1580. bpf_object__for_each_map(map, obj) {
  1581. if (!is_mmapable_map(map, ident, sizeof(ident)))
  1582. continue;
  1583. map_type_id = bpf_map__btf_value_type_id(map);
  1584. if (map_type_id <= 0)
  1585. /* skip over internal maps with no type*/
  1586. continue;
  1587. map_type = btf__type_by_id(btf, map_type_id);
  1588. var = btf_var_secinfos(map_type);
  1589. len = btf_vlen(map_type);
  1590. for (i = 0; i < len; i++, var++) {
  1591. var_type = btf__type_by_id(btf, var->type);
  1592. var_name = btf__name_by_offset(btf, var_type->name_off);
  1593. if (btf_var(var_type)->linkage == BTF_VAR_STATIC)
  1594. continue;
  1595. /* Note that we use the dot prefix in .data as the
  1596. * field access operator i.e. maps%s becomes maps.data
  1597. */
  1598. codegen("\
  1599. \n\
  1600. \n\
  1601. s->vars[%3$d].name = \"%1$s\"; \n\
  1602. s->vars[%3$d].map = &obj->maps.%2$s; \n\
  1603. s->vars[%3$d].addr = (void **) &obj->%2$s.%1$s;\n\
  1604. ", var_name, ident, var_idx);
  1605. var_idx++;
  1606. }
  1607. }
  1608. codegen_maps_skeleton(obj, map_cnt, false /*mmaped*/, false /*links*/);
  1609. codegen_progs_skeleton(obj, prog_cnt, false /*links*/);
  1610. codegen("\
  1611. \n\
  1612. \n\
  1613. err = bpf_object__open_subskeleton(s); \n\
  1614. if (err) \n\
  1615. goto err; \n\
  1616. \n\
  1617. ");
  1618. gen_st_ops_shadow_init(btf, obj);
  1619. codegen("\
  1620. \n\
  1621. return obj; \n\
  1622. err: \n\
  1623. %1$s__destroy(obj); \n\
  1624. errno = -err; \n\
  1625. return NULL; \n\
  1626. } \n\
  1627. \n\
  1628. #ifdef __cplusplus \n\
  1629. struct %1$s *%1$s::open(const struct bpf_object *src) { return %1$s__open(src); }\n\
  1630. void %1$s::destroy(struct %1$s *skel) { %1$s__destroy(skel); }\n\
  1631. #endif /* __cplusplus */ \n\
  1632. \n\
  1633. #endif /* %2$s */ \n\
  1634. ",
  1635. obj_name, header_guard);
  1636. err = 0;
  1637. out:
  1638. bpf_object__close(obj);
  1639. if (obj_data)
  1640. munmap(obj_data, mmap_sz);
  1641. close(fd);
  1642. return err;
  1643. }
  1644. static int do_object(int argc, char **argv)
  1645. {
  1646. struct bpf_linker *linker;
  1647. const char *output_file, *file;
  1648. int err = 0;
  1649. if (!REQ_ARGS(2)) {
  1650. usage();
  1651. return -1;
  1652. }
  1653. output_file = GET_ARG();
  1654. linker = bpf_linker__new(output_file, NULL);
  1655. if (!linker) {
  1656. p_err("failed to create BPF linker instance");
  1657. return -1;
  1658. }
  1659. while (argc) {
  1660. file = GET_ARG();
  1661. err = bpf_linker__add_file(linker, file, NULL);
  1662. if (err) {
  1663. p_err("failed to link '%s': %s (%d)", file, strerror(errno), errno);
  1664. goto out;
  1665. }
  1666. }
  1667. err = bpf_linker__finalize(linker);
  1668. if (err) {
  1669. p_err("failed to finalize ELF file: %s (%d)", strerror(errno), errno);
  1670. goto out;
  1671. }
  1672. err = 0;
  1673. out:
  1674. bpf_linker__free(linker);
  1675. return err;
  1676. }
  1677. static int do_help(int argc, char **argv)
  1678. {
  1679. if (json_output) {
  1680. jsonw_null(json_wtr);
  1681. return 0;
  1682. }
  1683. fprintf(stderr,
  1684. "Usage: %1$s %2$s object OUTPUT_FILE INPUT_FILE [INPUT_FILE...]\n"
  1685. " %1$s %2$s skeleton FILE [name OBJECT_NAME]\n"
  1686. " %1$s %2$s subskeleton FILE [name OBJECT_NAME]\n"
  1687. " %1$s %2$s min_core_btf INPUT OUTPUT OBJECT [OBJECT...]\n"
  1688. " %1$s %2$s help\n"
  1689. "\n"
  1690. " " HELP_SPEC_OPTIONS " |\n"
  1691. " {-L|--use-loader} }\n"
  1692. "",
  1693. bin_name, "gen");
  1694. return 0;
  1695. }
  1696. static int btf_save_raw(const struct btf *btf, const char *path)
  1697. {
  1698. const void *data;
  1699. FILE *f = NULL;
  1700. __u32 data_sz;
  1701. int err = 0;
  1702. data = btf__raw_data(btf, &data_sz);
  1703. if (!data)
  1704. return -ENOMEM;
  1705. f = fopen(path, "wb");
  1706. if (!f)
  1707. return -errno;
  1708. if (fwrite(data, 1, data_sz, f) != data_sz)
  1709. err = -errno;
  1710. fclose(f);
  1711. return err;
  1712. }
  1713. struct btfgen_info {
  1714. struct btf *src_btf;
  1715. struct btf *marked_btf; /* btf structure used to mark used types */
  1716. };
  1717. static size_t btfgen_hash_fn(long key, void *ctx)
  1718. {
  1719. return key;
  1720. }
  1721. static bool btfgen_equal_fn(long k1, long k2, void *ctx)
  1722. {
  1723. return k1 == k2;
  1724. }
  1725. static void btfgen_free_info(struct btfgen_info *info)
  1726. {
  1727. if (!info)
  1728. return;
  1729. btf__free(info->src_btf);
  1730. btf__free(info->marked_btf);
  1731. free(info);
  1732. }
  1733. static struct btfgen_info *
  1734. btfgen_new_info(const char *targ_btf_path)
  1735. {
  1736. struct btfgen_info *info;
  1737. int err;
  1738. info = calloc(1, sizeof(*info));
  1739. if (!info)
  1740. return NULL;
  1741. info->src_btf = btf__parse(targ_btf_path, NULL);
  1742. if (!info->src_btf) {
  1743. err = -errno;
  1744. p_err("failed parsing '%s' BTF file: %s", targ_btf_path, strerror(errno));
  1745. goto err_out;
  1746. }
  1747. info->marked_btf = btf__parse(targ_btf_path, NULL);
  1748. if (!info->marked_btf) {
  1749. err = -errno;
  1750. p_err("failed parsing '%s' BTF file: %s", targ_btf_path, strerror(errno));
  1751. goto err_out;
  1752. }
  1753. return info;
  1754. err_out:
  1755. btfgen_free_info(info);
  1756. errno = -err;
  1757. return NULL;
  1758. }
  1759. #define MARKED UINT32_MAX
  1760. static void btfgen_mark_member(struct btfgen_info *info, int type_id, int idx)
  1761. {
  1762. const struct btf_type *t = btf__type_by_id(info->marked_btf, type_id);
  1763. struct btf_member *m = btf_members(t) + idx;
  1764. m->name_off = MARKED;
  1765. }
  1766. static int
  1767. btfgen_mark_type(struct btfgen_info *info, unsigned int type_id, bool follow_pointers)
  1768. {
  1769. const struct btf_type *btf_type = btf__type_by_id(info->src_btf, type_id);
  1770. struct btf_type *cloned_type;
  1771. struct btf_param *param;
  1772. struct btf_array *array;
  1773. int err, i;
  1774. if (type_id == 0)
  1775. return 0;
  1776. /* mark type on cloned BTF as used */
  1777. cloned_type = (struct btf_type *) btf__type_by_id(info->marked_btf, type_id);
  1778. cloned_type->name_off = MARKED;
  1779. /* recursively mark other types needed by it */
  1780. switch (btf_kind(btf_type)) {
  1781. case BTF_KIND_UNKN:
  1782. case BTF_KIND_INT:
  1783. case BTF_KIND_FLOAT:
  1784. case BTF_KIND_ENUM:
  1785. case BTF_KIND_ENUM64:
  1786. case BTF_KIND_STRUCT:
  1787. case BTF_KIND_UNION:
  1788. break;
  1789. case BTF_KIND_PTR:
  1790. if (follow_pointers) {
  1791. err = btfgen_mark_type(info, btf_type->type, follow_pointers);
  1792. if (err)
  1793. return err;
  1794. }
  1795. break;
  1796. case BTF_KIND_CONST:
  1797. case BTF_KIND_RESTRICT:
  1798. case BTF_KIND_VOLATILE:
  1799. case BTF_KIND_TYPEDEF:
  1800. err = btfgen_mark_type(info, btf_type->type, follow_pointers);
  1801. if (err)
  1802. return err;
  1803. break;
  1804. case BTF_KIND_ARRAY:
  1805. array = btf_array(btf_type);
  1806. /* mark array type */
  1807. err = btfgen_mark_type(info, array->type, follow_pointers);
  1808. /* mark array's index type */
  1809. err = err ? : btfgen_mark_type(info, array->index_type, follow_pointers);
  1810. if (err)
  1811. return err;
  1812. break;
  1813. case BTF_KIND_FUNC_PROTO:
  1814. /* mark ret type */
  1815. err = btfgen_mark_type(info, btf_type->type, follow_pointers);
  1816. if (err)
  1817. return err;
  1818. /* mark parameters types */
  1819. param = btf_params(btf_type);
  1820. for (i = 0; i < btf_vlen(btf_type); i++) {
  1821. err = btfgen_mark_type(info, param->type, follow_pointers);
  1822. if (err)
  1823. return err;
  1824. param++;
  1825. }
  1826. break;
  1827. /* tells if some other type needs to be handled */
  1828. default:
  1829. p_err("unsupported kind: %s (%d)", btf_kind_str(btf_type), type_id);
  1830. return -EINVAL;
  1831. }
  1832. return 0;
  1833. }
  1834. static int btfgen_record_field_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec)
  1835. {
  1836. struct btf *btf = info->src_btf;
  1837. const struct btf_type *btf_type;
  1838. struct btf_member *btf_member;
  1839. struct btf_array *array;
  1840. unsigned int type_id = targ_spec->root_type_id;
  1841. int idx, err;
  1842. /* mark root type */
  1843. btf_type = btf__type_by_id(btf, type_id);
  1844. err = btfgen_mark_type(info, type_id, false);
  1845. if (err)
  1846. return err;
  1847. /* mark types for complex types (arrays, unions, structures) */
  1848. for (int i = 1; i < targ_spec->raw_len; i++) {
  1849. /* skip typedefs and mods */
  1850. while (btf_is_mod(btf_type) || btf_is_typedef(btf_type)) {
  1851. type_id = btf_type->type;
  1852. btf_type = btf__type_by_id(btf, type_id);
  1853. }
  1854. switch (btf_kind(btf_type)) {
  1855. case BTF_KIND_STRUCT:
  1856. case BTF_KIND_UNION:
  1857. idx = targ_spec->raw_spec[i];
  1858. btf_member = btf_members(btf_type) + idx;
  1859. /* mark member */
  1860. btfgen_mark_member(info, type_id, idx);
  1861. /* mark member's type */
  1862. type_id = btf_member->type;
  1863. btf_type = btf__type_by_id(btf, type_id);
  1864. err = btfgen_mark_type(info, type_id, false);
  1865. if (err)
  1866. return err;
  1867. break;
  1868. case BTF_KIND_ARRAY:
  1869. array = btf_array(btf_type);
  1870. type_id = array->type;
  1871. btf_type = btf__type_by_id(btf, type_id);
  1872. break;
  1873. default:
  1874. p_err("unsupported kind: %s (%d)",
  1875. btf_kind_str(btf_type), btf_type->type);
  1876. return -EINVAL;
  1877. }
  1878. }
  1879. return 0;
  1880. }
  1881. /* Mark types, members, and member types. Compared to btfgen_record_field_relo,
  1882. * this function does not rely on the target spec for inferring members, but
  1883. * uses the associated BTF.
  1884. *
  1885. * The `behind_ptr` argument is used to stop marking of composite types reached
  1886. * through a pointer. This way, we can keep BTF size in check while providing
  1887. * reasonable match semantics.
  1888. */
  1889. static int btfgen_mark_type_match(struct btfgen_info *info, __u32 type_id, bool behind_ptr)
  1890. {
  1891. const struct btf_type *btf_type;
  1892. struct btf *btf = info->src_btf;
  1893. struct btf_type *cloned_type;
  1894. int i, err;
  1895. if (type_id == 0)
  1896. return 0;
  1897. btf_type = btf__type_by_id(btf, type_id);
  1898. /* mark type on cloned BTF as used */
  1899. cloned_type = (struct btf_type *)btf__type_by_id(info->marked_btf, type_id);
  1900. cloned_type->name_off = MARKED;
  1901. switch (btf_kind(btf_type)) {
  1902. case BTF_KIND_UNKN:
  1903. case BTF_KIND_INT:
  1904. case BTF_KIND_FLOAT:
  1905. case BTF_KIND_ENUM:
  1906. case BTF_KIND_ENUM64:
  1907. break;
  1908. case BTF_KIND_STRUCT:
  1909. case BTF_KIND_UNION: {
  1910. struct btf_member *m = btf_members(btf_type);
  1911. __u16 vlen = btf_vlen(btf_type);
  1912. if (behind_ptr)
  1913. break;
  1914. for (i = 0; i < vlen; i++, m++) {
  1915. /* mark member */
  1916. btfgen_mark_member(info, type_id, i);
  1917. /* mark member's type */
  1918. err = btfgen_mark_type_match(info, m->type, false);
  1919. if (err)
  1920. return err;
  1921. }
  1922. break;
  1923. }
  1924. case BTF_KIND_CONST:
  1925. case BTF_KIND_FWD:
  1926. case BTF_KIND_RESTRICT:
  1927. case BTF_KIND_TYPEDEF:
  1928. case BTF_KIND_VOLATILE:
  1929. return btfgen_mark_type_match(info, btf_type->type, behind_ptr);
  1930. case BTF_KIND_PTR:
  1931. return btfgen_mark_type_match(info, btf_type->type, true);
  1932. case BTF_KIND_ARRAY: {
  1933. struct btf_array *array;
  1934. array = btf_array(btf_type);
  1935. /* mark array type */
  1936. err = btfgen_mark_type_match(info, array->type, false);
  1937. /* mark array's index type */
  1938. err = err ? : btfgen_mark_type_match(info, array->index_type, false);
  1939. if (err)
  1940. return err;
  1941. break;
  1942. }
  1943. case BTF_KIND_FUNC_PROTO: {
  1944. __u16 vlen = btf_vlen(btf_type);
  1945. struct btf_param *param;
  1946. /* mark ret type */
  1947. err = btfgen_mark_type_match(info, btf_type->type, false);
  1948. if (err)
  1949. return err;
  1950. /* mark parameters types */
  1951. param = btf_params(btf_type);
  1952. for (i = 0; i < vlen; i++) {
  1953. err = btfgen_mark_type_match(info, param->type, false);
  1954. if (err)
  1955. return err;
  1956. param++;
  1957. }
  1958. break;
  1959. }
  1960. /* tells if some other type needs to be handled */
  1961. default:
  1962. p_err("unsupported kind: %s (%d)", btf_kind_str(btf_type), type_id);
  1963. return -EINVAL;
  1964. }
  1965. return 0;
  1966. }
  1967. /* Mark types, members, and member types. Compared to btfgen_record_field_relo,
  1968. * this function does not rely on the target spec for inferring members, but
  1969. * uses the associated BTF.
  1970. */
  1971. static int btfgen_record_type_match_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec)
  1972. {
  1973. return btfgen_mark_type_match(info, targ_spec->root_type_id, false);
  1974. }
  1975. static int btfgen_record_type_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec)
  1976. {
  1977. return btfgen_mark_type(info, targ_spec->root_type_id, true);
  1978. }
  1979. static int btfgen_record_enumval_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec)
  1980. {
  1981. return btfgen_mark_type(info, targ_spec->root_type_id, false);
  1982. }
  1983. static int btfgen_record_reloc(struct btfgen_info *info, struct bpf_core_spec *res)
  1984. {
  1985. switch (res->relo_kind) {
  1986. case BPF_CORE_FIELD_BYTE_OFFSET:
  1987. case BPF_CORE_FIELD_BYTE_SIZE:
  1988. case BPF_CORE_FIELD_EXISTS:
  1989. case BPF_CORE_FIELD_SIGNED:
  1990. case BPF_CORE_FIELD_LSHIFT_U64:
  1991. case BPF_CORE_FIELD_RSHIFT_U64:
  1992. return btfgen_record_field_relo(info, res);
  1993. case BPF_CORE_TYPE_ID_LOCAL: /* BPF_CORE_TYPE_ID_LOCAL doesn't require kernel BTF */
  1994. return 0;
  1995. case BPF_CORE_TYPE_ID_TARGET:
  1996. case BPF_CORE_TYPE_EXISTS:
  1997. case BPF_CORE_TYPE_SIZE:
  1998. return btfgen_record_type_relo(info, res);
  1999. case BPF_CORE_TYPE_MATCHES:
  2000. return btfgen_record_type_match_relo(info, res);
  2001. case BPF_CORE_ENUMVAL_EXISTS:
  2002. case BPF_CORE_ENUMVAL_VALUE:
  2003. return btfgen_record_enumval_relo(info, res);
  2004. default:
  2005. return -EINVAL;
  2006. }
  2007. }
  2008. static struct bpf_core_cand_list *
  2009. btfgen_find_cands(const struct btf *local_btf, const struct btf *targ_btf, __u32 local_id)
  2010. {
  2011. const struct btf_type *local_type;
  2012. struct bpf_core_cand_list *cands = NULL;
  2013. struct bpf_core_cand local_cand = {};
  2014. size_t local_essent_len;
  2015. const char *local_name;
  2016. int err;
  2017. local_cand.btf = local_btf;
  2018. local_cand.id = local_id;
  2019. local_type = btf__type_by_id(local_btf, local_id);
  2020. if (!local_type) {
  2021. err = -EINVAL;
  2022. goto err_out;
  2023. }
  2024. local_name = btf__name_by_offset(local_btf, local_type->name_off);
  2025. if (!local_name) {
  2026. err = -EINVAL;
  2027. goto err_out;
  2028. }
  2029. local_essent_len = bpf_core_essential_name_len(local_name);
  2030. cands = calloc(1, sizeof(*cands));
  2031. if (!cands)
  2032. return NULL;
  2033. err = bpf_core_add_cands(&local_cand, local_essent_len, targ_btf, "vmlinux", 1, cands);
  2034. if (err)
  2035. goto err_out;
  2036. return cands;
  2037. err_out:
  2038. bpf_core_free_cands(cands);
  2039. errno = -err;
  2040. return NULL;
  2041. }
  2042. /* Record relocation information for a single BPF object */
  2043. static int btfgen_record_obj(struct btfgen_info *info, const char *obj_path)
  2044. {
  2045. const struct btf_ext_info_sec *sec;
  2046. const struct bpf_core_relo *relo;
  2047. const struct btf_ext_info *seg;
  2048. struct hashmap_entry *entry;
  2049. struct hashmap *cand_cache = NULL;
  2050. struct btf_ext *btf_ext = NULL;
  2051. unsigned int relo_idx;
  2052. struct btf *btf = NULL;
  2053. size_t i;
  2054. int err;
  2055. btf = btf__parse(obj_path, &btf_ext);
  2056. if (!btf) {
  2057. err = -errno;
  2058. p_err("failed to parse BPF object '%s': %s", obj_path, strerror(errno));
  2059. return err;
  2060. }
  2061. if (!btf_ext) {
  2062. p_err("failed to parse BPF object '%s': section %s not found",
  2063. obj_path, BTF_EXT_ELF_SEC);
  2064. err = -EINVAL;
  2065. goto out;
  2066. }
  2067. if (btf_ext->core_relo_info.len == 0) {
  2068. err = 0;
  2069. goto out;
  2070. }
  2071. cand_cache = hashmap__new(btfgen_hash_fn, btfgen_equal_fn, NULL);
  2072. if (IS_ERR(cand_cache)) {
  2073. err = PTR_ERR(cand_cache);
  2074. goto out;
  2075. }
  2076. seg = &btf_ext->core_relo_info;
  2077. for_each_btf_ext_sec(seg, sec) {
  2078. for_each_btf_ext_rec(seg, sec, relo_idx, relo) {
  2079. struct bpf_core_spec specs_scratch[3] = {};
  2080. struct bpf_core_relo_res targ_res = {};
  2081. struct bpf_core_cand_list *cands = NULL;
  2082. const char *sec_name = btf__name_by_offset(btf, sec->sec_name_off);
  2083. if (relo->kind != BPF_CORE_TYPE_ID_LOCAL &&
  2084. !hashmap__find(cand_cache, relo->type_id, &cands)) {
  2085. cands = btfgen_find_cands(btf, info->src_btf, relo->type_id);
  2086. if (!cands) {
  2087. err = -errno;
  2088. goto out;
  2089. }
  2090. err = hashmap__set(cand_cache, relo->type_id, cands,
  2091. NULL, NULL);
  2092. if (err)
  2093. goto out;
  2094. }
  2095. err = bpf_core_calc_relo_insn(sec_name, relo, relo_idx, btf, cands,
  2096. specs_scratch, &targ_res);
  2097. if (err)
  2098. goto out;
  2099. /* specs_scratch[2] is the target spec */
  2100. err = btfgen_record_reloc(info, &specs_scratch[2]);
  2101. if (err)
  2102. goto out;
  2103. }
  2104. }
  2105. out:
  2106. btf__free(btf);
  2107. btf_ext__free(btf_ext);
  2108. if (!IS_ERR_OR_NULL(cand_cache)) {
  2109. hashmap__for_each_entry(cand_cache, entry, i) {
  2110. bpf_core_free_cands(entry->pvalue);
  2111. }
  2112. hashmap__free(cand_cache);
  2113. }
  2114. return err;
  2115. }
  2116. /* Generate BTF from relocation information previously recorded */
  2117. static struct btf *btfgen_get_btf(struct btfgen_info *info)
  2118. {
  2119. struct btf *btf_new = NULL;
  2120. unsigned int *ids = NULL;
  2121. unsigned int i, n = btf__type_cnt(info->marked_btf);
  2122. int err = 0;
  2123. btf_new = btf__new_empty();
  2124. if (!btf_new) {
  2125. err = -errno;
  2126. goto err_out;
  2127. }
  2128. ids = calloc(n, sizeof(*ids));
  2129. if (!ids) {
  2130. err = -errno;
  2131. goto err_out;
  2132. }
  2133. /* first pass: add all marked types to btf_new and add their new ids to the ids map */
  2134. for (i = 1; i < n; i++) {
  2135. const struct btf_type *cloned_type, *type;
  2136. const char *name;
  2137. int new_id;
  2138. cloned_type = btf__type_by_id(info->marked_btf, i);
  2139. if (cloned_type->name_off != MARKED)
  2140. continue;
  2141. type = btf__type_by_id(info->src_btf, i);
  2142. /* add members for struct and union */
  2143. if (btf_is_composite(type)) {
  2144. struct btf_member *cloned_m, *m;
  2145. unsigned short vlen;
  2146. int idx_src;
  2147. name = btf__str_by_offset(info->src_btf, type->name_off);
  2148. if (btf_is_struct(type))
  2149. err = btf__add_struct(btf_new, name, type->size);
  2150. else
  2151. err = btf__add_union(btf_new, name, type->size);
  2152. if (err < 0)
  2153. goto err_out;
  2154. new_id = err;
  2155. cloned_m = btf_members(cloned_type);
  2156. m = btf_members(type);
  2157. vlen = btf_vlen(cloned_type);
  2158. for (idx_src = 0; idx_src < vlen; idx_src++, cloned_m++, m++) {
  2159. /* add only members that are marked as used */
  2160. if (cloned_m->name_off != MARKED)
  2161. continue;
  2162. name = btf__str_by_offset(info->src_btf, m->name_off);
  2163. err = btf__add_field(btf_new, name, m->type,
  2164. btf_member_bit_offset(cloned_type, idx_src),
  2165. btf_member_bitfield_size(cloned_type, idx_src));
  2166. if (err < 0)
  2167. goto err_out;
  2168. }
  2169. } else {
  2170. err = btf__add_type(btf_new, info->src_btf, type);
  2171. if (err < 0)
  2172. goto err_out;
  2173. new_id = err;
  2174. }
  2175. /* add ID mapping */
  2176. ids[i] = new_id;
  2177. }
  2178. /* second pass: fix up type ids */
  2179. for (i = 1; i < btf__type_cnt(btf_new); i++) {
  2180. struct btf_type *btf_type = (struct btf_type *) btf__type_by_id(btf_new, i);
  2181. struct btf_field_iter it;
  2182. __u32 *type_id;
  2183. err = btf_field_iter_init(&it, btf_type, BTF_FIELD_ITER_IDS);
  2184. if (err)
  2185. goto err_out;
  2186. while ((type_id = btf_field_iter_next(&it)))
  2187. *type_id = ids[*type_id];
  2188. }
  2189. free(ids);
  2190. return btf_new;
  2191. err_out:
  2192. btf__free(btf_new);
  2193. free(ids);
  2194. errno = -err;
  2195. return NULL;
  2196. }
  2197. /* Create minimized BTF file for a set of BPF objects.
  2198. *
  2199. * The BTFGen algorithm is divided in two main parts: (1) collect the
  2200. * BTF types that are involved in relocations and (2) generate the BTF
  2201. * object using the collected types.
  2202. *
  2203. * In order to collect the types involved in the relocations, we parse
  2204. * the BTF and BTF.ext sections of the BPF objects and use
  2205. * bpf_core_calc_relo_insn() to get the target specification, this
  2206. * indicates how the types and fields are used in a relocation.
  2207. *
  2208. * Types are recorded in different ways according to the kind of the
  2209. * relocation. For field-based relocations only the members that are
  2210. * actually used are saved in order to reduce the size of the generated
  2211. * BTF file. For type-based relocations empty struct / unions are
  2212. * generated and for enum-based relocations the whole type is saved.
  2213. *
  2214. * The second part of the algorithm generates the BTF object. It creates
  2215. * an empty BTF object and fills it with the types recorded in the
  2216. * previous step. This function takes care of only adding the structure
  2217. * and union members that were marked as used and it also fixes up the
  2218. * type IDs on the generated BTF object.
  2219. */
  2220. static int minimize_btf(const char *src_btf, const char *dst_btf, const char *objspaths[])
  2221. {
  2222. struct btfgen_info *info;
  2223. struct btf *btf_new = NULL;
  2224. int err, i;
  2225. info = btfgen_new_info(src_btf);
  2226. if (!info) {
  2227. err = -errno;
  2228. p_err("failed to allocate info structure: %s", strerror(errno));
  2229. goto out;
  2230. }
  2231. for (i = 0; objspaths[i] != NULL; i++) {
  2232. err = btfgen_record_obj(info, objspaths[i]);
  2233. if (err) {
  2234. p_err("error recording relocations for %s: %s", objspaths[i],
  2235. strerror(errno));
  2236. goto out;
  2237. }
  2238. }
  2239. btf_new = btfgen_get_btf(info);
  2240. if (!btf_new) {
  2241. err = -errno;
  2242. p_err("error generating BTF: %s", strerror(errno));
  2243. goto out;
  2244. }
  2245. err = btf_save_raw(btf_new, dst_btf);
  2246. if (err) {
  2247. p_err("error saving btf file: %s", strerror(errno));
  2248. goto out;
  2249. }
  2250. out:
  2251. btf__free(btf_new);
  2252. btfgen_free_info(info);
  2253. return err;
  2254. }
  2255. static int do_min_core_btf(int argc, char **argv)
  2256. {
  2257. const char *input, *output, **objs;
  2258. int i, err;
  2259. if (!REQ_ARGS(3)) {
  2260. usage();
  2261. return -1;
  2262. }
  2263. input = GET_ARG();
  2264. output = GET_ARG();
  2265. objs = (const char **) calloc(argc + 1, sizeof(*objs));
  2266. if (!objs) {
  2267. p_err("failed to allocate array for object names");
  2268. return -ENOMEM;
  2269. }
  2270. i = 0;
  2271. while (argc)
  2272. objs[i++] = GET_ARG();
  2273. err = minimize_btf(input, output, objs);
  2274. free(objs);
  2275. return err;
  2276. }
  2277. static const struct cmd cmds[] = {
  2278. { "object", do_object },
  2279. { "skeleton", do_skeleton },
  2280. { "subskeleton", do_subskeleton },
  2281. { "min_core_btf", do_min_core_btf},
  2282. { "help", do_help },
  2283. { 0 }
  2284. };
  2285. int do_gen(int argc, char **argv)
  2286. {
  2287. return cmd_select(cmds, argc, argv, do_help);
  2288. }