Skip to content

Commit

Permalink
Add load /proc/kallsyms function
Browse files Browse the repository at this point in the history
Signed-off-by: Viet Anh Duong <[email protected]>
  • Loading branch information
vietanhduong committed Nov 15, 2023
1 parent 968878d commit 4ee3795
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 4 deletions.
33 changes: 29 additions & 4 deletions bcc/symbol.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,23 @@ func (s *Symbolizer) SymbolOrAddrIfUnknown(pid int, addr uintptr) string {
}

if module := C.GoString(symbol.module); module != "" {
return s.formatModuleName(C.GoString(symbol.module), uintptr(symbol.offset))
return formatModuleName(C.GoString(symbol.module), uintptr(symbol.offset))
}
return s.formatAddress(addr)
return formatAddress(addr)
}

func (s *Symbolizer) ResolveName(pid int, module, name string) (uintptr, error) {
cmodule := C.CString(module)
defer C.free(unsafe.Pointer(cmodule))
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))

var addr C.ulong
ret := C.bcc_symcache_resolve_name(s.getBCCSymbolCache(pid), cmodule, cname, &addr)
if ret < 0 {
return 0, fmt.Errorf("unable to resolve symbol name %q", name)
}
return uintptr(addr), nil
}

func (s *Symbolizer) ReleasePidSymCache(pid int) {
Expand All @@ -86,11 +100,11 @@ func (s *Symbolizer) getBCCSymbolCache(pid int) unsafe.Pointer {
return cache
}

func (s *Symbolizer) formatAddress(addr uintptr) string {
func formatAddress(addr uintptr) string {
return fmt.Sprintf("0x%016x", addr)
}

func (s *Symbolizer) formatModuleName(module string, offset uintptr) string {
func formatModuleName(module string, offset uintptr) string {
return fmt.Sprintf("[m] %s + 0x%08x", module, offset)
}

Expand Down Expand Up @@ -124,6 +138,17 @@ type bccSymbolOption struct {
useSymbolType uint32
}

// Ksymname Translate a kernel name into an address. This is the reverse of
// ksym. Returns -1 when the function name is unknown.
// TODO(vietanhduong): Implement symnol cache
func Ksymname(name string) (uint64, error) {
addr, err := bccResolveName("", name, -1)
if err != nil {
return 0, err
}
return addr, nil
}

// resolveSymbolPath returns the file and offset to locate symname in module
func resolveSymbolPath(module string, symname string, addr uint64, pid int) (string, uint64, error) {
if pid == -1 {
Expand Down
71 changes: 71 additions & 0 deletions bcc/symbol_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package bcc

import (
"bufio"
"fmt"
"math"
"os"
"strconv"
"strings"
)

const KernelAddressSpace = 0x00ffffffffffffff

type Symbol struct {
Name string
Module string
Address uint64
}

func (k *Symbol) String() string {
if k == nil {
return ""
}
return fmt.Sprintf("module=%s symbol=%s address=0x%016x", k.Module, k.Name, k.Address)
}

func LoadProcKallsym() ([]*Symbol, error) {
var ret []*Symbol
LoadProcKallsymWithCallback(func(sym *Symbol) { ret = append(ret, sym) })
return ret, nil
}

func LoadProcKallsymWithCallback(callback func(sym *Symbol)) error {
f, err := os.Open("/proc/kallsyms")
if err != nil {
return fmt.Errorf("open /proc/kallsyms: %w", err)
}
defer f.Close()

scanner := bufio.NewScanner(f)
for scanner.Scan() {
parts := strings.Fields(scanner.Text())
if len(parts) < 3 { // This should never happen
continue
}
sym := &Symbol{Name: parts[2], Module: "kernel"}

if parts[1][0] == 'b' || parts[1][0] == 'B' ||
parts[1][0] == 'd' || parts[1][0] == 'D' ||
parts[1][0] == 'r' || parts[1][0] == 'R' {
continue
}

sym.Address, _ = strconv.ParseUint(parts[0], 16, 0)
if sym.Address == 0 || sym.Address == math.MaxUint64 || sym.Address < KernelAddressSpace {
continue
}

parts = append(parts, "")
if len(parts[3]) > 0 && parts[3][0] == '[' && parts[3][len(parts[3])-1] == ']' {
sym.Module = parts[3][1 : len(parts[3])-1]
}

callback(sym)
}

if err = scanner.Err(); err != nil {
return fmt.Errorf("scanner error: %w", err)
}
return nil
}
19 changes: 19 additions & 0 deletions examples/bcc/ksymbol/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package main

import (
"log"
"os"

"github.com/vietanhduong/go-bpf/bcc"
)

func main() {
ksyms, err := bcc.LoadProcKallsym()
if err != nil {
log.Printf("Failed to load Kallsyms: %v", err)
os.Exit(1)
}
for _, sym := range ksyms {
log.Println(sym.String())
}
}

0 comments on commit 4ee3795

Please sign in to comment.