Skip to content

Commit f8f3cb5

Browse files
committed
Basic attempt at unwinding, with bogus file names
1 parent 977e31f commit f8f3cb5

File tree

3 files changed

+97
-13
lines changed

3 files changed

+97
-13
lines changed

interpreter/beam/beam.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"os"
1414
"regexp"
1515
"strconv"
16+
"unsafe"
1617

1718
log "github.com/sirupsen/logrus"
1819

@@ -27,11 +28,16 @@ import (
2728
"go.opentelemetry.io/ebpf-profiler/support"
2829
)
2930

31+
// #include "../../support/ebpf/types.h"
32+
// #include "../../support/ebpf/v8_tracer.h"
33+
import "C"
34+
3035
var (
3136
// regex for matching the process name
32-
beamRegex = regexp.MustCompile(`beam.smp`)
33-
_ interpreter.Data = &beamData{}
34-
_ interpreter.Instance = &beamInstance{}
37+
beamRegex = regexp.MustCompile(`beam.smp`)
38+
_ interpreter.Data = &beamData{}
39+
_ interpreter.Instance = &beamInstance{}
40+
BogusFileID = libpf.NewFileID(0xf00d, 0x1001)
3541
)
3642

3743
type beamData struct {
@@ -124,6 +130,14 @@ func Loader(ebpf interpreter.EbpfHandler, info *interpreter.LoaderInfo) (interpr
124130

125131
func (d *beamData) Attach(ebpf interpreter.EbpfHandler, pid libpf.PID, bias libpf.Address, rm remotememory.RemoteMemory) (interpreter.Instance, error) {
126132
log.Infof("BEAM interpreter attaching")
133+
134+
data := C.BEAMProcInfo{
135+
version: C.uint(d.version),
136+
}
137+
if err := ebpf.UpdateProcData(libpf.BEAM, pid, unsafe.Pointer(&data)); err != nil {
138+
return nil, err
139+
}
140+
127141
return &beamInstance{
128142
data: d,
129143
rm: rm,
@@ -255,6 +269,12 @@ func (i *beamInstance) Symbolize(symbolReporter reporter.SymbolReporter, frame *
255269
log.Warnf("BEAM failed to symbolize")
256270
return interpreter.ErrMismatchInterpreterType
257271
}
258-
log.Infof("BEAM symbolizing")
272+
log.Infof("BEAM symbolizing %v", frame)
273+
frameID := libpf.NewFrameID(BogusFileID, frame.Lineno)
274+
symbolReporter.FrameMetadata(&reporter.FrameMetadataArgs{
275+
FrameID: frameID,
276+
FunctionName: "Some Bogus Name",
277+
})
278+
trace.AppendFrameID(libpf.BEAMFrame, frameID)
259279
return nil
260280
}

support/ebpf/beam_tracer.ebpf.c

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,95 @@
22
#include "tracemgmt.h"
33
#include "types.h"
44

5+
// The number of frames to unwind per frame-unwinding eBPF program.
6+
#define FRAMES_PER_PROGRAM 8
7+
58
bpf_map_def SEC("maps") beam_procs = {
69
.type = BPF_MAP_TYPE_HASH,
710
.key_size = sizeof(pid_t),
811
.value_size = sizeof(BEAMProcInfo),
912
.max_entries = 1024,
1013
};
1114

15+
static inline __attribute__((__always_inline__))
16+
ErrorCode unwind_one_frame(PerCPURecord *record, BEAMProcInfo *info, bool top) {
17+
UnwindState *state = &record->state;
18+
Trace *trace = &record->trace;
19+
unsigned long regs[2], sp = state->sp, fp = state->fp, pc = state->pc;
20+
21+
DEBUG_PRINT("beam: pc: %lx, sp: %lx, fp: %lx", pc, sp, fp);
22+
23+
if (fp) {
24+
unwinder_mark_nonleaf_frame(state);
25+
}
26+
_push_with_return_address(trace, 0xf00d, pc, FRAME_MARKER_BEAM, state->return_address);
27+
28+
// Data that will be sent to HA is in these variables.
29+
//uintptr_t pointer_and_type = 0, delta_or_marker = 0;
30+
31+
frame_done:
32+
// Unwind with frame pointer
33+
if (bpf_probe_read_user(regs, sizeof(regs), (void*)fp)) {
34+
DEBUG_PRINT("beam: --> bad frame pointer");
35+
return ERR_UNREACHABLE;
36+
}
37+
38+
state->sp = fp + sizeof(regs);
39+
state->fp = regs[0];
40+
state->pc = regs[1];
41+
if (state->fp) {
42+
unwinder_mark_nonleaf_frame(state);
43+
}
44+
45+
DEBUG_PRINT("beam: pc: %lx, sp: %lx, fp: %lx",
46+
(unsigned long) state->pc, (unsigned long) state->sp,
47+
(unsigned long) state->fp);
48+
49+
return ERR_OK;
50+
}
51+
1252
SEC("perf_event/unwind_beam")
1353
int unwind_beam(struct pt_regs *ctx) {
14-
static const char fmt[] = "Unwinding BEAM stack";
15-
bpf_trace_printk(fmt, sizeof(fmt));
16-
DEBUG_PRINT("Unwinding BEAM stack");
54+
DEBUG_PRINT(">>>>>>>>>>>>>>>>>Unwinding BEAM stack<<<<<<<<<<<<<<<<<");
1755

1856
PerCPURecord *record = get_per_cpu_record();
1957
if (!record) {
2058
return -1;
2159
}
2260

23-
int unwinder = get_next_unwinder_after_interpreter(record);
24-
u32 pid = record->trace.pid;
61+
Trace *trace = &record->trace;
62+
u32 pid = trace->pid;
63+
DEBUG_PRINT("==== unwind_beam %d ====", trace->stack_len);
2564

26-
BEAMProcInfo *beaminfo = bpf_map_lookup_elem(&beam_procs, &pid);
27-
if (!beaminfo) {
28-
DEBUG_PRINT("No BEAM introspection data");
65+
int unwinder = PROG_UNWIND_STOP;
66+
ErrorCode error = ERR_OK;
67+
BEAMProcInfo *info = bpf_map_lookup_elem(&beam_procs, &pid);
68+
if (!info) {
69+
DEBUG_PRINT("beam: no BEAMProcInfo for this pid");
2970
goto exit;
3071
}
3172

32-
DEBUG_PRINT("==== unwind_beam stack_len: %d, pid: %d ====", record->trace.stack_len, record->trace.pid);
73+
#pragma unroll
74+
for (int i = 0; i < FRAMES_PER_PROGRAM; i++) {
75+
error = unwind_one_frame(record, info, i == 0);
76+
if (error) {
77+
break;
78+
}
79+
80+
if (record->state.fp == 0) {
81+
unwinder = PROG_UNWIND_STOP;
82+
break;
83+
}
84+
85+
error = get_next_unwinder_after_native_frame(record, &unwinder);
86+
if (error || unwinder != PROG_UNWIND_BEAM) {
87+
break;
88+
}
89+
}
3390

3491
exit:
92+
record->state.unwind_error = error;
3593
tail_call(ctx, unwinder);
94+
DEBUG_PRINT("beam: tail call for next frame unwinder (%d) failed", unwinder);
3695
return -1;
3796
}

tracer/tracer.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,11 @@ func initializeMapsAndPrograms(kernelSymbols *libpf.SymbolMap, cfg *Config) (
483483
name: "unwind_dotnet",
484484
enable: cfg.IncludeTracers.Has(types.DotnetTracer),
485485
},
486+
{
487+
progID: uint32(support.ProgUnwindBeam),
488+
name: "unwind_beam",
489+
enable: cfg.IncludeTracers.Has(types.BEAMTracer),
490+
},
486491
}
487492

488493
if err = loadPerfUnwinders(coll, ebpfProgs, ebpfMaps["perf_progs"], tailCallProgs,

0 commit comments

Comments
 (0)