Repository: aya-rs/aya (language: rust)

Issue:
bpf(2) fails with invalid argument when creating .bss map
I wanted to test out a simple example of using .data, .rodata, and .bss maps in Aya. It seems that .data and .rodata work just fine, but creating the .bss map always seems to fail with an invalid argument error. Inspecting the strace dump (shown below), the offending part of the bpf_attr struct appears to be an incorrect map value size of 0.

Here is my minimal reproduction aya-bpf code:
```rust
#![no_std]
#![no_main]

#[used]
static TEST_RODATA: i32 = 0;
#[used]
static mut TEST_DATA: i32 = 1;
#[used]
static mut TEST_BSS: i32 = 0;
```

Relevant strace dump (offending bpf syscall is the last one, others included for context):
```
46537 bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_ARRAY, key_size=4, value_size=4, max_entries=1, map_flags=0, inner_map_fd=0, map_name=".rodata", map_ifindex=0, btf_fd=0, btf_key_type_id=0, btf_value_type_id=0, btf_vmlinux_value_type_id=0}, 128) = 3
46537 bpf(BPF_MAP_UPDATE_ELEM, {map_fd=3, key=0x563ce3ec1204, value=0x563ce4ea7020, flags=BPF_ANY}, 128) = 0
46537 bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_ARRAY, key_size=4, value_size=4, max_entries=1, map_flags=0, inner_map_fd=0, map_name=".data", map_ifindex=0, btf_fd=0, btf_key_type_id=0, btf_value_type_id=0, btf_vmlinux_value_type_id=0}, 128) = 4
46537 bpf(BPF_MAP_UPDATE_ELEM, {map_fd=4, key=0x563ce3ec1204, value=0x563ce4eaec90, flags=BPF_ANY}, 128) = 0
46537 bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_ARRAY, key_size=4, value_size=0, max_entries=1, map_flags=0, inner_map_fd=0, map_name=".bss", map_ifindex=0, btf_fd=0, btf_key_type_id=0, btf_value_type_id=0, btf_vmlinux_value_type_id=0}, 128) = -1 EINVAL (Invalid argument)
```


Discussion / hints:

Fix patch:
diff --git a/aya/src/obj/mod.rs b/aya/src/obj/mod.rs
index c4c766309..5e3c99c30 100644
--- a/aya/src/obj/mod.rs
+++ b/aya/src/obj/mod.rs
@@ -410,6 +410,7 @@ struct Section<'a> {
     address: u64,
     name: &'a str,
     data: &'a [u8],
+    size: u64,
     relocations: Vec<Relocation>,
 }
 
@@ -428,6 +429,7 @@ impl<'data, 'file, 'a> TryFrom<&'a ObjSection<'data, 'file>> for Section<'a> {
             address: section.address(),
             name: section.name().map_err(map_err)?,
             data: section.data().map_err(map_err)?,
+            size: section.size(),
             relocations: section
                 .relocations()
                 .map(|(offset, r)| {
@@ -505,7 +507,9 @@ fn parse_map(section: &Section, name: &str) -> Result<Map, ParseError> {
         let def = bpf_map_def {
             map_type: BPF_MAP_TYPE_ARRAY as u32,
             key_size: mem::size_of::<u32>() as u32,
-            value_size: section.data.len() as u32,
+            // We need to use section.size here since
+            // .bss will always have data.len() == 0
+            value_size: section.size as u32,
             max_entries: 1,
             map_flags: 0, /* FIXME: set rodata readonly */
             ..Default::default()
@@ -607,6 +611,7 @@ mod tests {
             address: 0,
             name,
             data,
+            size: data.len() as u64,
             relocations: Vec::new(),
         }
     }


Test patch: