Skip to content
Open
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
2 changes: 2 additions & 0 deletions perforator/agent/collector/pkg/profile/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,8 @@ type InterpreterLocationKey struct {
Linestart int32
Line int32
Language models.Language
// Lua function names depend on the caller, even for the same proto and line.
Name string
}

type functionKey struct {
Expand Down
27 changes: 26 additions & 1 deletion perforator/agent/collector/pkg/profiler/native_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func (r *nativeRuntimeResolver) resolveInterpreterSection(key linux.ProcessKey,
if r.lua == nil {
return fmt.Errorf("interpreter resolver is unavailable")
}
err = resolveInterpreterSection(r.lua.ResolveFrame, key, section, writer)
err = resolveLuaSection(r.lua.ResolveFrame, key, section, writer)
default:
return fmt.Errorf("unsupported interpreter language %d", section.Language)
}
Expand Down Expand Up @@ -203,6 +203,31 @@ func resolveInterpreterSection[T runtimeFrame](resolve func(linux.ProcessKey, *T
return nil
}

func resolveLuaSection(resolve func(linux.ProcessKey, *unwinder.LuaFrame, *unwinder.LuaFrame, runtimewriter.Frame) error, key linux.ProcessKey, section nativepipeline.LanguageSection, writer *runtimewriter.Writer) error {
frames, err := viewRuntimeFrames[unwinder.LuaFrame](section)
if err != nil {
return err
}
for i := range frames {
output, err := writer.AddFrame(0, 1)
if err != nil {
return err
}

var callerFrame *unwinder.LuaFrame

// Frames run from callee to caller. The caller's PC names callee's frame.
if i+1 < len(frames) {
callerFrame = &frames[i+1]
}

if err := resolve(key, &frames[i], callerFrame, output); err != nil {
return err
}
}
return nil
}

// Frames borrow the BPF payload for the synchronous resolver call.
func viewRuntimeFrames[T runtimeFrame | unwinder.JvmFrame](section nativepipeline.LanguageSection) ([]T, error) {
var frame T
Expand Down
4 changes: 4 additions & 0 deletions perforator/agent/collector/progs/unwinder/arch/x86/regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct user_regs {
u64 rdi;
u64 rdx;
u64 r14;
u64 rbx;
};

static ALWAYS_INLINE u64 regs_get_current_instruction(struct user_regs* regs) {
Expand All @@ -30,6 +31,7 @@ struct pt_regs___kernel {
u64 di;
u64 dx;
u64 r14;
u64 bx;
};

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -75,6 +77,7 @@ static NOINLINE bool extract_saved_userspace_registers(struct user_regs* regs) {
regs->rdi = BPF_CORE_READ(kregs, di);
regs->rdx = BPF_CORE_READ(kregs, dx);
regs->r14 = BPF_CORE_READ(kregs, r14);
regs->rbx = BPF_CORE_READ(kregs, bx);

return true;
}
Expand All @@ -90,6 +93,7 @@ static NOINLINE bool find_task_userspace_registers(struct pt_regs* kregs, struct
uregs->rdi = kregs->rdi;
uregs->rdx = kregs->rdx;
uregs->r14 = kregs->r14;
uregs->rbx = kregs->rbx;

return true;
}
Expand Down
Loading