Repository: cilium/ebpf
Pull request #1177 (2023-10-19 12:08:18)

btf: support both elf and raw BTF in loadKernelSpec
We use the cilium ebpf library in some old centos 4.18 kernel and the btf file generated by phaloe tools for CO-RE，the error occurs as like "apply CO-RE relocations: bad magic number '[159 235 1 0]' in record at byte 0x0", since the btf file we used is raw format when the cilium ebpf library only support parse elf format btf file。

Support both elf and raw BTF parse will make the cilium library be available in old centos 4.18 kernel(centos 8.0 or centos 8.1 kernel).

What's more, I see the libbpf added the same feature: https://github.com/libbpf/libbpf/commit/0420f75dbcf732e3230ae212970b33a80026e225

The similar commit in cilium library: https://github.com/cilium/ebpf/commit/48bf2ba10aee9422c9e7f43836afec0788052658

lmb: Hi, can you tell me why you need this?
wxx213: > Hi, can you tell me why you need this?

Okay, I added it in my first comment just now.
wxx213: > > Hi, can you tell me why you need this?
> 
> Okay, I added it in my first comment just now.

@lmb Hi, could you help to check this?
ti-mo: Makes sense to me. I was always under the impression the binaries in the search paths were raw BTF, but apparently not. @wxx213 Code doesn't compile, though. :slightly_smiling_face: 
wxx213: > Makes sense to me. I was always under the impression the binaries in the search paths were raw BTF, but apparently not. @wxx213 Code doesn't compile, though. 🙂

Sorry, I didn't notice the build issue, fix done.

Patch:
diff --git a/btf/btf.go b/btf/btf.go
index a2ee2d1..9291b8c 100644
--- a/btf/btf.go
+++ b/btf/btf.go
@@ -322,12 +322,12 @@ func loadKernelSpec() (_ *Spec, fallback bool, _ error) {
 	}
 	defer file.Close()
 
-	spec, err := loadSpecFromELF(file)
+	spec, err := LoadSpecFromReader(file)
 	return spec, true, err
 }
 
 // findVMLinux scans multiple well-known paths for vmlinux kernel images.
-func findVMLinux() (*internal.SafeELFFile, error) {
+func findVMLinux() (*os.File, error) {
 	release, err := internal.KernelRelease()
 	if err != nil {
 		return nil, err
@@ -346,7 +346,7 @@ func findVMLinux() (*internal.SafeELFFile, error) {
 	}
 
 	for _, loc := range locations {
-		file, err := internal.OpenSafeELFFile(fmt.Sprintf(loc, release))
+		file, err := os.Open(fmt.Sprintf(loc, release))
 		if errors.Is(err, os.ErrNotExist) {
 			continue
 		}


Test patch:
diff --git a/btf/btf_test.go b/btf/btf_test.go
index 4976fe4..843acad 100644
--- a/btf/btf_test.go
+++ b/btf/btf_test.go
@@ -251,7 +251,7 @@ func TestFindVMLinux(t *testing.T) {
 	}
 	defer file.Close()
 
-	spec, err := loadSpecFromELF(file)
+	spec, err := LoadSpecFromReader(file)
 	if err != nil {
 		t.Fatal("Can't load BTF:", err)
 	}
diff --git a/elf_reader_test.go b/elf_reader_test.go
index 6d13338..aff1316 100644
--- a/elf_reader_test.go
+++ b/elf_reader_test.go
@@ -1025,7 +1025,7 @@ func TestLibBPFCompat(t *testing.T) {
 			t.Skip("Skipping since weak relocations are not supported")
 		case "bloom_filter_map", "bloom_filter_bench":
 			t.Skip("Skipping due to missing MapExtra field in MapSpec")
-		case "netif_receive_skb":
+		case "netif_receive_skb", "local_kptr_stash":
 			t.Skip("Skipping due to possible bug in upstream CO-RE generation")
 		case "test_usdt", "test_urandom_usdt", "test_usdt_multispec":
 			t.Skip("Skipping due to missing support for usdt.bpf.h")