From a8b47d29d8f2c0563d2b7443e7bea1983ebefdce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Wed, 16 Jul 2025 15:53:26 +0300 Subject: [PATCH 1/3] drop use of CGO in profiler core --- Makefile | 6 +- interpreter/golabels/golabels.go | 8 +- interpreter/golabels/runtime_data.go | 34 +-- interpreter/hotspot/instance.go | 61 +++--- interpreter/nodev8/v8.go | 108 +++++----- interpreter/perl/data.go | 5 +- interpreter/perl/instance.go | 66 +++--- interpreter/python/python.go | 48 ++--- metrics/metrics.go | 6 +- processmanager/ebpf/ebpf.go | 162 +++++++------- support/ebpf/tracer.ebpf.amd64 | Bin 2342528 -> 2342536 bytes support/ebpf/tracer.ebpf.arm64 | Bin 2316856 -> 2316872 bytes support/ebpf/types.h | 14 +- support/ebpf/v8_tracer.ebpf.c | 12 +- support/ebpf/v8_tracer.h | 12 +- support/types.go | 311 +++++++++++++++++++++++++++ support/types_def.go | 154 +++++++++++++ tracer/events.go | 12 +- tracer/systemconfig.go | 51 +++-- tracer/tracer.go | 189 +++++----------- 20 files changed, 799 insertions(+), 460 deletions(-) diff --git a/Makefile b/Makefile index cb2223a06..3c1683a4e 100644 --- a/Makefile +++ b/Makefile @@ -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 @@ -103,7 +103,7 @@ vanity-import-fix: $(PORTO) @porto --include-internal -w . test: generate ebpf test-deps - go test $(GO_FLAGS) -tags $(GO_TAGS) ./... + 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. @@ -130,7 +130,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), \ diff --git a/interpreter/golabels/golabels.go b/interpreter/golabels/golabels.go index 971399c24..ab31688fa 100644 --- a/interpreter/golabels/golabels.go +++ b/interpreter/golabels/golabels.go @@ -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 } @@ -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, diff --git a/interpreter/golabels/runtime_data.go b/interpreter/golabels/runtime_data.go index fd6b2ae3f..a36b8e4cc 100644 --- a/interpreter/golabels/runtime_data.go +++ b/interpreter/golabels/runtime_data.go @@ -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 } diff --git a/interpreter/hotspot/instance.go b/interpreter/hotspot/instance.go index 44a8c4c15..f68f0b83e 100644 --- a/interpreter/hotspot/instance.go +++ b/interpreter/hotspot/instance.go @@ -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 @@ -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)) @@ -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 @@ -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 { @@ -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 diff --git a/interpreter/nodev8/v8.go b/interpreter/nodev8/v8.go index 349fde23b..651762d5a 100644 --- a/interpreter/nodev8/v8.go +++ b/interpreter/nodev8/v8.go @@ -184,19 +184,15 @@ import ( "go.opentelemetry.io/ebpf-profiler/util" ) -// #include "../../support/ebpf/types.h" -// #include "../../support/ebpf/v8_tracer.h" -import "C" - const ( // Use build-time constants for the HeapObject/SMI Tags for code size and speed. // They are unlikely to change, and likely require larger modifications on change. - SmiTag = C.SmiTag - SmiTagMask = C.SmiTagMask - SmiTagShift = C.SmiTagShift - SmiValueShift = C.SmiValueShift - HeapObjectTag = C.HeapObjectTag - HeapObjectTagMask = C.HeapObjectTagMask + SmiTag = support.V8SmiTag + SmiTagMask = support.V8SmiTagMask + SmiTagShift = support.V8SmiTagShift + SmiValueShift = support.V8SmiValueShift + HeapObjectTag = support.V8HeapObjectTag + HeapObjectTagMask = support.V8HeapObjectTagMask // The largest possible identifier for V8 frame type (marker) MaxFrameType = 64 @@ -939,7 +935,7 @@ func (i *v8Instance) getStringPtr(ptr libpf.Address) (libpf.String, error) { // analyzeScopeInfo reads and heuristically analyzes V8 ScopeInfo data. It tries to // extract the function name, and its start and end line. func (i *v8Instance) analyzeScopeInfo(ptr libpf.Address) (name libpf.String, - startPos, endPos int, err error) { + startPos, endPos int) { vms := &i.d.vmStructs var data libpf.Address if vms.ScopeInfo.HeapObject { @@ -959,8 +955,8 @@ func (i *v8Instance) analyzeScopeInfo(ptr libpf.Address) (name libpf.String, const numSlots = 16 const slotSize = pointerSize slotData := make([]byte, numSlots*slotSize) - if err = i.rm.Read(data, slotData); err != nil { - return libpf.NullString, 0, 0, nil + if err := i.rm.Read(data, slotData); err != nil { + return libpf.NullString, 0, 0 } // Skip reserved slots and the context locals @@ -984,12 +980,12 @@ func (i *v8Instance) analyzeScopeInfo(ptr libpf.Address) (name libpf.String, startPos = int(decodeSMI(prev)) endPos = int(decodeSMI(cur)) if startPos < endPos { - return name, startPos, endPos, nil + return name, startPos, endPos } } prev = cur } - return name, 0, 0, nil + return name, 0, 0 } // readFixedTable reads the data of a FixedArray object. @@ -1026,9 +1022,9 @@ func (i *v8Instance) readFixedTablePtr(taggedPtr libpf.Address, tag uint16, } // getSource reads and caches needed V8 Source object data. -func (i *v8Instance) getSource(addr libpf.Address) (*v8Source, error) { +func (i *v8Instance) getSource(addr libpf.Address) *v8Source { if value, ok := i.addrToSource.Get(addr); ok { - return value, nil + return value } vms := &i.d.vmStructs @@ -1076,7 +1072,7 @@ func (i *v8Instance) getSource(addr libpf.Address) (*v8Source, error) { } i.addrToSource.Add(addr, src) - return src, nil + return src } // getSFI reads and caches needed V8 SharedFunctionInfo object data. @@ -1103,7 +1099,7 @@ func (i *v8Instance) getSFI(taggedPtr libpf.Address) (*v8SFI, error) { } switch { case nosType == vms.Type.ScopeInfo: - sfi.funcName, sfi.funcStartPos, sfi.funcEndPos, err = i.analyzeScopeInfo(nosAddr) + sfi.funcName, sfi.funcStartPos, sfi.funcEndPos = i.analyzeScopeInfo(nosAddr) case nosType < vms.Fixed.FirstNonstringType: sfi.funcName, err = i.getString(nosAddr, nosType) } @@ -1148,7 +1144,7 @@ func (i *v8Instance) getSFI(taggedPtr libpf.Address) (*v8SFI, error) { sodiAddr, sodiType, _ := i.readObjectPtr(addr + libpf.Address(vms.SharedFunctionInfo.ScriptOrDebugInfo)) if sodiType == vms.Type.Script { - sfi.source, _ = i.getSource(sodiAddr) + sfi.source = i.getSource(sodiAddr) if sfi.funcStartPos != sfi.funcEndPos { sfi.funcStartLine = mapPositionToLine(sfi.source.lineTable, int32(sfi.funcStartPos)) @@ -1578,7 +1574,7 @@ func (i *v8Instance) symbolizeSFI(symbolReporter reporter.SymbolReporter, pointe // Adjust the bytecode pointer as needed //nolint:lll // https://chromium.googlesource.com/v8/v8.git/+/refs/tags/9.2.230.1/src/execution/frames.cc#1793 - bytecodeDelta := int64(delta & C.V8_LINE_DELTA_MASK) + bytecodeDelta := int64(delta & support.V8LineDeltaMask) bytecodeDelta -= int64(vms.BytecodeArray.Data) - HeapObjectTag if bytecodeDelta < 0 { // Should not be happening @@ -1694,7 +1690,7 @@ func (i *v8Instance) symbolizeCode(symbolReporter reporter.SymbolReporter, code delta uint64, trace *libpf.Trace) error { var err error sfi := code.sfi - delta &= C.V8_LINE_DELTA_MASK + delta &= support.V8LineDeltaMask // This is a native PC delta and points to the instruction after // the call function. Adjust to get the CALL instruction. @@ -1762,22 +1758,22 @@ func (i *v8Instance) Symbolize(symbolReporter reporter.SymbolReporter, pointerAndType := libpf.Address(frame.File) deltaOrMarker := uint64(frame.Lineno) - frameType := pointerAndType & C.V8_FILE_TYPE_MASK - pointer := pointerAndType&^C.V8_FILE_TYPE_MASK | HeapObjectTag + frameType := pointerAndType & support.V8FileTypeMask + pointer := pointerAndType&^support.V8FileTypeMask | HeapObjectTag var err error switch frameType { - case C.V8_FILE_TYPE_MARKER: + case support.V8FileTypeMarker: // This is a stub V8 frame, with deltaOrMarker containing the marker. // Convert the V8 build specific marker ID to a static ID and symbolize // that if needed. err = i.symbolizeMarkerFrame(symbolReporter, deltaOrMarker, trace) - case C.V8_FILE_TYPE_BYTECODE, C.V8_FILE_TYPE_NATIVE_SFI: + case support.V8FileTypeByteCode, support.V8FileTypeNativeSFI: err = i.symbolizeSFI(symbolReporter, pointer, deltaOrMarker, trace) - case C.V8_FILE_TYPE_NATIVE_CODE, C.V8_FILE_TYPE_NATIVE_JSFUNC: + case support.V8FileTypeNativeCode, support.V8FileTypeNativeJSFunc: var code *v8Code - codeCookie := uint32(deltaOrMarker & C.V8_LINE_COOKIE_MASK >> C.V8_LINE_COOKIE_SHIFT) - if frameType == C.V8_FILE_TYPE_NATIVE_CODE { + codeCookie := uint32(deltaOrMarker & support.V8LineCookieMask >> support.V8LineCookieShift) + if frameType == support.V8FileTypeNativeCode { code, err = i.getCode(pointer, codeCookie) } else { code, err = i.getCodeFromJSFunc(pointer, codeCookie) @@ -1804,41 +1800,41 @@ func (d *v8Data) String() string { // mapFramePointerOffset converts the frame pointer offset in bytes to eBPF used // word offset relative to the number of slots read -func mapFramePointerOffset(relBytes uint8) C.u8 { - slotOffset := int(C.V8_FP_CONTEXT_SIZE) + int(int8(relBytes)) - if slotOffset < 0 || slotOffset > C.V8_FP_CONTEXT_SIZE-pointerSize { - return C.V8_FP_CONTEXT_SIZE +func mapFramePointerOffset(relBytes uint8) uint8 { + slotOffset := int(support.V8FpContextSize) + int(int8(relBytes)) + if slotOffset < 0 || slotOffset > support.V8FpContextSize-pointerSize { + return support.V8FpContextSize } - return C.u8(slotOffset) + return uint8(slotOffset) } func (d *v8Data) Attach(ebpf interpreter.EbpfHandler, pid libpf.PID, _ libpf.Address, rm remotememory.RemoteMemory) (interpreter.Instance, error) { vms := &d.vmStructs - data := C.V8ProcInfo{ - version: C.uint(d.version), + data := support.V8ProcInfo{ + Version: d.version, - fp_marker: mapFramePointerOffset(vms.FramePointer.Context), - fp_function: mapFramePointerOffset(vms.FramePointer.Function), - fp_bytecode_offset: mapFramePointerOffset(vms.FramePointer.BytecodeOffset), + Fp_marker: mapFramePointerOffset(vms.FramePointer.Context), + Fp_function: mapFramePointerOffset(vms.FramePointer.Function), + Fp_bytecode_offset: mapFramePointerOffset(vms.FramePointer.BytecodeOffset), - type_JSFunction_first: C.u16(vms.Fixed.FirstJSFunctionType), - type_JSFunction_last: C.u16(vms.Fixed.LastJSFunctionType), - type_Code: C.u16(vms.Type.Code), - type_SharedFunctionInfo: C.u16(vms.Type.SharedFunctionInfo), + Type_JSFunction_first: vms.Fixed.FirstJSFunctionType, + Type_JSFunction_last: vms.Fixed.LastJSFunctionType, + Type_Code: vms.Type.Code, + Type_SharedFunctionInfo: vms.Type.SharedFunctionInfo, - off_HeapObject_map: C.u8(vms.HeapObject.Map), - off_Map_instancetype: C.u8(vms.Map.InstanceType), - off_JSFunction_code: C.u8(vms.JSFunction.Code), - off_JSFunction_shared: C.u8(vms.JSFunction.SharedFunctionInfo), + Off_HeapObject_map: uint8(vms.HeapObject.Map), + Off_Map_instancetype: uint8(vms.Map.InstanceType), + Off_JSFunction_code: uint8(vms.JSFunction.Code), + Off_JSFunction_shared: uint8(vms.JSFunction.SharedFunctionInfo), - off_Code_instruction_start: C.u8(vms.Code.InstructionStart), - off_Code_instruction_size: C.u8(vms.Code.InstructionSize), - off_Code_flags: C.u8(vms.Code.Flags), + Off_Code_instruction_start: uint8(vms.Code.InstructionStart), + Off_Code_instruction_size: uint8(vms.Code.InstructionSize), + Off_Code_flags: uint8(vms.Code.Flags), - codekind_shift: C.u8(vms.CodeKind.FieldShift), - codekind_mask: C.u8(vms.CodeKind.FieldMask), - codekind_baseline: C.u8(vms.CodeKind.Baseline), + Codekind_shift: vms.CodeKind.FieldShift, + Codekind_mask: uint8(vms.CodeKind.FieldMask), + Codekind_baseline: vms.CodeKind.Baseline, } if err := ebpf.UpdateProcData(libpf.V8, pid, unsafe.Pointer(&data)); err != nil { return nil, err @@ -2217,9 +2213,9 @@ func Loader(ebpf interpreter.EbpfHandler, info *interpreter.LoaderInfo) (interpr return nil, errors.New("incompatible tagging scheme") } - if mapFramePointerOffset(vms.FramePointer.Context) >= C.V8_FP_CONTEXT_SIZE || - mapFramePointerOffset(vms.FramePointer.Function) >= C.V8_FP_CONTEXT_SIZE || - mapFramePointerOffset(vms.FramePointer.BytecodeOffset) >= C.V8_FP_CONTEXT_SIZE { + if mapFramePointerOffset(vms.FramePointer.Context) >= support.V8FpContextSize || + mapFramePointerOffset(vms.FramePointer.Function) >= support.V8FpContextSize || + mapFramePointerOffset(vms.FramePointer.BytecodeOffset) >= support.V8FpContextSize { return nil, fmt.Errorf("incompatible framepointer offsets (%d/%d/%d)", vms.FramePointer.Context, vms.FramePointer.Function, vms.FramePointer.BytecodeOffset) diff --git a/interpreter/perl/data.go b/interpreter/perl/data.go index d77ed5fcc..af30cc882 100644 --- a/interpreter/perl/data.go +++ b/interpreter/perl/data.go @@ -17,9 +17,6 @@ import ( "go.opentelemetry.io/ebpf-profiler/support" ) -// #include "../../support/ebpf/types.h" -import "C" - type perlData struct { // vmStructs reflects the Perl internal class names and the offsets of named field // The struct names are based on the Perl C "struct name", the alternate typedef seen @@ -146,7 +143,7 @@ func (d *perlData) Attach(_ interpreter.EbpfHandler, _ libpf.PID, bias libpf.Add return &perlInstance{ d: d, rm: rm, - bias: C.u64(bias), + bias: bias, addrToHEK: addrToHEK, addrToCOP: addrToCOP, addrToGV: addrToGV, diff --git a/interpreter/perl/instance.go b/interpreter/perl/instance.go index 9e92bc3e2..11cd6aa3f 100644 --- a/interpreter/perl/instance.go +++ b/interpreter/perl/instance.go @@ -23,13 +23,11 @@ import ( "go.opentelemetry.io/ebpf-profiler/remotememory" "go.opentelemetry.io/ebpf-profiler/reporter" "go.opentelemetry.io/ebpf-profiler/successfailurecounter" + "go.opentelemetry.io/ebpf-profiler/support" "go.opentelemetry.io/ebpf-profiler/tpbase" "go.opentelemetry.io/ebpf-profiler/util" ) -// #include "../../support/ebpf/types.h" -import "C" - type perlInstance struct { interpreter.InstanceStubs @@ -39,7 +37,7 @@ type perlInstance struct { d *perlData rm remotememory.RemoteMemory - bias C.u64 + bias libpf.Address // addrToHEK maps a PERL Hash Element Key (string with hash) to a Go string addrToHEK *freelru.LRU[libpf.Address, string] @@ -84,42 +82,42 @@ func hashCOPKey(k copKey) uint32 { func (i *perlInstance) UpdateTSDInfo(ebpf interpreter.EbpfHandler, pid libpf.PID, tsdInfo tpbase.TSDInfo) error { d := i.d - stateInTSD := C.u8(0) + stateInTSD := uint8(0) if d.stateInTSD { stateInTSD = 1 } vms := &d.vmStructs - data := C.PerlProcInfo{ - version: C.uint(d.version), - stateAddr: C.u64(d.stateAddr) + i.bias, - stateInTSD: stateInTSD, - - tsdInfo: C.TSDInfo{ - offset: C.s16(tsdInfo.Offset), - multiplier: C.u8(tsdInfo.Multiplier), - indirect: C.u8(tsdInfo.Indirect), + data := support.PerlProcInfo{ + Version: d.version, + StateAddr: uint64(d.stateAddr) + uint64(i.bias), + StateInTSD: stateInTSD, + + TsdInfo: support.TSDInfo{ + Offset: tsdInfo.Offset, + Multiplier: tsdInfo.Multiplier, + Indirect: tsdInfo.Indirect, }, - interpreter_curcop: C.u16(vms.interpreter.curcop), - interpreter_curstackinfo: C.u16(vms.interpreter.curstackinfo), - - si_cxstack: C.u8(vms.stackinfo.si_cxstack), - si_next: C.u8(vms.stackinfo.si_next), - si_cxix: C.u8(vms.stackinfo.si_cxix), - si_type: C.u8(vms.stackinfo.si_type), - - context_type: C.u8(vms.context.cx_type), - context_blk_oldcop: C.u8(vms.context.blk_oldcop), - context_blk_sub_retop: C.u8(vms.context.blk_sub_retop), - context_blk_sub_cv: C.u8(vms.context.blk_sub_cv), - context_sizeof: C.u8(vms.context.sizeof), - - sv_flags: C.u8(vms.sv.sv_flags), - sv_any: C.u8(vms.sv.sv_any), - svu_gp: C.u8(vms.sv.svu_gp), - xcv_flags: C.u8(vms.xpvcv.xcv_flags), - xcv_gv: C.u8(vms.xpvcv.xcv_gv), - gp_egv: C.u8(vms.gp.gp_egv), + Interpreter_curcop: uint16(vms.interpreter.curcop), + Interpreter_curstackinfo: uint16(vms.interpreter.curstackinfo), + + Si_cxstack: uint8(vms.stackinfo.si_cxstack), + Si_next: uint8(vms.stackinfo.si_next), + Si_cxix: uint8(vms.stackinfo.si_cxix), + Si_type: uint8(vms.stackinfo.si_type), + + Context_type: uint8(vms.context.cx_type), + Context_blk_oldcop: uint8(vms.context.blk_oldcop), + Context_blk_sub_retop: uint8(vms.context.blk_sub_retop), + Context_blk_sub_cv: uint8(vms.context.blk_sub_cv), + Context_sizeof: uint8(vms.context.sizeof), + + Sv_flags: uint8(vms.sv.sv_flags), + Sv_any: uint8(vms.sv.sv_any), + Svu_gp: uint8(vms.sv.svu_gp), + Xcv_flags: uint8(vms.xpvcv.xcv_flags), + Xcv_gv: uint8(vms.xpvcv.xcv_gv), + Gp_egv: uint8(vms.gp.gp_egv), } err := ebpf.UpdateProcData(libpf.Perl, pid, unsafe.Pointer(&data)) diff --git a/interpreter/python/python.go b/interpreter/python/python.go index 586a014d5..bb5fb094d 100644 --- a/interpreter/python/python.go +++ b/interpreter/python/python.go @@ -38,10 +38,6 @@ import ( "go.opentelemetry.io/ebpf-profiler/util" ) -// #include -// #include "../../support/ebpf/types.h" -import "C" - // The following regexs are intended to match either a path to a Python binary or // library. var ( @@ -135,7 +131,7 @@ func (d *pythonData) Attach(_ interpreter.EbpfHandler, _ libpf.PID, bias libpf.A i := &pythonInstance{ d: d, rm: rm, - bias: C.u64(bias), + bias: bias, addrToCodeObject: addrToCodeObject, } @@ -349,7 +345,7 @@ type pythonInstance struct { d *pythonData rm remotememory.RemoteMemory - bias C.u64 + bias libpf.Address // addrToCodeObject maps a Python Code object to a pythonCodeObject which caches // the needed data from it. @@ -400,28 +396,28 @@ func (p *pythonInstance) UpdateTSDInfo(ebpf interpreter.EbpfHandler, pid libpf.P tsdInfo tpbase.TSDInfo) error { d := p.d vm := &d.vmStructs - cdata := C.PyProcInfo{ - autoTLSKeyAddr: C.u64(d.autoTLSKey) + p.bias, - version: C.u16(d.version), - - tsdInfo: C.TSDInfo{ - offset: C.s16(tsdInfo.Offset), - multiplier: C.u8(tsdInfo.Multiplier), - indirect: C.u8(tsdInfo.Indirect), + cdata := support.PyProcInfo{ + AutoTLSKeyAddr: uint64(d.autoTLSKey) + uint64(p.bias), + Version: d.version, + + TsdInfo: support.TSDInfo{ + Offset: tsdInfo.Offset, + Multiplier: tsdInfo.Multiplier, + Indirect: tsdInfo.Indirect, }, - PyThreadState_frame: C.u8(vm.PyThreadState.Frame), - PyCFrame_current_frame: C.u8(vm.PyCFrame.CurrentFrame), - PyFrameObject_f_back: C.u8(vm.PyFrameObject.Back), - PyFrameObject_f_code: C.u8(vm.PyFrameObject.Code), - PyFrameObject_f_lasti: C.u8(vm.PyFrameObject.LastI), - PyFrameObject_entry_member: C.u8(vm.PyFrameObject.EntryMember), - PyFrameObject_entry_val: C.u8(vm.PyFrameObject.EntryVal), - PyCodeObject_co_argcount: C.u8(vm.PyCodeObject.ArgCount), - PyCodeObject_co_kwonlyargcount: C.u8(vm.PyCodeObject.KwOnlyArgCount), - PyCodeObject_co_flags: C.u8(vm.PyCodeObject.Flags), - PyCodeObject_co_firstlineno: C.u8(vm.PyCodeObject.FirstLineno), - PyCodeObject_sizeof: C.u8(vm.PyCodeObject.Sizeof), + PyThreadState_frame: uint8(vm.PyThreadState.Frame), + PyCFrame_current_frame: uint8(vm.PyCFrame.CurrentFrame), + PyFrameObject_f_back: uint8(vm.PyFrameObject.Back), + PyFrameObject_f_code: uint8(vm.PyFrameObject.Code), + PyFrameObject_f_lasti: uint8(vm.PyFrameObject.LastI), + PyFrameObject_entry_member: uint8(vm.PyFrameObject.EntryMember), + PyFrameObject_entry_val: uint8(vm.PyFrameObject.EntryVal), + PyCodeObject_co_argcount: uint8(vm.PyCodeObject.ArgCount), + PyCodeObject_co_kwonlyargcount: uint8(vm.PyCodeObject.KwOnlyArgCount), + PyCodeObject_co_flags: uint8(vm.PyCodeObject.Flags), + PyCodeObject_co_firstlineno: uint8(vm.PyCodeObject.FirstLineno), + PyCodeObject_sizeof: uint8(vm.PyCodeObject.Sizeof), } err := ebpf.UpdateProcData(libpf.Python, pid, unsafe.Pointer(&cdata)) diff --git a/metrics/metrics.go b/metrics/metrics.go index ec4776cbf..a0a9bebbb 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -10,19 +10,19 @@ import ( "encoding/json" "fmt" "sync" + "time" log "github.com/sirupsen/logrus" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/ebpf-profiler/libpf" "go.opentelemetry.io/ebpf-profiler/vc" ) var ( // prevTimestamp holds the timestamp of the buffered metrics - prevTimestamp libpf.UnixTime32 + prevTimestamp uint32 // metricsBuffer buffers the metricsBuffer for the timestamp assigned to prevTimestamp metricsBuffer = make([]Metric, IDMax) @@ -123,7 +123,7 @@ var report = func() { // This ensures that the buffered metrics from the previous timestamp are sent // with the correctly assigned TSMetric.Timestamp. func AddSlice(newMetrics []Metric) { - now := libpf.UnixTime32(libpf.NowAsUInt32()) + now := uint32(time.Now().Unix()) mutex.Lock() defer mutex.Unlock() diff --git a/processmanager/ebpf/ebpf.go b/processmanager/ebpf/ebpf.go index 3c0d22583..bbcedc896 100644 --- a/processmanager/ebpf/ebpf.go +++ b/processmanager/ebpf/ebpf.go @@ -26,12 +26,6 @@ import ( "golang.org/x/exp/constraints" ) -/* -#include -#include "../../support/ebpf/types.h" -*/ -import "C" - const ( // updatePoolWorkers decides how many background workers we spawn to // process map-in-map updates. @@ -269,10 +263,10 @@ func (impl *ebpfMapsImpl) UpdateInterpreterOffsets(ebpfProgIndex uint16, fileID } func InterpreterOffsetKeyValue(ebpfProgIndex uint16, fileID host.FileID, - offsetRanges []util.Range) (key uint64, value C.OffsetRange, err error) { + offsetRanges []util.Range) (key uint64, value support.OffsetRange, err error) { rLen := len(offsetRanges) if rLen < 1 || rLen > 2 { - return 0, C.OffsetRange{}, fmt.Errorf("invalid ranges %v", offsetRanges) + return 0, support.OffsetRange{}, fmt.Errorf("invalid ranges %v", offsetRanges) } // The keys of this map are executable-id-and-offset-into-text entries, and // the offset_range associated with them gives the precise area in that page @@ -280,10 +274,10 @@ func InterpreterOffsetKeyValue(ebpfProgIndex uint16, fileID host.FileID, // nicely from native code into interpreted code. key = uint64(fileID) first := offsetRanges[0] - value = C.OffsetRange{ - lower_offset1: C.u64(first.Start), - upper_offset1: C.u64(first.End), - program_index: C.u16(ebpfProgIndex), + value = support.OffsetRange{ + Lower_offset1: first.Start, + Upper_offset1: first.End, + Program_index: ebpfProgIndex, } if len(offsetRanges) == 2 { // Fields {lower,upper}_offset2 may be used to specify an optional second range @@ -291,8 +285,8 @@ func InterpreterOffsetKeyValue(ebpfProgIndex uint16, fileID host.FileID, // consists of two non-contiguous memory ranges, which may happen due to Hot/Cold // split compiler optimization second := offsetRanges[1] - value.lower_offset2 = C.u64(second.Start) - value.upper_offset2 = C.u64(second.End) + value.Lower_offset2 = second.Start + value.Upper_offset2 = second.End } return key, value, nil } @@ -366,19 +360,19 @@ func (impl *ebpfMapsImpl) UpdatePidInterpreterMapping(pid libpf.PID, prefix lpm. bePid := bits.ReverseBytes32(uint32(pid)) bePage := bits.ReverseBytes64(prefix.Key) - cKey := C.PIDPage{ - prefixLen: C.u32(support.BitWidthPID + prefix.Length), - pid: C.u32(bePid), - page: C.u64(bePage), + cKey := support.PIDPage{ + PrefixLen: support.BitWidthPID + prefix.Length, + Pid: bePid, + Page: bePage, } biasAndUnwindProgram, err := support.EncodeBiasAndUnwindProgram(bias, interpreterProgram) if err != nil { return err } - cValue := C.PIDPageMappingInfo{ - file_id: C.u64(fileID), - bias_and_unwind_program: C.u64(biasAndUnwindProgram), + cValue := support.PIDPageMappingInfo{ + File_id: uint64(fileID), + Bias_and_unwind_program: biasAndUnwindProgram, } return impl.pidPageToMappingInfo.Update(unsafe.Pointer(&cKey), unsafe.Pointer(&cValue), @@ -395,10 +389,10 @@ func (impl *ebpfMapsImpl) DeletePidInterpreterMapping(pid libpf.PID, prefix lpm. bePid := bits.ReverseBytes32(uint32(pid)) bePage := bits.ReverseBytes64(prefix.Key) - cKey := C.PIDPage{ - prefixLen: C.u32(support.BitWidthPID + prefix.Length), - pid: C.u32(bePid), - page: C.u64(bePage), + cKey := support.PIDPage{ + PrefixLen: support.BitWidthPID + prefix.Length, + Pid: bePid, + Page: bePage, } return impl.pidPageToMappingInfo.Delete(unsafe.Pointer(&cKey)) } @@ -432,29 +426,29 @@ func (impl *ebpfMapsImpl) CollectMetrics() []metrics.Metric { return counts } -// poolPIDPage caches reusable heap-allocated C.PIDPage instances +// poolPIDPage caches reusable heap-allocated support.PIDPage instances // to avoid excessive heap allocations. var poolPIDPage = sync.Pool{ New: func() any { - return new(C.PIDPage) + return new(support.PIDPage) }, } -// getPIDPage initializes a C.PIDPage instance. -func getPIDPage(pid libpf.PID, prefix lpm.Prefix) C.PIDPage { +// getPIDPage initializes a support.PIDPage instance. +func getPIDPage(pid libpf.PID, prefix lpm.Prefix) support.PIDPage { // pid_page_to_mapping_info is an LPM trie and expects the pid and page // to be in big endian format. - return C.PIDPage{ - pid: C.u32(bits.ReverseBytes32(uint32(pid))), - page: C.u64(bits.ReverseBytes64(prefix.Key)), - prefixLen: C.u32(support.BitWidthPID + prefix.Length), + return support.PIDPage{ + Pid: bits.ReverseBytes32(uint32(pid)), + Page: bits.ReverseBytes64(prefix.Key), + PrefixLen: support.BitWidthPID + prefix.Length, } } -// getPIDPagePooled returns a heap-allocated and initialized C.PIDPage instance. +// getPIDPagePooled returns a heap-allocated and initialized support.PIDPage instance. // After usage, put the instance back into the pool with poolPIDPage.Put(). -func getPIDPagePooled(pid libpf.PID, prefix lpm.Prefix) *C.PIDPage { - cPIDPage := poolPIDPage.Get().(*C.PIDPage) +func getPIDPagePooled(pid libpf.PID, prefix lpm.Prefix) *support.PIDPage { + cPIDPage := poolPIDPage.Get().(*support.PIDPage) *cPIDPage = getPIDPage(pid, prefix) return cPIDPage } @@ -463,16 +457,16 @@ func getPIDPagePooled(pid libpf.PID, prefix lpm.Prefix) *C.PIDPage { // to avoid excessive heap allocations. var poolPIDPageMappingInfo = sync.Pool{ New: func() any { - return new(C.PIDPageMappingInfo) + return new(support.PIDPageMappingInfo) }, } -// getPIDPageMappingInfo returns a heap-allocated and initialized C.PIDPageMappingInfo instance. +// getPIDPageMappingInfo returns a heap-allocated and initialized PIDPageMappingInfo instance. // After usage, put the instance back into the pool with poolPIDPageMappingInfo.Put(). -func getPIDPageMappingInfo(fileID, biasAndUnwindProgram uint64) *C.PIDPageMappingInfo { - cInfo := poolPIDPageMappingInfo.Get().(*C.PIDPageMappingInfo) - cInfo.file_id = C.u64(fileID) - cInfo.bias_and_unwind_program = C.u64(biasAndUnwindProgram) +func getPIDPageMappingInfo(fileID, biasAndUnwindProgram uint64) *support.PIDPageMappingInfo { + cInfo := poolPIDPageMappingInfo.Get().(*support.PIDPageMappingInfo) + cInfo.File_id = fileID + cInfo.Bias_and_unwind_program = biasAndUnwindProgram return cInfo } @@ -577,13 +571,13 @@ func (impl *ebpfMapsImpl) UpdateUnwindInfo(index uint16, info sdtypes.UnwindInfo index, impl.unwindInfoArray.MaxEntries()) } - key := C.u32(index) - value := C.UnwindInfo{ - opcode: C.u8(info.Opcode), - fpOpcode: C.u8(info.FPOpcode), - mergeOpcode: C.u8(info.MergeOpcode), - param: C.s32(info.Param), - fpParam: C.s32(info.FPParam), + key := uint32(index) + value := support.UnwindInfo{ + Opcode: info.Opcode, + FpOpcode: info.FPOpcode, + MergeOpcode: info.MergeOpcode, + Param: info.Param, + FpParam: info.FPParam, } return impl.trackMapError(metrics.IDUnwindInfoArrayUpdate, impl.unwindInfoArray.Update(unsafe.Pointer(&key), unsafe.Pointer(&value), @@ -601,9 +595,6 @@ func (impl *ebpfMapsImpl) UpdateExeIDToStackDeltas(fileID host.FileID, deltas [] } outerMap := impl.getOuterMap(mapID) - keySize := uint32(C.sizeof_uint32_t) - valueSize := uint32(C.sizeof_StackDelta) - restoreRlimit, err := rlimit.MaximizeMemlock() if err != nil { return 0, fmt.Errorf("failed to increase rlimit: %v", err) @@ -611,8 +602,8 @@ func (impl *ebpfMapsImpl) UpdateExeIDToStackDeltas(fileID host.FileID, deltas [] defer restoreRlimit() innerMap, err := cebpf.NewMap(&cebpf.MapSpec{ Type: cebpf.Array, - KeySize: keySize, - ValueSize: valueSize, + KeySize: 4, + ValueSize: support.Sizeof_StackDelta, MaxEntries: 1 << mapID, }) if err != nil { @@ -639,18 +630,18 @@ func (impl *ebpfMapsImpl) UpdateExeIDToStackDeltas(fileID host.FileID, deltas [] if impl.hasGenericBatchOperations { innerKeys := make([]uint32, numDeltas) - stackDeltas := make([]C.StackDelta, numDeltas) + stackDeltas := make([]support.StackDelta, numDeltas) // Prepare values for batch update. for index, delta := range deltas { innerKeys[index] = uint32(index) - stackDeltas[index].addrLow = C.uint16_t(delta.AddressLow) - stackDeltas[index].unwindInfo = C.uint16_t(delta.UnwindInfo) + stackDeltas[index].AddrLow = delta.AddressLow + stackDeltas[index].UnwindInfo = delta.UnwindInfo } _, err := innerMap.BatchUpdate( ptrCastMarshaler[uint32](innerKeys), - ptrCastMarshaler[C.StackDelta](stackDeltas), + ptrCastMarshaler[support.StackDelta](stackDeltas), &cebpf.BatchOptions{Flags: uint64(cebpf.UpdateAny)}) if err != nil { return 0, impl.trackMapError(metrics.IDExeIDToStackDeltasBatchUpdate, @@ -662,10 +653,10 @@ func (impl *ebpfMapsImpl) UpdateExeIDToStackDeltas(fileID host.FileID, deltas [] } innerKey := uint32(0) - stackDelta := C.StackDelta{} + stackDelta := support.StackDelta{} for index, delta := range deltas { - stackDelta.addrLow = C.uint16_t(delta.AddressLow) - stackDelta.unwindInfo = C.uint16_t(delta.UnwindInfo) + stackDelta.AddrLow = delta.AddressLow + stackDelta.UnwindInfo = delta.UnwindInfo innerKey = uint32(index) if err := innerMap.Update(unsafe.Pointer(&innerKey), unsafe.Pointer(&stackDelta), cebpf.UpdateAny); err != nil { @@ -697,28 +688,28 @@ func (impl *ebpfMapsImpl) DeleteExeIDToStackDeltas(fileID host.FileID, mapID uin func (impl *ebpfMapsImpl) UpdateStackDeltaPages(fileID host.FileID, numDeltasPerPage []uint16, mapID uint16, firstPageAddr uint64) error { firstDelta := uint32(0) - keys := make([]C.StackDeltaPageKey, len(numDeltasPerPage)) - values := make([]C.StackDeltaPageInfo, len(numDeltasPerPage)) + keys := make([]support.StackDeltaPageKey, len(numDeltasPerPage)) + values := make([]support.StackDeltaPageInfo, len(numDeltasPerPage)) // Prepare the key/value combinations that will be loaded. for pageNumber, numDeltas := range numDeltasPerPage { pageAddr := firstPageAddr + uint64(pageNumber)<0CuI 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 nIq<^H?4YWSXS?cDXhIHF-Y delta 34172 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 diff --git a/support/ebpf/tracer.ebpf.arm64 b/support/ebpf/tracer.ebpf.arm64 index cec5790421e3b69c6888f90ad1411647c85ca139..bae7df19160f530d5630f8234528fef2b68f4dca 100644 GIT binary patch delta 34544 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 B2Ydhk diff --git a/support/ebpf/types.h b/support/ebpf/types.h index c9e3cbf8c..2d2d5eb60 100644 --- a/support/ebpf/types.h +++ b/support/ebpf/types.h @@ -8,10 +8,10 @@ // ID values used as index to maps/metrics array. // If you add enums below please update the following places too: -// - The host agent ebpf metricID to DB IDMetric translation table in: -// tracer/tracer.go/(StartMapMonitors). -// - The ebpf userland test code metricID stringification table in: -// support/ebpf/tests/tostring.c +// - The actual metric knob in: +// metrics/metrics.json +// - The mapping of this enum to the metric in Go: +// support/types_def.go enum { // number of calls to interpreter unwinding in get_next_interpreter() metricID_UnwindCallInterpreter = 0, @@ -533,8 +533,8 @@ typedef struct __attribute__((packed)) ApmCorrelationBuf { #define CUSTOM_LABEL_MAX_VAL_LEN 48 typedef struct CustomLabel { - char key[CUSTOM_LABEL_MAX_KEY_LEN]; - char val[CUSTOM_LABEL_MAX_VAL_LEN]; + u8 key[CUSTOM_LABEL_MAX_KEY_LEN]; + u8 val[CUSTOM_LABEL_MAX_VAL_LEN]; } CustomLabel; #define MAX_CUSTOM_LABELS 10 @@ -555,7 +555,7 @@ typedef struct Trace { // Monotonic kernel time in nanosecond precision. u64 ktime; // The current COMM of the thread of this Trace. - char comm[COMM_LEN]; + u8 comm[COMM_LEN]; // APM transaction ID or all-zero if not present. ApmSpanID apm_transaction_id; // APM trace ID or all-zero if not present. diff --git a/support/ebpf/v8_tracer.ebpf.c b/support/ebpf/v8_tracer.ebpf.c index 29b0e7004..615708029 100644 --- a/support/ebpf/v8_tracer.ebpf.c +++ b/support/ebpf/v8_tracer.ebpf.c @@ -54,10 +54,10 @@ static EBPF_INLINE ErrorCode push_v8( // Verify a V8 tagged pointer static EBPF_INLINE uintptr_t v8_verify_pointer(uintptr_t maybe_pointer) { - if ((maybe_pointer & HeapObjectTagMask) != HeapObjectTag) { + if ((maybe_pointer & V8_HeapObjectTagMask) != V8_HeapObjectTag) { return 0; } - return maybe_pointer & ~HeapObjectTagMask; + return maybe_pointer & ~V8_HeapObjectTagMask; } // Read and verify a V8 tagged pointer from given memory location. @@ -75,10 +75,10 @@ static EBPF_INLINE uintptr_t v8_read_object_ptr(uintptr_t addr) // Returns the SMI value, or def_value in case of errors. static EBPF_INLINE uintptr_t v8_parse_smi(uintptr_t maybe_smi, uintptr_t def_value) { - if ((maybe_smi & SmiTagMask) != SmiTag) { + if ((maybe_smi & V8_SmiTagMask) != V8_SmiTag) { return def_value; } - return maybe_smi >> SmiValueShift; + return maybe_smi >> V8_SmiValueShift; } // Read the type tag of a Heap Object at given memory location. @@ -135,10 +135,10 @@ static EBPF_INLINE ErrorCode unwind_one_v8_frame(PerCPURecord *record, V8ProcInf // Before V8 5.8.261 the frame marker was a SMI. Now it has the tag, but it's not shifted fully. // The special coding was done to reduce the frame marker push to . - if ((fp_marker & SmiTagMask) == SmiTag) { + if ((fp_marker & V8_SmiTagMask) == V8_SmiTag) { // Shift with the tag length only (shift on normal SMI is different). pointer_and_type = V8_FILE_TYPE_MARKER; - delta_or_marker = fp_marker >> SmiTagShift; + delta_or_marker = fp_marker >> V8_SmiTagShift; DEBUG_PRINT("v8: -> stub frame, tag %ld", delta_or_marker); goto frame_done; } diff --git a/support/ebpf/v8_tracer.h b/support/ebpf/v8_tracer.h index b88b49593..54093beb7 100644 --- a/support/ebpf/v8_tracer.h +++ b/support/ebpf/v8_tracer.h @@ -4,17 +4,17 @@ // They are unlikely to change, and likely require larger modifications on change. // https://chromium.googlesource.com/v8/v8.git/+/refs/heads/9.2.230/include/v8-internal.h#52 -#define SmiTag 0x0 +#define V8_SmiTag 0x0 // https://chromium.googlesource.com/v8/v8.git/+/refs/heads/9.2.230/include/v8-internal.h#54 -#define SmiTagMask 0x1 +#define V8_SmiTagMask 0x1 // https://chromium.googlesource.com/v8/v8.git/+/refs/heads/9.2.230/include/v8-internal.h#91 -#define SmiTagShift 1 +#define V8_SmiTagShift 1 // https://chromium.googlesource.com/v8/v8.git/+/refs/heads/9.2.230/include/v8-internal.h#98 -#define SmiValueShift 32 +#define V8_SmiValueShift 32 // https://chromium.googlesource.com/v8/v8.git/+/refs/heads/9.2.230/include/v8-internal.h#39 -#define HeapObjectTag 0x1 +#define V8_HeapObjectTag 0x1 // https://chromium.googlesource.com/v8/v8.git/+/refs/heads/9.2.230/include/v8-internal.h#42 -#define HeapObjectTagMask 0x3 +#define V8_HeapObjectTagMask 0x3 // The Trace 'file' field is split to object pointer (aligned to 8 bytes), // and the zero bits due to alignment are re-used as the following flags. diff --git a/support/types.go b/support/types.go index e21b8fc53..491e83f36 100644 --- a/support/types.go +++ b/support/types.go @@ -6,6 +6,10 @@ package support // import "go.opentelemetry.io/ebpf-profiler/support" +import ( + "go.opentelemetry.io/ebpf-profiler/metrics" +) + const ( FrameMarkerUnknown = 0x0 FrameMarkerErrorBit = 0x80 @@ -85,12 +89,132 @@ const ( TraceOriginOffCPU = 0x2 ) +type ApmSpanID [8]byte +type ApmTraceID [16]byte +type CustomLabel struct { + Key [16]uint8 + Val [48]uint8 +} +type CustomLabelsArray struct { + Len uint32 + Labels [10]CustomLabel +} +type Event struct { + Type uint32 +} +type Frame struct { + File_id uint64 + Addr_or_line uint64 + Kind uint8 + Return_address uint8 + Pad [6]uint8 +} +type OffsetRange struct { + Lower_offset1 uint64 + Upper_offset1 uint64 + Lower_offset2 uint64 + Upper_offset2 uint64 + Program_index uint16 + Pad_cgo_0 [6]byte +} +type PIDPage struct { + PrefixLen uint32 + Pid uint32 + Page uint64 +} +type PIDPageMappingInfo struct { + File_id uint64 + Bias_and_unwind_program uint64 +} +type StackDelta struct { + AddrLow uint16 + UnwindInfo uint16 +} +type StackDeltaPageInfo struct { + FirstDelta uint32 + NumDeltas uint16 + MapID uint16 +} +type StackDeltaPageKey struct { + FileID uint64 + Page uint64 +} +type SystemAnalysis struct { + Address uint64 + Pid uint32 + Code [128]uint8 + Pad_cgo_0 [4]byte +} +type SystemConfig struct { + Inverse_pac_mask uint64 + Tpbase_offset uint64 + Task_stack_offset uint32 + Stack_ptregs_offset uint32 + Off_cpu_threshold uint32 + Drop_error_only_traces bool + Pad_cgo_0 [3]byte +} +type TSDInfo struct { + Offset int16 + Multiplier uint8 + Indirect uint8 +} +type Trace struct { + Pid uint32 + Tid uint32 + Ktime uint64 + Comm [16]uint8 + Apm_transaction_id [8]byte + Apm_trace_id [16]byte + Custom_labels CustomLabelsArray + Kernel_stack_id int32 + Stack_len uint32 + Origin uint32 + Offtime uint64 + Frames [128]Frame +} +type UnwindInfo struct { + Opcode uint8 + FpOpcode uint8 + MergeOpcode uint8 + Param int32 + FpParam int32 +} + type ApmIntProcInfo struct { Offset uint64 } type DotnetProcInfo struct { Version uint32 } +type GoLabelsOffsets struct { + M_offset uint32 + Curg uint32 + Labels uint32 + Hmap_count uint32 + Hmap_log2_bucket_count uint32 + Hmap_buckets uint32 + Tls_offset int32 +} +type HotspotProcInfo struct { + Codecache_start uint64 + Codecache_end uint64 + Nmethod_deopt_offset uint16 + Nmethod_compileid uint16 + Nmethod_orig_pc_offset uint16 + Codeblob_name uint8 + Codeblob_codestart uint8 + Codeblob_codeend uint8 + Codeblob_framecomplete uint8 + Codeblob_framesize uint8 + Heapblock_size uint8 + Method_constmethod uint8 + Cmethod_size uint8 + Jvm_version uint8 + Segment_shift uint8 + Nmethod_uses_offsets uint8 + Pad_cgo_0 [7]byte +} type PHPProcInfo struct { Current_execute_data uint64 Jit_return_address uint64 @@ -102,6 +226,48 @@ type PHPProcInfo struct { Zend_op_lineno uint8 Pad_cgo_0 [2]byte } +type PerlProcInfo struct { + StateAddr uint64 + Version uint32 + TsdInfo TSDInfo + Interpreter_curcop uint16 + Interpreter_curstackinfo uint16 + StateInTSD uint8 + Si_cxstack uint8 + Si_next uint8 + Si_cxix uint8 + Si_type uint8 + Context_type uint8 + Context_blk_oldcop uint8 + Context_blk_sub_retop uint8 + Context_blk_sub_cv uint8 + Context_sizeof uint8 + Sv_flags uint8 + Sv_any uint8 + Svu_gp uint8 + Xcv_flags uint8 + Xcv_gv uint8 + Gp_egv uint8 + Pad_cgo_0 [4]byte +} +type PyProcInfo struct { + AutoTLSKeyAddr uint64 + Version uint16 + TsdInfo TSDInfo + PyThreadState_frame uint8 + PyCFrame_current_frame uint8 + PyFrameObject_f_back uint8 + PyFrameObject_f_code uint8 + PyFrameObject_f_lasti uint8 + PyFrameObject_entry_member uint8 + PyFrameObject_entry_val uint8 + PyCodeObject_co_argcount uint8 + PyCodeObject_co_kwonlyargcount uint8 + PyCodeObject_co_flags uint8 + PyCodeObject_co_firstlineno uint8 + PyCodeObject_sizeof uint8 + Pad_cgo_0 [6]byte +} type RubyProcInfo struct { Version uint32 Current_ctx_ptr uint64 @@ -120,8 +286,33 @@ type RubyProcInfo struct { Running_ec uint16 Pad_cgo_0 [2]byte } +type V8ProcInfo struct { + Version uint32 + Type_JSFunction_first uint16 + Type_JSFunction_last uint16 + Type_Code uint16 + Type_SharedFunctionInfo uint16 + Off_HeapObject_map uint8 + Off_Map_instancetype uint8 + Off_JSFunction_code uint8 + Off_JSFunction_shared uint8 + Off_Code_instruction_start uint8 + Off_Code_instruction_size uint8 + Off_Code_flags uint8 + Fp_marker uint8 + Fp_function uint8 + Fp_bytecode_offset uint8 + Codekind_shift uint8 + Codekind_mask uint8 + Codekind_baseline uint8 + Pad_cgo_0 [3]byte +} const ( + Sizeof_Frame = 0x18 + Sizeof_StackDelta = 0x4 + Sizeof_Trace = 0xed0 + sizeof_ApmIntProcInfo = 0x8 sizeof_DotnetProcInfo = 0x4 sizeof_PHPProcInfo = 0x18 @@ -146,3 +337,123 @@ const ( UnwindDerefMask int32 = 0x7 UnwindDerefMultiplier int32 = 0x8 ) + +const ( + FrameHotspotStub = 0x0 + FrameHotspotVtable = 0x1 + FrameHotspotInterpreter = 0x2 + FrameHotspotNative = 0x3 + + V8SmiTag = 0x0 + V8SmiTagMask = 0x1 + V8SmiTagShift = 0x1 + V8SmiValueShift = 0x20 + V8HeapObjectTag = 0x1 + V8HeapObjectTagMask = 0x3 + + V8FpContextSize = 0x40 + + V8FileTypeMarker = 0x0 + V8FileTypeByteCode = 0x1 + V8FileTypeNativeSFI = 0x2 + V8FileTypeNativeCode = 0x3 + V8FileTypeNativeJSFunc = 0x4 + V8FileTypeMask = 0x7 + + V8LineCookieShift = 0x20 + V8LineCookieMask = 0xffffffff00000000 + V8LineDeltaMask = 0xffffffff +) + +var MetricsTranslation = []metrics.MetricID{ + 0x0: metrics.IDUnwindCallInterpreter, + 0x1: metrics.IDUnwindErrZeroPC, + 0x2: metrics.IDUnwindErrStackLengthExceeded, + 0x3: metrics.IDUnwindErrBadTLSAddr, + 0x4: metrics.IDUnwindErrBadTPBaseAddr, + 0x5: metrics.IDUnwindNativeAttempts, + 0x6: metrics.IDUnwindNativeFrames, + 0x7: metrics.IDUnwindNativeStackDeltaStop, + 0x8: metrics.IDUnwindNativeErrLookupTextSection, + 0x9: metrics.IDUnwindNativeErrLookupIterations, + 0xa: metrics.IDUnwindNativeErrLookupRange, + 0xb: metrics.IDUnwindNativeErrKernelAddress, + 0xc: metrics.IDUnwindNativeErrWrongTextSection, + 0xe: metrics.IDUnwindNativeErrPCRead, + 0x15: metrics.IDUnwindPythonAttempts, + 0x16: metrics.IDUnwindPythonFrames, + 0x17: metrics.IDUnwindPythonErrBadPyThreadStateCurrentAddr, + 0x18: metrics.IDUnwindPythonErrZeroThreadState, + 0x19: metrics.IDUnwindPythonErrBadThreadStateFrameAddr, + 0x1c: metrics.IDUnwindPythonZeroFrameCodeObject, + 0x1e: metrics.IDUnwindPythonErrBadCodeObjectArgCountAddr, + 0xd: metrics.IDUnwindNativeErrStackDeltaInvalid, + 0x28: metrics.IDErrEmptyStack, + 0x29: metrics.IDUnwindHotspotAttempts, + 0x2a: metrics.IDUnwindHotspotFrames, + 0x2b: metrics.IDUnwindHotspotErrNoCodeblob, + 0x2c: metrics.IDUnwindHotspotErrInvalidCodeblob, + 0x2d: metrics.IDUnwindHotspotErrInterpreterFP, + 0x2f: metrics.IDUnwindHotspotErrLrUnwindingMidTrace, + 0x30: metrics.IDHotspotUnsupportedFrameSize, + 0x31: metrics.IDUnwindNativeSmallPC, + 0x32: metrics.IDUnwindNativeErrLookupStackDeltaInnerMap, + 0x33: metrics.IDUnwindNativeErrLookupStackDeltaOuterMap, + 0x34: metrics.IDErrBPFCurrentComm, + 0x22: metrics.IDUnwindPHPAttempts, + 0x23: metrics.IDUnwindPHPFrames, + 0x24: metrics.IDUnwindPHPErrBadCurrentExecuteData, + 0x25: metrics.IDUnwindPHPErrBadZendExecuteData, + 0x26: metrics.IDUnwindPHPErrBadZendFunction, + 0x27: metrics.IDUnwindPHPErrBadZendOpline, + 0x35: metrics.IDUnwindRubyAttempts, + 0x36: metrics.IDUnwindRubyFrames, + 0xf: metrics.IDUnwindPerlAttempts, + 0x10: metrics.IDUnwindPerlFrames, + 0x11: metrics.IDUnwindPerlTLS, + 0x12: metrics.IDUnwindPerlReadStackInfo, + 0x13: metrics.IDUnwindPerlReadContextStackEntry, + 0x14: metrics.IDUnwindPerlResolveEGV, + 0x2e: metrics.IDUnwindHotspotErrInvalidRA, + 0x37: metrics.IDUnwindV8Attempts, + 0x38: metrics.IDUnwindV8Frames, + 0x39: metrics.IDUnwindV8ErrBadFP, + 0x3a: metrics.IDUnwindV8ErrBadJSFunc, + 0x3b: metrics.IDUnwindV8ErrBadCode, + 0x3d: metrics.IDReportedPIDsErr, + 0x3e: metrics.IDPIDEventsErr, + 0x3c: metrics.IDUnwindNativeLr0, + 0x3f: metrics.IDNumProcNew, + 0x40: metrics.IDNumProcExit, + 0x41: metrics.IDNumUnknownPC, + 0x42: metrics.IDNumGenericPID, + 0x43: metrics.IDUnwindPythonErrBadCFrameFrameAddr, + 0x44: metrics.IDMaxTailCalls, + 0x45: metrics.IDUnwindPythonErrNoProcInfo, + 0x46: metrics.IDUnwindPythonErrBadAutoTlsKeyAddr, + 0x47: metrics.IDUnwindPythonErrReadThreadStateAddr, + 0x48: metrics.IDUnwindPythonErrReadTsdBase, + 0x49: metrics.IDUnwindRubyErrNoProcInfo, + 0x4a: metrics.IDUnwindRubyErrReadStackPtr, + 0x4b: metrics.IDUnwindRubyErrReadStackSize, + 0x4c: metrics.IDUnwindRubyErrReadCfp, + 0x4d: metrics.IDUnwindRubyErrReadEp, + 0x4e: metrics.IDUnwindRubyErrReadIseqBody, + 0x4f: metrics.IDUnwindRubyErrReadIseqEncoded, + 0x50: metrics.IDUnwindRubyErrReadIseqSize, + 0x51: metrics.IDUnwindNativeErrLrUnwindingMidTrace, + 0x52: metrics.IDUnwindNativeErrReadKernelModeRegs, + 0x53: metrics.IDUnwindNativeErrChaseIrqStackLink, + 0x54: metrics.IDUnwindV8ErrNoProcInfo, + 0x55: metrics.IDUnwindNativeErrBadUnwindInfoIndex, + 0x56: metrics.IDUnwindApmIntErrReadTsdBase, + 0x57: metrics.IDUnwindApmIntErrReadCorrBufPtr, + 0x58: metrics.IDUnwindApmIntErrReadCorrBuf, + 0x59: metrics.IDUnwindApmIntReadSuccesses, + 0x5a: metrics.IDUnwindDotnetAttempts, + 0x5b: metrics.IDUnwindDotnetFrames, + 0x5c: metrics.IDUnwindDotnetErrNoProcInfo, + 0x5d: metrics.IDUnwindDotnetErrBadFP, + 0x5e: metrics.IDUnwindDotnetErrCodeHeader, + 0x5f: metrics.IDUnwindDotnetErrCodeTooLarge, +} diff --git a/support/types_def.go b/support/types_def.go index a141a2340..51faf42ea 100644 --- a/support/types_def.go +++ b/support/types_def.go @@ -5,10 +5,15 @@ package support // import "go.opentelemetry.io/ebpf-profiler/support" +import ( + "go.opentelemetry.io/ebpf-profiler/metrics" +) + /* #include "./ebpf/types.h" #include "./ebpf/frametypes.h" #include "./ebpf/stackdeltatypes.h" +#include "./ebpf/v8_tracer.h" */ import "C" @@ -95,12 +100,39 @@ const ( TraceOriginOffCPU = C.TRACE_OFF_CPU ) +type ApmSpanID C.ApmSpanID +type ApmTraceID C.ApmTraceID +type CustomLabel C.CustomLabel +type CustomLabelsArray C.CustomLabelsArray +type Event C.Event +type Frame C.Frame +type OffsetRange C.OffsetRange +type PIDPage C.PIDPage +type PIDPageMappingInfo C.PIDPageMappingInfo +type StackDelta C.StackDelta +type StackDeltaPageInfo C.StackDeltaPageInfo +type StackDeltaPageKey C.StackDeltaPageKey +type SystemAnalysis C.SystemAnalysis +type SystemConfig C.SystemConfig +type TSDInfo C.TSDInfo +type Trace C.Trace +type UnwindInfo C.UnwindInfo + type ApmIntProcInfo C.ApmIntProcInfo type DotnetProcInfo C.DotnetProcInfo +type GoLabelsOffsets C.GoLabelsOffsets +type HotspotProcInfo C.HotspotProcInfo type PHPProcInfo C.PHPProcInfo +type PerlProcInfo C.PerlProcInfo +type PyProcInfo C.PyProcInfo type RubyProcInfo C.RubyProcInfo +type V8ProcInfo C.V8ProcInfo const ( + Sizeof_Frame = C.sizeof_Frame + Sizeof_StackDelta = C.sizeof_StackDelta + Sizeof_Trace = C.sizeof_Trace + sizeof_ApmIntProcInfo = C.sizeof_ApmIntProcInfo sizeof_DotnetProcInfo = C.sizeof_DotnetProcInfo sizeof_PHPProcInfo = C.sizeof_PHPProcInfo @@ -128,3 +160,125 @@ const ( UnwindDerefMask int32 = C.UNWIND_DEREF_MASK UnwindDerefMultiplier int32 = C.UNWIND_DEREF_MULTIPLIER ) + +const ( + // Hotspot specific + FrameHotspotStub = C.FRAME_HOTSPOT_STUB + FrameHotspotVtable = C.FRAME_HOTSPOT_VTABLE + FrameHotspotInterpreter = C.FRAME_HOTSPOT_INTERPRETER + FrameHotspotNative = C.FRAME_HOTSPOT_NATIVE + + // V8 specific + V8SmiTag = C.V8_SmiTag + V8SmiTagMask = C.V8_SmiTagMask + V8SmiTagShift = C.V8_SmiTagShift + V8SmiValueShift = C.V8_SmiValueShift + V8HeapObjectTag = C.V8_HeapObjectTag + V8HeapObjectTagMask = C.V8_HeapObjectTagMask + + V8FpContextSize = C.V8_FP_CONTEXT_SIZE + + V8FileTypeMarker = C.V8_FILE_TYPE_MARKER + V8FileTypeByteCode = C.V8_FILE_TYPE_BYTECODE + V8FileTypeNativeSFI = C.V8_FILE_TYPE_NATIVE_SFI + V8FileTypeNativeCode = C.V8_FILE_TYPE_NATIVE_CODE + V8FileTypeNativeJSFunc = C.V8_FILE_TYPE_NATIVE_JSFUNC + V8FileTypeMask = C.V8_FILE_TYPE_MASK + + V8LineCookieShift = C.V8_LINE_COOKIE_SHIFT + V8LineCookieMask = C.V8_LINE_COOKIE_MASK + V8LineDeltaMask = C.V8_LINE_DELTA_MASK +) + +var MetricsTranslation = []metrics.MetricID{ + C.metricID_UnwindCallInterpreter: metrics.IDUnwindCallInterpreter, + C.metricID_UnwindErrZeroPC: metrics.IDUnwindErrZeroPC, + C.metricID_UnwindErrStackLengthExceeded: metrics.IDUnwindErrStackLengthExceeded, + C.metricID_UnwindErrBadTSDAddr: metrics.IDUnwindErrBadTLSAddr, + C.metricID_UnwindErrBadTPBaseAddr: metrics.IDUnwindErrBadTPBaseAddr, + C.metricID_UnwindNativeAttempts: metrics.IDUnwindNativeAttempts, + C.metricID_UnwindNativeFrames: metrics.IDUnwindNativeFrames, + C.metricID_UnwindNativeStackDeltaStop: metrics.IDUnwindNativeStackDeltaStop, + C.metricID_UnwindNativeErrLookupTextSection: metrics.IDUnwindNativeErrLookupTextSection, + C.metricID_UnwindNativeErrLookupIterations: metrics.IDUnwindNativeErrLookupIterations, + C.metricID_UnwindNativeErrLookupRange: metrics.IDUnwindNativeErrLookupRange, + C.metricID_UnwindNativeErrKernelAddress: metrics.IDUnwindNativeErrKernelAddress, + C.metricID_UnwindNativeErrWrongTextSection: metrics.IDUnwindNativeErrWrongTextSection, + C.metricID_UnwindNativeErrPCRead: metrics.IDUnwindNativeErrPCRead, + C.metricID_UnwindPythonAttempts: metrics.IDUnwindPythonAttempts, + C.metricID_UnwindPythonFrames: metrics.IDUnwindPythonFrames, + C.metricID_UnwindPythonErrBadPyThreadStateCurrentAddr: metrics.IDUnwindPythonErrBadPyThreadStateCurrentAddr, + C.metricID_UnwindPythonErrZeroThreadState: metrics.IDUnwindPythonErrZeroThreadState, + C.metricID_UnwindPythonErrBadThreadStateFrameAddr: metrics.IDUnwindPythonErrBadThreadStateFrameAddr, + C.metricID_UnwindPythonZeroFrameCodeObject: metrics.IDUnwindPythonZeroFrameCodeObject, + C.metricID_UnwindPythonErrBadCodeObjectArgCountAddr: metrics.IDUnwindPythonErrBadCodeObjectArgCountAddr, + C.metricID_UnwindNativeErrStackDeltaInvalid: metrics.IDUnwindNativeErrStackDeltaInvalid, + C.metricID_ErrEmptyStack: metrics.IDErrEmptyStack, + C.metricID_UnwindHotspotAttempts: metrics.IDUnwindHotspotAttempts, + C.metricID_UnwindHotspotFrames: metrics.IDUnwindHotspotFrames, + C.metricID_UnwindHotspotErrNoCodeblob: metrics.IDUnwindHotspotErrNoCodeblob, + C.metricID_UnwindHotspotErrInvalidCodeblob: metrics.IDUnwindHotspotErrInvalidCodeblob, + C.metricID_UnwindHotspotErrInterpreterFP: metrics.IDUnwindHotspotErrInterpreterFP, + C.metricID_UnwindHotspotErrLrUnwindingMidTrace: metrics.IDUnwindHotspotErrLrUnwindingMidTrace, + C.metricID_UnwindHotspotUnsupportedFrameSize: metrics.IDHotspotUnsupportedFrameSize, + C.metricID_UnwindNativeSmallPC: metrics.IDUnwindNativeSmallPC, + C.metricID_UnwindNativeErrLookupStackDeltaInnerMap: metrics.IDUnwindNativeErrLookupStackDeltaInnerMap, + C.metricID_UnwindNativeErrLookupStackDeltaOuterMap: metrics.IDUnwindNativeErrLookupStackDeltaOuterMap, + C.metricID_ErrBPFCurrentComm: metrics.IDErrBPFCurrentComm, + C.metricID_UnwindPHPAttempts: metrics.IDUnwindPHPAttempts, + C.metricID_UnwindPHPFrames: metrics.IDUnwindPHPFrames, + C.metricID_UnwindPHPErrBadCurrentExecuteData: metrics.IDUnwindPHPErrBadCurrentExecuteData, + C.metricID_UnwindPHPErrBadZendExecuteData: metrics.IDUnwindPHPErrBadZendExecuteData, + C.metricID_UnwindPHPErrBadZendFunction: metrics.IDUnwindPHPErrBadZendFunction, + C.metricID_UnwindPHPErrBadZendOpline: metrics.IDUnwindPHPErrBadZendOpline, + C.metricID_UnwindRubyAttempts: metrics.IDUnwindRubyAttempts, + C.metricID_UnwindRubyFrames: metrics.IDUnwindRubyFrames, + C.metricID_UnwindPerlAttempts: metrics.IDUnwindPerlAttempts, + C.metricID_UnwindPerlFrames: metrics.IDUnwindPerlFrames, + C.metricID_UnwindPerlTSD: metrics.IDUnwindPerlTLS, + C.metricID_UnwindPerlReadStackInfo: metrics.IDUnwindPerlReadStackInfo, + C.metricID_UnwindPerlReadContextStackEntry: metrics.IDUnwindPerlReadContextStackEntry, + C.metricID_UnwindPerlResolveEGV: metrics.IDUnwindPerlResolveEGV, + C.metricID_UnwindHotspotErrInvalidRA: metrics.IDUnwindHotspotErrInvalidRA, + C.metricID_UnwindV8Attempts: metrics.IDUnwindV8Attempts, + C.metricID_UnwindV8Frames: metrics.IDUnwindV8Frames, + C.metricID_UnwindV8ErrBadFP: metrics.IDUnwindV8ErrBadFP, + C.metricID_UnwindV8ErrBadJSFunc: metrics.IDUnwindV8ErrBadJSFunc, + C.metricID_UnwindV8ErrBadCode: metrics.IDUnwindV8ErrBadCode, + C.metricID_ReportedPIDsErr: metrics.IDReportedPIDsErr, + C.metricID_PIDEventsErr: metrics.IDPIDEventsErr, + C.metricID_UnwindNativeLr0: metrics.IDUnwindNativeLr0, + C.metricID_NumProcNew: metrics.IDNumProcNew, + C.metricID_NumProcExit: metrics.IDNumProcExit, + C.metricID_NumUnknownPC: metrics.IDNumUnknownPC, + C.metricID_NumGenericPID: metrics.IDNumGenericPID, + C.metricID_UnwindPythonErrBadCFrameFrameAddr: metrics.IDUnwindPythonErrBadCFrameFrameAddr, + C.metricID_MaxTailCalls: metrics.IDMaxTailCalls, + C.metricID_UnwindPythonErrNoProcInfo: metrics.IDUnwindPythonErrNoProcInfo, + C.metricID_UnwindPythonErrBadAutoTlsKeyAddr: metrics.IDUnwindPythonErrBadAutoTlsKeyAddr, + C.metricID_UnwindPythonErrReadThreadStateAddr: metrics.IDUnwindPythonErrReadThreadStateAddr, + C.metricID_UnwindPythonErrReadTsdBase: metrics.IDUnwindPythonErrReadTsdBase, + C.metricID_UnwindRubyErrNoProcInfo: metrics.IDUnwindRubyErrNoProcInfo, + C.metricID_UnwindRubyErrReadStackPtr: metrics.IDUnwindRubyErrReadStackPtr, + C.metricID_UnwindRubyErrReadStackSize: metrics.IDUnwindRubyErrReadStackSize, + C.metricID_UnwindRubyErrReadCfp: metrics.IDUnwindRubyErrReadCfp, + C.metricID_UnwindRubyErrReadEp: metrics.IDUnwindRubyErrReadEp, + C.metricID_UnwindRubyErrReadIseqBody: metrics.IDUnwindRubyErrReadIseqBody, + C.metricID_UnwindRubyErrReadIseqEncoded: metrics.IDUnwindRubyErrReadIseqEncoded, + C.metricID_UnwindRubyErrReadIseqSize: metrics.IDUnwindRubyErrReadIseqSize, + C.metricID_UnwindNativeErrLrUnwindingMidTrace: metrics.IDUnwindNativeErrLrUnwindingMidTrace, + C.metricID_UnwindNativeErrReadKernelModeRegs: metrics.IDUnwindNativeErrReadKernelModeRegs, + C.metricID_UnwindNativeErrChaseIrqStackLink: metrics.IDUnwindNativeErrChaseIrqStackLink, + C.metricID_UnwindV8ErrNoProcInfo: metrics.IDUnwindV8ErrNoProcInfo, + C.metricID_UnwindNativeErrBadUnwindInfoIndex: metrics.IDUnwindNativeErrBadUnwindInfoIndex, + C.metricID_UnwindApmIntErrReadTsdBase: metrics.IDUnwindApmIntErrReadTsdBase, + C.metricID_UnwindApmIntErrReadCorrBufPtr: metrics.IDUnwindApmIntErrReadCorrBufPtr, + C.metricID_UnwindApmIntErrReadCorrBuf: metrics.IDUnwindApmIntErrReadCorrBuf, + C.metricID_UnwindApmIntReadSuccesses: metrics.IDUnwindApmIntReadSuccesses, + C.metricID_UnwindDotnetAttempts: metrics.IDUnwindDotnetAttempts, + C.metricID_UnwindDotnetFrames: metrics.IDUnwindDotnetFrames, + C.metricID_UnwindDotnetErrNoProcInfo: metrics.IDUnwindDotnetErrNoProcInfo, + C.metricID_UnwindDotnetErrBadFP: metrics.IDUnwindDotnetErrBadFP, + C.metricID_UnwindDotnetErrCodeHeader: metrics.IDUnwindDotnetErrCodeHeader, + C.metricID_UnwindDotnetErrCodeTooLarge: metrics.IDUnwindDotnetErrCodeTooLarge, +} diff --git a/tracer/events.go b/tracer/events.go index a574d5e8d..dbc1ca0f6 100644 --- a/tracer/events.go +++ b/tracer/events.go @@ -22,12 +22,6 @@ import ( "go.opentelemetry.io/ebpf-profiler/times" ) -/* -#include -#include "../support/ebpf/types.h" -*/ -import "C" - const ( // Length of the pidEvents channel. It must be large enough so the // consuming goroutine doesn't go idle due to scheduling, but small enough @@ -73,8 +67,8 @@ func (t *Tracer) handleGenericPID() { // C structure in the received data is transformed to a Go structure and the event // handler is invoked. func (t *Tracer) triggerPidEvent(data []byte) { - event := (*C.Event)(unsafe.Pointer(&data[0])) - if event.event_type == support.EventTypeGenericPID { + event := (*support.Event)(unsafe.Pointer(&data[0])) + if event.Type == support.EventTypeGenericPID { t.handleGenericPID() } } @@ -137,7 +131,7 @@ func (t *Tracer) startTraceEventMonitor(ctx context.Context, traceOutChan chan<- *host.Trace) func() []metrics.Metric { eventsMap := t.ebpfMaps["trace_events"] eventReader, err := perf.NewReader(eventsMap, - t.samplesPerSecond*int(unsafe.Sizeof(C.Trace{}))) + t.samplesPerSecond*support.Sizeof_Trace) if err != nil { log.Fatalf("Failed to setup perf reporting via %s: %v", eventsMap, err) } diff --git a/tracer/systemconfig.go b/tracer/systemconfig.go index d2d63a2d8..a568f9012 100644 --- a/tracer/systemconfig.go +++ b/tracer/systemconfig.go @@ -16,6 +16,7 @@ import ( "go.opentelemetry.io/ebpf-profiler/libpf" "go.opentelemetry.io/ebpf-profiler/pacmask" "go.opentelemetry.io/ebpf-profiler/rlimit" + "go.opentelemetry.io/ebpf-profiler/support" "go.opentelemetry.io/ebpf-profiler/tracer/types" cebpf "github.com/cilium/ebpf" @@ -24,9 +25,6 @@ import ( log "github.com/sirupsen/logrus" ) -// #include "../support/ebpf/types.h" -import "C" - // memberByName resolves btf Member from a Struct with given name func memberByName(t *btf.Struct, field string) (*btf.Member, error) { for i, m := range t.Members { @@ -72,7 +70,7 @@ func getTSDBaseFieldSpec() string { } // parseBTF resolves the SystemConfig data from kernel BTF -func parseBTF(syscfg *C.SystemConfig) error { +func parseBTF(syscfg *support.SystemConfig) error { fh, err := os.Open("/sys/kernel/btf/vmlinux") if err != nil { return err @@ -94,13 +92,13 @@ func parseBTF(syscfg *C.SystemConfig) error { if err != nil { return err } - syscfg.task_stack_offset = C.u32(stackOffset) + syscfg.Task_stack_offset = uint32(stackOffset) tpbaseOffset, err := calculateFieldOffset(taskStruct, getTSDBaseFieldSpec()) if err != nil { return err } - syscfg.tpbase_offset = C.u64(tpbaseOffset) + syscfg.Tpbase_offset = uint64(tpbaseOffset) return nil } @@ -111,9 +109,9 @@ func executeSystemAnalysisBpfCode(progSpec *cebpf.ProgramSpec, maps map[string]* systemAnalysis := maps["system_analysis"] key0 := uint32(0) - data := C.SystemAnalysis{ - pid: C.uint(os.Getpid()), - address: C.u64(address), + data := support.SystemAnalysis{ + Pid: uint32(os.Getpid()), + Address: uint64(address), } if err = systemAnalysis.Update(unsafe.Pointer(&key0), unsafe.Pointer(&data), @@ -152,14 +150,13 @@ func executeSystemAnalysisBpfCode(progSpec *cebpf.ProgramSpec, maps map[string]* return nil, 0, fmt.Errorf("failed to configure tracepoint: %v", err) } err = systemAnalysis.Lookup(unsafe.Pointer(&key0), unsafe.Pointer(&data)) - progLink.Close() + _ = progLink.Close() if err != nil { return nil, 0, fmt.Errorf("failed to get analysis data: %v", err) } - //nolint:gocritic - return C.GoBytes(unsafe.Pointer(&data.code[0]), C.int(len(data.code))), - uint64(data.address), nil + return unsafe.Slice(unsafe.SliceData(data.Code[:]), len(data.Code)), + data.Address, nil } // loadKernelCode will request the ebpf code to read the first X bytes from given address. @@ -183,20 +180,20 @@ func readTaskStruct(coll *cebpf.CollectionSpec, maps map[string]*cebpf.Map, // determineStackPtregs determines the offset of `struct pt_regs` within the entry stack // when the `stack` field offset within `task_struct` is already known. func determineStackPtregs(coll *cebpf.CollectionSpec, maps map[string]*cebpf.Map, - syscfg *C.SystemConfig) error { - data, ptregs, err := readTaskStruct(coll, maps, libpf.SymbolValue(syscfg.task_stack_offset)) + syscfg *support.SystemConfig) error { + data, ptregs, err := readTaskStruct(coll, maps, libpf.SymbolValue(syscfg.Task_stack_offset)) if err != nil { return err } stackBase := binary.LittleEndian.Uint64(data) - syscfg.stack_ptregs_offset = C.u32(ptregs - stackBase) + syscfg.Stack_ptregs_offset = uint32(ptregs - stackBase) return nil } // determineStackLayout scans `task_struct` for offset of the `stack` field, and using // its value determines the offset of `struct pt_regs` within the entry stack. func determineStackLayout(coll *cebpf.CollectionSpec, maps map[string]*cebpf.Map, - syscfg *C.SystemConfig) error { + syscfg *support.SystemConfig) error { const maxTaskStructSize = 8 * 1024 const maxStackSize = 64 * 1024 @@ -215,8 +212,8 @@ func determineStackLayout(coll *cebpf.CollectionSpec, maps map[string]*cebpf.Map continue } if ptregs > stackBase && ptregs < stackBase+maxStackSize { - syscfg.task_stack_offset = C.u32(offs + i) - syscfg.stack_ptregs_offset = C.u32(ptregs - stackBase) + syscfg.Task_stack_offset = uint32(offs + i) + syscfg.Stack_ptregs_offset = uint32(ptregs - stackBase) return nil } } @@ -234,10 +231,10 @@ func loadSystemConfig(coll *cebpf.CollectionSpec, maps map[string]*cebpf.Map, } else { log.Debug("PAC is not enabled on the system.") } - syscfg := C.SystemConfig{ - inverse_pac_mask: ^C.u64(pacMask), - drop_error_only_traces: C.bool(filterErrorFrames), - off_cpu_threshold: C.u32(offCPUThreshold), + syscfg := support.SystemConfig{ + Inverse_pac_mask: ^pacMask, + Drop_error_only_traces: filterErrorFrames, + Off_cpu_threshold: offCPUThreshold, } if err := parseBTF(&syscfg); err != nil { @@ -254,7 +251,7 @@ func loadSystemConfig(coll *cebpf.CollectionSpec, maps map[string]*cebpf.Map, if err != nil { return err } - syscfg.tpbase_offset = C.u64(tpbaseOffset) + syscfg.Tpbase_offset = tpbaseOffset } } else { // Sadly BTF does not currently include THREAD_SIZE which is needed @@ -267,9 +264,9 @@ func loadSystemConfig(coll *cebpf.CollectionSpec, maps map[string]*cebpf.Map, } log.Infof("Found offsets: task stack %#x, pt_regs %#x, tpbase %#x", - syscfg.task_stack_offset, - syscfg.stack_ptregs_offset, - syscfg.tpbase_offset) + syscfg.Task_stack_offset, + syscfg.Stack_ptregs_offset, + syscfg.Tpbase_offset) key0 := uint32(0) return maps["system_config"].Update(unsafe.Pointer(&key0), unsafe.Pointer(&syscfg), diff --git a/tracer/tracer.go b/tracer/tracer.go index 00ea5058f..bef290fa0 100644 --- a/tracer/tracer.go +++ b/tracer/tracer.go @@ -40,12 +40,6 @@ import ( "go.opentelemetry.io/ebpf-profiler/tracer/types" ) -/* -#include -#include "../support/ebpf/types.h" -*/ -import "C" - // Compile time check to make sure config.Times satisfies the interfaces. var _ Intervals = (*times.Times)(nil) @@ -169,6 +163,18 @@ type progLoaderHelper struct { noTailCallTarget bool } +// Convert a C-string to Go string +func goString(p unsafe.Pointer, maxLen int) string { + ptr := uintptr(p) + length := 0 + for ; length < maxLen; length++ { + if *(*byte)(unsafe.Pointer(ptr + uintptr(length))) == 0 { + break + } + } + return strings.Clone(unsafe.String((*byte)(p), length)) +} + // NewTracer loads eBPF code and map definitions from the ELF module at the configured path. func NewTracer(ctx context.Context, cfg *Config) (*Tracer, error) { kernelSymbolizer, err := kallsyms.NewSymbolizer() @@ -201,8 +207,6 @@ func NewTracer(ctx context.Context, cfg *Config) (*Tracer, error) { return nil, fmt.Errorf("failed to create processManager: %v", err) } - const fallbackSymbolsCacheSize = 16384 - perfEventList := []*perf.Event{} tracer := &Tracer{ @@ -262,8 +266,8 @@ func buildStackDeltaTemplates(coll *cebpf.CollectionSpec) error { } def.InnerMap = &cebpf.MapSpec{ Type: cebpf.Array, - KeySize: uint32(C.sizeof_uint32_t), - ValueSize: uint32(C.sizeof_StackDelta), + KeySize: 4, + ValueSize: support.Sizeof_StackDelta, MaxEntries: 1 << i, } } @@ -666,8 +670,8 @@ func loadProgram(ebpfProgs map[string]*cebpf.Program, tailcallMap *cebpf.Map, // It returns the number of kernel frames for kstackID or an error. func (t *Tracer) insertKernelFrames(trace *host.Trace, ustackLen uint32, kstackID int32) (uint32, error) { - cKstackID := C.s32(kstackID) - kstackVal := make([]C.uint64_t, support.PerfMaxStackDepth) + cKstackID := kstackID + kstackVal := make([]uint64, support.PerfMaxStackDepth) if err := t.ebpfMaps["kernel_stackmap"].Lookup(unsafe.Pointer(&cKstackID), unsafe.Pointer(&kstackVal[0])); err != nil { @@ -874,34 +878,34 @@ func (t *Tracer) eBPFMetricsCollector( // If the raw trace contains a kernel stack ID, the kernel stack is also // retrieved and inserted at the appropriate position. func (t *Tracer) loadBpfTrace(raw []byte, cpu int) *host.Trace { - frameListOffs := int(unsafe.Offsetof(C.Trace{}.frames)) + frameListOffs := int(unsafe.Offsetof(support.Trace{}.Frames)) if len(raw) < frameListOffs { panic("trace record too small") } - frameSize := int(unsafe.Sizeof(C.Frame{})) - ptr := (*C.Trace)(unsafe.Pointer(unsafe.SliceData(raw))) + frameSize := support.Sizeof_Frame + ptr := (*support.Trace)(unsafe.Pointer(unsafe.SliceData(raw))) // NOTE: can't do exact check here: kernel adds a few padding bytes to messages. - if len(raw) < frameListOffs+int(ptr.stack_len)*frameSize { + if len(raw) < frameListOffs+int(ptr.Stack_len)*frameSize { panic("unexpected record size") } - pid := libpf.PID(ptr.pid) + pid := libpf.PID(ptr.Pid) procMeta := t.processManager.MetaForPID(pid) trace := &host.Trace{ - Comm: C.GoString((*C.char)(unsafe.Pointer(&ptr.comm))), + Comm: goString(unsafe.Pointer(&ptr.Comm), len(ptr.Comm)), ExecutablePath: procMeta.Executable, ContainerID: procMeta.ContainerID, ProcessName: procMeta.Name, - APMTraceID: *(*libpf.APMTraceID)(unsafe.Pointer(&ptr.apm_trace_id)), - APMTransactionID: *(*libpf.APMTransactionID)(unsafe.Pointer(&ptr.apm_transaction_id)), + APMTraceID: *(*libpf.APMTraceID)(unsafe.Pointer(&ptr.Apm_trace_id)), + APMTransactionID: *(*libpf.APMTransactionID)(unsafe.Pointer(&ptr.Apm_transaction_id)), PID: pid, - TID: libpf.PID(ptr.tid), - Origin: libpf.Origin(ptr.origin), - OffTime: int64(ptr.offtime), - KTime: times.KTime(ptr.ktime), + TID: libpf.PID(ptr.Tid), + Origin: libpf.Origin(ptr.Origin), + OffTime: int64(ptr.Offtime), + KTime: times.KTime(ptr.Ktime), CPU: cpu, EnvVars: procMeta.EnvVariables, } @@ -915,18 +919,18 @@ func (t *Tracer) loadBpfTrace(raw []byte, cpu int) *host.Trace { // - PID, kernel stack ID, length & frame array // Intentionally excluded: // - ktime, COMM, APM trace, APM transaction ID, Origin and Off Time - ptr.comm = [16]C.char{} - ptr.apm_trace_id = C.ApmTraceID{} - ptr.apm_transaction_id = C.ApmSpanID{} - ptr.ktime = 0 - ptr.origin = 0 - ptr.offtime = 0 + ptr.Comm = [16]uint8{} + ptr.Apm_trace_id = support.ApmTraceID{} + ptr.Apm_transaction_id = support.ApmSpanID{} + ptr.Ktime = 0 + ptr.Origin = 0 + ptr.Offtime = 0 trace.Hash = host.TraceHash(xxh3.Hash128(raw).Lo) userFrameOffs := 0 - if ptr.kernel_stack_id >= 0 { + if ptr.Kernel_stack_id >= 0 { kstackLen, err := t.insertKernelFrames( - trace, uint32(ptr.stack_len), int32(ptr.kernel_stack_id)) + trace, ptr.Stack_len, ptr.Kernel_stack_id) if err != nil { log.Errorf("Failed to get kernel stack frames for 0x%x: %v", trace.Hash, err) @@ -935,12 +939,12 @@ func (t *Tracer) loadBpfTrace(raw []byte, cpu int) *host.Trace { } } - if ptr.custom_labels.len > 0 { - trace.CustomLabels = make(map[string]string, int(ptr.custom_labels.len)) - for i := 0; i < int(ptr.custom_labels.len); i++ { - lbl := ptr.custom_labels.labels[i] - key := C.GoString((*C.char)(unsafe.Pointer(&lbl.key))) - val := C.GoString((*C.char)(unsafe.Pointer(&lbl.val))) + if ptr.Custom_labels.Len > 0 { + trace.CustomLabels = make(map[string]string, int(ptr.Custom_labels.Len)) + for i := 0; i < int(ptr.Custom_labels.Len); i++ { + lbl := ptr.Custom_labels.Labels[i] + key := goString(unsafe.Pointer(&lbl.Key), len(lbl.Key)) + val := goString(unsafe.Pointer(&lbl.Val), len(lbl.Val)) trace.CustomLabels[key] = val } } @@ -948,16 +952,16 @@ func (t *Tracer) loadBpfTrace(raw []byte, cpu int) *host.Trace { // If there are no kernel frames, or reading them failed, we are responsible // for allocating the columnar frame array. if len(trace.Frames) == 0 { - trace.Frames = make([]host.Frame, ptr.stack_len) + trace.Frames = make([]host.Frame, ptr.Stack_len) } - for i := 0; i < int(ptr.stack_len); i++ { - rawFrame := &ptr.frames[i] + for i := 0; i < int(ptr.Stack_len); i++ { + rawFrame := &ptr.Frames[i] trace.Frames[userFrameOffs+i] = host.Frame{ - File: host.FileID(rawFrame.file_id), - Lineno: libpf.AddressOrLineno(rawFrame.addr_or_line), - Type: libpf.FrameType(rawFrame.kind), - ReturnAddress: rawFrame.return_address != 0, + File: host.FileID(rawFrame.File_id), + Lineno: libpf.AddressOrLineno(rawFrame.Addr_or_line), + Type: libpf.FrameType(rawFrame.Kind), + ReturnAddress: rawFrame.Return_address != 0, } } return trace @@ -989,99 +993,7 @@ func (t *Tracer) StartMapMonitors(ctx context.Context, traceOutChan chan<- *host // translateIDs is a translation table for eBPF IDs into Metric IDs. // Index is the ebpfID, value is the corresponding metricID. - //nolint:lll - translateIDs := []metrics.MetricID{ - C.metricID_UnwindCallInterpreter: metrics.IDUnwindCallInterpreter, - C.metricID_UnwindErrZeroPC: metrics.IDUnwindErrZeroPC, - C.metricID_UnwindErrStackLengthExceeded: metrics.IDUnwindErrStackLengthExceeded, - C.metricID_UnwindErrBadTSDAddr: metrics.IDUnwindErrBadTLSAddr, - C.metricID_UnwindErrBadTPBaseAddr: metrics.IDUnwindErrBadTPBaseAddr, - C.metricID_UnwindNativeAttempts: metrics.IDUnwindNativeAttempts, - C.metricID_UnwindNativeFrames: metrics.IDUnwindNativeFrames, - C.metricID_UnwindNativeStackDeltaStop: metrics.IDUnwindNativeStackDeltaStop, - C.metricID_UnwindNativeErrLookupTextSection: metrics.IDUnwindNativeErrLookupTextSection, - C.metricID_UnwindNativeErrLookupIterations: metrics.IDUnwindNativeErrLookupIterations, - C.metricID_UnwindNativeErrLookupRange: metrics.IDUnwindNativeErrLookupRange, - C.metricID_UnwindNativeErrKernelAddress: metrics.IDUnwindNativeErrKernelAddress, - C.metricID_UnwindNativeErrWrongTextSection: metrics.IDUnwindNativeErrWrongTextSection, - C.metricID_UnwindNativeErrPCRead: metrics.IDUnwindNativeErrPCRead, - C.metricID_UnwindPythonAttempts: metrics.IDUnwindPythonAttempts, - C.metricID_UnwindPythonFrames: metrics.IDUnwindPythonFrames, - C.metricID_UnwindPythonErrBadPyThreadStateCurrentAddr: metrics.IDUnwindPythonErrBadPyThreadStateCurrentAddr, - C.metricID_UnwindPythonErrZeroThreadState: metrics.IDUnwindPythonErrZeroThreadState, - C.metricID_UnwindPythonErrBadThreadStateFrameAddr: metrics.IDUnwindPythonErrBadThreadStateFrameAddr, - C.metricID_UnwindPythonZeroFrameCodeObject: metrics.IDUnwindPythonZeroFrameCodeObject, - C.metricID_UnwindPythonErrBadCodeObjectArgCountAddr: metrics.IDUnwindPythonErrBadCodeObjectArgCountAddr, - C.metricID_UnwindNativeErrStackDeltaInvalid: metrics.IDUnwindNativeErrStackDeltaInvalid, - C.metricID_ErrEmptyStack: metrics.IDErrEmptyStack, - C.metricID_UnwindHotspotAttempts: metrics.IDUnwindHotspotAttempts, - C.metricID_UnwindHotspotFrames: metrics.IDUnwindHotspotFrames, - C.metricID_UnwindHotspotErrNoCodeblob: metrics.IDUnwindHotspotErrNoCodeblob, - C.metricID_UnwindHotspotErrInvalidCodeblob: metrics.IDUnwindHotspotErrInvalidCodeblob, - C.metricID_UnwindHotspotErrInterpreterFP: metrics.IDUnwindHotspotErrInterpreterFP, - C.metricID_UnwindHotspotErrLrUnwindingMidTrace: metrics.IDUnwindHotspotErrLrUnwindingMidTrace, - C.metricID_UnwindHotspotUnsupportedFrameSize: metrics.IDHotspotUnsupportedFrameSize, - C.metricID_UnwindNativeSmallPC: metrics.IDUnwindNativeSmallPC, - C.metricID_UnwindNativeErrLookupStackDeltaInnerMap: metrics.IDUnwindNativeErrLookupStackDeltaInnerMap, - C.metricID_UnwindNativeErrLookupStackDeltaOuterMap: metrics.IDUnwindNativeErrLookupStackDeltaOuterMap, - C.metricID_ErrBPFCurrentComm: metrics.IDErrBPFCurrentComm, - C.metricID_UnwindPHPAttempts: metrics.IDUnwindPHPAttempts, - C.metricID_UnwindPHPFrames: metrics.IDUnwindPHPFrames, - C.metricID_UnwindPHPErrBadCurrentExecuteData: metrics.IDUnwindPHPErrBadCurrentExecuteData, - C.metricID_UnwindPHPErrBadZendExecuteData: metrics.IDUnwindPHPErrBadZendExecuteData, - C.metricID_UnwindPHPErrBadZendFunction: metrics.IDUnwindPHPErrBadZendFunction, - C.metricID_UnwindPHPErrBadZendOpline: metrics.IDUnwindPHPErrBadZendOpline, - C.metricID_UnwindRubyAttempts: metrics.IDUnwindRubyAttempts, - C.metricID_UnwindRubyFrames: metrics.IDUnwindRubyFrames, - C.metricID_UnwindPerlAttempts: metrics.IDUnwindPerlAttempts, - C.metricID_UnwindPerlFrames: metrics.IDUnwindPerlFrames, - C.metricID_UnwindPerlTSD: metrics.IDUnwindPerlTLS, - C.metricID_UnwindPerlReadStackInfo: metrics.IDUnwindPerlReadStackInfo, - C.metricID_UnwindPerlReadContextStackEntry: metrics.IDUnwindPerlReadContextStackEntry, - C.metricID_UnwindPerlResolveEGV: metrics.IDUnwindPerlResolveEGV, - C.metricID_UnwindHotspotErrInvalidRA: metrics.IDUnwindHotspotErrInvalidRA, - C.metricID_UnwindV8Attempts: metrics.IDUnwindV8Attempts, - C.metricID_UnwindV8Frames: metrics.IDUnwindV8Frames, - C.metricID_UnwindV8ErrBadFP: metrics.IDUnwindV8ErrBadFP, - C.metricID_UnwindV8ErrBadJSFunc: metrics.IDUnwindV8ErrBadJSFunc, - C.metricID_UnwindV8ErrBadCode: metrics.IDUnwindV8ErrBadCode, - C.metricID_ReportedPIDsErr: metrics.IDReportedPIDsErr, - C.metricID_PIDEventsErr: metrics.IDPIDEventsErr, - C.metricID_UnwindNativeLr0: metrics.IDUnwindNativeLr0, - C.metricID_NumProcNew: metrics.IDNumProcNew, - C.metricID_NumProcExit: metrics.IDNumProcExit, - C.metricID_NumUnknownPC: metrics.IDNumUnknownPC, - C.metricID_NumGenericPID: metrics.IDNumGenericPID, - C.metricID_UnwindPythonErrBadCFrameFrameAddr: metrics.IDUnwindPythonErrBadCFrameFrameAddr, - C.metricID_MaxTailCalls: metrics.IDMaxTailCalls, - C.metricID_UnwindPythonErrNoProcInfo: metrics.IDUnwindPythonErrNoProcInfo, - C.metricID_UnwindPythonErrBadAutoTlsKeyAddr: metrics.IDUnwindPythonErrBadAutoTlsKeyAddr, - C.metricID_UnwindPythonErrReadThreadStateAddr: metrics.IDUnwindPythonErrReadThreadStateAddr, - C.metricID_UnwindPythonErrReadTsdBase: metrics.IDUnwindPythonErrReadTsdBase, - C.metricID_UnwindRubyErrNoProcInfo: metrics.IDUnwindRubyErrNoProcInfo, - C.metricID_UnwindRubyErrReadStackPtr: metrics.IDUnwindRubyErrReadStackPtr, - C.metricID_UnwindRubyErrReadStackSize: metrics.IDUnwindRubyErrReadStackSize, - C.metricID_UnwindRubyErrReadCfp: metrics.IDUnwindRubyErrReadCfp, - C.metricID_UnwindRubyErrReadEp: metrics.IDUnwindRubyErrReadEp, - C.metricID_UnwindRubyErrReadIseqBody: metrics.IDUnwindRubyErrReadIseqBody, - C.metricID_UnwindRubyErrReadIseqEncoded: metrics.IDUnwindRubyErrReadIseqEncoded, - C.metricID_UnwindRubyErrReadIseqSize: metrics.IDUnwindRubyErrReadIseqSize, - C.metricID_UnwindNativeErrLrUnwindingMidTrace: metrics.IDUnwindNativeErrLrUnwindingMidTrace, - C.metricID_UnwindNativeErrReadKernelModeRegs: metrics.IDUnwindNativeErrReadKernelModeRegs, - C.metricID_UnwindNativeErrChaseIrqStackLink: metrics.IDUnwindNativeErrChaseIrqStackLink, - C.metricID_UnwindV8ErrNoProcInfo: metrics.IDUnwindV8ErrNoProcInfo, - C.metricID_UnwindNativeErrBadUnwindInfoIndex: metrics.IDUnwindNativeErrBadUnwindInfoIndex, - C.metricID_UnwindApmIntErrReadTsdBase: metrics.IDUnwindApmIntErrReadTsdBase, - C.metricID_UnwindApmIntErrReadCorrBufPtr: metrics.IDUnwindApmIntErrReadCorrBufPtr, - C.metricID_UnwindApmIntErrReadCorrBuf: metrics.IDUnwindApmIntErrReadCorrBuf, - C.metricID_UnwindApmIntReadSuccesses: metrics.IDUnwindApmIntReadSuccesses, - C.metricID_UnwindDotnetAttempts: metrics.IDUnwindDotnetAttempts, - C.metricID_UnwindDotnetFrames: metrics.IDUnwindDotnetFrames, - C.metricID_UnwindDotnetErrNoProcInfo: metrics.IDUnwindDotnetErrNoProcInfo, - C.metricID_UnwindDotnetErrBadFP: metrics.IDUnwindDotnetErrBadFP, - C.metricID_UnwindDotnetErrCodeHeader: metrics.IDUnwindDotnetErrCodeHeader, - C.metricID_UnwindDotnetErrCodeTooLarge: metrics.IDUnwindDotnetErrCodeTooLarge, - } + translateIDs := support.MetricsTranslation // previousMetricValue stores the previously retrieved metric values to // calculate and store delta values. @@ -1165,6 +1077,7 @@ func (t *Tracer) probabilisticProfile(interval time.Duration, threshold uint) { enableSampling := false var probProfilingStatus = probProfilingDisable + //nolint:gosec if rand.UintN(ProbabilisticThresholdMax) < threshold { enableSampling = true probProfilingStatus = probProfilingEnable From db8451a42d0f94584173d82e519c9fff976cd8b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Thu, 17 Jul 2025 00:17:28 +0300 Subject: [PATCH 2/3] simplfy things as byte is alias for uint8 --- tracer/systemconfig.go | 3 +-- tracer/tracer.go | 24 +++++++++++------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/tracer/systemconfig.go b/tracer/systemconfig.go index a568f9012..0075d0812 100644 --- a/tracer/systemconfig.go +++ b/tracer/systemconfig.go @@ -155,8 +155,7 @@ func executeSystemAnalysisBpfCode(progSpec *cebpf.ProgramSpec, maps map[string]* return nil, 0, fmt.Errorf("failed to get analysis data: %v", err) } - return unsafe.Slice(unsafe.SliceData(data.Code[:]), len(data.Code)), - data.Address, nil + return data.Code[:], data.Address, nil } // loadKernelCode will request the ebpf code to read the first X bytes from given address. diff --git a/tracer/tracer.go b/tracer/tracer.go index bef290fa0..fcca906b6 100644 --- a/tracer/tracer.go +++ b/tracer/tracer.go @@ -6,6 +6,7 @@ package tracer // import "go.opentelemetry.io/ebpf-profiler/tracer" import ( "bufio" + "bytes" "context" "errors" "fmt" @@ -163,16 +164,13 @@ type progLoaderHelper struct { noTailCallTarget bool } -// Convert a C-string to Go string -func goString(p unsafe.Pointer, maxLen int) string { - ptr := uintptr(p) - length := 0 - for ; length < maxLen; length++ { - if *(*byte)(unsafe.Pointer(ptr + uintptr(length))) == 0 { - break - } +// Convert a C-string to Go string. +func goString(cstr []byte) string { + index := bytes.IndexByte(cstr, byte(0)) + if index < 0 { + index = len(cstr) } - return strings.Clone(unsafe.String((*byte)(p), length)) + return strings.Clone(unsafe.String(unsafe.SliceData(cstr), index)) } // NewTracer loads eBPF code and map definitions from the ELF module at the configured path. @@ -895,7 +893,7 @@ func (t *Tracer) loadBpfTrace(raw []byte, cpu int) *host.Trace { pid := libpf.PID(ptr.Pid) procMeta := t.processManager.MetaForPID(pid) trace := &host.Trace{ - Comm: goString(unsafe.Pointer(&ptr.Comm), len(ptr.Comm)), + Comm: goString(ptr.Comm[:]), ExecutablePath: procMeta.Executable, ContainerID: procMeta.ContainerID, ProcessName: procMeta.Name, @@ -919,7 +917,7 @@ func (t *Tracer) loadBpfTrace(raw []byte, cpu int) *host.Trace { // - PID, kernel stack ID, length & frame array // Intentionally excluded: // - ktime, COMM, APM trace, APM transaction ID, Origin and Off Time - ptr.Comm = [16]uint8{} + ptr.Comm = [16]byte{} ptr.Apm_trace_id = support.ApmTraceID{} ptr.Apm_transaction_id = support.ApmSpanID{} ptr.Ktime = 0 @@ -943,8 +941,8 @@ func (t *Tracer) loadBpfTrace(raw []byte, cpu int) *host.Trace { trace.CustomLabels = make(map[string]string, int(ptr.Custom_labels.Len)) for i := 0; i < int(ptr.Custom_labels.Len); i++ { lbl := ptr.Custom_labels.Labels[i] - key := goString(unsafe.Pointer(&lbl.Key), len(lbl.Key)) - val := goString(unsafe.Pointer(&lbl.Val), len(lbl.Val)) + key := goString(lbl.Key[:]) + val := goString(lbl.Val[:]) trace.CustomLabels[key] = val } } From 9b73042f2169336253fce15d5c54a2ce8cf39050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Sat, 19 Jul 2025 09:58:12 +0300 Subject: [PATCH 3/3] review: add comment about cgo needed for tests --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 3c1683a4e..42c87ad25 100644 --- a/Makefile +++ b/Makefile @@ -103,6 +103,7 @@ vanity-import-fix: $(PORTO) @porto --include-internal -w . test: generate ebpf test-deps + # 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