#define KSYMS_SEC ".ksyms"
 #define STRUCT_OPS_SEC ".struct_ops"
 #define STRUCT_OPS_LINK_SEC ".struct_ops.link"
+#define ARENA_SEC ".arena.1"
 
 enum libbpf_map_type {
        LIBBPF_MAP_UNSPEC,
        Elf *elf;
        Elf64_Ehdr *ehdr;
        Elf_Data *symbols;
+       Elf_Data *arena_data;
        size_t shstrndx; /* section index for section name strings */
        size_t strtabidx;
        struct elf_sec_desc *secs;
        int text_shndx;
        int symbols_shndx;
        bool has_st_ops;
+       int arena_data_shndx;
 };
 
 struct usdt_manager;
 
        struct usdt_manager *usdt_man;
 
+       struct bpf_map *arena_map;
+       void *arena_data;
+       size_t arena_data_sz;
+
        struct kern_feature_cache *feat_cache;
        char *token_path;
        int token_fd;
        elf_end(obj->efile.elf);
        obj->efile.elf = NULL;
        obj->efile.symbols = NULL;
+       obj->efile.arena_data = NULL;
 
        zfree(&obj->efile.secs);
        obj->efile.sec_cnt = 0;
        def->value_size = data_sz;
        def->max_entries = 1;
        def->map_flags = type == LIBBPF_MAP_RODATA || type == LIBBPF_MAP_KCONFIG
-                        ? BPF_F_RDONLY_PROG : 0;
+               ? BPF_F_RDONLY_PROG : 0;
 
        /* failures are fine because of maps like .rodata.str1.1 */
        (void) map_fill_btf_type_info(obj, map);
        return 0;
 }
 
+static int init_arena_map_data(struct bpf_object *obj, struct bpf_map *map,
+                              const char *sec_name, int sec_idx,
+                              void *data, size_t data_sz)
+{
+       const long page_sz = sysconf(_SC_PAGE_SIZE);
+       size_t mmap_sz;
+
+       mmap_sz = bpf_map_mmap_sz(obj->arena_map);
+       if (roundup(data_sz, page_sz) > mmap_sz) {
+               pr_warn("elf: sec '%s': declared ARENA map size (%zu) is too small to hold global __arena variables of size %zu\n",
+                       sec_name, mmap_sz, data_sz);
+               return -E2BIG;
+       }
+
+       obj->arena_data = malloc(data_sz);
+       if (!obj->arena_data)
+               return -ENOMEM;
+       memcpy(obj->arena_data, data, data_sz);
+       obj->arena_data_sz = data_sz;
+
+       /* make bpf_map__init_value() work for ARENA maps */
+       map->mmaped = obj->arena_data;
+
+       return 0;
+}
+
 static int bpf_object__init_user_btf_maps(struct bpf_object *obj, bool strict,
                                          const char *pin_root_path)
 {
                        return err;
        }
 
+       for (i = 0; i < obj->nr_maps; i++) {
+               struct bpf_map *map = &obj->maps[i];
+
+               if (map->def.type != BPF_MAP_TYPE_ARENA)
+                       continue;
+
+               if (obj->arena_map) {
+                       pr_warn("map '%s': only single ARENA map is supported (map '%s' is also ARENA)\n",
+                               map->name, obj->arena_map->name);
+                       return -EINVAL;
+               }
+               obj->arena_map = map;
+
+               if (obj->efile.arena_data) {
+                       err = init_arena_map_data(obj, map, ARENA_SEC, obj->efile.arena_data_shndx,
+                                                 obj->efile.arena_data->d_buf,
+                                                 obj->efile.arena_data->d_size);
+                       if (err)
+                               return err;
+               }
+       }
+       if (obj->efile.arena_data && !obj->arena_map) {
+               pr_warn("elf: sec '%s': to use global __arena variables the ARENA map should be explicitly declared in SEC(\".maps\")\n",
+                       ARENA_SEC);
+               return -ENOENT;
+       }
+
        return 0;
 }
 
                                sec_desc->shdr = sh;
                                sec_desc->data = data;
                                obj->efile.has_st_ops = true;
+                       } else if (strcmp(name, ARENA_SEC) == 0) {
+                               obj->efile.arena_data = data;
+                               obj->efile.arena_data_shndx = idx;
                        } else {
                                pr_info("elf: skipping unrecognized data section(%d) %s\n",
                                        idx, name);
        type = bpf_object__section_to_libbpf_map_type(obj, shdr_idx);
        sym_sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, shdr_idx));
 
+       /* arena data relocation */
+       if (shdr_idx == obj->efile.arena_data_shndx) {
+               reloc_desc->type = RELO_DATA;
+               reloc_desc->insn_idx = insn_idx;
+               reloc_desc->map_idx = obj->arena_map - obj->maps;
+               reloc_desc->sym_off = sym->st_value;
+               return 0;
+       }
+
        /* generic map reference relocation */
        if (type == LIBBPF_MAP_UNSPEC) {
                if (!bpf_object__shndx_is_maps(obj, shdr_idx)) {
                        bpf_gen__map_freeze(obj->gen_loader, map - obj->maps);
                return 0;
        }
+
        err = bpf_map_update_elem(map->fd, &zero, map->mmaped, 0);
        if (err) {
                err = -errno;
                                                map->name, err);
                                        return err;
                                }
+                               if (obj->arena_data) {
+                                       memcpy(map->mmaped, obj->arena_data, obj->arena_data_sz);
+                                       zfree(&obj->arena_data);
+                               }
                        }
                        if (map->init_slots_sz && map->def.type != BPF_MAP_TYPE_PROG_ARRAY) {
                                err = init_map_in_map_slots(obj, map);
        zfree(&map->init_slots);
        map->init_slots_sz = 0;
 
-       if (map->mmaped) {
-               size_t mmap_sz;
-
-               mmap_sz = bpf_map_mmap_sz(map);
-               munmap(map->mmaped, mmap_sz);
-               map->mmaped = NULL;
-       }
+       if (map->mmaped && map->mmaped != map->obj->arena_data)
+               munmap(map->mmaped, bpf_map_mmap_sz(map));
+       map->mmaped = NULL;
 
        if (map->st_ops) {
                zfree(&map->st_ops->data);
        if (obj->token_fd > 0)
                close(obj->token_fd);
 
+       zfree(&obj->arena_data);
+
        free(obj);
 }
 
 int bpf_map__set_initial_value(struct bpf_map *map,
                               const void *data, size_t size)
 {
+       size_t actual_sz;
+
        if (map->obj->loaded || map->reused)
                return libbpf_err(-EBUSY);
 
-       if (!map->mmaped || map->libbpf_type == LIBBPF_MAP_KCONFIG ||
-           size != map->def.value_size)
+       if (!map->mmaped || map->libbpf_type == LIBBPF_MAP_KCONFIG)
+               return libbpf_err(-EINVAL);
+
+       if (map->def.type == BPF_MAP_TYPE_ARENA)
+               actual_sz = map->obj->arena_data_sz;
+       else
+               actual_sz = map->def.value_size;
+       if (size != actual_sz)
                return libbpf_err(-EINVAL);
 
        memcpy(map->mmaped, data, size);
        return 0;
 }
 
-void *bpf_map__initial_value(struct bpf_map *map, size_t *psize)
+void *bpf_map__initial_value(const struct bpf_map *map, size_t *psize)
 {
        if (bpf_map__is_struct_ops(map)) {
                if (psize)
 
        if (!map->mmaped)
                return NULL;
-       *psize = map->def.value_size;
+
+       if (map->def.type == BPF_MAP_TYPE_ARENA)
+               *psize = map->obj->arena_data_sz;
+       else
+               *psize = map->def.value_size;
+
        return map->mmaped;
 }
 
                        continue;
                }
 
+               if (map->def.type == BPF_MAP_TYPE_ARENA) {
+                       *mmaped = map->mmaped;
+                       continue;
+               }
+
                if (map->def.map_flags & BPF_F_RDONLY_PROG)
                        prot = PROT_READ;
                else