Lines Matching +full:d +full:-

1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
4 * BTF-to-C type converter.
27 static const size_t PREFIX_CNT = sizeof(PREFIXES) - 1;
31 return lvl >= PREFIX_CNT ? PREFIXES : &PREFIXES[PREFIX_CNT - lvl]; in pfx()
46 /* per-type auxiliary state */
54 /* whether unique non-duplicate name was already assigned */
89 /* per-type auxiliary state */
92 /* per-type optional cached unique name, must be freed, if present */
96 /* topo-sorted list of dependent type definitions */
132 static const char *btf_name_of(const struct btf_dump *d, __u32 name_off) in btf_name_of() argument
134 return btf__name_by_offset(d->btf, name_off); in btf_name_of()
137 static void btf_dump_printf(const struct btf_dump *d, const char *fmt, ...) in btf_dump_printf() argument
142 d->printf_fn(d->cb_ctx, fmt, args); in btf_dump_printf()
146 static int btf_dump_mark_referenced(struct btf_dump *d);
147 static int btf_dump_resize(struct btf_dump *d);
154 struct btf_dump *d; in btf_dump__new() local
158 return libbpf_err_ptr(-EINVAL); in btf_dump__new()
161 return libbpf_err_ptr(-EINVAL); in btf_dump__new()
163 d = calloc(1, sizeof(struct btf_dump)); in btf_dump__new()
164 if (!d) in btf_dump__new()
165 return libbpf_err_ptr(-ENOMEM); in btf_dump__new()
167 d->btf = btf; in btf_dump__new()
168 d->printf_fn = printf_fn; in btf_dump__new()
169 d->cb_ctx = ctx; in btf_dump__new()
170 d->ptr_sz = btf__pointer_size(btf) ? : sizeof(void *); in btf_dump__new()
172 d->type_names = hashmap__new(str_hash_fn, str_equal_fn, NULL); in btf_dump__new()
173 if (IS_ERR(d->type_names)) { in btf_dump__new()
174 err = PTR_ERR(d->type_names); in btf_dump__new()
175 d->type_names = NULL; in btf_dump__new()
178 d->ident_names = hashmap__new(str_hash_fn, str_equal_fn, NULL); in btf_dump__new()
179 if (IS_ERR(d->ident_names)) { in btf_dump__new()
180 err = PTR_ERR(d->ident_names); in btf_dump__new()
181 d->ident_names = NULL; in btf_dump__new()
185 err = btf_dump_resize(d); in btf_dump__new()
189 return d; in btf_dump__new()
191 btf_dump__free(d); in btf_dump__new()
195 static int btf_dump_resize(struct btf_dump *d) in btf_dump_resize() argument
197 int err, last_id = btf__type_cnt(d->btf) - 1; in btf_dump_resize()
199 if (last_id <= d->last_id) in btf_dump_resize()
202 if (libbpf_ensure_mem((void **)&d->type_states, &d->type_states_cap, in btf_dump_resize()
203 sizeof(*d->type_states), last_id + 1)) in btf_dump_resize()
204 return -ENOMEM; in btf_dump_resize()
205 if (libbpf_ensure_mem((void **)&d->cached_names, &d->cached_names_cap, in btf_dump_resize()
206 sizeof(*d->cached_names), last_id + 1)) in btf_dump_resize()
207 return -ENOMEM; in btf_dump_resize()
209 if (d->last_id == 0) { in btf_dump_resize()
211 d->type_states[0].order_state = ORDERED; in btf_dump_resize()
212 d->type_states[0].emit_state = EMITTED; in btf_dump_resize()
216 err = btf_dump_mark_referenced(d); in btf_dump_resize()
220 d->last_id = last_id; in btf_dump_resize()
230 free((void *)cur->pkey); in btf_dump_free_names()
235 void btf_dump__free(struct btf_dump *d) in btf_dump__free() argument
239 if (IS_ERR_OR_NULL(d)) in btf_dump__free()
242 free(d->type_states); in btf_dump__free()
243 if (d->cached_names) { in btf_dump__free()
245 for (i = 0; i <= d->last_id; i++) { in btf_dump__free()
246 if (d->cached_names[i]) in btf_dump__free()
247 free((void *)d->cached_names[i]); in btf_dump__free()
250 free(d->cached_names); in btf_dump__free()
251 free(d->emit_queue); in btf_dump__free()
252 free(d->decl_stack); in btf_dump__free()
253 btf_dump_free_names(d->type_names); in btf_dump__free()
254 btf_dump_free_names(d->ident_names); in btf_dump__free()
256 free(d); in btf_dump__free()
259 static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr);
260 static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id);
267 * filter out BTF types according to user-defined criterias and emitted only
272 * Dumping is done in two high-level passes:
278 int btf_dump__dump_type(struct btf_dump *d, __u32 id) in btf_dump__dump_type() argument
282 if (id >= btf__type_cnt(d->btf)) in btf_dump__dump_type()
283 return libbpf_err(-EINVAL); in btf_dump__dump_type()
285 err = btf_dump_resize(d); in btf_dump__dump_type()
289 d->emit_queue_cnt = 0; in btf_dump__dump_type()
290 err = btf_dump_order_type(d, id, false); in btf_dump__dump_type()
294 for (i = 0; i < d->emit_queue_cnt; i++) in btf_dump__dump_type()
295 btf_dump_emit_type(d, d->emit_queue[i], 0 /*top-level*/); in btf_dump__dump_type()
302 * determine top-level anonymous enums that need to be emitted as an
306 * type declaration; or as a top-level anonymous enum, typically used for
309 * top-level anonymous enum won't be referenced by anything, while embedded
312 static int btf_dump_mark_referenced(struct btf_dump *d) in btf_dump_mark_referenced() argument
314 int i, j, n = btf__type_cnt(d->btf); in btf_dump_mark_referenced()
318 for (i = d->last_id + 1; i < n; i++) { in btf_dump_mark_referenced()
319 t = btf__type_by_id(d->btf, i); in btf_dump_mark_referenced()
339 d->type_states[t->type].referenced = 1; in btf_dump_mark_referenced()
345 d->type_states[a->index_type].referenced = 1; in btf_dump_mark_referenced()
346 d->type_states[a->type].referenced = 1; in btf_dump_mark_referenced()
354 d->type_states[m->type].referenced = 1; in btf_dump_mark_referenced()
361 d->type_states[p->type].referenced = 1; in btf_dump_mark_referenced()
368 d->type_states[v->type].referenced = 1; in btf_dump_mark_referenced()
372 return -EINVAL; in btf_dump_mark_referenced()
378 static int btf_dump_add_emit_queue_id(struct btf_dump *d, __u32 id) in btf_dump_add_emit_queue_id() argument
383 if (d->emit_queue_cnt >= d->emit_queue_cap) { in btf_dump_add_emit_queue_id()
384 new_cap = max(16, d->emit_queue_cap * 3 / 2); in btf_dump_add_emit_queue_id()
385 new_queue = libbpf_reallocarray(d->emit_queue, new_cap, sizeof(new_queue[0])); in btf_dump_add_emit_queue_id()
387 return -ENOMEM; in btf_dump_add_emit_queue_id()
388 d->emit_queue = new_queue; in btf_dump_add_emit_queue_id()
389 d->emit_queue_cap = new_cap; in btf_dump_add_emit_queue_id()
392 d->emit_queue[d->emit_queue_cnt++] = id; in btf_dump_add_emit_queue_id()
419 * struct A {}; // if this was forward-declaration: compilation error
431 * between struct A and struct B. If struct A was forward-declared before
438 * - weak link (relationship) between X and Y, if Y *CAN* be
439 * forward-declared at the point of X definition;
440 * - strong link, if Y *HAS* to be fully-defined before X can be defined.
443 * BTF_KIND_PTR type in the chain and at least one non-anonymous type
458 * marked as ORDERED. We can mark PTR as ORDERED as well, as it semi-forces
464 * - 1, if type is part of strong link (so there is strong topological
466 * - 0, if type is part of weak link (so can be satisfied through forward
468 * - <0, on error (e.g., unsatisfiable type loop detected).
470 static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr) in btf_dump_order_type() argument
475 * stand-alone fwd decl, enum, typedef, struct, union). Ptrs, arrays, in btf_dump_order_type()
479 * So for all non-defining kinds, we never even set ordering state, in btf_dump_order_type()
483 struct btf_dump_type_aux_state *tstate = &d->type_states[id]; in btf_dump_order_type()
489 if (tstate->order_state == ORDERED) in btf_dump_order_type()
492 t = btf__type_by_id(d->btf, id); in btf_dump_order_type()
494 if (tstate->order_state == ORDERING) { in btf_dump_order_type()
496 if (btf_is_composite(t) && through_ptr && t->name_off != 0) in btf_dump_order_type()
499 return -ELOOP; in btf_dump_order_type()
505 tstate->order_state = ORDERED; in btf_dump_order_type()
509 err = btf_dump_order_type(d, t->type, true); in btf_dump_order_type()
510 tstate->order_state = ORDERED; in btf_dump_order_type()
514 return btf_dump_order_type(d, btf_array(t)->type, false); in btf_dump_order_type()
524 if (through_ptr && t->name_off != 0) in btf_dump_order_type()
527 tstate->order_state = ORDERING; in btf_dump_order_type()
531 err = btf_dump_order_type(d, m->type, false); in btf_dump_order_type()
536 if (t->name_off != 0) { in btf_dump_order_type()
537 err = btf_dump_add_emit_queue_id(d, id); in btf_dump_order_type()
542 tstate->order_state = ORDERED; in btf_dump_order_type()
549 * non-anonymous or non-referenced enums are top-level in btf_dump_order_type()
553 if (t->name_off != 0 || !tstate->referenced) { in btf_dump_order_type()
554 err = btf_dump_add_emit_queue_id(d, id); in btf_dump_order_type()
558 tstate->order_state = ORDERED; in btf_dump_order_type()
564 is_strong = btf_dump_order_type(d, t->type, through_ptr); in btf_dump_order_type()
568 /* typedef is similar to struct/union w.r.t. fwd-decls */ in btf_dump_order_type()
573 err = btf_dump_add_emit_queue_id(d, id); in btf_dump_order_type()
577 d->type_states[id].order_state = ORDERED; in btf_dump_order_type()
584 return btf_dump_order_type(d, t->type, through_ptr); in btf_dump_order_type()
590 err = btf_dump_order_type(d, t->type, through_ptr); in btf_dump_order_type()
597 err = btf_dump_order_type(d, p->type, through_ptr); in btf_dump_order_type()
609 d->type_states[id].order_state = ORDERED; in btf_dump_order_type()
613 return -EINVAL; in btf_dump_order_type()
617 static void btf_dump_emit_missing_aliases(struct btf_dump *d, __u32 id,
620 static void btf_dump_emit_struct_fwd(struct btf_dump *d, __u32 id,
622 static void btf_dump_emit_struct_def(struct btf_dump *d, __u32 id,
625 static void btf_dump_emit_enum_fwd(struct btf_dump *d, __u32 id,
627 static void btf_dump_emit_enum_def(struct btf_dump *d, __u32 id,
630 static void btf_dump_emit_fwd_def(struct btf_dump *d, __u32 id,
633 static void btf_dump_emit_typedef_def(struct btf_dump *d, __u32 id,
642 static void btf_dump_emit_type_decl(struct btf_dump *d, __u32 id,
644 static void btf_dump_emit_type_chain(struct btf_dump *d,
648 static const char *btf_dump_type_name(struct btf_dump *d, __u32 id);
649 static const char *btf_dump_ident_name(struct btf_dump *d, __u32 id);
650 static size_t btf_dump_name_dups(struct btf_dump *d, struct hashmap *name_map,
653 static bool btf_dump_is_blacklisted(struct btf_dump *d, __u32 id) in btf_dump_is_blacklisted() argument
655 const struct btf_type *t = btf__type_by_id(d->btf, id); in btf_dump_is_blacklisted()
657 /* __builtin_va_list is a compiler built-in, which causes compilation in btf_dump_is_blacklisted()
660 * C header from BTF). As it is built-in, it should be already defined in btf_dump_is_blacklisted()
663 if (t->name_off == 0) in btf_dump_is_blacklisted()
665 return strcmp(btf_name_of(d, t->name_off), "__builtin_va_list") == 0; in btf_dump_is_blacklisted()
669 * Emit C-syntax definitions of types from chains of BTF types.
671 * High-level handling of determining necessary forward declarations are handled
672 * by btf_dump_emit_type() itself, but all nitty-gritty details of emitting type
686 static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id) in btf_dump_emit_type() argument
688 struct btf_dump_type_aux_state *tstate = &d->type_states[id]; in btf_dump_emit_type()
693 if (tstate->emit_state == EMITTED) in btf_dump_emit_type()
696 t = btf__type_by_id(d->btf, id); in btf_dump_emit_type()
699 if (tstate->emit_state == EMITTING) { in btf_dump_emit_type()
700 if (tstate->fwd_emitted) in btf_dump_emit_type()
708 * part of - then no need for fwd declaration in btf_dump_emit_type()
712 if (t->name_off == 0) { in btf_dump_emit_type()
717 btf_dump_emit_struct_fwd(d, id, t); in btf_dump_emit_type()
718 btf_dump_printf(d, ";\n\n"); in btf_dump_emit_type()
719 tstate->fwd_emitted = 1; in btf_dump_emit_type()
727 if (!btf_dump_is_blacklisted(d, id)) { in btf_dump_emit_type()
728 btf_dump_emit_typedef_def(d, id, t, 0); in btf_dump_emit_type()
729 btf_dump_printf(d, ";\n\n"); in btf_dump_emit_type()
731 tstate->fwd_emitted = 1; in btf_dump_emit_type()
743 btf_dump_emit_missing_aliases(d, id, t); in btf_dump_emit_type()
745 tstate->emit_state = EMITTED; in btf_dump_emit_type()
750 btf_dump_emit_enum_def(d, id, t, 0); in btf_dump_emit_type()
751 btf_dump_printf(d, ";\n\n"); in btf_dump_emit_type()
753 tstate->emit_state = EMITTED; in btf_dump_emit_type()
760 btf_dump_emit_type(d, t->type, cont_id); in btf_dump_emit_type()
763 btf_dump_emit_type(d, btf_array(t)->type, cont_id); in btf_dump_emit_type()
766 btf_dump_emit_fwd_def(d, id, t); in btf_dump_emit_type()
767 btf_dump_printf(d, ";\n\n"); in btf_dump_emit_type()
768 tstate->emit_state = EMITTED; in btf_dump_emit_type()
771 tstate->emit_state = EMITTING; in btf_dump_emit_type()
772 btf_dump_emit_type(d, t->type, id); in btf_dump_emit_type()
780 if (!tstate->fwd_emitted && !btf_dump_is_blacklisted(d, id)) { in btf_dump_emit_type()
781 btf_dump_emit_typedef_def(d, id, t, 0); in btf_dump_emit_type()
782 btf_dump_printf(d, ";\n\n"); in btf_dump_emit_type()
784 tstate->emit_state = EMITTED; in btf_dump_emit_type()
788 tstate->emit_state = EMITTING; in btf_dump_emit_type()
789 /* if it's a top-level struct/union definition or struct/union in btf_dump_emit_type()
793 * members have necessary forward-declarations, where in btf_dump_emit_type()
796 if (top_level_def || t->name_off == 0) { in btf_dump_emit_type()
801 new_cont_id = t->name_off == 0 ? cont_id : id; in btf_dump_emit_type()
803 btf_dump_emit_type(d, m->type, new_cont_id); in btf_dump_emit_type()
804 } else if (!tstate->fwd_emitted && id != cont_id) { in btf_dump_emit_type()
805 btf_dump_emit_struct_fwd(d, id, t); in btf_dump_emit_type()
806 btf_dump_printf(d, ";\n\n"); in btf_dump_emit_type()
807 tstate->fwd_emitted = 1; in btf_dump_emit_type()
811 btf_dump_emit_struct_def(d, id, t, 0); in btf_dump_emit_type()
812 btf_dump_printf(d, ";\n\n"); in btf_dump_emit_type()
813 tstate->emit_state = EMITTED; in btf_dump_emit_type()
815 tstate->emit_state = NOT_EMITTED; in btf_dump_emit_type()
823 btf_dump_emit_type(d, t->type, cont_id); in btf_dump_emit_type()
825 btf_dump_emit_type(d, p->type, cont_id); in btf_dump_emit_type()
843 /* all non-bitfield fields have to be naturally aligned */ in btf_is_struct_packed()
845 align = btf__align_of(btf, m->type); in btf_is_struct_packed()
847 if (align && bit_sz == 0 && m->offset % (8 * align) != 0) in btf_is_struct_packed()
851 /* size of a non-packed struct has to be a multiple of its alignment */ in btf_is_struct_packed()
852 if (t->size % max_align != 0) in btf_is_struct_packed()
861 static void btf_dump_emit_bit_padding(const struct btf_dump *d, in btf_dump_emit_bit_padding() argument
869 {"long", d->ptr_sz * 8}, {"int", 32}, {"short", 16}, {"char", 8} in btf_dump_emit_bit_padding()
886 * that even if struct itself has, let's say 4-byte alignment in btf_dump_emit_bit_padding()
887 * (i.e., it only uses up to int-aligned types), using `long: in btf_dump_emit_bit_padding()
916 (new_off != next_off && next_off - new_off <= new_off - cur_off)) in btf_dump_emit_bit_padding()
918 btf_dump_printf(d, "\n%s%s: %d;", pfx(lvl), pad_type, in btf_dump_emit_bit_padding()
919 in_bitfield ? new_off - cur_off : 0); in btf_dump_emit_bit_padding()
930 bits = min(next_off - cur_off, pad_bits); in btf_dump_emit_bit_padding()
932 btf_dump_printf(d, "\n%s%s: %d;", pfx(lvl), pad_type, pad_bits); in btf_dump_emit_bit_padding()
942 for (i = ARRAY_SIZE(pads) - 1; i >= 0; i--) { in btf_dump_emit_bit_padding()
948 btf_dump_printf(d, "\n%s%s: %d;", pfx(lvl), pad_type, bits); in btf_dump_emit_bit_padding()
955 static void btf_dump_emit_struct_fwd(struct btf_dump *d, __u32 id, in btf_dump_emit_struct_fwd() argument
958 btf_dump_printf(d, "%s%s%s", in btf_dump_emit_struct_fwd()
960 t->name_off ? " " : "", in btf_dump_emit_struct_fwd()
961 btf_dump_type_name(d, id)); in btf_dump_emit_struct_fwd()
964 static void btf_dump_emit_struct_def(struct btf_dump *d, in btf_dump_emit_struct_def() argument
975 align = btf__align_of(d->btf, id); in btf_dump_emit_struct_def()
976 packed = is_struct ? btf_is_struct_packed(d->btf, id, t) : 0; in btf_dump_emit_struct_def()
978 btf_dump_printf(d, "%s%s%s {", in btf_dump_emit_struct_def()
980 t->name_off ? " " : "", in btf_dump_emit_struct_def()
981 btf_dump_type_name(d, id)); in btf_dump_emit_struct_def()
988 fname = btf_name_of(d, m->name_off); in btf_dump_emit_struct_def()
991 m_align = packed ? 1 : btf__align_of(d->btf, m->type); in btf_dump_emit_struct_def()
995 btf_dump_emit_bit_padding(d, off, m_off, m_align, in_bitfield, lvl + 1); in btf_dump_emit_struct_def()
996 btf_dump_printf(d, "\n%s", pfx(lvl + 1)); in btf_dump_emit_struct_def()
997 btf_dump_emit_type_decl(d, m->type, fname, lvl + 1); in btf_dump_emit_struct_def()
1000 btf_dump_printf(d, ": %d", m_sz); in btf_dump_emit_struct_def()
1004 m_sz = max((__s64)0, btf__resolve_size(d->btf, m->type)); in btf_dump_emit_struct_def()
1009 btf_dump_printf(d, ";"); in btf_dump_emit_struct_def()
1014 btf_dump_emit_bit_padding(d, off, t->size * 8, align, false, lvl + 1); in btf_dump_emit_struct_def()
1020 if (vlen || t->size) { in btf_dump_emit_struct_def()
1021 btf_dump_printf(d, "\n"); in btf_dump_emit_struct_def()
1022 btf_dump_printf(d, "%s}", pfx(lvl)); in btf_dump_emit_struct_def()
1024 btf_dump_printf(d, "}"); in btf_dump_emit_struct_def()
1027 btf_dump_printf(d, " __attribute__((packed))"); in btf_dump_emit_struct_def()
1041 static void btf_dump_emit_missing_aliases(struct btf_dump *d, __u32 id, in btf_dump_emit_missing_aliases() argument
1044 const char *name = btf_dump_type_name(d, id); in btf_dump_emit_missing_aliases()
1049 btf_dump_printf(d, "typedef %s %s;\n\n", in btf_dump_emit_missing_aliases()
1056 static void btf_dump_emit_enum_fwd(struct btf_dump *d, __u32 id, in btf_dump_emit_enum_fwd() argument
1059 btf_dump_printf(d, "enum %s", btf_dump_type_name(d, id)); in btf_dump_emit_enum_fwd()
1062 static void btf_dump_emit_enum32_val(struct btf_dump *d, in btf_dump_emit_enum32_val() argument
1074 name = btf_name_of(d, v->name_off); in btf_dump_emit_enum32_val()
1076 dup_cnt = btf_dump_name_dups(d, d->ident_names, name); in btf_dump_emit_enum32_val()
1078 fmt_str = is_signed ? "\n%s%s___%zd = %d," : "\n%s%s___%zd = %u,"; in btf_dump_emit_enum32_val()
1079 btf_dump_printf(d, fmt_str, pfx(lvl + 1), name, dup_cnt, v->val); in btf_dump_emit_enum32_val()
1081 fmt_str = is_signed ? "\n%s%s = %d," : "\n%s%s = %u,"; in btf_dump_emit_enum32_val()
1082 btf_dump_printf(d, fmt_str, pfx(lvl + 1), name, v->val); in btf_dump_emit_enum32_val()
1087 static void btf_dump_emit_enum64_val(struct btf_dump *d, in btf_dump_emit_enum64_val() argument
1100 name = btf_name_of(d, v->name_off); in btf_dump_emit_enum64_val()
1101 dup_cnt = btf_dump_name_dups(d, d->ident_names, name); in btf_dump_emit_enum64_val()
1106 btf_dump_printf(d, fmt_str, in btf_dump_emit_enum64_val()
1112 btf_dump_printf(d, fmt_str, in btf_dump_emit_enum64_val()
1118 static void btf_dump_emit_enum_def(struct btf_dump *d, __u32 id, in btf_dump_emit_enum_def() argument
1124 btf_dump_printf(d, "enum%s%s", in btf_dump_emit_enum_def()
1125 t->name_off ? " " : "", in btf_dump_emit_enum_def()
1126 btf_dump_type_name(d, id)); in btf_dump_emit_enum_def()
1131 btf_dump_printf(d, " {"); in btf_dump_emit_enum_def()
1133 btf_dump_emit_enum32_val(d, t, lvl, vlen); in btf_dump_emit_enum_def()
1135 btf_dump_emit_enum64_val(d, t, lvl, vlen); in btf_dump_emit_enum_def()
1136 btf_dump_printf(d, "\n%s}", pfx(lvl)); in btf_dump_emit_enum_def()
1139 if (t->size == 1) { in btf_dump_emit_enum_def()
1140 /* one-byte enums can be forced with mode(byte) attribute */ in btf_dump_emit_enum_def()
1141 btf_dump_printf(d, " __attribute__((mode(byte)))"); in btf_dump_emit_enum_def()
1142 } else if (t->size == 8 && d->ptr_sz == 8) { in btf_dump_emit_enum_def()
1143 /* enum can be 8-byte sized if one of the enumerator values in btf_dump_emit_enum_def()
1144 * doesn't fit in 32-bit integer, or by adding mode(word) in btf_dump_emit_enum_def()
1145 * attribute (but probably only on 64-bit architectures); do in btf_dump_emit_enum_def()
1152 /* enum can't represent 64-bit values, so we need word mode */ in btf_dump_emit_enum_def()
1156 * non-zero upper 32-bits (which means that all values in btf_dump_emit_enum_def()
1157 * fit in 32-bit integers and won't cause compiler to in btf_dump_emit_enum_def()
1158 * bump enum to be 64-bit naturally in btf_dump_emit_enum_def()
1171 btf_dump_printf(d, " __attribute__((mode(word)))"); in btf_dump_emit_enum_def()
1176 static void btf_dump_emit_fwd_def(struct btf_dump *d, __u32 id, in btf_dump_emit_fwd_def() argument
1179 const char *name = btf_dump_type_name(d, id); in btf_dump_emit_fwd_def()
1182 btf_dump_printf(d, "union %s", name); in btf_dump_emit_fwd_def()
1184 btf_dump_printf(d, "struct %s", name); in btf_dump_emit_fwd_def()
1187 static void btf_dump_emit_typedef_def(struct btf_dump *d, __u32 id, in btf_dump_emit_typedef_def() argument
1190 const char *name = btf_dump_ident_name(d, id); in btf_dump_emit_typedef_def()
1198 if (t->type == 0 && strcmp(name, "__gnuc_va_list") == 0) { in btf_dump_emit_typedef_def()
1199 btf_dump_printf(d, "typedef __builtin_va_list __gnuc_va_list"); in btf_dump_emit_typedef_def()
1203 btf_dump_printf(d, "typedef "); in btf_dump_emit_typedef_def()
1204 btf_dump_emit_type_decl(d, t->type, name, lvl); in btf_dump_emit_typedef_def()
1207 static int btf_dump_push_decl_stack_id(struct btf_dump *d, __u32 id) in btf_dump_push_decl_stack_id() argument
1212 if (d->decl_stack_cnt >= d->decl_stack_cap) { in btf_dump_push_decl_stack_id()
1213 new_cap = max(16, d->decl_stack_cap * 3 / 2); in btf_dump_push_decl_stack_id()
1214 new_stack = libbpf_reallocarray(d->decl_stack, new_cap, sizeof(new_stack[0])); in btf_dump_push_decl_stack_id()
1216 return -ENOMEM; in btf_dump_push_decl_stack_id()
1217 d->decl_stack = new_stack; in btf_dump_push_decl_stack_id()
1218 d->decl_stack_cap = new_cap; in btf_dump_push_decl_stack_id()
1221 d->decl_stack[d->decl_stack_cnt++] = id; in btf_dump_push_decl_stack_id()
1232 * - function prototypes (especially nesting of function prototypes);
1233 * - arrays;
1234 * - const/volatile/restrict for pointers vs other types.
1248 * [typedef] -> [array] -> [ptr] -> [const] -> [ptr] -> [const] -> [int]
1267 int btf_dump__emit_type_decl(struct btf_dump *d, __u32 id, in btf_dump__emit_type_decl() argument
1274 return libbpf_err(-EINVAL); in btf_dump__emit_type_decl()
1276 err = btf_dump_resize(d); in btf_dump__emit_type_decl()
1282 d->strip_mods = OPTS_GET(opts, strip_mods, false); in btf_dump__emit_type_decl()
1283 btf_dump_emit_type_decl(d, id, fname, lvl); in btf_dump__emit_type_decl()
1284 d->strip_mods = false; in btf_dump__emit_type_decl()
1288 static void btf_dump_emit_type_decl(struct btf_dump *d, __u32 id, in btf_dump_emit_type_decl() argument
1295 stack_start = d->decl_stack_cnt; in btf_dump_emit_type_decl()
1297 t = btf__type_by_id(d->btf, id); in btf_dump_emit_type_decl()
1298 if (d->strip_mods && btf_is_mod(t)) in btf_dump_emit_type_decl()
1301 err = btf_dump_push_decl_stack_id(d, id); in btf_dump_emit_type_decl()
1309 d->decl_stack_cnt = stack_start; in btf_dump_emit_type_decl()
1324 id = t->type; in btf_dump_emit_type_decl()
1327 id = btf_array(t)->type; in btf_dump_emit_type_decl()
1349 * emitting of declarations. Those stack frames are non-overlapping in btf_dump_emit_type_decl()
1350 * portions of shared btf_dump->decl_stack. To make it a bit nicer to in btf_dump_emit_type_decl()
1355 decl_stack.ids = d->decl_stack + stack_start; in btf_dump_emit_type_decl()
1356 decl_stack.cnt = d->decl_stack_cnt - stack_start; in btf_dump_emit_type_decl()
1357 btf_dump_emit_type_chain(d, &decl_stack, fname, lvl); in btf_dump_emit_type_decl()
1360 * frame before returning. But it works with a read-only view into in btf_dump_emit_type_decl()
1362 * perspective of shared btf_dump->decl_stack, per se. We need to in btf_dump_emit_type_decl()
1366 d->decl_stack_cnt = stack_start; in btf_dump_emit_type_decl()
1369 static void btf_dump_emit_mods(struct btf_dump *d, struct id_stack *decl_stack) in btf_dump_emit_mods() argument
1374 while (decl_stack->cnt) { in btf_dump_emit_mods()
1375 id = decl_stack->ids[decl_stack->cnt - 1]; in btf_dump_emit_mods()
1376 t = btf__type_by_id(d->btf, id); in btf_dump_emit_mods()
1380 btf_dump_printf(d, "volatile "); in btf_dump_emit_mods()
1383 btf_dump_printf(d, "const "); in btf_dump_emit_mods()
1386 btf_dump_printf(d, "restrict "); in btf_dump_emit_mods()
1391 decl_stack->cnt--; in btf_dump_emit_mods()
1395 static void btf_dump_drop_mods(struct btf_dump *d, struct id_stack *decl_stack) in btf_dump_drop_mods() argument
1400 while (decl_stack->cnt) { in btf_dump_drop_mods()
1401 id = decl_stack->ids[decl_stack->cnt - 1]; in btf_dump_drop_mods()
1402 t = btf__type_by_id(d->btf, id); in btf_dump_drop_mods()
1405 decl_stack->cnt--; in btf_dump_drop_mods()
1409 static void btf_dump_emit_name(const struct btf_dump *d, in btf_dump_emit_name() argument
1414 btf_dump_printf(d, "%s%s", separate ? " " : "", name); in btf_dump_emit_name()
1417 static void btf_dump_emit_type_chain(struct btf_dump *d, in btf_dump_emit_type_chain() argument
1425 * for cases where we have single pointer in a chain. E.g., in ptr -> in btf_dump_emit_type_chain()
1436 while (decls->cnt) { in btf_dump_emit_type_chain()
1437 id = decls->ids[--decls->cnt]; in btf_dump_emit_type_chain()
1440 btf_dump_emit_mods(d, decls); in btf_dump_emit_type_chain()
1441 btf_dump_printf(d, "void"); in btf_dump_emit_type_chain()
1446 t = btf__type_by_id(d->btf, id); in btf_dump_emit_type_chain()
1452 btf_dump_emit_mods(d, decls); in btf_dump_emit_type_chain()
1453 name = btf_name_of(d, t->name_off); in btf_dump_emit_type_chain()
1454 btf_dump_printf(d, "%s", name); in btf_dump_emit_type_chain()
1458 btf_dump_emit_mods(d, decls); in btf_dump_emit_type_chain()
1460 if (t->name_off == 0 && !d->skip_anon_defs) in btf_dump_emit_type_chain()
1461 btf_dump_emit_struct_def(d, id, t, lvl); in btf_dump_emit_type_chain()
1463 btf_dump_emit_struct_fwd(d, id, t); in btf_dump_emit_type_chain()
1467 btf_dump_emit_mods(d, decls); in btf_dump_emit_type_chain()
1469 if (t->name_off == 0 && !d->skip_anon_defs) in btf_dump_emit_type_chain()
1470 btf_dump_emit_enum_def(d, id, t, lvl); in btf_dump_emit_type_chain()
1472 btf_dump_emit_enum_fwd(d, id, t); in btf_dump_emit_type_chain()
1475 btf_dump_emit_mods(d, decls); in btf_dump_emit_type_chain()
1476 btf_dump_emit_fwd_def(d, id, t); in btf_dump_emit_type_chain()
1479 btf_dump_emit_mods(d, decls); in btf_dump_emit_type_chain()
1480 btf_dump_printf(d, "%s", btf_dump_ident_name(d, id)); in btf_dump_emit_type_chain()
1483 btf_dump_printf(d, "%s", last_was_ptr ? "*" : " *"); in btf_dump_emit_type_chain()
1486 btf_dump_printf(d, " volatile"); in btf_dump_emit_type_chain()
1489 btf_dump_printf(d, " const"); in btf_dump_emit_type_chain()
1492 btf_dump_printf(d, " restrict"); in btf_dump_emit_type_chain()
1495 btf_dump_emit_mods(d, decls); in btf_dump_emit_type_chain()
1496 name = btf_name_of(d, t->name_off); in btf_dump_emit_type_chain()
1498 btf_dump_printf(d, " __attribute__((%s))", name); in btf_dump_emit_type_chain()
1500 btf_dump_printf(d, " __attribute__((btf_type_tag(\"%s\")))", name); in btf_dump_emit_type_chain()
1517 btf_dump_drop_mods(d, decls); in btf_dump_emit_type_chain()
1519 if (decls->cnt == 0) { in btf_dump_emit_type_chain()
1520 btf_dump_emit_name(d, fname, last_was_ptr); in btf_dump_emit_type_chain()
1521 btf_dump_printf(d, "[%u]", a->nelems); in btf_dump_emit_type_chain()
1525 next_id = decls->ids[decls->cnt - 1]; in btf_dump_emit_type_chain()
1526 next_t = btf__type_by_id(d->btf, next_id); in btf_dump_emit_type_chain()
1528 /* we need space if we have named non-pointer */ in btf_dump_emit_type_chain()
1530 btf_dump_printf(d, " "); in btf_dump_emit_type_chain()
1531 /* no parentheses for multi-dimensional array */ in btf_dump_emit_type_chain()
1533 btf_dump_printf(d, "("); in btf_dump_emit_type_chain()
1534 btf_dump_emit_type_chain(d, decls, fname, lvl); in btf_dump_emit_type_chain()
1536 btf_dump_printf(d, ")"); in btf_dump_emit_type_chain()
1537 btf_dump_printf(d, "[%u]", a->nelems); in btf_dump_emit_type_chain()
1553 btf_dump_drop_mods(d, decls); in btf_dump_emit_type_chain()
1554 if (decls->cnt) { in btf_dump_emit_type_chain()
1555 btf_dump_printf(d, " ("); in btf_dump_emit_type_chain()
1556 btf_dump_emit_type_chain(d, decls, fname, lvl); in btf_dump_emit_type_chain()
1557 btf_dump_printf(d, ")"); in btf_dump_emit_type_chain()
1559 btf_dump_emit_name(d, fname, last_was_ptr); in btf_dump_emit_type_chain()
1561 btf_dump_printf(d, "("); in btf_dump_emit_type_chain()
1568 * no args case can be special-cased here as well. in btf_dump_emit_type_chain()
1570 if (vlen == 0 || (vlen == 1 && p->type == 0)) { in btf_dump_emit_type_chain()
1571 btf_dump_printf(d, "void)"); in btf_dump_emit_type_chain()
1577 btf_dump_printf(d, ", "); in btf_dump_emit_type_chain()
1580 if (i == vlen - 1 && p->type == 0) { in btf_dump_emit_type_chain()
1581 btf_dump_printf(d, "..."); in btf_dump_emit_type_chain()
1585 name = btf_name_of(d, p->name_off); in btf_dump_emit_type_chain()
1586 btf_dump_emit_type_decl(d, p->type, name, lvl); in btf_dump_emit_type_chain()
1589 btf_dump_printf(d, ")"); in btf_dump_emit_type_chain()
1601 btf_dump_emit_name(d, fname, last_was_ptr); in btf_dump_emit_type_chain()
1605 static void btf_dump_emit_type_cast(struct btf_dump *d, __u32 id, in btf_dump_emit_type_cast() argument
1614 if (d->typed_dump->is_array_member) in btf_dump_emit_type_cast()
1620 t = btf__type_by_id(d->btf, id); in btf_dump_emit_type_cast()
1625 btf_dump_printf(d, "("); in btf_dump_emit_type_cast()
1627 d->skip_anon_defs = true; in btf_dump_emit_type_cast()
1628 d->strip_mods = true; in btf_dump_emit_type_cast()
1629 btf_dump_emit_type_decl(d, id, "", 0); in btf_dump_emit_type_cast()
1630 d->strip_mods = false; in btf_dump_emit_type_cast()
1631 d->skip_anon_defs = false; in btf_dump_emit_type_cast()
1634 btf_dump_printf(d, ")"); in btf_dump_emit_type_cast()
1638 static size_t btf_dump_name_dups(struct btf_dump *d, struct hashmap *name_map, in btf_dump_name_dups() argument
1661 static const char *btf_dump_resolve_name(struct btf_dump *d, __u32 id, in btf_dump_resolve_name() argument
1664 struct btf_dump_type_aux_state *s = &d->type_states[id]; in btf_dump_resolve_name()
1665 const struct btf_type *t = btf__type_by_id(d->btf, id); in btf_dump_resolve_name()
1666 const char *orig_name = btf_name_of(d, t->name_off); in btf_dump_resolve_name()
1667 const char **cached_name = &d->cached_names[id]; in btf_dump_resolve_name()
1670 if (t->name_off == 0) in btf_dump_resolve_name()
1673 if (s->name_resolved) in btf_dump_resolve_name()
1677 s->name_resolved = 1; in btf_dump_resolve_name()
1681 dup_cnt = btf_dump_name_dups(d, name_map, orig_name); in btf_dump_resolve_name()
1690 s->name_resolved = 1; in btf_dump_resolve_name()
1694 static const char *btf_dump_type_name(struct btf_dump *d, __u32 id) in btf_dump_type_name() argument
1696 return btf_dump_resolve_name(d, id, d->type_names); in btf_dump_type_name()
1699 static const char *btf_dump_ident_name(struct btf_dump *d, __u32 id) in btf_dump_ident_name() argument
1701 return btf_dump_resolve_name(d, id, d->ident_names); in btf_dump_ident_name()
1704 static int btf_dump_dump_type_data(struct btf_dump *d,
1712 static const char *btf_dump_data_newline(struct btf_dump *d) in btf_dump_data_newline() argument
1714 return d->typed_dump->compact || d->typed_dump->depth == 0 ? "" : "\n"; in btf_dump_data_newline()
1717 static const char *btf_dump_data_delim(struct btf_dump *d) in btf_dump_data_delim() argument
1719 return d->typed_dump->depth == 0 ? "" : ","; in btf_dump_data_delim()
1722 static void btf_dump_data_pfx(struct btf_dump *d) in btf_dump_data_pfx() argument
1724 int i, lvl = d->typed_dump->indent_lvl + d->typed_dump->depth; in btf_dump_data_pfx()
1726 if (d->typed_dump->compact) in btf_dump_data_pfx()
1730 btf_dump_printf(d, "%s", d->typed_dump->indent_str); in btf_dump_data_pfx()
1738 #define btf_dump_type_values(d, fmt, ...) \ argument
1739 btf_dump_printf(d, fmt "%s%s", \
1741 btf_dump_data_delim(d), \
1742 btf_dump_data_newline(d))
1744 static int btf_dump_unsupported_data(struct btf_dump *d, in btf_dump_unsupported_data() argument
1748 btf_dump_printf(d, "<unsupported kind:%u>", btf_kind(t)); in btf_dump_unsupported_data()
1749 return -ENOTSUP; in btf_dump_unsupported_data()
1752 static int btf_dump_get_bitfield_value(struct btf_dump *d, in btf_dump_get_bitfield_value() argument
1766 if (t->size > 8) { in btf_dump_get_bitfield_value()
1767 pr_warn("unexpected bitfield size %d\n", t->size); in btf_dump_get_bitfield_value()
1768 return -EINVAL; in btf_dump_get_bitfield_value()
1775 for (i = t->size - 1; i >= 0; i--) in btf_dump_get_bitfield_value()
1779 for (i = 0; i < t->size; i++) in btf_dump_get_bitfield_value()
1781 nr_copy_bits = t->size * 8 - bits_offset; in btf_dump_get_bitfield_value()
1785 left_shift_bits = 64 - nr_copy_bits; in btf_dump_get_bitfield_value()
1786 right_shift_bits = 64 - bit_sz; in btf_dump_get_bitfield_value()
1793 static int btf_dump_bitfield_check_zero(struct btf_dump *d, in btf_dump_bitfield_check_zero() argument
1802 err = btf_dump_get_bitfield_value(d, t, data, bits_offset, bit_sz, &check_num); in btf_dump_bitfield_check_zero()
1806 return -ENODATA; in btf_dump_bitfield_check_zero()
1810 static int btf_dump_bitfield_data(struct btf_dump *d, in btf_dump_bitfield_data() argument
1819 err = btf_dump_get_bitfield_value(d, t, data, bits_offset, bit_sz, &print_num); in btf_dump_bitfield_data()
1823 btf_dump_type_values(d, "0x%llx", (unsigned long long)print_num); in btf_dump_bitfield_data()
1829 static int btf_dump_base_type_check_zero(struct btf_dump *d, in btf_dump_base_type_check_zero() argument
1837 /* For pointer types, pointer size is not defined on a per-type basis. in btf_dump_base_type_check_zero()
1841 nr_bytes = d->ptr_sz; in btf_dump_base_type_check_zero()
1843 nr_bytes = t->size; in btf_dump_base_type_check_zero()
1846 pr_warn("unexpected size %d for id [%u]\n", nr_bytes, id); in btf_dump_base_type_check_zero()
1847 return -EINVAL; in btf_dump_base_type_check_zero()
1851 return -ENODATA; in btf_dump_base_type_check_zero()
1866 static int btf_dump_int_data(struct btf_dump *d, in btf_dump_int_data() argument
1875 int sz = t->size; in btf_dump_int_data()
1878 pr_warn("unexpected size %d for id [%u]\n", sz, type_id); in btf_dump_int_data()
1879 return -EINVAL; in btf_dump_int_data()
1882 /* handle packed int data - accesses of integers not aligned on in btf_dump_int_data()
1885 if (!ptr_is_aligned(d->btf, type_id, data)) { in btf_dump_int_data()
1895 /* avoid use of __int128 as some 32-bit platforms do not in btf_dump_int_data()
1908 btf_dump_type_values(d, "0x%llx", (unsigned long long)lsi); in btf_dump_int_data()
1910 btf_dump_type_values(d, "0x%llx%016llx", (unsigned long long)msi, in btf_dump_int_data()
1916 btf_dump_type_values(d, "%lld", *(long long *)data); in btf_dump_int_data()
1918 btf_dump_type_values(d, "%llu", *(unsigned long long *)data); in btf_dump_int_data()
1922 btf_dump_type_values(d, "%d", *(__s32 *)data); in btf_dump_int_data()
1924 btf_dump_type_values(d, "%u", *(__u32 *)data); in btf_dump_int_data()
1928 btf_dump_type_values(d, "%d", *(__s16 *)data); in btf_dump_int_data()
1930 btf_dump_type_values(d, "%u", *(__u16 *)data); in btf_dump_int_data()
1933 if (d->typed_dump->is_array_char) { in btf_dump_int_data()
1935 if (d->typed_dump->is_array_terminated) in btf_dump_int_data()
1938 btf_dump_type_values(d, "'\\0'"); in btf_dump_int_data()
1939 d->typed_dump->is_array_terminated = true; in btf_dump_int_data()
1943 btf_dump_type_values(d, "'%c'", *(char *)data); in btf_dump_int_data()
1948 btf_dump_type_values(d, "%d", *(__s8 *)data); in btf_dump_int_data()
1950 btf_dump_type_values(d, "%u", *(__u8 *)data); in btf_dump_int_data()
1953 pr_warn("unexpected sz %d for id [%u]\n", sz, type_id); in btf_dump_int_data()
1954 return -EINVAL; in btf_dump_int_data()
1961 double d; member
1965 static int btf_dump_float_data(struct btf_dump *d, in btf_dump_float_data() argument
1972 int sz = t->size; in btf_dump_float_data()
1975 if (!ptr_is_aligned(d->btf, type_id, data)) { in btf_dump_float_data()
1982 btf_dump_type_values(d, "%Lf", flp->ld); in btf_dump_float_data()
1985 btf_dump_type_values(d, "%lf", flp->d); in btf_dump_float_data()
1988 btf_dump_type_values(d, "%f", flp->f); in btf_dump_float_data()
1991 pr_warn("unexpected size %d for id [%u]\n", sz, type_id); in btf_dump_float_data()
1992 return -EINVAL; in btf_dump_float_data()
1997 static int btf_dump_var_data(struct btf_dump *d, in btf_dump_var_data() argument
2002 enum btf_func_linkage linkage = btf_var(v)->linkage; in btf_dump_var_data()
2023 btf_dump_printf(d, "%s", l); in btf_dump_var_data()
2024 type_id = v->type; in btf_dump_var_data()
2025 t = btf__type_by_id(d->btf, type_id); in btf_dump_var_data()
2026 btf_dump_emit_type_cast(d, type_id, false); in btf_dump_var_data()
2027 btf_dump_printf(d, " %s = ", btf_name_of(d, v->name_off)); in btf_dump_var_data()
2028 return btf_dump_dump_type_data(d, NULL, t, type_id, data, 0, 0); in btf_dump_var_data()
2031 static int btf_dump_array_data(struct btf_dump *d, in btf_dump_array_data() argument
2043 elem_type_id = array->type; in btf_dump_array_data()
2044 elem_type = skip_mods_and_typedefs(d->btf, elem_type_id, NULL); in btf_dump_array_data()
2045 elem_size = btf__resolve_size(d->btf, elem_type_id); in btf_dump_array_data()
2049 return -EINVAL; in btf_dump_array_data()
2059 d->typed_dump->is_array_char = true; in btf_dump_array_data()
2069 d->typed_dump->depth++; in btf_dump_array_data()
2070 btf_dump_printf(d, "[%s", btf_dump_data_newline(d)); in btf_dump_array_data()
2075 is_array_member = d->typed_dump->is_array_member; in btf_dump_array_data()
2076 d->typed_dump->is_array_member = true; in btf_dump_array_data()
2077 is_array_terminated = d->typed_dump->is_array_terminated; in btf_dump_array_data()
2078 d->typed_dump->is_array_terminated = false; in btf_dump_array_data()
2079 for (i = 0; i < array->nelems; i++, data += elem_size) { in btf_dump_array_data()
2080 if (d->typed_dump->is_array_terminated) in btf_dump_array_data()
2082 btf_dump_dump_type_data(d, NULL, elem_type, elem_type_id, data, 0, 0); in btf_dump_array_data()
2084 d->typed_dump->is_array_member = is_array_member; in btf_dump_array_data()
2085 d->typed_dump->is_array_terminated = is_array_terminated; in btf_dump_array_data()
2086 d->typed_dump->depth--; in btf_dump_array_data()
2087 btf_dump_data_pfx(d); in btf_dump_array_data()
2088 btf_dump_type_values(d, "]"); in btf_dump_array_data()
2093 static int btf_dump_struct_data(struct btf_dump *d, in btf_dump_struct_data() argument
2109 d->typed_dump->depth++; in btf_dump_struct_data()
2110 btf_dump_printf(d, "{%s", btf_dump_data_newline(d)); in btf_dump_struct_data()
2118 mtype = btf__type_by_id(d->btf, m->type); in btf_dump_struct_data()
2119 mname = btf_name_of(d, m->name_off); in btf_dump_struct_data()
2123 err = btf_dump_dump_type_data(d, mname, mtype, m->type, data + moffset / 8, in btf_dump_struct_data()
2128 d->typed_dump->depth--; in btf_dump_struct_data()
2129 btf_dump_data_pfx(d); in btf_dump_struct_data()
2130 btf_dump_type_values(d, "}"); in btf_dump_struct_data()
2139 static int btf_dump_ptr_data(struct btf_dump *d, in btf_dump_ptr_data() argument
2144 if (ptr_is_aligned(d->btf, id, data) && d->ptr_sz == sizeof(void *)) { in btf_dump_ptr_data()
2145 btf_dump_type_values(d, "%p", *(void **)data); in btf_dump_ptr_data()
2149 memcpy(&pt, data, d->ptr_sz); in btf_dump_ptr_data()
2150 if (d->ptr_sz == 4) in btf_dump_ptr_data()
2151 btf_dump_type_values(d, "0x%x", pt.p); in btf_dump_ptr_data()
2153 btf_dump_type_values(d, "0x%llx", pt.lp); in btf_dump_ptr_data()
2158 static int btf_dump_get_enum_value(struct btf_dump *d, in btf_dump_get_enum_value() argument
2166 if (!ptr_is_aligned(d->btf, id, data)) { in btf_dump_get_enum_value()
2170 err = btf_dump_get_bitfield_value(d, t, data, 0, 0, &val); in btf_dump_get_enum_value()
2177 switch (t->size) { in btf_dump_get_enum_value()
2191 pr_warn("unexpected size %d for enum, id:[%u]\n", t->size, id); in btf_dump_get_enum_value()
2192 return -EINVAL; in btf_dump_get_enum_value()
2196 static int btf_dump_enum_data(struct btf_dump *d, in btf_dump_enum_data() argument
2205 err = btf_dump_get_enum_value(d, t, data, id, &value); in btf_dump_enum_data()
2214 if (value != e->val) in btf_dump_enum_data()
2216 btf_dump_type_values(d, "%s", btf_name_of(d, e->name_off)); in btf_dump_enum_data()
2220 btf_dump_type_values(d, is_signed ? "%d" : "%u", value); in btf_dump_enum_data()
2227 btf_dump_type_values(d, "%s", btf_name_of(d, e->name_off)); in btf_dump_enum_data()
2231 btf_dump_type_values(d, is_signed ? "%lldLL" : "%lluULL", in btf_dump_enum_data()
2237 static int btf_dump_datasec_data(struct btf_dump *d, in btf_dump_datasec_data() argument
2247 btf_dump_type_values(d, "SEC(\"%s\") ", btf_name_of(d, t->name_off)); in btf_dump_datasec_data()
2250 var = btf__type_by_id(d->btf, vsi->type); in btf_dump_datasec_data()
2251 err = btf_dump_dump_type_data(d, NULL, var, vsi->type, data + vsi->offset, 0, 0); in btf_dump_datasec_data()
2254 btf_dump_printf(d, ";"); in btf_dump_datasec_data()
2259 /* return size of type, or if base type overflows, return -E2BIG. */
2260 static int btf_dump_type_data_check_overflow(struct btf_dump *d, in btf_dump_type_data_check_overflow() argument
2279 return data + nr_bytes > d->typed_dump->data_end ? -E2BIG : nr_bytes; in btf_dump_type_data_check_overflow()
2282 size = btf__resolve_size(d->btf, id); in btf_dump_type_data_check_overflow()
2287 return -EINVAL; in btf_dump_type_data_check_overflow()
2297 t = skip_mods_and_typedefs(d->btf, id, NULL); in btf_dump_type_data_check_overflow()
2301 return -EINVAL; in btf_dump_type_data_check_overflow()
2310 if (data + bits_offset / 8 + size > d->typed_dump->data_end) in btf_dump_type_data_check_overflow()
2311 return -E2BIG; in btf_dump_type_data_check_overflow()
2319 static int btf_dump_type_data_check_zero(struct btf_dump *d, in btf_dump_type_data_check_zero() argument
2330 * - we ask for them (emit_zeros) in btf_dump_type_data_check_zero()
2331 * - if we are at top-level so we see "struct empty { }" in btf_dump_type_data_check_zero()
2332 * - or if we are an array member and the array is non-empty and in btf_dump_type_data_check_zero()
2334 * have an integer array 0, 1, 0, 1 and only show non-zero values. in btf_dump_type_data_check_zero()
2336 * with a '\0', the array-level check_zero() will prevent showing it; in btf_dump_type_data_check_zero()
2340 if (d->typed_dump->emit_zeroes || d->typed_dump->depth == 0 || in btf_dump_type_data_check_zero()
2341 (d->typed_dump->is_array_member && in btf_dump_type_data_check_zero()
2342 !d->typed_dump->is_array_char)) in btf_dump_type_data_check_zero()
2345 t = skip_mods_and_typedefs(d->btf, id, NULL); in btf_dump_type_data_check_zero()
2350 return btf_dump_bitfield_check_zero(d, t, data, bits_offset, bit_sz); in btf_dump_type_data_check_zero()
2351 return btf_dump_base_type_check_zero(d, t, id, data); in btf_dump_type_data_check_zero()
2354 return btf_dump_base_type_check_zero(d, t, id, data); in btf_dump_type_data_check_zero()
2361 elem_type_id = array->type; in btf_dump_type_data_check_zero()
2362 elem_size = btf__resolve_size(d->btf, elem_type_id); in btf_dump_type_data_check_zero()
2363 elem_type = skip_mods_and_typedefs(d->btf, elem_type_id, NULL); in btf_dump_type_data_check_zero()
2371 * non-zero because the string is terminated. in btf_dump_type_data_check_zero()
2373 for (i = 0; i < array->nelems; i++) { in btf_dump_type_data_check_zero()
2375 return -ENODATA; in btf_dump_type_data_check_zero()
2376 err = btf_dump_type_data_check_zero(d, elem_type, in btf_dump_type_data_check_zero()
2381 if (err != -ENODATA) in btf_dump_type_data_check_zero()
2384 return -ENODATA; in btf_dump_type_data_check_zero()
2391 /* if any struct/union member is non-zero, the struct/union in btf_dump_type_data_check_zero()
2392 * is considered non-zero and dumped. in btf_dump_type_data_check_zero()
2398 mtype = btf__type_by_id(d->btf, m->type); in btf_dump_type_data_check_zero()
2406 err = btf_dump_type_data_check_zero(d, mtype, m->type, data + moffset / 8, in btf_dump_type_data_check_zero()
2411 return -ENODATA; in btf_dump_type_data_check_zero()
2415 err = btf_dump_get_enum_value(d, t, data, id, &value); in btf_dump_type_data_check_zero()
2419 return -ENODATA; in btf_dump_type_data_check_zero()
2427 static int btf_dump_dump_type_data(struct btf_dump *d, in btf_dump_dump_type_data() argument
2437 size = btf_dump_type_data_check_overflow(d, t, id, data, bits_offset, bit_sz); in btf_dump_dump_type_data()
2440 err = btf_dump_type_data_check_zero(d, t, id, data, bits_offset, bit_sz); in btf_dump_dump_type_data()
2445 if (err == -ENODATA) in btf_dump_dump_type_data()
2449 btf_dump_data_pfx(d); in btf_dump_dump_type_data()
2451 if (!d->typed_dump->skip_names) { in btf_dump_dump_type_data()
2453 btf_dump_printf(d, ".%s = ", fname); in btf_dump_dump_type_data()
2454 btf_dump_emit_type_cast(d, id, true); in btf_dump_dump_type_data()
2457 t = skip_mods_and_typedefs(d->btf, id, NULL); in btf_dump_dump_type_data()
2465 err = btf_dump_unsupported_data(d, t, id); in btf_dump_dump_type_data()
2469 err = btf_dump_bitfield_data(d, t, data, bits_offset, bit_sz); in btf_dump_dump_type_data()
2471 err = btf_dump_int_data(d, t, id, data, bits_offset); in btf_dump_dump_type_data()
2474 err = btf_dump_float_data(d, t, id, data); in btf_dump_dump_type_data()
2477 err = btf_dump_ptr_data(d, t, id, data); in btf_dump_dump_type_data()
2480 err = btf_dump_array_data(d, t, id, data); in btf_dump_dump_type_data()
2484 err = btf_dump_struct_data(d, t, id, data); in btf_dump_dump_type_data()
2493 err = btf_dump_get_bitfield_value(d, t, data, bits_offset, bit_sz, in btf_dump_dump_type_data()
2498 err = btf_dump_enum_data(d, t, id, &enum_val); in btf_dump_dump_type_data()
2500 err = btf_dump_enum_data(d, t, id, data); in btf_dump_dump_type_data()
2503 err = btf_dump_var_data(d, t, id, data); in btf_dump_dump_type_data()
2506 err = btf_dump_datasec_data(d, t, id, data); in btf_dump_dump_type_data()
2510 BTF_INFO_KIND(t->info), id); in btf_dump_dump_type_data()
2511 return -EINVAL; in btf_dump_dump_type_data()
2518 int btf_dump__dump_type_data(struct btf_dump *d, __u32 id, in btf_dump__dump_type_data() argument
2527 return libbpf_err(-EINVAL); in btf_dump__dump_type_data()
2529 t = btf__type_by_id(d->btf, id); in btf_dump__dump_type_data()
2531 return libbpf_err(-ENOENT); in btf_dump__dump_type_data()
2533 d->typed_dump = &typed_dump; in btf_dump__dump_type_data()
2534 d->typed_dump->data_end = data + data_sz; in btf_dump__dump_type_data()
2535 d->typed_dump->indent_lvl = OPTS_GET(opts, indent_level, 0); in btf_dump__dump_type_data()
2539 d->typed_dump->indent_str[0] = '\t'; in btf_dump__dump_type_data()
2541 libbpf_strlcpy(d->typed_dump->indent_str, opts->indent_str, in btf_dump__dump_type_data()
2542 sizeof(d->typed_dump->indent_str)); in btf_dump__dump_type_data()
2544 d->typed_dump->compact = OPTS_GET(opts, compact, false); in btf_dump__dump_type_data()
2545 d->typed_dump->skip_names = OPTS_GET(opts, skip_names, false); in btf_dump__dump_type_data()
2546 d->typed_dump->emit_zeroes = OPTS_GET(opts, emit_zeroes, false); in btf_dump__dump_type_data()
2548 ret = btf_dump_dump_type_data(d, NULL, t, id, data, 0, 0); in btf_dump__dump_type_data()
2550 d->typed_dump = NULL; in btf_dump__dump_type_data()