MCPcopy Index your code
hub / github.com/cilium/ebpf / loadFunctions

Method loadFunctions

elf_reader.go:441–507  ·  view source on GitHub ↗

loadFunctions extracts instruction streams from the given program section starting at each symbol in the section. The section's symbols must already be narrowed down to STT_NOTYPE (emitted by clang <8) or STT_FUNC. The resulting map is indexed by function name.

(sec *elfSection)

Source from the content-addressed store, hash-verified

439//
440// The resulting map is indexed by function name.
441func (ec *elfCode) loadFunctions(sec *elfSection) (map[string]asm.Instructions, error) {
442 progs := make(map[string]asm.Instructions)
443
444 // Pull out ExtInfos once per section to avoid map lookups on every
445 // instruction.
446 fo, lo, ro := ec.extInfo.Section(sec.Name)
447
448 // Raw instruction count since start of the section. ExtInfos point at raw
449 // insn offsets and ignore the gaps between symbols in case of linked objects.
450 // We need to count them, we can't obtain this info by any other means.
451 var raw asm.RawInstructionOffset
452
453 // Sort symbols by offset so we can track instructions by their raw offsets.
454 for _, sym := range sec.symbolsSorted() {
455 if progs[sym.Name] != nil {
456 return nil, fmt.Errorf("duplicate symbol %s in section %s", sym.Name, sec.Name)
457 }
458
459 if sym.Value > math.MaxUint32 || sym.Size > math.MaxUint32 {
460 return nil, fmt.Errorf("symbol %s: offset or size exceeds 32 bits in section %s", sym.Name, sec.Name)
461 }
462 if sym.Value+sym.Size > sec.Size {
463 return nil, fmt.Errorf("symbol %s: size goes out of bounds of section %s", sym.Name, sec.Name)
464 }
465
466 // Decode the symbol's instruction stream, limited to its size.
467 sr := internal.NewBufferedSectionReader(sec, int64(sym.Value), int64(sym.Size))
468 insns := make(asm.Instructions, 0, sym.Size/asm.InstructionSize)
469 insns, err := asm.AppendInstructions(insns, sr, ec.ByteOrder, platform.Linux)
470 if err != nil {
471 return nil, fmt.Errorf("decoding instructions for symbol %s in section %s: %w", sym.Name, sec.Name, err)
472 }
473 if len(insns) == 0 {
474 return nil, fmt.Errorf("no instructions found for symbol %s in section %s", sym.Name, sec.Name)
475 }
476
477 // Mark the first instruction as the start of a function.
478 insns[0] = insns[0].WithSymbol(sym.Name)
479
480 iter := insns.Iterate()
481 for iter.Next() {
482 // Global byte offset of the instruction within the ELF section.
483 offset := sym.Value + iter.Offset.Bytes()
484
485 // Apply any relocations for the current instruction. If no relocation is
486 // present, resolve any section-relative function calls.
487 if rel, ok := sec.relocations[offset]; ok {
488 if err := ec.relocateInstruction(iter.Ins, rel); err != nil {
489 return nil, fmt.Errorf("offset %d in section %s: relocating instruction: %w", offset, sec.Name, err)
490 }
491 } else {
492 if err := referenceRelativeJump(iter.Ins, offset, sec.symbols); err != nil {
493 return nil, fmt.Errorf("offset %d in section %s: resolving relative jump: %w", offset, sec.Name, err)
494 }
495 }
496
497 assignMetadata(iter.Ins, raw, &fo, &lo, &ro)
498

Callers 1

loadProgramSectionsMethod · 0.95

Calls 12

relocateInstructionMethod · 0.95
NewBufferedSectionReaderFunction · 0.92
AppendInstructionsFunction · 0.92
referenceRelativeJumpFunction · 0.85
assignMetadataFunction · 0.85
SectionMethod · 0.80
symbolsSortedMethod · 0.80
WithSymbolMethod · 0.80
WidthMethod · 0.80
IterateMethod · 0.45
NextMethod · 0.45
BytesMethod · 0.45

Tested by

no test coverage detected