1 //===-- RegisterContextMinidump_x86_64.cpp --------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "RegisterContextMinidump_x86_64.h"
11 #include "lldb/Utility/DataBufferHeap.h"
16 using namespace lldb_private
;
17 using namespace minidump
;
19 static llvm::MutableArrayRef
<uint8_t> getDestRegister(uint8_t *context
,
20 const RegisterInfo
®
) {
21 auto bytes
= reg
.mutable_data(context
);
23 switch (reg
.kinds
[lldb::eRegisterKindLLDB
]) {
30 return bytes
.take_front(2);
32 case lldb_rflags_x86_64
:
33 return bytes
.take_front(4);
36 return bytes
.take_front(8);
41 static void writeRegister(const void *reg_src
, uint8_t *context
,
42 const RegisterInfo
®
) {
43 llvm::MutableArrayRef
<uint8_t> reg_dest
= getDestRegister(context
, reg
);
44 memcpy(reg_dest
.data(), reg_src
, reg_dest
.size());
47 // TODO: Fix the registers in this file!
48 // writeRegister checks x86_64 registers without base registers. This causes
49 // an overlap in the register enum values. So we were truncating fs_base.
50 // We should standardize to the x86_64_with_base registers.
51 static void writeBaseRegister(const void *reg_src
, uint8_t *context
,
52 const RegisterInfo
®
) {
53 auto bytes
= reg
.mutable_data(context
);
54 llvm::MutableArrayRef
<uint8_t> reg_dest
= bytes
.take_front(8);
55 memcpy(reg_dest
.data(), reg_src
, reg_dest
.size());
58 lldb::DataBufferSP
lldb_private::minidump::ConvertMinidumpContext_x86_64(
59 llvm::ArrayRef
<uint8_t> source_data
,
60 RegisterInfoInterface
*target_reg_interface
) {
62 const RegisterInfo
*reg_info
= target_reg_interface
->GetRegisterInfo();
64 lldb::WritableDataBufferSP
result_context_buf(
65 new DataBufferHeap(target_reg_interface
->GetGPRSize(), 0));
66 uint8_t *result_base
= result_context_buf
->GetBytes();
68 if (source_data
.size() < sizeof(MinidumpContext_x86_64
))
71 const MinidumpContext_x86_64
*context
;
72 consumeObject(source_data
, context
);
74 const MinidumpContext_x86_64_Flags context_flags
=
75 static_cast<MinidumpContext_x86_64_Flags
>(
76 static_cast<uint32_t>(context
->context_flags
));
77 auto x86_64_Flag
= MinidumpContext_x86_64_Flags::x86_64_Flag
;
78 auto ControlFlag
= MinidumpContext_x86_64_Flags::Control
;
79 auto IntegerFlag
= MinidumpContext_x86_64_Flags::Integer
;
80 auto SegmentsFlag
= MinidumpContext_x86_64_Flags::Segments
;
81 auto LLDBSpecificFlag
= MinidumpContext_x86_64_Flags::LLDBSpecific
;
83 if ((context_flags
& x86_64_Flag
) != x86_64_Flag
)
86 if ((context_flags
& ControlFlag
) == ControlFlag
) {
87 writeRegister(&context
->cs
, result_base
, reg_info
[lldb_cs_x86_64
]);
88 writeRegister(&context
->ss
, result_base
, reg_info
[lldb_ss_x86_64
]);
89 writeRegister(&context
->eflags
, result_base
, reg_info
[lldb_rflags_x86_64
]);
90 writeRegister(&context
->rsp
, result_base
, reg_info
[lldb_rsp_x86_64
]);
91 writeRegister(&context
->rip
, result_base
, reg_info
[lldb_rip_x86_64
]);
94 if ((context_flags
& SegmentsFlag
) == SegmentsFlag
) {
95 writeRegister(&context
->ds
, result_base
, reg_info
[lldb_ds_x86_64
]);
96 writeRegister(&context
->es
, result_base
, reg_info
[lldb_es_x86_64
]);
97 writeRegister(&context
->fs
, result_base
, reg_info
[lldb_fs_x86_64
]);
98 writeRegister(&context
->gs
, result_base
, reg_info
[lldb_gs_x86_64
]);
101 if ((context_flags
& IntegerFlag
) == IntegerFlag
) {
102 writeRegister(&context
->rax
, result_base
, reg_info
[lldb_rax_x86_64
]);
103 writeRegister(&context
->rcx
, result_base
, reg_info
[lldb_rcx_x86_64
]);
104 writeRegister(&context
->rdx
, result_base
, reg_info
[lldb_rdx_x86_64
]);
105 writeRegister(&context
->rbx
, result_base
, reg_info
[lldb_rbx_x86_64
]);
106 writeRegister(&context
->rbp
, result_base
, reg_info
[lldb_rbp_x86_64
]);
107 writeRegister(&context
->rsi
, result_base
, reg_info
[lldb_rsi_x86_64
]);
108 writeRegister(&context
->rdi
, result_base
, reg_info
[lldb_rdi_x86_64
]);
109 writeRegister(&context
->r8
, result_base
, reg_info
[lldb_r8_x86_64
]);
110 writeRegister(&context
->r9
, result_base
, reg_info
[lldb_r9_x86_64
]);
111 writeRegister(&context
->r10
, result_base
, reg_info
[lldb_r10_x86_64
]);
112 writeRegister(&context
->r11
, result_base
, reg_info
[lldb_r11_x86_64
]);
113 writeRegister(&context
->r12
, result_base
, reg_info
[lldb_r12_x86_64
]);
114 writeRegister(&context
->r13
, result_base
, reg_info
[lldb_r13_x86_64
]);
115 writeRegister(&context
->r14
, result_base
, reg_info
[lldb_r14_x86_64
]);
116 writeRegister(&context
->r15
, result_base
, reg_info
[lldb_r15_x86_64
]);
119 // See comment on base regsiter
120 if ((context_flags
& LLDBSpecificFlag
) == LLDBSpecificFlag
) {
121 writeBaseRegister(&context
->fs_base
, result_base
,
122 reg_info
[x86_64_with_base::lldb_fs_base
]);
123 writeBaseRegister(&context
->gs_base
, result_base
,
124 reg_info
[x86_64_with_base::lldb_gs_base
]);
127 // TODO parse the floating point registers
129 return result_context_buf
;