Browse Source

aya: btf: switch ComputedRelocationValue::value to u64

This is in preparation of adding Enum64 relocation support
Alessandro Decina 2 years ago
parent
commit
d6b976c
2 changed files with 26 additions and 33 deletions
  1. 17 17
      aya-obj/src/btf/relocation.rs
  2. 9 16
      test/integration-test/src/tests/relocations.rs

+ 17 - 17
aya-obj/src/btf/relocation.rs

@@ -786,7 +786,7 @@ struct ComputedRelocation {
 
 #[derive(Debug)]
 struct ComputedRelocationValue {
-    value: u32,
+    value: u64,
     size: u32,
     type_id: Option<u32>,
 }
@@ -854,7 +854,7 @@ impl ComputedRelocation {
                 ins.imm = target_value as i32;
             }
             BPF_LDX | BPF_ST | BPF_STX => {
-                if target_value > i16::MAX as u32 {
+                if target_value > i16::MAX as u64 {
                     return Err(RelocationError::InvalidInstruction {
                         relocation_number: rel.number,
                         index: ins_index,
@@ -914,7 +914,7 @@ impl ComputedRelocation {
                     },
                 )?;
 
-                next_ins.imm = 0;
+                next_ins.imm = (target_value >> 32) as i32;
             }
             class => {
                 return Err(RelocationError::InvalidInstruction {
@@ -934,11 +934,11 @@ impl ComputedRelocation {
     ) -> Result<ComputedRelocationValue, RelocationError> {
         use RelocationKind::*;
         let value = match (rel.kind, spec) {
-            (EnumVariantExists, spec) => spec.is_some() as u32,
+            (EnumVariantExists, spec) => spec.is_some() as u64,
             (EnumVariantValue, Some(spec)) => {
                 let accessor = &spec.accessors[0];
                 match spec.btf.type_by_id(accessor.type_id)? {
-                    BtfType::Enum(en) => en.variants[accessor.index].value as u32,
+                    BtfType::Enum(en) => en.variants[accessor.index].value as u64,
                     // candidate selection ensures that rel_kind == local_kind == target_kind
                     _ => unreachable!(),
                 }
@@ -969,7 +969,7 @@ impl ComputedRelocation {
             // this is the bpf_preserve_field_info(member_access, FIELD_EXISTENCE) case. If we
             // managed to build a spec, it means the field exists.
             return Ok(ComputedRelocationValue {
-                value: spec.is_some() as u32,
+                value: spec.is_some() as u64,
                 size: 0,
                 type_id: None,
             });
@@ -991,12 +991,12 @@ impl ComputedRelocation {
             // the last accessor is unnamed, meaning that this is an array access
             return match rel.kind {
                 FieldByteOffset => Ok(ComputedRelocationValue {
-                    value: (spec.bit_offset / 8) as u32,
+                    value: (spec.bit_offset / 8) as u64,
                     size: spec.btf.type_size(accessor.type_id)? as u32,
                     type_id: Some(accessor.type_id),
                 }),
                 FieldByteSize => Ok(ComputedRelocationValue {
-                    value: spec.btf.type_size(accessor.type_id)? as u32,
+                    value: spec.btf.type_size(accessor.type_id)? as u64,
                     size: 0,
                     type_id: Some(accessor.type_id),
                 }),
@@ -1061,30 +1061,30 @@ impl ComputedRelocation {
         #[allow(clippy::wildcard_in_or_patterns)]
         match rel.kind {
             FieldByteOffset => {
-                value.value = byte_off;
+                value.value = byte_off as u64;
                 if !is_bitfield {
                     value.size = byte_size;
                     value.type_id = Some(member_type_id);
                 }
             }
             FieldByteSize => {
-                value.value = byte_size;
+                value.value = byte_size as u64;
             }
             FieldSigned => match member_ty {
                 BtfType::Enum(_) => value.value = 1,
-                BtfType::Int(i) => value.value = i.encoding() as u32 & IntEncoding::Signed as u32,
+                BtfType::Int(i) => value.value = i.encoding() as u64 & IntEncoding::Signed as u64,
                 _ => (),
             },
             #[cfg(target_endian = "little")]
             FieldLShift64 => {
-                value.value = 64 - (bit_off + bit_size - byte_off * 8);
+                value.value = 64 - (bit_off + bit_size - byte_off * 8) as u64;
             }
             #[cfg(target_endian = "big")]
             FieldLShift64 => {
                 value.value = (8 - byte_size) * 8 + (bit_off - byte_off * 8);
             }
             FieldRShift64 => {
-                value.value = 64 - bit_size;
+                value.value = 64 - bit_size as u64;
             }
             FieldExists // this is handled at the start of the function
             | _ => panic!("bug! this should not be reached"),
@@ -1101,11 +1101,11 @@ impl ComputedRelocation {
         use RelocationKind::*;
 
         let value = match (rel.kind, target_spec) {
-            (TypeIdLocal, _) => local_spec.root_type_id,
-            (TypeIdTarget, Some(target_spec)) => target_spec.root_type_id,
-            (TypeExists, target_spec) => target_spec.is_some() as u32,
+            (TypeIdLocal, _) => local_spec.root_type_id as u64,
+            (TypeIdTarget, Some(target_spec)) => target_spec.root_type_id as u64,
+            (TypeExists, target_spec) => target_spec.is_some() as u64,
             (TypeSize, Some(target_spec)) => {
-                target_spec.btf.type_size(target_spec.root_type_id)? as u32
+                target_spec.btf.type_size(target_spec.root_type_id)? as u64
             }
             _ => {
                 return Err(RelocationError::MissingTargetDefinition {

+ 9 - 16
test/integration-test/src/tests/relocations.rs

@@ -28,9 +28,7 @@ fn relocate_field() {
         relocation_code: r#"
             __u8 memory[] = {1, 2, 3, 4};
             struct foo *ptr = (struct foo *) &memory;
-            bpf_probe_read_kernel(&value,
-                                  sizeof(__u8),
-                                  __builtin_preserve_access_index(&ptr->c));
+            value = __builtin_preserve_access_index(ptr->c);
         "#,
     }
     .build()
@@ -73,9 +71,7 @@ fn relocate_pointer() {
         relocation_code: r#"
             __u8 memory[] = {42, 0, 0, 0, 0, 0, 0, 0};
             struct bar* ptr = (struct bar *) &memory;
-            bpf_probe_read_kernel(&value,
-                                  sizeof(void *),
-                                  __builtin_preserve_access_index(&ptr->f));
+            value = (__u64) __builtin_preserve_access_index(ptr->f);
         "#,
     }
     .build()
@@ -121,14 +117,13 @@ impl RelocationTest {
                 #include <linux/bpf.h>
 
                 static long (*bpf_map_update_elem)(void *map, const void *key, const void *value, __u64 flags) = (void *) 2;
-                static long (*bpf_probe_read_kernel)(void *dst, __u32 size, const void *unsafe_ptr) = (void *) 113;
 
                 {local_definition}
 
                 struct {{
                   int (*type)[BPF_MAP_TYPE_ARRAY];
                   __u32 *key;
-                  __u32 *value;
+                  __u64 *value;
                   int (*max_entries)[1];
                 }} output_map
                 __attribute__((section(".maps"), used));
@@ -136,7 +131,7 @@ impl RelocationTest {
                 __attribute__((section("tracepoint/bpf_prog"), used))
                 int bpf_prog(void *ctx) {{
                   __u32 key = 0;
-                  __u32 value = 0;
+                  __u64 value = 0;
                   {relocation_code}
                   bpf_map_update_elem(&output_map, &key, &value, BPF_ANY);
                   return 0;
@@ -165,11 +160,9 @@ impl RelocationTest {
             r#"
                 #include <linux/bpf.h>
 
-                static long (*bpf_probe_read_kernel)(void *dst, __u32 size, const void *unsafe_ptr) = (void *) 113;
-
                 {target_btf}
                 int main() {{
-                    __u32 value = 0;
+                    __u64 value = 0;
                     // This is needed to make sure to emit BTF for the defined types,
                     // it could be dead code eliminated if we don't.
                     {relocation_code};
@@ -218,17 +211,17 @@ struct RelocationTestRunner {
 
 impl RelocationTestRunner {
     /// Run test and return the output value
-    fn run(&self) -> Result<u32> {
+    fn run(&self) -> Result<u64> {
         self.run_internal(true).context("Error running with BTF")
     }
 
     /// Run without loading btf
-    fn run_no_btf(&self) -> Result<u32> {
+    fn run_no_btf(&self) -> Result<u64> {
         self.run_internal(false)
             .context("Error running without BTF")
     }
 
-    fn run_internal(&self, with_relocations: bool) -> Result<u32> {
+    fn run_internal(&self, with_relocations: bool) -> Result<u64> {
         let mut loader = BpfLoader::new();
         if with_relocations {
             loader.btf(Some(&self.btf));
@@ -250,7 +243,7 @@ impl RelocationTestRunner {
         // To inspect the loaded eBPF bytecode, increse the timeout and run:
         // $ sudo bpftool prog dump xlated name bpf_prog
 
-        let output_map: Array<_, u32> = bpf.take_map("output_map").unwrap().try_into().unwrap();
+        let output_map: Array<_, u64> = bpf.take_map("output_map").unwrap().try_into().unwrap();
         let key = 0;
         output_map.get(&key, 0).context("Getting key 0 failed")
     }