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