1
+ // This product includes software developed at Datadog (https://www.datadoghq.com/).
2
+ // Copyright 2024 Datadog, Inc.
3
+
1
4
package reporter
2
5
3
6
import (
4
7
"bytes"
5
8
"debug/elf"
6
9
"encoding/binary"
10
+ "errors"
7
11
"fmt"
8
12
"unsafe"
9
13
10
14
"go.opentelemetry.io/ebpf-profiler/libpf"
11
15
"go.opentelemetry.io/ebpf-profiler/libpf/pfelf"
12
16
)
13
17
14
- type version int
18
+ type headerVersion int
15
19
16
20
const (
17
- verUnknown version = iota
21
+ verUnknown headerVersion = iota
18
22
ver12
19
23
ver116
20
24
ver118
@@ -30,9 +34,9 @@ const (
30
34
)
31
35
32
36
type GoPCLnTabInfo struct {
33
- Address uint64 // goPCLnTab address
34
- Data []byte // goPCLnTab data
35
- Version version // gopclntab header version
37
+ Address uint64 // goPCLnTab address
38
+ Data []byte // goPCLnTab data
39
+ Version headerVersion // gopclntab header version
36
40
Offsets TableOffsets
37
41
GoFuncAddr uint64 // goFunc address
38
42
GoFuncData []byte // goFunc data
@@ -84,11 +88,13 @@ type pclntabHeader118 struct {
84
88
85
89
// pclntabFuncMap is the Golang function symbol table map entry
86
90
type pclntabFuncMap struct {
87
- pc uint64
88
- funcOff uint64
91
+ pc uint64 //nolint:unused
92
+ funcOff uint64 //nolint:unused
89
93
}
90
94
91
95
// pclntabFunc is the Golang function definition (struct _func in the spec) as before Go 1.18.
96
+ //
97
+ //nolint:unused
92
98
type pclntabFunc struct {
93
99
startPc uint64
94
100
nameOff , argsSize , frameSize int32
@@ -99,6 +105,8 @@ type pclntabFunc struct {
99
105
// pclntabFunc118 is the Golang function definition (struct _func in the spec)
100
106
// starting with Go 1.18.
101
107
// see: go/src/runtime/runtime2.go (struct _func)
108
+ //
109
+ //nolint:unused
102
110
type pclntabFunc118 struct {
103
111
entryoff uint32 // start pc, as offset from pcHeader.textStart
104
112
nameOff , argsSize , frameSize int32
@@ -128,7 +136,7 @@ func sectionContaining(elfFile *pfelf.File, addr uint64) *pfelf.Section {
128
136
return nil
129
137
}
130
138
131
- func goFuncOffset (v version ) (uint32 , error ) {
139
+ func goFuncOffset (v headerVersion ) (uint32 , error ) {
132
140
if v < ver118 {
133
141
return 0 , fmt .Errorf ("unsupported version: %v" , v )
134
142
}
@@ -138,14 +146,14 @@ func goFuncOffset(v version) (uint32, error) {
138
146
return 40 * ptrSize , nil
139
147
}
140
148
141
- func FindModuleData (ef * pfelf.File , goPCLnTabInfo * GoPCLnTabInfo , symtab * libpf.SymbolMap ) ([]byte , uint64 , error ) {
149
+ func FindModuleData (ef * pfelf.File , goPCLnTabInfo * GoPCLnTabInfo , symtab * libpf.SymbolMap ) (data []byte , address uint64 , returnedErr error ) {
142
150
// First try to locate module data by looking for runtime.firstmoduledata symbol.
143
151
if symtab != nil {
144
152
if symAddr , err := symtab .LookupSymbolAddress ("runtime.firstmoduledata" ); err == nil {
145
153
addr := uint64 (symAddr )
146
154
section := sectionContaining (ef , addr )
147
155
if section == nil {
148
- return nil , 0 , fmt . Errorf ("could not find section containing runtime.firstmoduledata" )
156
+ return nil , 0 , errors . New ("could not find section containing runtime.firstmoduledata" )
149
157
}
150
158
data , err := section .Data (maxBytesGoPclntab )
151
159
if err != nil {
@@ -163,8 +171,6 @@ func FindModuleData(ef *pfelf.File, goPCLnTabInfo *GoPCLnTabInfo, symtab *libpf.
163
171
return nil , 0 , fmt .Errorf ("could not read .noptrdata section: %w" , err )
164
172
}
165
173
166
- // asume here that pointer size is 8
167
- const ptrSize = 8
168
174
var buf [2 * ptrSize ]byte
169
175
binary .NativeEndian .PutUint64 (buf [:], goPCLnTabInfo .Address )
170
176
binary .NativeEndian .PutUint64 (buf [ptrSize :], goPCLnTabInfo .Address + goPCLnTabInfo .Offsets .FuncNameTabOffset )
@@ -194,10 +200,10 @@ func FindModuleData(ef *pfelf.File, goPCLnTabInfo *GoPCLnTabInfo, symtab *libpf.
194
200
return noPtrSectionData [n :], noPtrSection .Addr + uint64 (n ), nil
195
201
}
196
202
197
- return nil , 0 , fmt . Errorf ("could not find moduledata" )
203
+ return nil , 0 , errors . New ("could not find moduledata" )
198
204
}
199
205
200
- func FindGoFunc (ef * pfelf.File , goPCLnTabInfo * GoPCLnTabInfo , symtab * libpf.SymbolMap ) ([]byte , uint64 , error ) {
206
+ func FindGoFunc (ef * pfelf.File , goPCLnTabInfo * GoPCLnTabInfo , symtab * libpf.SymbolMap ) (data []byte , address uint64 , returnedErr error ) {
201
207
// First try to locate goFunc with go:func.* symbol.
202
208
if symtab != nil {
203
209
if goFuncAddr , err := symtab .LookupSymbolAddress ("go:func.*" ); err == nil {
@@ -227,7 +233,7 @@ func FindGoFunc(ef *pfelf.File, goPCLnTabInfo *GoPCLnTabInfo, symtab *libpf.Symb
227
233
goFuncVal := binary .LittleEndian .Uint64 (moduleData [goFuncOff :])
228
234
sec := sectionContaining (ef , goFuncVal )
229
235
if sec == nil {
230
- return nil , 0 , fmt . Errorf ("could not find section containing gofunc" )
236
+ return nil , 0 , errors . New ("could not find section containing gofunc" )
231
237
}
232
238
secData , err := sec .Data (maxBytesGoPclntab )
233
239
if err != nil {
@@ -256,7 +262,7 @@ func pclntabHeaderSignature(arch elf.Machine) []byte {
256
262
return []byte {0xff , 0xff , 0xff , 0x00 , 0x00 , quantum , 0x08 }
257
263
}
258
264
259
- func SearchGoPclntab (ef * pfelf.File ) ([]byte , uint64 , error ) {
265
+ func SearchGoPclntab (ef * pfelf.File ) (data []byte , address uint64 , err error ) {
260
266
signature := pclntabHeaderSignature (ef .Machine )
261
267
262
268
for i := range ef .Progs {
@@ -267,7 +273,7 @@ func SearchGoPclntab(ef *pfelf.File) ([]byte, uint64, error) {
267
273
continue
268
274
}
269
275
270
- data , err : = p .Data (maxBytesGoPclntab )
276
+ data , err = p .Data (maxBytesGoPclntab )
271
277
if err != nil {
272
278
return nil , 0 , err
273
279
}
@@ -359,19 +365,22 @@ func FindGoPCLnTab(ef *pfelf.File, useHeuristicSearchAsFallback bool) (goPCLnTab
359
365
return nil , nil
360
366
}
361
367
362
- version := verUnknown
368
+ var version headerVersion
363
369
var offsets TableOffsets
364
370
hdrSize := uintptr (PclntabHeaderSize ())
365
371
mapSize := unsafe .Sizeof (pclntabFuncMap {})
372
+ //nolint:gocritic
366
373
// funSize := unsafe.Sizeof(pclntabFunc{})
367
374
dataLen := uintptr (len (data ))
368
375
if dataLen < hdrSize {
369
376
return nil , fmt .Errorf (".gopclntab is too short (%v)" , len (data ))
370
377
}
378
+ //nolint:gocritic
371
379
// var textStart uintptr
372
380
// var functab, funcdata, funcnametab, filetab, pctab, cutab []byte
373
381
374
382
hdr := (* pclntabHeader )(unsafe .Pointer (& data [0 ]))
383
+ //nolint:gocritic
375
384
// fieldSize := uintptr(hdr.ptrSize)
376
385
switch hdr .magic {
377
386
case magicGo1_2 :
0 commit comments