collection.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. package ebpf
  2. import (
  3. "github.com/cilium/ebpf/asm"
  4. "github.com/pkg/errors"
  5. )
  6. // CollectionOptions control loading a collection into the kernel.
  7. type CollectionOptions struct {
  8. Programs ProgramOptions
  9. }
  10. // CollectionSpec describes a collection.
  11. type CollectionSpec struct {
  12. Maps map[string]*MapSpec
  13. Programs map[string]*ProgramSpec
  14. }
  15. // Copy returns a recursive copy of the spec.
  16. func (cs *CollectionSpec) Copy() *CollectionSpec {
  17. if cs == nil {
  18. return nil
  19. }
  20. cpy := CollectionSpec{
  21. Maps: make(map[string]*MapSpec, len(cs.Maps)),
  22. Programs: make(map[string]*ProgramSpec, len(cs.Programs)),
  23. }
  24. for name, spec := range cs.Maps {
  25. cpy.Maps[name] = spec.Copy()
  26. }
  27. for name, spec := range cs.Programs {
  28. cpy.Programs[name] = spec.Copy()
  29. }
  30. return &cpy
  31. }
  32. // Collection is a collection of Programs and Maps associated
  33. // with their symbols
  34. type Collection struct {
  35. Programs map[string]*Program
  36. Maps map[string]*Map
  37. }
  38. // NewCollection creates a Collection from a specification.
  39. //
  40. // Only maps referenced by at least one of the programs are initialized.
  41. func NewCollection(spec *CollectionSpec) (*Collection, error) {
  42. return NewCollectionWithOptions(spec, CollectionOptions{})
  43. }
  44. // NewCollectionWithOptions creates a Collection from a specification.
  45. //
  46. // Only maps referenced by at least one of the programs are initialized.
  47. func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Collection, error) {
  48. maps := make(map[string]*Map)
  49. for mapName, mapSpec := range spec.Maps {
  50. m, err := NewMap(mapSpec)
  51. if err != nil {
  52. return nil, errors.Wrapf(err, "map %s", mapName)
  53. }
  54. maps[mapName] = m
  55. }
  56. progs := make(map[string]*Program)
  57. for progName, origProgSpec := range spec.Programs {
  58. progSpec := origProgSpec.Copy()
  59. // Rewrite any reference to a valid map.
  60. for i := range progSpec.Instructions {
  61. var (
  62. ins = &progSpec.Instructions[i]
  63. m = maps[ins.Reference]
  64. )
  65. if ins.Reference == "" || m == nil {
  66. continue
  67. }
  68. if ins.Src == asm.R1 {
  69. // Don't overwrite maps already rewritten, users can
  70. // rewrite programs in the spec themselves
  71. continue
  72. }
  73. if err := ins.RewriteMapPtr(m.FD()); err != nil {
  74. return nil, errors.Wrapf(err, "progam %s: map %s", progName, ins.Reference)
  75. }
  76. }
  77. prog, err := NewProgramWithOptions(progSpec, opts.Programs)
  78. if err != nil {
  79. return nil, errors.Wrapf(err, "program %s", progName)
  80. }
  81. progs[progName] = prog
  82. }
  83. return &Collection{
  84. progs,
  85. maps,
  86. }, nil
  87. }
  88. // LoadCollection parses an object file and converts it to a collection.
  89. func LoadCollection(file string) (*Collection, error) {
  90. spec, err := LoadCollectionSpec(file)
  91. if err != nil {
  92. return nil, err
  93. }
  94. return NewCollection(spec)
  95. }
  96. // Close frees all maps and programs associated with the collection.
  97. //
  98. // The collection mustn't be used afterwards.
  99. func (coll *Collection) Close() {
  100. for _, prog := range coll.Programs {
  101. prog.Close()
  102. }
  103. for _, m := range coll.Maps {
  104. m.Close()
  105. }
  106. }
  107. // DetachMap removes the named map from the Collection.
  108. //
  109. // This means that a later call to Close() will not affect this map.
  110. //
  111. // Returns nil if no map of that name exists.
  112. func (coll *Collection) DetachMap(name string) *Map {
  113. m := coll.Maps[name]
  114. delete(coll.Maps, name)
  115. return m
  116. }
  117. // DetachProgram removes the named program from the Collection.
  118. //
  119. // This means that a later call to Close() will not affect this program.
  120. //
  121. // Returns nil if no program of that name exists.
  122. func (coll *Collection) DetachProgram(name string) *Program {
  123. p := coll.Programs[name]
  124. delete(coll.Programs, name)
  125. return p
  126. }