* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/bpf.h>
+#include <stdalign.h>
+#include <sys/syscall.h>
#include <sys/timerfd.h>
#include <time.h>
#include "lsfd.h"
+#define offsetofend(TYPE, MEMBER) \
+ (offsetof(TYPE, MEMBER) + sizeof_member(TYPE, MEMBER))
+
struct unkn {
struct file file;
const struct anon_ops *anon_ops;
struct anon_bpf_prog_data {
int type;
int id;
+ char name[BPF_OBJ_NAME_LEN + 1];
};
static bool anon_bpf_prog_probe(const char *str)
else
xasprintf(str, "UNKNOWN(%d)", data->type);
return true;
+ case COL_BPF_NAME:
+ *str = xstrdup(data->name);
+ return true;
default:
return false;
}
else
xasprintf(&str, "id=%d type=UNKNOWN(%d)", data->id, data->type);
+ if (*data->name)
+ xstrfappend(&str, " name=%s", data->name);
+
return str;
}
struct anon_bpf_prog_data *data = xmalloc(sizeof(*data));
data->type = -1;
data->id = -1;
+ data->name[0] = '\0';
unkn->anon_data = data;
}
free(data);
}
+static void anon_bpf_prog_get_more_info(struct anon_bpf_prog_data *prog_data)
+{
+ union bpf_attr attr = {
+ .prog_id = (int32_t)prog_data->id,
+ .next_id = 0,
+ .open_flags = 0,
+ };
+ struct bpf_prog_info info = { 0 };
+ union bpf_attr info_attr = {
+ .info.info_len = sizeof(info),
+ .info.info = (uint64_t)(uintptr_t)&info,
+ };
+
+ int bpf_fd = syscall(SYS_bpf, BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr));
+ if (bpf_fd < 0)
+ return;
+
+ info_attr.info.bpf_fd = bpf_fd;
+ if (syscall(SYS_bpf, BPF_OBJ_GET_INFO_BY_FD, &info_attr, offsetofend(union bpf_attr, info)) == 0) {
+ memcpy(prog_data->name,
+ info.name,
+ BPF_OBJ_NAME_LEN);
+ prog_data->name[BPF_OBJ_NAME_LEN] = '\0';
+ }
+ close (bpf_fd);
+}
+
static int anon_bpf_prog_handle_fdinfo(struct unkn *unkn, const char *key, const char *value)
{
if (strcmp(key, "prog_id") == 0) {
if (rc < 0)
return 0; /* ignore -- parse failed */
((struct anon_bpf_prog_data *)unkn->anon_data)->id = (int)t;
+ anon_bpf_prog_get_more_info((struct anon_bpf_prog_data *)unkn->anon_data);
return 1;
}
struct anon_bpf_map_data {
int type;
int id;
+ char name[BPF_OBJ_NAME_LEN + 1];
};
static bool anon_bpf_map_probe(const char *str)
else
xasprintf(str, "UNKNOWN(%d)", data->type);
return true;
+ case COL_BPF_NAME:
+ *str = xstrdup(data->name);
+ return true;
default:
return false;
}
xasprintf(&str, "id=%d type=%s", data->id, t);
else
xasprintf(&str, "id=%d type=UNKNOWN(%d)", data->id, data->type);
+
+ if (*data->name)
+ xstrfappend(&str, " name=%s", data->name);
+
return str;
}
struct anon_bpf_map_data *data = xmalloc(sizeof(*data));
data->type = -1;
data->id = -1;
+ data->name[0] = '\0';
unkn->anon_data = data;
}
free(data);
}
+static void anon_bpf_map_get_more_info(struct anon_bpf_map_data *map_data)
+{
+ union bpf_attr attr = {
+ .map_id = (int32_t)map_data->id,
+ .next_id = 0,
+ .open_flags = 0,
+ };
+ struct bpf_map_info info = { 0 };
+ union bpf_attr info_attr = {
+ .info.info_len = sizeof(info),
+ .info.info = (uint64_t)(uintptr_t)&info,
+ };
+
+ int bpf_fd = syscall(SYS_bpf, BPF_MAP_GET_FD_BY_ID, &attr, sizeof(attr));
+ if (bpf_fd < 0)
+ return;
+
+ info_attr.info.bpf_fd = bpf_fd;
+ if (syscall(SYS_bpf, BPF_OBJ_GET_INFO_BY_FD, &info_attr, offsetofend(union bpf_attr, info)) == 0) {
+ memcpy(map_data->name,
+ info.name,
+ BPF_OBJ_NAME_LEN);
+ map_data->name[BPF_OBJ_NAME_LEN] = '\0';
+ }
+ close (bpf_fd);
+}
+
static int anon_bpf_map_handle_fdinfo(struct unkn *unkn, const char *key, const char *value)
{
if (strcmp(key, "map_id") == 0) {
if (rc < 0)
return 0; /* ignore -- parse failed */
((struct anon_bpf_map_data *)unkn->anon_data)->id = (int)t;
+ anon_bpf_map_get_more_info((struct anon_bpf_map_data *)unkn->anon_data);
return 1;
}