Skip to content

Commit

Permalink
btf: include CO-RE relocations of bpf2bpf subprograms
Browse files Browse the repository at this point in the history
ProgramSpecs read from an ELF contain the full instruction streams from the
bpf2bpf subprograms they call. When marshaling a program to be inserted into
the kernel, FuncInfos and LineInfos are collected from all called subprogs,
but CO-RE relocations were notably skipped after the linker rework in 9d739bd.

This commit gathers CO-RE relos for all subprogs included in the final
instruction stream and modifies their offsets to point to their new locations.

Signed-off-by: Timo Beckers <timo@isovalent.com>
  • Loading branch information
ti-mo committed Mar 7, 2022
1 parent c14704a commit 8449fa7
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 6 deletions.
8 changes: 4 additions & 4 deletions internal/btf/btf.go
Expand Up @@ -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
}

Expand All @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion internal/btf/core_test.go
Expand Up @@ -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)
Expand Down
11 changes: 11 additions & 0 deletions internal/btf/ext_info.go
Expand Up @@ -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
Expand Down
19 changes: 19 additions & 0 deletions linker.go
Expand Up @@ -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
Expand Down Expand Up @@ -80,6 +81,24 @@ 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 {
if sym.spec.BTF == nil {
continue
}
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 {
Expand Down
3 changes: 2 additions & 1 deletion prog.go
Expand Up @@ -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)
}
Expand Down

0 comments on commit 8449fa7

Please sign in to comment.