ebpflibbpf

Why does libbpf copy global variables to memory before creating BPF maps?


To use global variables in eBPF, libbpf internally creates BPF maps.

I found that global variables are copied into memory during the open phase, before creating the BPF maps.

static int
bpf_object__init_internal_map(struct bpf_object *obj, enum libbpf_map_type type,
                  const char *real_name, int sec_idx, void *data, size_t data_sz)
{
    struct bpf_map *map;
    map = bpf_object__add_map(obj);

    mmap_sz = bpf_map_mmap_sz(map);
    map->mmaped = mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE,
               MAP_SHARED | MAP_ANONYMOUS, -1, 0);

    if (data)
        memcpy(map->mmaped, data, data_sz);
}

What is the reason for copying global variables into memory before map creation? Why aren't the BPF maps created directly without this memory copy step?

I did some more research, but I still couldn't find a definitive explanation.


Solution

  • This logic was introduced in commit eba9c5f498a1 upstream. The description explains why this was implemented:

    Refactor global data map initialization to use anonymous mmap()-ed memory instead of malloc()-ed one. This allows to do a transparent re-mmap()-ing of already existing memory address to point to BPF map's memory after bpf_object__load() step (done in follow up patch). This choreographed setup allows to have a nice and unsurprising way to pre-initialize read-only (and r/w as well) maps by user and after BPF map creation keep working with mmap()-ed contents of this map. All in a way that doesn't require user code to update any pointers: the illusion of working with memory contents is preserved before and after actual BPF map instantiation.