Skip to content

Commit 6021836

Browse files
committed
linker: resolve ksyms in one go
Calling kallsyms.Address is incredibly expensive because we need to scan all of /proc/kallsyms for a single address. Move to AssignAddresses instead and remove Address. Signed-off-by: Lorenz Bauer <[email protected]>
1 parent 0f68fc4 commit 6021836

File tree

2 files changed

+32
-38
lines changed

2 files changed

+32
-38
lines changed

internal/kallsyms/kallsyms.go

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,6 @@ var errAmbiguousKsym = errors.New("multiple kernel symbols with the same name")
1717

1818
var symAddrs cache[string, uint64]
1919

20-
// Address returns the address of the given symbol in the kernel. Returns 0 and
21-
// no error if the symbol is not present. Returns an error if multiple addresses
22-
// were found for a symbol.
23-
//
24-
// Consider [AssignAddresses] if you need to resolve multiple symbols, as it
25-
// will only perform one iteration over /proc/kallsyms.
26-
func Address(symbol string) (uint64, error) {
27-
if symbol == "" {
28-
return 0, nil
29-
}
30-
31-
if addr, ok := symAddrs.Load(symbol); ok {
32-
return addr, nil
33-
}
34-
35-
request := map[string]uint64{symbol: 0}
36-
if err := AssignAddresses(request); err != nil {
37-
return 0, err
38-
}
39-
40-
return request[symbol], nil
41-
}
42-
4320
// AssignAddresses looks up the addresses of the requested symbols in the kernel
4421
// and assigns them to their corresponding values in the symbols map. Results
4522
// of all lookups are cached, successful or otherwise.

linker.go

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,13 @@ func resolveKconfigReferences(insns asm.Instructions) (_ *Map, err error) {
485485
}
486486

487487
func resolveKsymReferences(insns asm.Instructions) error {
488-
var missing []string
488+
type fixup struct {
489+
*asm.Instruction
490+
*ksymMeta
491+
}
492+
493+
var symbols map[string]uint64
494+
var fixups []fixup
489495

490496
iter := insns.Iterate()
491497
for iter.Next() {
@@ -495,25 +501,36 @@ func resolveKsymReferences(insns asm.Instructions) error {
495501
continue
496502
}
497503

498-
addr, err := kallsyms.Address(meta.Name)
499-
if err != nil {
500-
return fmt.Errorf("resolve ksym %s: %w", meta.Name, err)
501-
}
502-
if addr != 0 {
503-
ins.Constant = int64(addr)
504-
continue
504+
if symbols == nil {
505+
symbols = make(map[string]uint64)
505506
}
506507

507-
if meta.Binding == elf.STB_WEAK {
508-
// A weak ksym variable in eBPF C means its resolution is optional.
509-
// Set a zero constant explicitly for clarity.
510-
ins.Constant = 0
508+
symbols[meta.Name] = 0
509+
fixups = append(fixups, fixup{
510+
iter.Ins, meta,
511+
})
512+
}
513+
514+
if len(symbols) == 0 {
515+
return nil
516+
}
517+
518+
if err := kallsyms.AssignAddresses(symbols); err != nil {
519+
return fmt.Errorf("resolve ksym addresses: %w", err)
520+
}
521+
522+
var missing []string
523+
for _, fixup := range fixups {
524+
addr := symbols[fixup.Name]
525+
// A weak ksym variable in eBPF C means its resolution is optional.
526+
if addr == 0 && fixup.Binding != elf.STB_WEAK {
527+
if !slices.Contains(missing, fixup.Name) {
528+
missing = append(missing, fixup.Name)
529+
}
511530
continue
512531
}
513532

514-
if !slices.Contains(missing, meta.Name) {
515-
missing = append(missing, meta.Name)
516-
}
533+
fixup.Constant = int64(addr)
517534
}
518535

519536
if len(missing) > 0 {

0 commit comments

Comments
 (0)