diff --git a/internal/btf/btf.go b/internal/btf/btf.go index 2eef4093d..86eec0a24 100644 --- a/internal/btf/btf.go +++ b/internal/btf/btf.go @@ -843,11 +843,11 @@ func (p *Program) Spec() *Spec { return p.spec } -// Fixups returns the changes required to adjust the program to the target. +// CORERelocate returns the changes required to adjust the program to the target. // // Passing a nil target will relocate against the running kernel. -func (p *Program) Fixups(target *Spec) (COREFixups, error) { - if len(p.CoreRelos) == 0 { +func CORERelocate(local, target *Spec, relos CoreRelos) (COREFixups, error) { + if len(relos) == 0 { return nil, nil } @@ -859,7 +859,7 @@ func (p *Program) Fixups(target *Spec) (COREFixups, error) { } } - return coreRelocate(p.spec, target, p.CoreRelos) + return coreRelocate(local, target, relos) } func marshalBTF(types interface{}, strings []byte, bo binary.ByteOrder) []byte { diff --git a/internal/btf/core_test.go b/internal/btf/core_test.go index 7c5755fd5..e9a358bdf 100644 --- a/internal/btf/core_test.go +++ b/internal/btf/core_test.go @@ -509,7 +509,7 @@ func TestCoreRelocation(t *testing.T) { t.Fatal("Retrieve program:", err) } - relos, err := prog.Fixups(spec) + relos, err := CORERelocate(prog.Spec(), spec, prog.CoreRelos) if want := errs[name]; want != nil { if !errors.Is(err, want) { t.Fatal("Expected", want, "got", err) diff --git a/internal/btf/ext_info.go b/internal/btf/ext_info.go index 2be0622c8..6342d197c 100644 --- a/internal/btf/ext_info.go +++ b/internal/btf/ext_info.go @@ -447,6 +447,17 @@ type CoreRelo struct { type CoreRelos []CoreRelo +// Offset adds offset to the instruction offset of all CoreRelos +// and returns the result. +func (cr CoreRelos) Offset(offset uint32) CoreRelos { + var relos CoreRelos + for _, relo := range cr { + relo.insnOff += offset + relos = append(relos, relo) + } + return relos +} + var extInfoReloSize = binary.Size(bpfCoreRelo{}) // parseCoreRelos parses a core_relos sub-section within .BTF.ext ito a map of diff --git a/linker.go b/linker.go index d45c00148..9cf4c63a6 100644 --- a/linker.go +++ b/linker.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/cilium/ebpf/asm" + "github.com/cilium/ebpf/internal/btf" ) // The linker is responsible for resolving bpf-to-bpf calls between programs @@ -80,6 +81,21 @@ func findReferences(progs map[string]*ProgramSpec) error { return nil } +// collectCoreRelos returns a list of CO-RE relocations of the layout's progs +// in order. +func collectCoreRelos(layout []reference) btf.CoreRelos { + if len(layout) == 0 { + return nil + } + + var relos btf.CoreRelos + for _, sym := range layout { + relos = append(relos, sym.spec.BTF.CoreRelos.Offset(uint32(sym.offset))...) + } + + return relos +} + // marshalFuncInfos returns the BTF func infos of all progs in order. func marshalFuncInfos(layout []reference) ([]byte, error) { if len(layout) == 0 { diff --git a/prog.go b/prog.go index 61714d405..47ca18eb4 100644 --- a/prog.go +++ b/prog.go @@ -293,7 +293,8 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand var btfDisabled bool var core btf.COREFixups if spec.BTF != nil { - core, err = spec.BTF.Fixups(targetBTF) + relos := collectCoreRelos(layout) + core, err = btf.CORERelocate(spec.BTF.Spec(), targetBTF, relos) if err != nil { return nil, fmt.Errorf("CO-RE relocations: %w", err) }