1//===----------------------- ABISysV_i386.cpp -------------------*- C++ -*-===//
2//
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
6//===----------------------------------------------------------------------===//
7
8#include "ABISysV_i386.h"
9
10#include "llvm/ADT/STLExtras.h"
11#include "llvm/ADT/Triple.h"
12
13#include "lldb/Core/Module.h"
14#include "lldb/Core/PluginManager.h"
15#include "lldb/Core/Value.h"
16#include "lldb/Core/ValueObjectConstResult.h"
17#include "lldb/Core/ValueObjectMemory.h"
18#include "lldb/Core/ValueObjectRegister.h"
19#include "lldb/Symbol/UnwindPlan.h"
20#include "lldb/Target/Process.h"
21#include "lldb/Target/RegisterContext.h"
22#include "lldb/Target/StackFrame.h"
23#include "lldb/Target/Target.h"
24#include "lldb/Target/Thread.h"
25#include "lldb/Utility/ConstString.h"
26#include "lldb/Utility/DataExtractor.h"
27#include "lldb/Utility/Log.h"
28#include "lldb/Utility/RegisterValue.h"
29#include "lldb/Utility/Status.h"
30
31using namespace lldb;
32using namespace lldb_private;
33
34//   This source file uses the following document as a reference:
35//====================================================================
36//             System V Application Binary Interface
37//    Intel386 Architecture Processor Supplement, Version 1.0
38//                         Edited by
39//      H.J. Lu, David L Kreitzer, Milind Girkar, Zia Ansari
40//
41//                        (Based on
42//           System V Application Binary Interface,
43//          AMD64 Architecture Processor Supplement,
44//                         Edited by
45//     H.J. Lu, Michael Matz, Milind Girkar, Jan Hubicka,
46//               Andreas Jaeger, Mark Mitchell)
47//
48//                     February 3, 2015
49//====================================================================
50
51// DWARF Register Number Mapping
52// See Table 2.14 of the reference document (specified on top of this file)
53// Comment: Table 2.14 is followed till 'mm' entries. After that, all entries
54// are ignored here.
55
56enum dwarf_regnums {
57  dwarf_eax = 0,
58  dwarf_ecx,
59  dwarf_edx,
60  dwarf_ebx,
61  dwarf_esp,
62  dwarf_ebp,
63  dwarf_esi,
64  dwarf_edi,
65  dwarf_eip,
66  dwarf_eflags,
67
68  dwarf_st0 = 11,
69  dwarf_st1,
70  dwarf_st2,
71  dwarf_st3,
72  dwarf_st4,
73  dwarf_st5,
74  dwarf_st6,
75  dwarf_st7,
76
77  dwarf_xmm0 = 21,
78  dwarf_xmm1,
79  dwarf_xmm2,
80  dwarf_xmm3,
81  dwarf_xmm4,
82  dwarf_xmm5,
83  dwarf_xmm6,
84  dwarf_xmm7,
85  dwarf_ymm0 = dwarf_xmm0,
86  dwarf_ymm1 = dwarf_xmm1,
87  dwarf_ymm2 = dwarf_xmm2,
88  dwarf_ymm3 = dwarf_xmm3,
89  dwarf_ymm4 = dwarf_xmm4,
90  dwarf_ymm5 = dwarf_xmm5,
91  dwarf_ymm6 = dwarf_xmm6,
92  dwarf_ymm7 = dwarf_xmm7,
93
94  dwarf_mm0 = 29,
95  dwarf_mm1,
96  dwarf_mm2,
97  dwarf_mm3,
98  dwarf_mm4,
99  dwarf_mm5,
100  dwarf_mm6,
101  dwarf_mm7,
102
103  dwarf_bnd0 = 101,
104  dwarf_bnd1,
105  dwarf_bnd2,
106  dwarf_bnd3
107};
108
109static RegisterInfo g_register_infos[] = {
110    // clang-format off
111    //NAME       ALT     SZ OFF  ENCODING         FORMAT                 EH_FRAME             DWARF                GENERIC                   PROCESS PLUGIN       LLDB NATIVE           VALUE    INVAL    DYN EXPR SZ
112    //========== ======= == ===  =============    ====================   ===================  ===================  ========================= ===================  ===================   =======  =======  ======== ==
113    {"eax",      nullptr, 4,  0, eEncodingUint,   eFormatHex,           {dwarf_eax,           dwarf_eax,           LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
114    {"ebx",      nullptr, 4,  0, eEncodingUint,   eFormatHex,           {dwarf_ebx,           dwarf_ebx,           LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
115    {"ecx",      nullptr, 4,  0, eEncodingUint,   eFormatHex,           {dwarf_ecx,           dwarf_ecx,           LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
116    {"edx",      nullptr, 4,  0, eEncodingUint,   eFormatHex,           {dwarf_edx,           dwarf_edx,           LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
117    {"esi",      nullptr, 4,  0, eEncodingUint,   eFormatHex,           {dwarf_esi,           dwarf_esi,           LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
118    {"edi",      nullptr, 4,  0, eEncodingUint,   eFormatHex,           {dwarf_edi,           dwarf_edi,           LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
119    {"ebp",      "fp",    4,  0, eEncodingUint,   eFormatHex,           {dwarf_ebp,           dwarf_ebp,           LLDB_REGNUM_GENERIC_FP,   LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
120    {"esp",      "sp",    4,  0, eEncodingUint,   eFormatHex,           {dwarf_esp,           dwarf_esp,           LLDB_REGNUM_GENERIC_SP,   LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
121    {"eip",      "pc",    4,  0, eEncodingUint,   eFormatHex,           {dwarf_eip,           dwarf_eip,           LLDB_REGNUM_GENERIC_PC,   LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
122    {"eflags",   nullptr, 4,  0, eEncodingUint,   eFormatHex,           {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
123    {"cs",       nullptr, 4,  0, eEncodingUint,   eFormatHex,           {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
124    {"ss",       nullptr, 4,  0, eEncodingUint,   eFormatHex,           {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
125    {"ds",       nullptr, 4,  0, eEncodingUint,   eFormatHex,           {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
126    {"es",       nullptr, 4,  0, eEncodingUint,   eFormatHex,           {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
127    {"fs",       nullptr, 4,  0, eEncodingUint,   eFormatHex,           {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
128    {"gs",       nullptr, 4,  0, eEncodingUint,   eFormatHex,           {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
129    {"st0",      nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st0,           LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
130    {"st1",      nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st1,           LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
131    {"st2",      nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st2,           LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
132    {"st3",      nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st3,           LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
133    {"st4",      nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st4,           LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
134    {"st5",      nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st5,           LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
135    {"st6",      nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st6,           LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
136    {"st7",      nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st7,           LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
137    {"fctrl",    nullptr, 4,  0, eEncodingUint,   eFormatHex,           {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
138    {"fstat",    nullptr, 4,  0, eEncodingUint,   eFormatHex,           {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
139    {"ftag",     nullptr, 4,  0, eEncodingUint,   eFormatHex,           {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
140    {"fiseg",    nullptr, 4,  0, eEncodingUint,   eFormatHex,           {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
141    {"fioff",    nullptr, 4,  0, eEncodingUint,   eFormatHex,           {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
142    {"foseg",    nullptr, 4,  0, eEncodingUint,   eFormatHex,           {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
143    {"fooff",    nullptr, 4,  0, eEncodingUint,   eFormatHex,           {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
144    {"fop",      nullptr, 4,  0, eEncodingUint,   eFormatHex,           {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
145    {"xmm0",     nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm0,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
146    {"xmm1",     nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm1,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
147    {"xmm2",     nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm2,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
148    {"xmm3",     nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm3,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
149    {"xmm4",     nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm4,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
150    {"xmm5",     nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm5,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
151    {"xmm6",     nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm6,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
152    {"xmm7",     nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm7,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
153    {"mxcsr",    nullptr, 4,  0, eEncodingUint,   eFormatHex,           {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
154    {"ymm0",     nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm0,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
155    {"ymm1",     nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm1,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
156    {"ymm2",     nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm2,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
157    {"ymm3",     nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm3,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
158    {"ymm4",     nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm4,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
159    {"ymm5",     nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm5,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
160    {"ymm6",     nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm6,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
161    {"ymm7",     nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm7,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
162    {"bnd0",     nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt64,{dwarf_bnd0,          dwarf_bnd0,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
163    {"bnd1",     nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt64,{dwarf_bnd1,          dwarf_bnd1,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
164    {"bnd2",     nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt64,{dwarf_bnd2,          dwarf_bnd2,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
165    {"bnd3",     nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt64,{dwarf_bnd3,          dwarf_bnd3,          LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
166    {"bndcfgu",  nullptr, 8,  0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
167    {"bndstatus",nullptr, 8,  0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0}
168    // clang-format on
169};
170
171static const uint32_t k_num_register_infos =
172    llvm::array_lengthof(g_register_infos);
173static bool g_register_info_names_constified = false;
174
175const lldb_private::RegisterInfo *
176ABISysV_i386::GetRegisterInfoArray(uint32_t &count) {
177  // Make the C-string names and alt_names for the register infos into const
178  // C-string values by having the ConstString unique the names in the global
179  // constant C-string pool.
180  if (!g_register_info_names_constified) {
181    g_register_info_names_constified = true;
182    for (uint32_t i = 0; i < k_num_register_infos; ++i) {
183      if (g_register_infos[i].name)
184        g_register_infos[i].name =
185            ConstString(g_register_infos[i].name).GetCString();
186      if (g_register_infos[i].alt_name)
187        g_register_infos[i].alt_name =
188            ConstString(g_register_infos[i].alt_name).GetCString();
189    }
190  }
191  count = k_num_register_infos;
192  return g_register_infos;
193}
194
195// Static Functions
196
197ABISP
198ABISysV_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
199  if (arch.GetTriple().getVendor() != llvm::Triple::Apple) {
200    if (arch.GetTriple().getArch() == llvm::Triple::x86) {
201      return ABISP(
202          new ABISysV_i386(std::move(process_sp), MakeMCRegisterInfo(arch)));
203    }
204  }
205  return ABISP();
206}
207
208bool ABISysV_i386::PrepareTrivialCall(Thread &thread, addr_t sp,
209                                      addr_t func_addr, addr_t return_addr,
210                                      llvm::ArrayRef<addr_t> args) const {
211  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
212
213  if (!reg_ctx)
214    return false;
215
216  uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
217      eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
218  uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
219      eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
220
221  // While using register info to write a register value to memory, the
222  // register info just needs to have the correct size of a 32 bit register,
223  // the actual register it pertains to is not important, just the size needs
224  // to be correct. "eax" is used here for this purpose.
225  const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
226  if (!reg_info_32)
227    return false; // TODO this should actually never happen
228
229  Status error;
230  RegisterValue reg_value;
231
232  // Make room for the argument(s) on the stack
233  sp -= 4 * args.size();
234
235  // SP Alignment
236  sp &= ~(16ull - 1ull); // 16-byte alignment
237
238  // Write arguments onto the stack
239  addr_t arg_pos = sp;
240  for (addr_t arg : args) {
241    reg_value.SetUInt32(arg);
242    error = reg_ctx->WriteRegisterValueToMemory(
243        reg_info_32, arg_pos, reg_info_32->byte_size, reg_value);
244    if (error.Fail())
245      return false;
246    arg_pos += 4;
247  }
248
249  // The return address is pushed onto the stack
250  sp -= 4;
251  reg_value.SetUInt32(return_addr);
252  error = reg_ctx->WriteRegisterValueToMemory(
253      reg_info_32, sp, reg_info_32->byte_size, reg_value);
254  if (error.Fail())
255    return false;
256
257  // Setting %esp to the actual stack value.
258  if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp))
259    return false;
260
261  // Setting %eip to the address of the called function.
262  if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr))
263    return false;
264
265  return true;
266}
267
268static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width,
269                                bool is_signed, Process *process,
270                                addr_t &current_stack_argument) {
271  uint32_t byte_size = (bit_width + (8 - 1)) / 8;
272  Status error;
273
274  if (!process)
275    return false;
276
277  if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size,
278                                           is_signed, scalar, error)) {
279    current_stack_argument += byte_size;
280    return true;
281  }
282  return false;
283}
284
285bool ABISysV_i386::GetArgumentValues(Thread &thread, ValueList &values) const {
286  unsigned int num_values = values.GetSize();
287  unsigned int value_index;
288
289  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
290
291  if (!reg_ctx)
292    return false;
293
294  // Get pointer to the first stack argument
295  addr_t sp = reg_ctx->GetSP(0);
296  if (!sp)
297    return false;
298
299  addr_t current_stack_argument = sp + 4; // jump over return address
300
301  for (value_index = 0; value_index < num_values; ++value_index) {
302    Value *value = values.GetValueAtIndex(value_index);
303
304    if (!value)
305      return false;
306
307    // Currently: Support for extracting values with Clang QualTypes only.
308    CompilerType compiler_type(value->GetCompilerType());
309    llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
310    if (bit_size) {
311      bool is_signed;
312      if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
313        ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed,
314                            thread.GetProcess().get(), current_stack_argument);
315      } else if (compiler_type.IsPointerType()) {
316        ReadIntegerArgument(value->GetScalar(), *bit_size, false,
317                            thread.GetProcess().get(), current_stack_argument);
318      }
319    }
320  }
321  return true;
322}
323
324Status ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
325                                          lldb::ValueObjectSP &new_value_sp) {
326  Status error;
327  if (!new_value_sp) {
328    error.SetErrorString("Empty value object for return value.");
329    return error;
330  }
331
332  CompilerType compiler_type = new_value_sp->GetCompilerType();
333  if (!compiler_type) {
334    error.SetErrorString("Null clang type for return value.");
335    return error;
336  }
337
338  const uint32_t type_flags = compiler_type.GetTypeInfo();
339  Thread *thread = frame_sp->GetThread().get();
340  RegisterContext *reg_ctx = thread->GetRegisterContext().get();
341  DataExtractor data;
342  Status data_error;
343  size_t num_bytes = new_value_sp->GetData(data, data_error);
344  bool register_write_successful = true;
345
346  if (data_error.Fail()) {
347    error.SetErrorStringWithFormat(
348        "Couldn't convert return value to raw data: %s",
349        data_error.AsCString());
350    return error;
351  }
352
353  // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
354  // The terminology 'Fundamental Data Types' used here is adopted from Table
355  // 2.1 of the reference document (specified on top of this file)
356
357  if (type_flags & eTypeIsPointer) // 'Pointer'
358  {
359    if (num_bytes != sizeof(uint32_t)) {
360      error.SetErrorString("Pointer to be returned is not 4 bytes wide");
361      return error;
362    }
363    lldb::offset_t offset = 0;
364    const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
365    uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
366    register_write_successful =
367        reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
368  } else if ((type_flags & eTypeIsScalar) ||
369             (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
370  {
371    lldb::offset_t offset = 0;
372    const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
373
374    if (type_flags & eTypeIsInteger) // 'Integral' except enum
375    {
376      switch (num_bytes) {
377      default:
378        break;
379      case 16:
380        // For clang::BuiltinType::UInt128 & Int128 ToDo: Need to decide how to
381        // handle it
382        break;
383      case 8: {
384        uint32_t raw_value_low = data.GetMaxU32(&offset, 4);
385        const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0);
386        uint32_t raw_value_high = data.GetMaxU32(&offset, num_bytes - offset);
387        register_write_successful =
388            (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value_low) &&
389             reg_ctx->WriteRegisterFromUnsigned(edx_info, raw_value_high));
390        break;
391      }
392      case 4:
393      case 2:
394      case 1: {
395        uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
396        register_write_successful =
397            reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
398        break;
399      }
400      }
401    } else if (type_flags & eTypeIsEnumeration) // handles enum
402    {
403      uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
404      register_write_successful =
405          reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
406    } else if (type_flags & eTypeIsFloat) // 'Floating Point'
407    {
408      RegisterValue st0_value, fstat_value, ftag_value;
409      const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
410      const RegisterInfo *fstat_info =
411          reg_ctx->GetRegisterInfoByName("fstat", 0);
412      const RegisterInfo *ftag_info = reg_ctx->GetRegisterInfoByName("ftag", 0);
413
414      /* According to Page 3-12 of document
415      System V Application Binary Interface, Intel386 Architecture Processor
416      Supplement, Fourth Edition
417      To return Floating Point values, all st% registers except st0 should be
418      empty after exiting from
419      a function. This requires setting fstat and ftag registers to specific
420      values.
421      fstat: The TOP field of fstat should be set to a value [0,7]. ABI doesn't
422      specify the specific
423      value of TOP in case of function return. Hence, we set the TOP field to 7
424      by our choice. */
425      uint32_t value_fstat_u32 = 0x00003800;
426
427      /* ftag: Implication of setting TOP to 7 and indicating all st% registers
428      empty except st0 is to set
429      7th bit of 4th byte of FXSAVE area to 1 and all other bits of this byte to
430      0. This is in accordance
431      with the document Intel 64 and IA-32 Architectures Software Developer's
432      Manual, January 2015 */
433      uint32_t value_ftag_u32 = 0x00000080;
434
435      if (num_bytes <= 12) // handles float, double, long double, __float80
436      {
437        long double value_long_dbl = 0.0;
438        if (num_bytes == 4)
439          value_long_dbl = data.GetFloat(&offset);
440        else if (num_bytes == 8)
441          value_long_dbl = data.GetDouble(&offset);
442        else if (num_bytes == 12)
443          value_long_dbl = data.GetLongDouble(&offset);
444        else {
445          error.SetErrorString("Invalid number of bytes for this return type");
446          return error;
447        }
448        st0_value.SetLongDouble(value_long_dbl);
449        fstat_value.SetUInt32(value_fstat_u32);
450        ftag_value.SetUInt32(value_ftag_u32);
451        register_write_successful =
452            reg_ctx->WriteRegister(st0_info, st0_value) &&
453            reg_ctx->WriteRegister(fstat_info, fstat_value) &&
454            reg_ctx->WriteRegister(ftag_info, ftag_value);
455      } else if (num_bytes == 16) // handles __float128
456      {
457        error.SetErrorString("Implementation is missing for this clang type.");
458      }
459    } else {
460      // Neither 'Integral' nor 'Floating Point'. If flow reaches here then
461      // check type_flags. This type_flags is not a valid type.
462      error.SetErrorString("Invalid clang type");
463    }
464  } else {
465    /* 'Complex Floating Point', 'Packed', 'Decimal Floating Point' and
466    'Aggregate' data types
467    are yet to be implemented */
468    error.SetErrorString("Currently only Integral and Floating Point clang "
469                         "types are supported.");
470  }
471  if (!register_write_successful)
472    error.SetErrorString("Register writing failed");
473  return error;
474}
475
476ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
477    Thread &thread, CompilerType &return_compiler_type) const {
478  ValueObjectSP return_valobj_sp;
479  Value value;
480
481  if (!return_compiler_type)
482    return return_valobj_sp;
483
484  value.SetCompilerType(return_compiler_type);
485
486  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
487  if (!reg_ctx)
488    return return_valobj_sp;
489
490  const uint32_t type_flags = return_compiler_type.GetTypeInfo();
491
492  unsigned eax_id =
493      reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
494  unsigned edx_id =
495      reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
496
497  // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
498  // The terminology 'Fundamental Data Types' used here is adopted from Table
499  // 2.1 of the reference document (specified on top of this file)
500
501  if (type_flags & eTypeIsPointer) // 'Pointer'
502  {
503    uint32_t ptr =
504        thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
505        0xffffffff;
506    value.SetValueType(Value::eValueTypeScalar);
507    value.GetScalar() = ptr;
508    return_valobj_sp = ValueObjectConstResult::Create(
509        thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
510  } else if ((type_flags & eTypeIsScalar) ||
511             (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
512  {
513    value.SetValueType(Value::eValueTypeScalar);
514    llvm::Optional<uint64_t> byte_size =
515        return_compiler_type.GetByteSize(nullptr);
516    if (!byte_size)
517      return return_valobj_sp;
518    bool success = false;
519
520    if (type_flags & eTypeIsInteger) // 'Integral' except enum
521    {
522      const bool is_signed = ((type_flags & eTypeIsSigned) != 0);
523      uint64_t raw_value =
524          thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
525          0xffffffff;
526      raw_value |=
527          (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) &
528           0xffffffff)
529          << 32;
530
531      switch (*byte_size) {
532      default:
533        break;
534
535      case 16:
536        // For clang::BuiltinType::UInt128 & Int128 ToDo: Need to decide how to
537        // handle it
538        break;
539
540      case 8:
541        if (is_signed)
542          value.GetScalar() = (int64_t)(raw_value);
543        else
544          value.GetScalar() = (uint64_t)(raw_value);
545        success = true;
546        break;
547
548      case 4:
549        if (is_signed)
550          value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
551        else
552          value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
553        success = true;
554        break;
555
556      case 2:
557        if (is_signed)
558          value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
559        else
560          value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
561        success = true;
562        break;
563
564      case 1:
565        if (is_signed)
566          value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
567        else
568          value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
569        success = true;
570        break;
571      }
572
573      if (success)
574        return_valobj_sp = ValueObjectConstResult::Create(
575            thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
576    } else if (type_flags & eTypeIsEnumeration) // handles enum
577    {
578      uint32_t enm =
579          thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
580          0xffffffff;
581      value.SetValueType(Value::eValueTypeScalar);
582      value.GetScalar() = enm;
583      return_valobj_sp = ValueObjectConstResult::Create(
584          thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
585    } else if (type_flags & eTypeIsFloat) // 'Floating Point'
586    {
587      if (*byte_size <= 12) // handles float, double, long double, __float80
588      {
589        const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
590        RegisterValue st0_value;
591
592        if (reg_ctx->ReadRegister(st0_info, st0_value)) {
593          DataExtractor data;
594          if (st0_value.GetData(data)) {
595            lldb::offset_t offset = 0;
596            long double value_long_double = data.GetLongDouble(&offset);
597
598            // float is 4 bytes.
599            if (*byte_size == 4) {
600              float value_float = (float)value_long_double;
601              value.GetScalar() = value_float;
602              success = true;
603            } else if (*byte_size == 8) {
604              // double is 8 bytes
605              // On Android Platform: long double is also 8 bytes It will be
606              // handled here only.
607              double value_double = (double)value_long_double;
608              value.GetScalar() = value_double;
609              success = true;
610            } else if (*byte_size == 12) {
611              // long double and __float80 are 12 bytes on i386.
612              value.GetScalar() = value_long_double;
613              success = true;
614            }
615          }
616        }
617
618        if (success)
619          return_valobj_sp = ValueObjectConstResult::Create(
620              thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
621      } else if (*byte_size == 16) // handles __float128
622      {
623        lldb::addr_t storage_addr = (uint32_t)(
624            thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
625            0xffffffff);
626        return_valobj_sp = ValueObjectMemory::Create(
627            &thread, "", Address(storage_addr, nullptr), return_compiler_type);
628      }
629    } else // Neither 'Integral' nor 'Floating Point'
630    {
631      // If flow reaches here then check type_flags This type_flags is
632      // unhandled
633    }
634  } else if (type_flags & eTypeIsComplex) // 'Complex Floating Point'
635  {
636    // ToDo: Yet to be implemented
637  } else if (type_flags & eTypeIsVector) // 'Packed'
638  {
639    llvm::Optional<uint64_t> byte_size =
640        return_compiler_type.GetByteSize(nullptr);
641    if (byte_size && *byte_size > 0) {
642      const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
643      if (vec_reg == nullptr)
644        vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
645
646      if (vec_reg) {
647        if (*byte_size <= vec_reg->byte_size) {
648          ProcessSP process_sp(thread.GetProcess());
649          if (process_sp) {
650            std::unique_ptr<DataBufferHeap> heap_data_up(
651                new DataBufferHeap(*byte_size, 0));
652            const ByteOrder byte_order = process_sp->GetByteOrder();
653            RegisterValue reg_value;
654            if (reg_ctx->ReadRegister(vec_reg, reg_value)) {
655              Status error;
656              if (reg_value.GetAsMemoryData(vec_reg, heap_data_up->GetBytes(),
657                                            heap_data_up->GetByteSize(),
658                                            byte_order, error)) {
659                DataExtractor data(DataBufferSP(heap_data_up.release()),
660                                   byte_order,
661                                   process_sp->GetTarget()
662                                       .GetArchitecture()
663                                       .GetAddressByteSize());
664                return_valobj_sp = ValueObjectConstResult::Create(
665                    &thread, return_compiler_type, ConstString(""), data);
666              }
667            }
668          }
669        } else if (*byte_size <= vec_reg->byte_size * 2) {
670          const RegisterInfo *vec_reg2 =
671              reg_ctx->GetRegisterInfoByName("xmm1", 0);
672          if (vec_reg2) {
673            ProcessSP process_sp(thread.GetProcess());
674            if (process_sp) {
675              std::unique_ptr<DataBufferHeap> heap_data_up(
676                  new DataBufferHeap(*byte_size, 0));
677              const ByteOrder byte_order = process_sp->GetByteOrder();
678              RegisterValue reg_value;
679              RegisterValue reg_value2;
680              if (reg_ctx->ReadRegister(vec_reg, reg_value) &&
681                  reg_ctx->ReadRegister(vec_reg2, reg_value2)) {
682
683                Status error;
684                if (reg_value.GetAsMemoryData(vec_reg, heap_data_up->GetBytes(),
685                                              vec_reg->byte_size, byte_order,
686                                              error) &&
687                    reg_value2.GetAsMemoryData(
688                        vec_reg2, heap_data_up->GetBytes() + vec_reg->byte_size,
689                        heap_data_up->GetByteSize() - vec_reg->byte_size,
690                        byte_order, error)) {
691                  DataExtractor data(DataBufferSP(heap_data_up.release()),
692                                     byte_order,
693                                     process_sp->GetTarget()
694                                         .GetArchitecture()
695                                         .GetAddressByteSize());
696                  return_valobj_sp = ValueObjectConstResult::Create(
697                      &thread, return_compiler_type, ConstString(""), data);
698                }
699              }
700            }
701          }
702        }
703      }
704    }
705  } else // 'Decimal Floating Point'
706  {
707    // ToDo: Yet to be implemented
708  }
709  return return_valobj_sp;
710}
711
712ValueObjectSP ABISysV_i386::GetReturnValueObjectImpl(
713    Thread &thread, CompilerType &return_compiler_type) const {
714  ValueObjectSP return_valobj_sp;
715
716  if (!return_compiler_type)
717    return return_valobj_sp;
718
719  ExecutionContext exe_ctx(thread.shared_from_this());
720  return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
721  if (return_valobj_sp)
722    return return_valobj_sp;
723
724  RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
725  if (!reg_ctx_sp)
726    return return_valobj_sp;
727
728  if (return_compiler_type.IsAggregateType()) {
729    unsigned eax_id =
730        reg_ctx_sp->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
731    lldb::addr_t storage_addr = (uint32_t)(
732        thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
733        0xffffffff);
734    return_valobj_sp = ValueObjectMemory::Create(
735        &thread, "", Address(storage_addr, nullptr), return_compiler_type);
736  }
737
738  return return_valobj_sp;
739}
740
741// This defines CFA as esp+4
742// The saved pc is at CFA-4 (i.e. esp+0)
743// The saved esp is CFA+0
744
745bool ABISysV_i386::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
746  unwind_plan.Clear();
747  unwind_plan.SetRegisterKind(eRegisterKindDWARF);
748
749  uint32_t sp_reg_num = dwarf_esp;
750  uint32_t pc_reg_num = dwarf_eip;
751
752  UnwindPlan::RowSP row(new UnwindPlan::Row);
753  row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4);
754  row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
755  row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
756  unwind_plan.AppendRow(row);
757  unwind_plan.SetSourceName("i386 at-func-entry default");
758  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
759  return true;
760}
761
762// This defines CFA as ebp+8
763// The saved pc is at CFA-4 (i.e. ebp+4)
764// The saved ebp is at CFA-8 (i.e. ebp+0)
765// The saved esp is CFA+0
766
767bool ABISysV_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
768  unwind_plan.Clear();
769  unwind_plan.SetRegisterKind(eRegisterKindDWARF);
770
771  uint32_t fp_reg_num = dwarf_ebp;
772  uint32_t sp_reg_num = dwarf_esp;
773  uint32_t pc_reg_num = dwarf_eip;
774
775  UnwindPlan::RowSP row(new UnwindPlan::Row);
776  const int32_t ptr_size = 4;
777
778  row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
779  row->SetOffset(0);
780
781  row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
782  row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
783  row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
784
785  unwind_plan.AppendRow(row);
786  unwind_plan.SetSourceName("i386 default unwind plan");
787  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
788  unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
789  unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
790  return true;
791}
792
793// According to "Register Usage" in reference document (specified on top of
794// this source file) ebx, ebp, esi, edi and esp registers are preserved i.e.
795// non-volatile i.e. callee-saved on i386
796bool ABISysV_i386::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
797  if (!reg_info)
798    return false;
799
800  // Saved registers are ebx, ebp, esi, edi, esp, eip
801  const char *name = reg_info->name;
802  if (name[0] == 'e') {
803    switch (name[1]) {
804    case 'b':
805      if (name[2] == 'x' || name[2] == 'p')
806        return name[3] == '\0';
807      break;
808    case 'd':
809      if (name[2] == 'i')
810        return name[3] == '\0';
811      break;
812    case 'i':
813      if (name[2] == 'p')
814        return name[3] == '\0';
815      break;
816    case 's':
817      if (name[2] == 'i' || name[2] == 'p')
818        return name[3] == '\0';
819      break;
820    }
821  }
822
823  if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
824    return true;
825  if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
826    return true;
827  if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
828    return true;
829
830  return false;
831}
832
833void ABISysV_i386::Initialize() {
834  PluginManager::RegisterPlugin(
835      GetPluginNameStatic(), "System V ABI for i386 targets", CreateInstance);
836}
837
838void ABISysV_i386::Terminate() {
839  PluginManager::UnregisterPlugin(CreateInstance);
840}
841
842// PluginInterface protocol
843
844lldb_private::ConstString ABISysV_i386::GetPluginNameStatic() {
845  static ConstString g_name("sysv-i386");
846  return g_name;
847}
848
849lldb_private::ConstString ABISysV_i386::GetPluginName() {
850  return GetPluginNameStatic();
851}
852