linker.go 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. package ebpf
  2. import (
  3. "github.com/cilium/ebpf/asm"
  4. )
  5. // link resolves bpf-to-bpf calls.
  6. //
  7. // Each section may contain multiple functions / labels, and is only linked
  8. // if the program being edited references one of these functions.
  9. //
  10. // Sections must not require linking themselves.
  11. func link(insns asm.Instructions, sections ...asm.Instructions) (asm.Instructions, error) {
  12. for _, section := range sections {
  13. var err error
  14. insns, err = linkSection(insns, section)
  15. if err != nil {
  16. return nil, err
  17. }
  18. }
  19. return insns, nil
  20. }
  21. func linkSection(insns, section asm.Instructions) (asm.Instructions, error) {
  22. // A map of symbols to the libraries which contain them.
  23. symbols, err := section.SymbolOffsets()
  24. if err != nil {
  25. return nil, err
  26. }
  27. for _, ins := range insns {
  28. if ins.Reference == "" {
  29. continue
  30. }
  31. if ins.OpCode.JumpOp() != asm.Call || ins.Src != asm.R1 {
  32. continue
  33. }
  34. if ins.Constant != -1 {
  35. // This is already a valid call, no need to link again.
  36. continue
  37. }
  38. if _, ok := symbols[ins.Reference]; !ok {
  39. // Symbol isn't available in this section
  40. continue
  41. }
  42. // At this point we know that at least one function in the
  43. // library is called from insns. Merge the two sections.
  44. // The rewrite of ins.Constant happens in asm.Instruction.Marshal.
  45. return append(insns, section...), nil
  46. }
  47. // None of the functions in the section are called. Do nothing.
  48. return insns, nil
  49. }