Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ $(error Unsupported architecture: $(TARGET_ARCH))
endif

export TARGET_ARCH
export CGO_ENABLED = 1
export CGO_ENABLED = 0
export GOARCH = $(TARGET_ARCH)
export CC = $(ARCH_PREFIX)-linux-gnu-gcc
export OBJCOPY = $(ARCH_PREFIX)-linux-gnu-objcopy
Expand Down Expand Up @@ -103,7 +103,8 @@ vanity-import-fix: $(PORTO)
@porto --include-internal -w .

test: generate ebpf test-deps
go test $(GO_FLAGS) -tags $(GO_TAGS) ./...
# tools/coredump tests build ebpf C-code using CGO to test it against coredumps
CGO_ENABLED=1 go test $(GO_FLAGS) -tags $(GO_TAGS) ./...

# This target isn't called from CI, it doesn't work for cross compile (ie TARGET_ARCH=arm64 on
# amd64) and the CI kernel tests run them already. Useful for local testing.
Expand All @@ -130,7 +131,7 @@ support/golbls_1_24.test: ./interpreter/golabels/test/main.go
CGO_ENABLED=0 GOTOOLCHAIN=go1.24.1 go build -tags $(GO_TAGS),nocgo -o $@ $<

support/golbls_cgo.test: ./interpreter/golabels/test/main-cgo.go
GOTOOLCHAIN=go1.24.1 go build -ldflags '-extldflags "-static"' -tags $(GO_TAGS),usecgo -o $@ $<
CGO_ENABLED=1 GOTOOLCHAIN=go1.24.1 go build -ldflags '-extldflags "-static"' -tags $(GO_TAGS),usecgo -o $@ $<

integration-test-binaries: generate ebpf rust-components support/golbls_1_23.test support/golbls_1_24.test support/golbls_cgo.test
$(foreach test_name, $(TEST_INTEGRATION_BINARY_DIRS), \
Expand Down
12 changes: 5 additions & 7 deletions interpreter/customlabels/customlabels.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package customlabels // import "go.opentelemetry.io/ebpf-profiler/interpreter/customlabels"

// #include <stdlib.h>
// #include "../../support/ebpf/types.h"
import "C"
import (
"errors"
"fmt"
Expand All @@ -13,6 +10,7 @@ import (
"go.opentelemetry.io/ebpf-profiler/libpf"
"go.opentelemetry.io/ebpf-profiler/libpf/pfelf"
"go.opentelemetry.io/ebpf-profiler/remotememory"
"go.opentelemetry.io/ebpf-profiler/support"
)

const (
Expand Down Expand Up @@ -127,10 +125,10 @@ func (d data) Attach(ebpf interpreter.EbpfHandler, pid libpf.PID,
currentHmTlsOffset = rm.Uint64(bias + d.currentHmTlsAddr + 8)
}

procInfo := C.NativeCustomLabelsProcInfo{
current_set_tls_offset: C.u64(currentSetTlsOffset),
has_current_hm: C.bool(d.hasCurrentHm),
current_hm_tls_offset: C.u64(currentHmTlsOffset),
procInfo := support.NativeCustomLabelsProcInfo{
Current_set_tls_offset: currentSetTlsOffset,
Has_current_hm: d.hasCurrentHm,
Current_hm_tls_offset: currentHmTlsOffset,
}
if err := ebpf.UpdateProcData(libpf.CustomLabels, pid, unsafe.Pointer(&procInfo)); err != nil {
return nil, err
Expand Down
4 changes: 2 additions & 2 deletions interpreter/customlabels/integrationtests/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,11 @@ func TestIntegration(t *testing.T) {

// Really, there should be zero frames in the
// `marked` workload that aren't under labels,
// but accept a 1% slop because the unwinder
// but accept a 5% slop because the unwinder
// isn't perfect (e.g. it might interrupt the
// process when the Node environment is in an
// undefined state)
require.Less(t, 100*unlabeledWorkloadFrames, totalWorkloadFrames)
require.Less(t, 20*unlabeledWorkloadFrames, totalWorkloadFrames)
})
}
}
Expand Down
8 changes: 3 additions & 5 deletions interpreter/golabels/golabels.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,12 @@ import (
"go.opentelemetry.io/ebpf-profiler/interpreter"
"go.opentelemetry.io/ebpf-profiler/libpf"
"go.opentelemetry.io/ebpf-profiler/remotememory"
"go.opentelemetry.io/ebpf-profiler/support"
)

// #include "../../support/ebpf/types.h"
import "C"

type data struct {
goVersion string
offsets C.GoLabelsOffsets
offsets support.GoLabelsOffsets
interpreter.InstanceStubs
}

Expand Down Expand Up @@ -64,7 +62,7 @@ func Loader(_ interpreter.EbpfHandler, info *interpreter.LoaderInfo) (interprete
if err != nil {
return nil, fmt.Errorf("failed to extract TLS offset: %w", err)
}
offsets.tls_offset = C.s32(tlsOffset)
offsets.Tls_offset = tlsOffset

return &data{
goVersion: goVersion,
Expand Down
34 changes: 17 additions & 17 deletions interpreter/golabels/runtime_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,49 @@

package golabels // import "go.opentelemetry.io/ebpf-profiler/interpreter/golabels"

// #include "../../support/ebpf/types.h"
import "C"
import (
"go/version"

"go.opentelemetry.io/ebpf-profiler/support"
)

// Offsets come from DWARF debug information, use tools/gooffsets to extract them.
// However since DWARF information can be stripped we record them here.
// TODO: Should we look for DWARF information to support new versions
// automatically when available?
func getOffsets(vers string) C.GoLabelsOffsets {
offsets := C.GoLabelsOffsets{
func getOffsets(vers string) support.GoLabelsOffsets {
offsets := support.GoLabelsOffsets{
// https://github.com/golang/go/blob/80e2e474b8d9124d03b744f/src/runtime/runtime2.go#L410
m_offset: 48,
M_offset: 48,
// https://github.com/golang/go/blob/80e2e474b8d9124d03b744f/src/runtime/runtime2.go#L541
curg: 192,
Curg: 192,
// https://github.com/golang/go/blob/80e2e474b8d9124d03b744f/src/runtime/runtime2.go#L483
labels: 0,
Labels: 0,
// https://github.com/golang/go/blob/6885bad7dd86880be6929c0/src/runtime/map.go#L112
hmap_count: 0,
Hmap_count: 0,
// https://github.com/golang/go/blob/6885bad7dd86880be6929c0/src/runtime/map.go#L114
hmap_log2_bucket_count: 0,
Hmap_log2_bucket_count: 0,
// https://github.com/golang/go/blob/6885bad7dd86880be6929c0/src/runtime/map.go#L118
hmap_buckets: 0,
Hmap_buckets: 0,
}

// Version enforcement takes place in the Loader function.
if version.Compare(vers, "go1.24") >= 0 {
offsets.labels = 352
offsets.Labels = 352
return offsets
}

// These are the same for all versions but we have to leave them zero for 1.24+ detection.
offsets.hmap_log2_bucket_count = 9
offsets.hmap_buckets = 16
offsets.Hmap_log2_bucket_count = 9
offsets.Hmap_buckets = 16
if version.Compare(vers, "go1.23") >= 0 {
offsets.labels = 352
offsets.Labels = 352
} else if version.Compare(vers, "go1.21") >= 0 {
offsets.labels = 344
offsets.Labels = 344
} else if version.Compare(vers, "go1.17") >= 0 {
offsets.labels = 360
offsets.Labels = 360
} else {
offsets.labels = 344
offsets.Labels = 344
}
return offsets
}
61 changes: 27 additions & 34 deletions interpreter/hotspot/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ import (
"go.opentelemetry.io/ebpf-profiler/util"
)

// #include "../../support/ebpf/types.h"
// #include "../../support/ebpf/frametypes.h"
import "C"

// heapRange contains info for an individual heap.
type heapRange struct {
codeStart, codeEnd libpf.Address
Expand Down Expand Up @@ -237,9 +233,9 @@ func (d *hotspotInstance) getPoolSymbol(addr libpf.Address, ndx uint16) libpf.St

// getStubNameID read the stub name from the code blob at given address and generates a ID.
func (d *hotspotInstance) getStubNameID(symbolReporter reporter.SymbolReporter, ripOrBci uint32,
addr libpf.Address, _ uint32) (libpf.AddressOrLineno, error) {
addr libpf.Address, _ uint32) libpf.AddressOrLineno {
if value, ok := d.addrToStubNameID.Get(addr); ok {
return value, nil
return value
}
vms := &d.d.Get().vmStructs
constStubNameAddr := d.rm.Ptr(addr + libpf.Address(vms.CodeBlob.Name))
Expand All @@ -263,7 +259,7 @@ func (d *hotspotInstance) getStubNameID(symbolReporter reporter.SymbolReporter,
})
d.addrToStubNameID.Add(addr, stubID)

return stubID, nil
return stubID
}

// getMethod reads and returns the interesting data from "class Method" at given address
Expand Down Expand Up @@ -745,31 +741,31 @@ func (d *hotspotInstance) populateMainMappings(vmd *hotspotVMData,

// Set up the main eBPF info structure.
vms := &vmd.vmStructs
procInfo := C.HotspotProcInfo{
nmethod_deopt_offset: C.u16(vms.Nmethod.DeoptimizeOffset),
nmethod_compileid: C.u16(vms.Nmethod.CompileID),
nmethod_orig_pc_offset: C.u16(vms.Nmethod.OrigPcOffset),
codeblob_name: C.u8(vms.CodeBlob.Name),
codeblob_codestart: C.u8(vms.CodeBlob.CodeBegin),
codeblob_codeend: C.u8(vms.CodeBlob.CodeEnd),
codeblob_framecomplete: C.u8(vms.CodeBlob.FrameCompleteOffset),
codeblob_framesize: C.u8(vms.CodeBlob.FrameSize),
cmethod_size: C.u8(vms.ConstMethod.Sizeof),
heapblock_size: C.u8(vms.HeapBlock.Sizeof),
method_constmethod: C.u8(vms.Method.ConstMethod),
jvm_version: C.u8(vmd.version >> 24),
segment_shift: C.u8(heap.segmentShift),
nmethod_uses_offsets: C.u8(vmd.nmethodUsesOffsets),
procInfo := support.HotspotProcInfo{
Nmethod_deopt_offset: uint16(vms.Nmethod.DeoptimizeOffset),
Nmethod_compileid: uint16(vms.Nmethod.CompileID),
Nmethod_orig_pc_offset: uint16(vms.Nmethod.OrigPcOffset),
Codeblob_name: uint8(vms.CodeBlob.Name),
Codeblob_codestart: uint8(vms.CodeBlob.CodeBegin),
Codeblob_codeend: uint8(vms.CodeBlob.CodeEnd),
Codeblob_framecomplete: uint8(vms.CodeBlob.FrameCompleteOffset),
Codeblob_framesize: uint8(vms.CodeBlob.FrameSize),
Cmethod_size: uint8(vms.ConstMethod.Sizeof),
Heapblock_size: uint8(vms.HeapBlock.Sizeof),
Method_constmethod: uint8(vms.Method.ConstMethod),
Jvm_version: uint8(vmd.version >> 24),
Segment_shift: uint8(heap.segmentShift),
Nmethod_uses_offsets: vmd.nmethodUsesOffsets,
}

if vms.CodeCache.LowBound == 0 {
// JDK-8 has only one heap, use its bounds
procInfo.codecache_start = C.u64(heap.ranges[0].codeStart)
procInfo.codecache_end = C.u64(heap.ranges[0].codeEnd)
procInfo.Codecache_start = uint64(heap.ranges[0].codeStart)
procInfo.Codecache_end = uint64(heap.ranges[0].codeEnd)
} else {
// JDK9+ the VM tracks it separately
procInfo.codecache_start = C.u64(d.rm.Ptr(vms.CodeCache.LowBound + d.bias))
procInfo.codecache_end = C.u64(d.rm.Ptr(vms.CodeCache.HighBound + d.bias))
procInfo.Codecache_start = uint64(d.rm.Ptr(vms.CodeCache.LowBound + d.bias))
procInfo.Codecache_end = uint64(d.rm.Ptr(vms.CodeCache.HighBound + d.bias))
}

if err = ebpf.UpdateProcData(libpf.HotSpot, pid, unsafe.Pointer(&procInfo)); err != nil {
Expand Down Expand Up @@ -875,22 +871,19 @@ func (d *hotspotInstance) Symbolize(symbolReporter reporter.SymbolReporter,
sfCounter := successfailurecounter.New(&d.successCount, &d.failCount)
defer sfCounter.DefaultToFailure()

switch subtype {
case C.FRAME_HOTSPOT_STUB, C.FRAME_HOTSPOT_VTABLE:
switch uint8(subtype) {
case support.FrameHotspotStub, support.FrameHotspotVtable:
// These are stub frames that may or may not be interesting
// to be seen in the trace.
stubID, err1 := d.getStubNameID(symbolReporter, ripOrBci, ptr, ptrCheck)
if err1 != nil {
return err
}
stubID := d.getStubNameID(symbolReporter, ripOrBci, ptr, ptrCheck)
trace.AppendFrame(libpf.HotSpotFrame, hotspotStubsFileID, stubID)
case C.FRAME_HOTSPOT_INTERPRETER:
case support.FrameHotspotInterpreter:
method, err1 := d.getMethod(ptr, ptrCheck)
if err1 != nil {
return err1
}
method.symbolize(symbolReporter, ripOrBci, d, trace)
case C.FRAME_HOTSPOT_NATIVE:
case support.FrameHotspotNative:
jitinfo, err1 := d.getJITInfo(ptr, ptrCheck)
if err1 != nil {
return err1
Expand Down
22 changes: 8 additions & 14 deletions interpreter/luajit/luajit.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,6 @@ import (
"go.opentelemetry.io/ebpf-profiler/util"
)

// #include "../../support/ebpf/types.h"
// #include "../../support/ebpf/luajit.h"
import "C"

const LuaJITFFIFunc = C.LUAJIT_FFI_FUNC

// Records all the "global" pointers we've seen.
type vmMap map[libpf.Address]struct{}

Expand Down Expand Up @@ -92,10 +86,10 @@ var (

func (d *luajitData) Attach(ebpf interpreter.EbpfHandler, pid libpf.PID, _ libpf.Address,
rm remotememory.RemoteMemory) (interpreter.Instance, error) {
cdata := C.LuaJITProcInfo{
g2dispatch: C.u16(d.g2Dispatch),
cur_L_offset: C.u16(d.currentLOffset),
cframe_size_jit: C.u16(cframeSizeJIT),
cdata := support.LuaJITProcInfo{
G2dispatch: d.g2Dispatch,
Cur_L_offset: d.currentLOffset,
Cframe_size_jit: uint16(cframeSizeJIT),
}
if err := ebpf.UpdateProcData(libpf.LuaJIT, pid, unsafe.Pointer(&cdata)); err != nil {
return nil, err
Expand Down Expand Up @@ -210,7 +204,7 @@ func (l *luajitInstance) addJITRegion(ebpf interpreter.EbpfHandler, pid libpf.PI
logf("lj: add JIT region pid(%v) %#x:%#x", pid, start, end)
for _, prefix := range prefixes {
// TODO: fix these: WARN[0267] Failed to lookup file ID 0x2a00000000
fileID := uint64(C.LUAJIT_JIT_FILE_ID) << 32
fileID := support.LJFileId << 32
if err := ebpf.UpdatePidInterpreterMapping(pid, prefix, support.ProgUnwindLuaJIT,
host.FileID(fileID), 0); err != nil {
return err
Expand All @@ -231,7 +225,7 @@ func (l *luajitInstance) addTrace(ebpf interpreter.EbpfHandler, pid libpf.PID, t
}
logf("lj: add trace mapping for pid(%v) %x:%x", pid, start, end)
for _, prefix := range prefixes {
fileID := uint64(C.LUAJIT_JIT_FILE_ID)<<32 | spadjust
fileID := support.LJFileId<<32 | spadjust
if err := ebpf.UpdatePidInterpreterMapping(pid, prefix, support.ProgUnwindLuaJIT,
host.FileID(fileID), g); err != nil {
return nil, err
Expand Down Expand Up @@ -383,7 +377,7 @@ func (l *luajitInstance) symbolizeFrame(symbolReporter reporter.SymbolReporter,
frameID libpf.FrameID) error {
var line uint32
var fileName string
if ptAddr != C.LUAJIT_FFI_FUNC {
if ptAddr != support.LJFFIFunc {
pt, err := l.getGCproto(ptAddr)
if err != nil {
return err
Expand Down Expand Up @@ -438,7 +432,7 @@ func (l *luajitInstance) Symbolize(symbolReporter reporter.SymbolReporter, frame
}

var funcName string
if frame.File == C.LUAJIT_FFI_FUNC {
if frame.File == support.LJFFIFunc {
switch frame.Lineno & 7 {
case 0:
funcName = "lua-frame"
Expand Down
1 change: 1 addition & 0 deletions interpreter/nodev8/node_offsets_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading