MCPcopy
hub / github.com/cilium/ebpf / LoadCollectionSpecFromReader

Function LoadCollectionSpecFromReader

elf_reader.go:78–212  ·  view source on GitHub ↗

LoadCollectionSpecFromReader parses an ELF file into a CollectionSpec.

(rd io.ReaderAt)

Source from the content-addressed store, hash-verified

76
77// LoadCollectionSpecFromReader parses an ELF file into a CollectionSpec.
78func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
79 f, err := internal.NewSafeELFFile(rd)
80 if err != nil {
81 return nil, err
82 }
83
84 // Checks if the ELF file is for BPF data.
85 // Old LLVM versions set e_machine to EM_NONE.
86 if f.Machine != elf.EM_NONE && f.Machine != elf.EM_BPF {
87 return nil, fmt.Errorf("unexpected machine type for BPF ELF: %s", f.Machine)
88 }
89
90 var (
91 licenseSection *elf.Section
92 versionSection *elf.Section
93 sections = make(map[elf.SectionIndex]*elfSection)
94 relSections = make(map[elf.SectionIndex]*elf.Section)
95 )
96
97 // This is the target of relocations generated by inline assembly.
98 sections[elf.SHN_UNDEF] = newElfSection(new(elf.Section), undefSection)
99
100 // Collect all the sections we're interested in. This includes relocations
101 // which we parse later.
102 //
103 // Keep the documentation at docs/ebpf/loading/elf-sections.md up-to-date.
104 for i, sec := range f.Sections {
105 idx := elf.SectionIndex(i)
106
107 switch {
108 case strings.HasPrefix(sec.Name, "license"):
109 licenseSection = sec
110 case strings.HasPrefix(sec.Name, "version"):
111 versionSection = sec
112 case strings.HasPrefix(sec.Name, "maps"):
113 sections[idx] = newElfSection(sec, mapSection)
114 case sec.Name == ".maps":
115 sections[idx] = newElfSection(sec, btfMapSection)
116 case isDataSection(sec.Name):
117 sections[idx] = newElfSection(sec, dataSection)
118 case sec.Type == elf.SHT_REL:
119 // Store relocations under the section index of the target
120 relSections[elf.SectionIndex(sec.Info)] = sec
121 case sec.Type == elf.SHT_PROGBITS && sec.Size > 0:
122 if (sec.Flags&elf.SHF_EXECINSTR) != 0 && sec.Size > 0 {
123 sections[idx] = newElfSection(sec, programSection)
124 } else if sec.Name == structOpsLinkSec {
125 // classification based on sec names so that struct_ops-specific
126 // sections (.struct_ops.link) is correctly recognized
127 // as non-executable PROGBITS, allowing value placement and link metadata to be loaded.
128 sections[idx] = newElfSection(sec, structOpsSection)
129 } else if sec.Name == structOpsSec {
130 return nil, fmt.Errorf("section %q: got '.struct_ops' section: %w", sec.Name, ErrNotSupported)
131 }
132 }
133 }
134
135 license, err := loadLicense(licenseSection)

Callers 15

Example_socketELFFunction · 0.92
TestCORERelocationLoadFunction · 0.92
TestLD64IMMRelocFunction · 0.92
loadTestFunction · 0.92
loadTestFunction · 0.92
loadVariablesFunction · 0.92
loadVariablesFunction · 0.92
loadCounterFunction · 0.92
loadCounterFunction · 0.92
loadBpfFunction · 0.92
loadBpfFunction · 0.92
loadBpfFunction · 0.92

Calls 15

SymbolsMethod · 0.95
assignSymbolsMethod · 0.95
loadRelocationsMethod · 0.95
loadMapsMethod · 0.95
loadBTFMapsMethod · 0.95
loadDataSectionsMethod · 0.95
loadKconfigSectionMethod · 0.95
loadKsymsSectionMethod · 0.95
loadProgramSectionsMethod · 0.95
NewSafeELFFileFunction · 0.92

Tested by 5

Example_socketELFFunction · 0.74
TestCORERelocationLoadFunction · 0.74
TestLD64IMMRelocFunction · 0.74
FuzzLoadCollectionSpecFunction · 0.68

Used in the wild real call sites across dependent graphs

searching dependent graphs…