Skip to content
Draft
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
1 change: 1 addition & 0 deletions host/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type Frame struct {
File FileID
Lineno libpf.AddressOrLineno
Type libpf.FrameType
Extra libpf.AddressOrLineno
ReturnAddress bool
}

Expand Down
27 changes: 20 additions & 7 deletions support/ebpf/tracemgmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,27 +328,32 @@ static inline EBPF_INLINE bool unwinder_unwind_frame_pointer(UnwindState *state)
// calc_line). This should probably be renamed to something like "frame type
// specific data".
static inline EBPF_INLINE ErrorCode _push_with_max_frames(
Trace *trace, u64 file, u64 line, u8 frame_type, u8 return_address, u32 max_frames)
Trace *trace, u64 file, u64 line, u64 extra, u8 frame_type, u8 return_address, u32 max_frames)
{
if (trace->stack_len >= max_frames) {
DEBUG_PRINT("unable to push frame: stack is full");
increment_metric(metricID_UnwindErrStackLengthExceeded);
return ERR_STACK_LENGTH_EXCEEDED;
}

u64 extra_addr = (u64)extra & 0x0000FFFFFFFFFFFFULL;
#ifdef TESTING_COREDUMP
// tools/coredump uses CGO to build the eBPF code. This dispatches
// the frame information directly to helper implemented in ebpfhelpers.go.
int __push_frame(u64, u64, u64, u8, u8);
int __push_frame(u64, u64, u64, u64, u8, u8);
trace->stack_len++;
return __push_frame(__cgo_ctx->id, file, line, frame_type, return_address);
return __push_frame(__cgo_ctx->id, file, line, extra_addr, frame_type, return_address);
#else
trace->frames[trace->stack_len++] = (Frame){
Frame frame = {
.file_id = file,
.addr_or_line = line,
.kind = frame_type,
.return_address = return_address,
};
if (extra_addr != 0) {
__builtin_memcpy(frame.pad, &extra_addr, 6);
}
trace->frames[trace->stack_len++] = frame;

return ERR_OK;
#endif
Expand All @@ -359,19 +364,27 @@ static inline EBPF_INLINE ErrorCode
_push_with_return_address(Trace *trace, u64 file, u64 line, u8 frame_type, bool return_address)
{
return _push_with_max_frames(
trace, file, line, frame_type, return_address, MAX_NON_ERROR_FRAME_UNWINDS);
trace, file, line, 0, frame_type, return_address, MAX_NON_ERROR_FRAME_UNWINDS);
}

// Push the file ID, line number and frame type into FrameList
static inline EBPF_INLINE ErrorCode _push(Trace *trace, u64 file, u64 line, u8 frame_type)
{
return _push_with_max_frames(trace, file, line, frame_type, 0, MAX_NON_ERROR_FRAME_UNWINDS);
return _push_with_max_frames(trace, file, line, 0, frame_type, 0, MAX_NON_ERROR_FRAME_UNWINDS);
}

// Push the file ID, line number and frame type with an extra address into FrameList
static inline EBPF_INLINE ErrorCode
_push_with_extra(Trace *trace, u64 file, u64 line, u64 extra, u8 frame_type)
{
return _push_with_max_frames(
trace, file, line, extra, frame_type, 0, MAX_NON_ERROR_FRAME_UNWINDS);
}

// Push a critical error frame.
static inline EBPF_INLINE ErrorCode push_error(Trace *trace, ErrorCode error)
{
return _push_with_max_frames(trace, 0, error, FRAME_MARKER_ABORT, 0, MAX_FRAME_UNWINDS);
return _push_with_max_frames(trace, 0, error, 0, FRAME_MARKER_ABORT, 0, MAX_FRAME_UNWINDS);
}

// Send a trace to user-land via the `trace_events` perf event buffer.
Expand Down
Binary file modified support/ebpf/tracer.ebpf.amd64
Binary file not shown.
Binary file modified support/ebpf/tracer.ebpf.arm64
Binary file not shown.
3 changes: 2 additions & 1 deletion tools/coredump/ebpfhelpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ func __bpf_log(buf unsafe.Pointer, sz C.int) {
}

//export __push_frame
func __push_frame(id, file, line C.u64, frameType, returnAddress C.uchar) C.int {
func __push_frame(id, file, line, extra C.u64, frameType, returnAddress C.uchar) C.int {
ctx := ebpfContextMap[id]

ctx.trace.Frames = append(ctx.trace.Frames, host.Frame{
File: host.FileID(file),
Lineno: libpf.AddressOrLineno(line),
Type: libpf.FrameType(frameType),
Extra: libpf.AddressOrLineno(extra),
ReturnAddress: returnAddress != 0,
})

Expand Down
12 changes: 12 additions & 0 deletions tracer/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"bufio"
"bytes"
"context"
"encoding/binary"
"errors"
"fmt"
"math"
Expand Down Expand Up @@ -857,6 +858,13 @@ func (t *Tracer) eBPFMetricsCollector(
return metricsUpdates
}

func reconstruct48BitAddress(bytes [6]uint8) uint64 {
// Pad to 8 bytes for binary.LittleEndian
padded := [8]uint8{}
copy(padded[:], bytes[:])
return binary.LittleEndian.Uint64(padded[:])
}

// loadBpfTrace parses a raw BPF trace into a `host.Trace` instance.
//
// If the raw trace contains a kernel stack ID, the kernel stack is also
Expand Down Expand Up @@ -930,6 +938,10 @@ func (t *Tracer) loadBpfTrace(raw []byte, cpu int) *host.Trace {
Type: libpf.FrameType(rawFrame.Kind),
ReturnAddress: rawFrame.Return_address != 0,
}
// If there is additional data in the padding, append it as an extra value
if rawFrame.Pad[0] != 0 {
trace.Frames[i].Extra = libpf.AddressOrLineno(reconstruct48BitAddress(rawFrame.Pad))
}
}
return trace
}
Expand Down