aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/backtrace/cursors/interop/interop_x86_64.cpp
blob: b4e6cfbe6edde027e0da2cd3c3f0e9ce73a6ed12 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include "interop.h"

namespace NYT::NBacktrace {

////////////////////////////////////////////////////////////////////////////////

TFramePointerCursorContext FramePointerCursorContextFromUcontext(const ucontext_t& ucontext)
{
#if defined(_linux_)
    return {
        .Rip = static_cast<ui64>(ucontext.uc_mcontext.gregs[REG_RIP]),
        .Rsp = static_cast<ui64>(ucontext.uc_mcontext.gregs[REG_RSP]),
        .Rbp = static_cast<ui64>(ucontext.uc_mcontext.gregs[REG_RBP]),
    };
#elif defined(_darwin_)
    return {
        .Rip = static_cast<ui64>(ucontext.uc_mcontext->__ss.__rip),
        .Rsp = static_cast<ui64>(ucontext.uc_mcontext->__ss.__rsp),
        .Rbp = static_cast<ui64>(ucontext.uc_mcontext->__ss.__rbp),
    };
#else
    #error Unsupported platform
#endif
}

std::optional<unw_context_t> TrySynthesizeLibunwindContextFromMachineContext(
    const TContMachineContext& machineContext)
{
    unw_context_t unwindContext;
    if (unw_getcontext(&unwindContext) != 0) {
        return {};
    }

    // Some dirty hacks follow.
    struct TUnwindContextRegisters
    {
        ui64 Rax;
        ui64 Rbx;
        ui64 Rcx;
        ui64 Rdx;
        ui64 Rdi;
        ui64 Rsi;
        ui64 Rbp;
        ui64 Rsp;
        ui64 R8;
        ui64 R9;
        ui64 R10;
        ui64 R11;
        ui64 R12;
        ui64 R13;
        ui64 R14;
        ui64 R15;
        ui64 Rip;
        ui64 Rflags;
        ui64 CS;
        ui64 FS;
        ui64 GS;
    };

    struct TMachineContextRegisters
    {
        ui64 Rbx;
        ui64 Rbp;
        ui64 R12;
        ui64 R13;
        ui64 R14;
        ui64 R15;
        ui64 Rsp;
        ui64 Rip;
    };

    static_assert(sizeof(TContMachineContext) >= sizeof(TMachineContextRegisters));
    static_assert(sizeof(unw_context_t) >= sizeof(TUnwindContextRegisters));
    const auto* machineContextRegisters = reinterpret_cast<const TMachineContextRegisters*>(&machineContext);
    auto* unwindContextRegisters = reinterpret_cast<TUnwindContextRegisters*>(&unwindContext);
    #define XX(register) unwindContextRegisters->register = machineContextRegisters->register;
    XX(Rbx)
    XX(Rbp)
    XX(R12)
    XX(R13)
    XX(R14)
    XX(R15)
    XX(Rsp)
    XX(Rip)
    #undef XX
    return unwindContext;
}

TFramePointerCursorContext FramePointerCursorContextFromLibunwindCursor(
    const unw_cursor_t& cursor)
{
    TFramePointerCursorContext context{};
    auto& mutableCursor = const_cast<unw_cursor_t&>(cursor);
    YT_VERIFY(unw_get_reg(&mutableCursor, UNW_REG_IP, &context.Rip) == 0);
    YT_VERIFY(unw_get_reg(&mutableCursor, UNW_X86_64_RSP, &context.Rsp) == 0);
    YT_VERIFY(unw_get_reg(&mutableCursor, UNW_X86_64_RBP, &context.Rbp) == 0);
    return context;
}

////////////////////////////////////////////////////////////////////////////////

} // namespace NYT::NBacktrace