int inner_map_fd = map_fd[maps[i].def.inner_map_idx];
 
                        map_fd[i] = bpf_create_map_in_map_node(maps[i].def.type,
+                                                       maps[i].name,
                                                        maps[i].def.key_size,
                                                        inner_map_fd,
                                                        maps[i].def.max_entries,
                                                        numa_node);
                } else {
                        map_fd[i] = bpf_create_map_node(maps[i].def.type,
+                                                       maps[i].name,
                                                        maps[i].def.key_size,
                                                        maps[i].def.value_size,
                                                        maps[i].def.max_entries,
 
 
                        inner_lru_map_fds[cpu] =
                                bpf_create_map_node(BPF_MAP_TYPE_LRU_HASH,
+                                                   test_map_names[INNER_LRU_HASH_PREALLOC],
                                                    sizeof(uint32_t),
                                                    sizeof(long),
                                                    inner_lru_hash_size, 0,
 
 /* Specify numa node during map creation */
 #define BPF_F_NUMA_NODE                (1U << 2)
 
+#define BPF_OBJ_NAME_LEN 16U
+
 union bpf_attr {
        struct { /* anonymous struct used by BPF_MAP_CREATE command */
                __u32   map_type;       /* one of enum bpf_map_type */
                __u32   numa_node;      /* numa node (effective only if
                                         * BPF_F_NUMA_NODE is set).
                                         */
+               __u8    map_name[BPF_OBJ_NAME_LEN];
        };
 
        struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */
                __aligned_u64   log_buf;        /* user supplied buffer */
                __u32           kern_version;   /* checked when prog_type=kprobe */
                __u32           prog_flags;
+               __u8            prog_name[BPF_OBJ_NAME_LEN];
        };
 
        struct { /* anonymous struct used by BPF_OBJ_* commands */
        __u32 xlated_prog_len;
        __aligned_u64 jited_prog_insns;
        __aligned_u64 xlated_prog_insns;
+       __u64 load_time;        /* ns since boottime */
+       __u32 created_by_uid;
+       __u32 nr_map_ids;
+       __aligned_u64 map_ids;
+       __u8  name[BPF_OBJ_NAME_LEN];
 } __attribute__((aligned(8)));
 
 struct bpf_map_info {
        __u32 value_size;
        __u32 max_entries;
        __u32 map_flags;
+       __u8  name[BPF_OBJ_NAME_LEN];
 } __attribute__((aligned(8)));
 
 /* User bpf_sock_ops struct to access socket values and specify request ops
 
 # endif
 #endif
 
+#define min(x, y) ((x) < (y) ? (x) : (y))
+
 static inline __u64 ptr_to_u64(const void *ptr)
 {
        return (__u64) (unsigned long) ptr;
        return syscall(__NR_bpf, cmd, attr, size);
 }
 
-int bpf_create_map_node(enum bpf_map_type map_type, int key_size,
-                       int value_size, int max_entries, __u32 map_flags,
-                       int node)
+int bpf_create_map_node(enum bpf_map_type map_type, const char *name,
+                       int key_size, int value_size, int max_entries,
+                       __u32 map_flags, int node)
 {
+       __u32 name_len = name ? strlen(name) : 0;
        union bpf_attr attr;
 
        memset(&attr, '\0', sizeof(attr));
        attr.value_size = value_size;
        attr.max_entries = max_entries;
        attr.map_flags = map_flags;
+       memcpy(attr.map_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1));
+
        if (node >= 0) {
                attr.map_flags |= BPF_F_NUMA_NODE;
                attr.numa_node = node;
 int bpf_create_map(enum bpf_map_type map_type, int key_size,
                   int value_size, int max_entries, __u32 map_flags)
 {
-       return bpf_create_map_node(map_type, key_size, value_size,
+       return bpf_create_map_node(map_type, NULL, key_size, value_size,
                                   max_entries, map_flags, -1);
 }
 
-int bpf_create_map_in_map_node(enum bpf_map_type map_type, int key_size,
-                              int inner_map_fd, int max_entries,
+int bpf_create_map_name(enum bpf_map_type map_type, const char *name,
+                       int key_size, int value_size, int max_entries,
+                       __u32 map_flags)
+{
+       return bpf_create_map_node(map_type, name, key_size, value_size,
+                                  max_entries, map_flags, -1);
+}
+
+int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name,
+                              int key_size, int inner_map_fd, int max_entries,
                               __u32 map_flags, int node)
 {
+       __u32 name_len = name ? strlen(name) : 0;
        union bpf_attr attr;
 
        memset(&attr, '\0', sizeof(attr));
        attr.inner_map_fd = inner_map_fd;
        attr.max_entries = max_entries;
        attr.map_flags = map_flags;
+       memcpy(attr.map_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1));
+
        if (node >= 0) {
                attr.map_flags |= BPF_F_NUMA_NODE;
                attr.numa_node = node;
        return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
 }
 
-int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size,
-                         int inner_map_fd, int max_entries, __u32 map_flags)
+int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
+                         int key_size, int inner_map_fd, int max_entries,
+                         __u32 map_flags)
 {
-       return bpf_create_map_in_map_node(map_type, key_size, inner_map_fd,
-                                         max_entries, map_flags, -1);
+       return bpf_create_map_in_map_node(map_type, name, key_size,
+                                         inner_map_fd, max_entries, map_flags,
+                                         -1);
 }
 
-int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
-                    size_t insns_cnt, const char *license,
-                    __u32 kern_version, char *log_buf, size_t log_buf_sz)
+int bpf_load_program_name(enum bpf_prog_type type, const char *name,
+                         const struct bpf_insn *insns,
+                         size_t insns_cnt, const char *license,
+                         __u32 kern_version, char *log_buf,
+                         size_t log_buf_sz)
 {
        int fd;
        union bpf_attr attr;
+       __u32 name_len = name ? strlen(name) : 0;
 
        bzero(&attr, sizeof(attr));
        attr.prog_type = type;
        attr.log_size = 0;
        attr.log_level = 0;
        attr.kern_version = kern_version;
+       memcpy(attr.prog_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1));
 
        fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
        if (fd >= 0 || !log_buf || !log_buf_sz)
        return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
 }
 
+int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
+                    size_t insns_cnt, const char *license,
+                    __u32 kern_version, char *log_buf,
+                    size_t log_buf_sz)
+{
+       return bpf_load_program_name(type, NULL, insns, insns_cnt, license,
+                                    kern_version, log_buf, log_buf_sz);
+}
+
 int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
                       size_t insns_cnt, int strict_alignment,
                       const char *license, __u32 kern_version,
 
 #include <linux/bpf.h>
 #include <stddef.h>
 
-int bpf_create_map_node(enum bpf_map_type map_type, int key_size,
-                       int value_size, int max_entries, __u32 map_flags,
-                       int node);
+int bpf_create_map_node(enum bpf_map_type map_type, const char *name,
+                       int key_size, int value_size, int max_entries,
+                       __u32 map_flags, int node);
+int bpf_create_map_name(enum bpf_map_type map_type, const char *name,
+                       int key_size, int value_size, int max_entries,
+                       __u32 map_flags);
 int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
                   int max_entries, __u32 map_flags);
-int bpf_create_map_in_map_node(enum bpf_map_type map_type, int key_size,
-                              int inner_map_fd, int max_entries,
+int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name,
+                              int key_size, int inner_map_fd, int max_entries,
                               __u32 map_flags, int node);
-int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size,
-                         int inner_map_fd, int max_entries, __u32 map_flags);
+int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
+                         int key_size, int inner_map_fd, int max_entries,
+                         __u32 map_flags);
 
 /* Recommend log buffer size */
 #define BPF_LOG_BUF_SIZE 65536
+int bpf_load_program_name(enum bpf_prog_type type, const char *name,
+                         const struct bpf_insn *insns,
+                         size_t insns_cnt, const char *license,
+                         __u32 kern_version, char *log_buf,
+                         size_t log_buf_sz);
 int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
                     size_t insns_cnt, const char *license,
                     __u32 kern_version, char *log_buf,
 
 struct bpf_program {
        /* Index in elf obj file, for relocation use. */
        int idx;
+       char *name;
        char *section_name;
        struct bpf_insn *insns;
        size_t insns_cnt;
        prog->clear_priv = NULL;
 
        bpf_program__unload(prog);
+       zfree(&prog->name);
        zfree(&prog->section_name);
        zfree(&prog->insns);
        zfree(&prog->reloc_desc);
 }
 
 static int
-bpf_program__init(void *data, size_t size, char *name, int idx,
-                   struct bpf_program *prog)
+bpf_program__init(void *data, size_t size, char *section_name, int idx,
+                 struct bpf_program *prog)
 {
        if (size < sizeof(struct bpf_insn)) {
-               pr_warning("corrupted section '%s'\n", name);
+               pr_warning("corrupted section '%s'\n", section_name);
                return -EINVAL;
        }
 
        bzero(prog, sizeof(*prog));
 
-       prog->section_name = strdup(name);
+       prog->section_name = strdup(section_name);
        if (!prog->section_name) {
-               pr_warning("failed to alloc name for prog %s\n",
-                          name);
+               pr_warning("failed to alloc name for prog under section %s\n",
+                          section_name);
                goto errout;
        }
 
        prog->insns = malloc(size);
        if (!prog->insns) {
-               pr_warning("failed to alloc insns for %s\n", name);
+               pr_warning("failed to alloc insns for prog under section %s\n",
+                          section_name);
                goto errout;
        }
        prog->insns_cnt = size / sizeof(struct bpf_insn);
 
 static int
 bpf_object__add_program(struct bpf_object *obj, void *data, size_t size,
-                       char *name, int idx)
+                       char *section_name, int idx)
 {
        struct bpf_program prog, *progs;
        int nr_progs, err;
 
-       err = bpf_program__init(data, size, name, idx, &prog);
+       err = bpf_program__init(data, size, section_name, idx, &prog);
        if (err)
                return err;
 
                 * is still valid, so don't need special treat for
                 * bpf_close_object().
                 */
-               pr_warning("failed to alloc a new program '%s'\n",
-                          name);
+               pr_warning("failed to alloc a new program under section '%s'\n",
+                          section_name);
                bpf_program__exit(&prog);
                return -ENOMEM;
        }
        return 0;
 }
 
+static int
+bpf_object__init_prog_names(struct bpf_object *obj)
+{
+       Elf_Data *symbols = obj->efile.symbols;
+       struct bpf_program *prog;
+       size_t pi, si;
+
+       for (pi = 0; pi < obj->nr_programs; pi++) {
+               char *name = NULL;
+
+               prog = &obj->programs[pi];
+
+               for (si = 0; si < symbols->d_size / sizeof(GElf_Sym) && !name;
+                    si++) {
+                       GElf_Sym sym;
+
+                       if (!gelf_getsym(symbols, si, &sym))
+                               continue;
+                       if (sym.st_shndx != prog->idx)
+                               continue;
+
+                       name = elf_strptr(obj->efile.elf,
+                                         obj->efile.strtabidx,
+                                         sym.st_name);
+                       if (!name) {
+                               pr_warning("failed to get sym name string for prog %s\n",
+                                          prog->section_name);
+                               return -LIBBPF_ERRNO__LIBELF;
+                       }
+               }
+
+               if (!name) {
+                       pr_warning("failed to find sym for prog %s\n",
+                                  prog->section_name);
+                       return -EINVAL;
+               }
+
+               prog->name = strdup(name);
+               if (!prog->name) {
+                       pr_warning("failed to allocate memory for prog sym %s\n",
+                                  name);
+                       return -ENOMEM;
+               }
+       }
+
+       return 0;
+}
+
 static struct bpf_object *bpf_object__new(const char *path,
                                          void *obj_buf,
                                          size_t obj_buf_sz)
                pr_warning("Corrupted ELF file: index of strtab invalid\n");
                return LIBBPF_ERRNO__FORMAT;
        }
-       if (obj->efile.maps_shndx >= 0)
+       if (obj->efile.maps_shndx >= 0) {
                err = bpf_object__init_maps(obj);
+               if (err)
+                       goto out;
+       }
+       err = bpf_object__init_prog_names(obj);
 out:
        return err;
 }
                struct bpf_map_def *def = &obj->maps[i].def;
                int *pfd = &obj->maps[i].fd;
 
-               *pfd = bpf_create_map(def->type,
-                                     def->key_size,
-                                     def->value_size,
-                                     def->max_entries,
-                                     0);
+               *pfd = bpf_create_map_name(def->type,
+                                          obj->maps[i].name,
+                                          def->key_size,
+                                          def->value_size,
+                                          def->max_entries,
+                                          0);
                if (*pfd < 0) {
                        size_t j;
                        int err = *pfd;
 }
 
 static int
-load_program(enum bpf_prog_type type, struct bpf_insn *insns,
+load_program(enum bpf_prog_type type, const char *name, struct bpf_insn *insns,
             int insns_cnt, char *license, u32 kern_version, int *pfd)
 {
        int ret;
        if (!log_buf)
                pr_warning("Alloc log buffer for bpf loader error, continue without log\n");
 
-       ret = bpf_load_program(type, insns, insns_cnt, license,
-                              kern_version, log_buf, BPF_LOG_BUF_SIZE);
+       ret = bpf_load_program_name(type, name, insns, insns_cnt, license,
+                                   kern_version, log_buf, BPF_LOG_BUF_SIZE);
 
        if (ret >= 0) {
                *pfd = ret;
                if (type != BPF_PROG_TYPE_KPROBE) {
                        int fd;
 
-                       fd = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns,
-                                             insns_cnt, license, kern_version,
-                                             NULL, 0);
+                       fd = bpf_load_program_name(BPF_PROG_TYPE_KPROBE, name,
+                                                  insns, insns_cnt, license,
+                                                  kern_version, NULL, 0);
                        if (fd >= 0) {
                                close(fd);
                                ret = -LIBBPF_ERRNO__PROGTYPE;
                        pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n",
                                   prog->section_name, prog->instances.nr);
                }
-               err = load_program(prog->type, prog->insns, prog->insns_cnt,
-                                  license, kern_version, &fd);
+               err = load_program(prog->type, prog->name, prog->insns,
+                                  prog->insns_cnt, license, kern_version, &fd);
                if (!err)
                        prog->instances.fds[0] = fd;
                goto out;
                        continue;
                }
 
-               err = load_program(prog->type, result.new_insn_ptr,
+               err = load_program(prog->type, prog->name,
+                                  result.new_insn_ptr,
                                   result.new_insn_cnt,
                                   license, kern_version, &fd);
 
 
                return inner_map_fd;
        }
 
-       outer_map_fd = bpf_create_map_in_map(BPF_MAP_TYPE_ARRAY_OF_MAPS,
+       outer_map_fd = bpf_create_map_in_map(BPF_MAP_TYPE_ARRAY_OF_MAPS, NULL,
                                             sizeof(int), inner_map_fd, 1, 0);
        if (outer_map_fd < 0)
                printf("Failed to create array of maps '%s'!\n",