Skip to content

Commit 333ac10

Browse files
florianlgnurizen
authored andcommitted
interpreter/golables: use .gopclntab for symbol lookup (open-telemetry#728)
Signed-off-by: Florian Lehner <florian.lehner@elastic.co>
1 parent e2ace32 commit 333ac10

5 files changed

Lines changed: 43 additions & 14 deletions

File tree

interpreter/apmint/apmint.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"go.opentelemetry.io/ebpf-profiler/host"
2020
"go.opentelemetry.io/ebpf-profiler/interpreter"
2121
"go.opentelemetry.io/ebpf-profiler/libpf"
22-
"go.opentelemetry.io/ebpf-profiler/libpf/pfelf"
2322
"go.opentelemetry.io/ebpf-profiler/remotememory"
2423
"go.opentelemetry.io/ebpf-profiler/support"
2524
)
@@ -65,7 +64,7 @@ func Loader(_ interpreter.EbpfHandler, info *interpreter.LoaderInfo) (interprete
6564
// Resolve process storage symbol.
6665
procStorageSym, err := ef.LookupSymbol(procStorageExport)
6766
if err != nil {
68-
if errors.Is(err, pfelf.ErrSymbolNotFound) {
67+
if errors.Is(err, libpf.ErrSymbolNotFound) {
6968
// APM<->profiling integration not supported by agent.
7069
return nil, nil
7170
}

interpreter/golabels/tls_amd64.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,27 @@ package golabels // import "go.opentelemetry.io/ebpf-profiler/interpreter/golabe
88
import (
99
log "github.com/sirupsen/logrus"
1010
"go.opentelemetry.io/ebpf-profiler/libpf/pfelf"
11+
"go.opentelemetry.io/ebpf-profiler/nativeunwind/elfunwindinfo"
1112
"golang.org/x/arch/x86/x86asm"
1213
)
1314

1415
// Most normal amd64 Go binaries use -8 as offset into TLS space for
1516
// storing the current g but "static" binaries it ends up as -80. There
1617
// may be dynamic relocating going on so just read it from a known
1718
// symbol if possible.
18-
func extractTLSGOffset(f *pfelf.File, path string) (int32, error) {
19-
syms, err := f.ReadSymbols()
19+
func extractTLSGOffset(f *pfelf.File) (int32, error) {
20+
pclntab, err := elfunwindinfo.NewGopclntab(f)
2021
if err != nil {
2122
log.Debugf("Failed to find symbols (%v) using default TLSG offset", err)
2223
return -8, nil
2324
}
25+
defer pclntab.Close()
26+
2427
// Dump of assembler code for function runtime.stackcheck:
2528
// 0x0000000000470080 <+0>: mov %fs:0xfffffffffffffff8,%rax
26-
sym, err := syms.LookupSymbol("runtime.stackcheck.abi0")
29+
sym, err := pclntab.LookupSymbol("runtime.stackcheck")
2730
if err != nil {
28-
// Binary must be stripped, hope default is correct and warn.
29-
log.Warnf("Failed to find stackcheck symbol, Go labels might not work: %v (%s)", err, path)
30-
return -8, nil
31+
return 0, err
3132
}
3233
b, err := f.VirtualMemory(int64(sym.Address), 16, 16)
3334
if err != nil {

libpf/pfelf/file.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@ const (
5151

5252
// List of public errors.
5353
var (
54-
// ErrSymbolNotFound is returned when the requested symbol was not found.
55-
ErrSymbolNotFound = errors.New("symbol not found")
56-
5754
// ErrNotELF is returned when the file is not an ELF file.
5855
ErrNotELF = errors.New("not an ELF file")
5956
)
@@ -1050,7 +1047,7 @@ func (f *File) LookupSymbol(symbol libpf.SymbolName) (*libpf.Symbol, error) {
10501047
mask := uint(1)<<(h%ptrSizeBits) |
10511048
uint(1)<<((h>>hdr.bloomShift)%ptrSizeBits)
10521049
if bloom&mask != mask {
1053-
return nil, ErrSymbolNotFound
1050+
return nil, libpf.ErrSymbolNotFound
10541051
}
10551052

10561053
// Read the initial symbol index to start looking from
@@ -1061,7 +1058,7 @@ func (f *File) LookupSymbol(symbol libpf.SymbolName) (*libpf.Symbol, error) {
10611058
return nil, err
10621059
}
10631060
if i == 0 {
1064-
return nil, ErrSymbolNotFound
1061+
return nil, libpf.ErrSymbolNotFound
10651062
}
10661063

10671064
// Search the hash bucket
@@ -1116,7 +1113,7 @@ func (f *File) LookupSymbol(symbol libpf.SymbolName) (*libpf.Symbol, error) {
11161113
return nil, errors.New("symbol hash not present")
11171114
}
11181115

1119-
return nil, ErrSymbolNotFound
1116+
return nil, libpf.ErrSymbolNotFound
11201117
}
11211118

11221119
// LookupSymbol searches for a given symbol in the ELF

libpf/symbol.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,18 @@
44
package libpf // import "go.opentelemetry.io/ebpf-profiler/libpf"
55

66
import (
7+
"errors"
78
"fmt"
89
"sort"
910
"strings"
1011
)
1112

13+
// List of public errors.
14+
var (
15+
// ErrSymbolNotFound is returned when the requested symbol was not found.
16+
ErrSymbolNotFound = errors.New("symbol not found")
17+
)
18+
1219
// SymbolValue represents the value associated with a symbol, e.g. either an
1320
// offset or an absolute address
1421
type SymbolValue uint64

nativeunwind/elfunwindinfo/elfgopclntab.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"strings"
1818
"unsafe"
1919

20+
"go.opentelemetry.io/ebpf-profiler/libpf"
2021
"go.opentelemetry.io/ebpf-profiler/libpf/pfelf"
2122
sdtypes "go.opentelemetry.io/ebpf-profiler/nativeunwind/stackdeltatypes"
2223
"go.opentelemetry.io/ebpf-profiler/support"
@@ -351,6 +352,30 @@ type Gopclntab struct {
351352
functab, funcdata, funcnametab, filetab, pctab, cutab []byte
352353
}
353354

355+
// LookupSymbol searches for a given symbol in .gopclntab.
356+
func (g *Gopclntab) LookupSymbol(symbol libpf.SymbolName) (*libpf.Symbol, error) {
357+
symString := string(symbol)
358+
for i := 0; i < g.numFuncs; i++ {
359+
_, funcOff := g.getFuncMapEntry(i)
360+
pc, fun := g.getFunc(funcOff)
361+
if fun == nil {
362+
continue
363+
}
364+
name := getString(g.funcnametab, int(fun.nameOff))
365+
if name == symString {
366+
nextPc, _ := g.getFuncMapEntry(i + 1)
367+
size := uint64(nextPc - pc)
368+
369+
return &libpf.Symbol{
370+
Name: symbol,
371+
Address: libpf.SymbolValue(pc),
372+
Size: size,
373+
}, nil
374+
}
375+
}
376+
return nil, libpf.ErrSymbolNotFound
377+
}
378+
354379
// NewGopclntab parses and returns the parsed data for further operations.
355380
func NewGopclntab(ef *pfelf.File) (*Gopclntab, error) {
356381
data, err := extractGoPclntab(ef)

0 commit comments

Comments
 (0)