int machine__process_bpf(struct machine *machine, union perf_event *event, struct perf_sample *sample)
{ if (dump_trace)
perf_event__fprintf_bpf(event, stdout);
switch (event->bpf.type) { case PERF_BPF_EVENT_PROG_LOAD: return machine__process_bpf_event_load(machine, event, sample);
case PERF_BPF_EVENT_PROG_UNLOAD: /* * Do not free bpf_prog_info and btf of the program here, * as annotation still need them. They will be freed at * the end of the session.
*/ break; default:
pr_debug("unexpected bpf event type of %d\n", event->bpf.type); break;
} return 0;
}
/* If it's not an .rodata map, don't bother. */ if (map_info.type != BPF_MAP_TYPE_ARRAY ||
map_info.key_size != sizeof(int) ||
map_info.max_entries != 1 ||
!map_info.btf_value_type_id ||
!strstr(map_info.name, ".rodata")) { goto out_close;
}
btf = btf__load_from_kernel_by_id(map_info.btf_id); if (!btf) goto out_close;
datasec = btf__type_by_id(btf, map_info.btf_value_type_id); if (!btf_is_datasec(datasec)) goto out_free_btf;
/* * If there aren't any variables with the "bpf_metadata_" prefix, * don't bother.
*/
vlen = btf_vlen(datasec);
vsi = btf_var_secinfos(datasec);
vars = 0; for (unsignedint i = 0; i < vlen; i++, vsi++) { conststruct btf_type *t_var = btf__type_by_id(btf, vsi->type); constchar *name = btf__name_by_offset(btf, t_var->name_off);
if (name_has_bpf_metadata_prefix(&name))
vars++;
} if (vars == 0) goto out_free_btf;
rodata = zalloc(map_info.value_size); if (!rodata) goto out_free_btf;
key = 0; if (bpf_map_lookup_elem(map_fd, &key, rodata)) {
free(rodata); goto out_free_btf;
}
close(map_fd);
info_linear = get_bpf_prog_info_linear(fd, arrays); if (IS_ERR_OR_NULL(info_linear)) {
info_linear = NULL;
pr_debug("%s: failed to get BPF program info. aborting\n", __func__); return -1;
}
if (info_linear->info_len < offsetof(struct bpf_prog_info, prog_tags)) {
free(info_linear);
pr_debug("%s: the kernel is too old, aborting\n", __func__); return -2;
}
info = &info_linear->info; if (!info->jited_ksyms) {
free(info_linear); return -1;
}
/* number of ksyms, func_lengths, and tags should match */
sub_prog_cnt = info->nr_jited_ksyms; if (sub_prog_cnt != info->nr_prog_tags ||
sub_prog_cnt != info->nr_jited_func_lens) {
free(info_linear); return -1;
}
/* check BTF func info support */ if (info->btf_id && info->nr_func_info && info->func_info_rec_size) { /* btf func info number should be same as sub_prog_cnt */ if (sub_prog_cnt != info->nr_func_info) {
pr_debug("%s: mismatch in BPF sub program count and BTF function info count, aborting\n", __func__);
free(info_linear); return -1;
}
btf = btf__load_from_kernel_by_id(info->btf_id); if (libbpf_get_error(btf)) {
pr_debug("%s: failed to get BTF of id %u, aborting\n", __func__, info->btf_id);
err = -1; goto out;
}
perf_env__fetch_btf(env, info->btf_id, btf);
}
/* Synthesize PERF_RECORD_KSYMBOL */ for (i = 0; i < sub_prog_cnt; i++) {
__u32 *prog_lens = (__u32 *)(uintptr_t)(info->jited_func_lens);
__u64 *prog_addrs = (__u64 *)(uintptr_t)(info->jited_ksyms); int name_len;
/* save bpf_prog_info to env */
info_node = malloc(sizeof(struct bpf_prog_info_node)); if (!info_node) {
err = -1; goto out;
}
info_node->info_linear = info_linear;
info_node->metadata = NULL; if (!perf_env__insert_bpf_prog_info(env, info_node)) { /* * Insert failed, likely because of a duplicate event * made by the sideband thread. Ignore synthesizing the * metadata.
*/
free(info_node); goto out;
} /* info_linear is now owned by info_node and shouldn't be freed below. */
info_linear = NULL;
/* * process after saving bpf_prog_info to env, so that * required information is ready for look up
*/
err = perf_tool__process_synth_event(tool, event,
machine, process);
info_linear = get_bpf_prog_info_linear(fd, arrays); if (IS_ERR_OR_NULL(info_linear)) {
pr_debug("%s: failed to get BPF program info. aborting\n", __func__);
err = PTR_ERR(info_linear); goto out;
}
btf_id = info_linear->info.btf_id;
info_node = malloc(sizeof(struct bpf_prog_info_node)); if (info_node) {
info_node->info_linear = info_linear;
info_node->metadata = bpf_metadata_create(&info_linear->info); if (!perf_env__insert_bpf_prog_info(env, info_node)) {
pr_debug("%s: duplicate add bpf info request for id %u\n",
__func__, btf_id);
free(info_linear);
free(info_node); goto out;
}
} else {
free(info_linear);
err = -ENOMEM; goto out;
}
if (btf_id == 0) goto out;
btf = btf__load_from_kernel_by_id(btf_id); if (!btf) {
err = -errno;
pr_debug("%s: failed to get BTF of id %u %d\n", __func__, btf_id, err);
} else {
perf_env__fetch_btf(env, btf_id, btf);
}
out:
btf__free(btf);
close(fd); return err;
}
staticint bpf_event__sb_cb(union perf_event *event, void *data)
{ struct perf_env *env = data; int ret = 0;
if (event->header.type != PERF_RECORD_BPF_EVENT) return -1;
switch (event->bpf.type) { case PERF_BPF_EVENT_PROG_LOAD:
ret = perf_env__add_bpf_info(env, event->bpf.id);
case PERF_BPF_EVENT_PROG_UNLOAD: /* * Do not free bpf_prog_info and btf of the program here, * as annotation still need them. They will be freed at * the end of the session.
*/ break; default:
pr_debug("unexpected bpf event type of %d\n", event->bpf.type); break;
}
return ret;
}
int evlist__add_bpf_sb_event(struct evlist *evlist, struct perf_env *env)
{ struct perf_event_attr attr = {
.type = PERF_TYPE_SOFTWARE,
.config = PERF_COUNT_SW_DUMMY,
.sample_id_all = 1,
.watermark = 1,
.bpf_event = 1,
.size = sizeof(attr), /* to capture ABI version */
};
/* * Older gcc versions don't support designated initializers, like above, * for unnamed union members, such as the following:
*/
attr.wakeup_watermark = 1;
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.14Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.