// SPDX-License-Identifier: GPL-2.0 
 | 
/* Copyright (c) 2020 Facebook */ 
 | 
#include <linux/bpf.h> 
 | 
#include <bpf/bpf_helpers.h> 
 | 
#include <bpf/bpf_tracing.h> 
 | 
#include <bpf/bpf_core_read.h> 
 | 
  
 | 
#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record) 
 | 
struct seq_file; 
 | 
struct bpf_iter_meta { 
 | 
    struct seq_file *seq; 
 | 
    __u64 session_id; 
 | 
    __u64 seq_num; 
 | 
}; 
 | 
  
 | 
struct bpf_map { 
 | 
    __u32 id; 
 | 
    char name[16]; 
 | 
    __u32 max_entries; 
 | 
}; 
 | 
  
 | 
struct bpf_iter__bpf_map { 
 | 
    struct bpf_iter_meta *meta; 
 | 
    struct bpf_map *map; 
 | 
}; 
 | 
  
 | 
struct btf_type { 
 | 
    __u32 name_off; 
 | 
}; 
 | 
  
 | 
struct btf_header { 
 | 
    __u32   str_len; 
 | 
}; 
 | 
  
 | 
struct btf { 
 | 
    const char *strings; 
 | 
    struct btf_type **types; 
 | 
    struct btf_header hdr; 
 | 
}; 
 | 
  
 | 
struct bpf_prog_aux { 
 | 
    __u32 id; 
 | 
    char name[16]; 
 | 
    const char *attach_func_name; 
 | 
    struct bpf_prog *dst_prog; 
 | 
    struct bpf_func_info *func_info; 
 | 
    struct btf *btf; 
 | 
}; 
 | 
  
 | 
struct bpf_prog { 
 | 
    struct bpf_prog_aux *aux; 
 | 
}; 
 | 
  
 | 
struct bpf_iter__bpf_prog { 
 | 
    struct bpf_iter_meta *meta; 
 | 
    struct bpf_prog *prog; 
 | 
}; 
 | 
#pragma clang attribute pop 
 | 
  
 | 
static const char *get_name(struct btf *btf, long btf_id, const char *fallback) 
 | 
{ 
 | 
    struct btf_type **types, *t; 
 | 
    unsigned int name_off; 
 | 
    const char *str; 
 | 
  
 | 
    if (!btf) 
 | 
        return fallback; 
 | 
    str = btf->strings; 
 | 
    types = btf->types; 
 | 
    bpf_probe_read_kernel(&t, sizeof(t), types + btf_id); 
 | 
    name_off = BPF_CORE_READ(t, name_off); 
 | 
    if (name_off >= btf->hdr.str_len) 
 | 
        return fallback; 
 | 
    return str + name_off; 
 | 
} 
 | 
  
 | 
SEC("iter/bpf_map") 
 | 
int dump_bpf_map(struct bpf_iter__bpf_map *ctx) 
 | 
{ 
 | 
    struct seq_file *seq = ctx->meta->seq; 
 | 
    __u64 seq_num = ctx->meta->seq_num; 
 | 
    struct bpf_map *map = ctx->map; 
 | 
  
 | 
    if (!map) 
 | 
        return 0; 
 | 
  
 | 
    if (seq_num == 0) 
 | 
        BPF_SEQ_PRINTF(seq, "  id name             max_entries\n"); 
 | 
  
 | 
    BPF_SEQ_PRINTF(seq, "%4u %-16s%6d\n", map->id, map->name, map->max_entries); 
 | 
    return 0; 
 | 
} 
 | 
  
 | 
SEC("iter/bpf_prog") 
 | 
int dump_bpf_prog(struct bpf_iter__bpf_prog *ctx) 
 | 
{ 
 | 
    struct seq_file *seq = ctx->meta->seq; 
 | 
    __u64 seq_num = ctx->meta->seq_num; 
 | 
    struct bpf_prog *prog = ctx->prog; 
 | 
    struct bpf_prog_aux *aux; 
 | 
  
 | 
    if (!prog) 
 | 
        return 0; 
 | 
  
 | 
    aux = prog->aux; 
 | 
    if (seq_num == 0) 
 | 
        BPF_SEQ_PRINTF(seq, "  id name             attached\n"); 
 | 
  
 | 
    BPF_SEQ_PRINTF(seq, "%4u %-16s %s %s\n", aux->id, 
 | 
               get_name(aux->btf, aux->func_info[0].type_id, aux->name), 
 | 
               aux->attach_func_name, aux->dst_prog->aux->name); 
 | 
    return 0; 
 | 
} 
 | 
char LICENSE[] SEC("license") = "GPL"; 
 |