]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/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-project / lldb / source / Plugins / ABI / SysV-i386 / ABISysV_i386.cpp
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
31 using namespace lldb;
32 using 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
56 enum 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
109 static 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
171 static const uint32_t k_num_register_infos =
172     llvm::array_lengthof(g_register_infos);
173 static bool g_register_info_names_constified = false;
174
175 const lldb_private::RegisterInfo *
176 ABISysV_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
197 ABISP
198 ABISysV_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(new ABISysV_i386(process_sp));
202     }
203   }
204   return ABISP();
205 }
206
207 bool ABISysV_i386::PrepareTrivialCall(Thread &thread, addr_t sp,
208                                       addr_t func_addr, addr_t return_addr,
209                                       llvm::ArrayRef<addr_t> args) const {
210   RegisterContext *reg_ctx = thread.GetRegisterContext().get();
211
212   if (!reg_ctx)
213     return false;
214
215   uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
216       eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
217   uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
218       eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
219
220   // While using register info to write a register value to memory, the
221   // register info just needs to have the correct size of a 32 bit register,
222   // the actual register it pertains to is not important, just the size needs
223   // to be correct. "eax" is used here for this purpose.
224   const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
225   if (!reg_info_32)
226     return false; // TODO this should actually never happen
227
228   Status error;
229   RegisterValue reg_value;
230
231   // Make room for the argument(s) on the stack
232   sp -= 4 * args.size();
233
234   // SP Alignment
235   sp &= ~(16ull - 1ull); // 16-byte alignment
236
237   // Write arguments onto the stack
238   addr_t arg_pos = sp;
239   for (addr_t arg : args) {
240     reg_value.SetUInt32(arg);
241     error = reg_ctx->WriteRegisterValueToMemory(
242         reg_info_32, arg_pos, reg_info_32->byte_size, reg_value);
243     if (error.Fail())
244       return false;
245     arg_pos += 4;
246   }
247
248   // The return address is pushed onto the stack
249   sp -= 4;
250   reg_value.SetUInt32(return_addr);
251   error = reg_ctx->WriteRegisterValueToMemory(
252       reg_info_32, sp, reg_info_32->byte_size, reg_value);
253   if (error.Fail())
254     return false;
255
256   // Setting %esp to the actual stack value.
257   if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp))
258     return false;
259
260   // Setting %eip to the address of the called function.
261   if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr))
262     return false;
263
264   return true;
265 }
266
267 static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width,
268                                 bool is_signed, Process *process,
269                                 addr_t &current_stack_argument) {
270   uint32_t byte_size = (bit_width + (8 - 1)) / 8;
271   Status error;
272
273   if (!process)
274     return false;
275
276   if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size,
277                                            is_signed, scalar, error)) {
278     current_stack_argument += byte_size;
279     return true;
280   }
281   return false;
282 }
283
284 bool ABISysV_i386::GetArgumentValues(Thread &thread, ValueList &values) const {
285   unsigned int num_values = values.GetSize();
286   unsigned int value_index;
287
288   RegisterContext *reg_ctx = thread.GetRegisterContext().get();
289
290   if (!reg_ctx)
291     return false;
292
293   // Get pointer to the first stack argument
294   addr_t sp = reg_ctx->GetSP(0);
295   if (!sp)
296     return false;
297
298   addr_t current_stack_argument = sp + 4; // jump over return address
299
300   for (value_index = 0; value_index < num_values; ++value_index) {
301     Value *value = values.GetValueAtIndex(value_index);
302
303     if (!value)
304       return false;
305
306     // Currently: Support for extracting values with Clang QualTypes only.
307     CompilerType compiler_type(value->GetCompilerType());
308     llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
309     if (bit_size) {
310       bool is_signed;
311       if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
312         ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed,
313                             thread.GetProcess().get(), current_stack_argument);
314       } else if (compiler_type.IsPointerType()) {
315         ReadIntegerArgument(value->GetScalar(), *bit_size, false,
316                             thread.GetProcess().get(), current_stack_argument);
317       }
318     }
319   }
320   return true;
321 }
322
323 Status ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
324                                           lldb::ValueObjectSP &new_value_sp) {
325   Status error;
326   if (!new_value_sp) {
327     error.SetErrorString("Empty value object for return value.");
328     return error;
329   }
330
331   CompilerType compiler_type = new_value_sp->GetCompilerType();
332   if (!compiler_type) {
333     error.SetErrorString("Null clang type for return value.");
334     return error;
335   }
336
337   const uint32_t type_flags = compiler_type.GetTypeInfo();
338   Thread *thread = frame_sp->GetThread().get();
339   RegisterContext *reg_ctx = thread->GetRegisterContext().get();
340   DataExtractor data;
341   Status data_error;
342   size_t num_bytes = new_value_sp->GetData(data, data_error);
343   bool register_write_successful = true;
344
345   if (data_error.Fail()) {
346     error.SetErrorStringWithFormat(
347         "Couldn't convert return value to raw data: %s",
348         data_error.AsCString());
349     return error;
350   }
351
352   // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
353   // The terminology 'Fundamental Data Types' used here is adopted from Table
354   // 2.1 of the reference document (specified on top of this file)
355
356   if (type_flags & eTypeIsPointer) // 'Pointer'
357   {
358     if (num_bytes != sizeof(uint32_t)) {
359       error.SetErrorString("Pointer to be returned is not 4 bytes wide");
360       return error;
361     }
362     lldb::offset_t offset = 0;
363     const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
364     uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
365     register_write_successful =
366         reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
367   } else if ((type_flags & eTypeIsScalar) ||
368              (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
369   {
370     lldb::offset_t offset = 0;
371     const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
372
373     if (type_flags & eTypeIsInteger) // 'Integral' except enum
374     {
375       switch (num_bytes) {
376       default:
377         break;
378       case 16:
379         // For clang::BuiltinType::UInt128 & Int128 ToDo: Need to decide how to
380         // handle it
381         break;
382       case 8: {
383         uint32_t raw_value_low = data.GetMaxU32(&offset, 4);
384         const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0);
385         uint32_t raw_value_high = data.GetMaxU32(&offset, num_bytes - offset);
386         register_write_successful =
387             (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value_low) &&
388              reg_ctx->WriteRegisterFromUnsigned(edx_info, raw_value_high));
389         break;
390       }
391       case 4:
392       case 2:
393       case 1: {
394         uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
395         register_write_successful =
396             reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
397         break;
398       }
399       }
400     } else if (type_flags & eTypeIsEnumeration) // handles enum
401     {
402       uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
403       register_write_successful =
404           reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
405     } else if (type_flags & eTypeIsFloat) // 'Floating Point'
406     {
407       RegisterValue st0_value, fstat_value, ftag_value;
408       const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
409       const RegisterInfo *fstat_info =
410           reg_ctx->GetRegisterInfoByName("fstat", 0);
411       const RegisterInfo *ftag_info = reg_ctx->GetRegisterInfoByName("ftag", 0);
412
413       /* According to Page 3-12 of document
414       System V Application Binary Interface, Intel386 Architecture Processor
415       Supplement, Fourth Edition
416       To return Floating Point values, all st% registers except st0 should be
417       empty after exiting from
418       a function. This requires setting fstat and ftag registers to specific
419       values.
420       fstat: The TOP field of fstat should be set to a value [0,7]. ABI doesn't
421       specify the specific
422       value of TOP in case of function return. Hence, we set the TOP field to 7
423       by our choice. */
424       uint32_t value_fstat_u32 = 0x00003800;
425
426       /* ftag: Implication of setting TOP to 7 and indicating all st% registers
427       empty except st0 is to set
428       7th bit of 4th byte of FXSAVE area to 1 and all other bits of this byte to
429       0. This is in accordance
430       with the document Intel 64 and IA-32 Architectures Software Developer's
431       Manual, January 2015 */
432       uint32_t value_ftag_u32 = 0x00000080;
433
434       if (num_bytes <= 12) // handles float, double, long double, __float80
435       {
436         long double value_long_dbl = 0.0;
437         if (num_bytes == 4)
438           value_long_dbl = data.GetFloat(&offset);
439         else if (num_bytes == 8)
440           value_long_dbl = data.GetDouble(&offset);
441         else if (num_bytes == 12)
442           value_long_dbl = data.GetLongDouble(&offset);
443         else {
444           error.SetErrorString("Invalid number of bytes for this return type");
445           return error;
446         }
447         st0_value.SetLongDouble(value_long_dbl);
448         fstat_value.SetUInt32(value_fstat_u32);
449         ftag_value.SetUInt32(value_ftag_u32);
450         register_write_successful =
451             reg_ctx->WriteRegister(st0_info, st0_value) &&
452             reg_ctx->WriteRegister(fstat_info, fstat_value) &&
453             reg_ctx->WriteRegister(ftag_info, ftag_value);
454       } else if (num_bytes == 16) // handles __float128
455       {
456         error.SetErrorString("Implementation is missing for this clang type.");
457       }
458     } else {
459       // Neither 'Integral' nor 'Floating Point'. If flow reaches here then
460       // check type_flags. This type_flags is not a valid type.
461       error.SetErrorString("Invalid clang type");
462     }
463   } else {
464     /* 'Complex Floating Point', 'Packed', 'Decimal Floating Point' and
465     'Aggregate' data types
466     are yet to be implemented */
467     error.SetErrorString("Currently only Integral and Floating Point clang "
468                          "types are supported.");
469   }
470   if (!register_write_successful)
471     error.SetErrorString("Register writing failed");
472   return error;
473 }
474
475 ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
476     Thread &thread, CompilerType &return_compiler_type) const {
477   ValueObjectSP return_valobj_sp;
478   Value value;
479
480   if (!return_compiler_type)
481     return return_valobj_sp;
482
483   value.SetCompilerType(return_compiler_type);
484
485   RegisterContext *reg_ctx = thread.GetRegisterContext().get();
486   if (!reg_ctx)
487     return return_valobj_sp;
488
489   const uint32_t type_flags = return_compiler_type.GetTypeInfo();
490
491   unsigned eax_id =
492       reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
493   unsigned edx_id =
494       reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
495
496   // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
497   // The terminology 'Fundamental Data Types' used here is adopted from Table
498   // 2.1 of the reference document (specified on top of this file)
499
500   if (type_flags & eTypeIsPointer) // 'Pointer'
501   {
502     uint32_t ptr =
503         thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
504         0xffffffff;
505     value.SetValueType(Value::eValueTypeScalar);
506     value.GetScalar() = ptr;
507     return_valobj_sp = ValueObjectConstResult::Create(
508         thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
509   } else if ((type_flags & eTypeIsScalar) ||
510              (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
511   {
512     value.SetValueType(Value::eValueTypeScalar);
513     llvm::Optional<uint64_t> byte_size =
514         return_compiler_type.GetByteSize(nullptr);
515     if (!byte_size)
516       return return_valobj_sp;
517     bool success = false;
518
519     if (type_flags & eTypeIsInteger) // 'Integral' except enum
520     {
521       const bool is_signed = ((type_flags & eTypeIsSigned) != 0);
522       uint64_t raw_value =
523           thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
524           0xffffffff;
525       raw_value |=
526           (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) &
527            0xffffffff)
528           << 32;
529
530       switch (*byte_size) {
531       default:
532         break;
533
534       case 16:
535         // For clang::BuiltinType::UInt128 & Int128 ToDo: Need to decide how to
536         // handle it
537         break;
538
539       case 8:
540         if (is_signed)
541           value.GetScalar() = (int64_t)(raw_value);
542         else
543           value.GetScalar() = (uint64_t)(raw_value);
544         success = true;
545         break;
546
547       case 4:
548         if (is_signed)
549           value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
550         else
551           value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
552         success = true;
553         break;
554
555       case 2:
556         if (is_signed)
557           value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
558         else
559           value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
560         success = true;
561         break;
562
563       case 1:
564         if (is_signed)
565           value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
566         else
567           value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
568         success = true;
569         break;
570       }
571
572       if (success)
573         return_valobj_sp = ValueObjectConstResult::Create(
574             thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
575     } else if (type_flags & eTypeIsEnumeration) // handles enum
576     {
577       uint32_t enm =
578           thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
579           0xffffffff;
580       value.SetValueType(Value::eValueTypeScalar);
581       value.GetScalar() = enm;
582       return_valobj_sp = ValueObjectConstResult::Create(
583           thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
584     } else if (type_flags & eTypeIsFloat) // 'Floating Point'
585     {
586       if (*byte_size <= 12) // handles float, double, long double, __float80
587       {
588         const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
589         RegisterValue st0_value;
590
591         if (reg_ctx->ReadRegister(st0_info, st0_value)) {
592           DataExtractor data;
593           if (st0_value.GetData(data)) {
594             lldb::offset_t offset = 0;
595             long double value_long_double = data.GetLongDouble(&offset);
596
597             // float is 4 bytes.
598             if (*byte_size == 4) {
599               float value_float = (float)value_long_double;
600               value.GetScalar() = value_float;
601               success = true;
602             } else if (*byte_size == 8) {
603               // double is 8 bytes
604               // On Android Platform: long double is also 8 bytes It will be
605               // handled here only.
606               double value_double = (double)value_long_double;
607               value.GetScalar() = value_double;
608               success = true;
609             } else if (*byte_size == 12) {
610               // long double and __float80 are 12 bytes on i386.
611               value.GetScalar() = value_long_double;
612               success = true;
613             }
614           }
615         }
616
617         if (success)
618           return_valobj_sp = ValueObjectConstResult::Create(
619               thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
620       } else if (*byte_size == 16) // handles __float128
621       {
622         lldb::addr_t storage_addr = (uint32_t)(
623             thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
624             0xffffffff);
625         return_valobj_sp = ValueObjectMemory::Create(
626             &thread, "", Address(storage_addr, nullptr), return_compiler_type);
627       }
628     } else // Neither 'Integral' nor 'Floating Point'
629     {
630       // If flow reaches here then check type_flags This type_flags is
631       // unhandled
632     }
633   } else if (type_flags & eTypeIsComplex) // 'Complex Floating Point'
634   {
635     // ToDo: Yet to be implemented
636   } else if (type_flags & eTypeIsVector) // 'Packed'
637   {
638     llvm::Optional<uint64_t> byte_size =
639         return_compiler_type.GetByteSize(nullptr);
640     if (byte_size && *byte_size > 0) {
641       const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
642       if (vec_reg == nullptr)
643         vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
644
645       if (vec_reg) {
646         if (*byte_size <= vec_reg->byte_size) {
647           ProcessSP process_sp(thread.GetProcess());
648           if (process_sp) {
649             std::unique_ptr<DataBufferHeap> heap_data_up(
650                 new DataBufferHeap(*byte_size, 0));
651             const ByteOrder byte_order = process_sp->GetByteOrder();
652             RegisterValue reg_value;
653             if (reg_ctx->ReadRegister(vec_reg, reg_value)) {
654               Status error;
655               if (reg_value.GetAsMemoryData(vec_reg, heap_data_up->GetBytes(),
656                                             heap_data_up->GetByteSize(),
657                                             byte_order, error)) {
658                 DataExtractor data(DataBufferSP(heap_data_up.release()),
659                                    byte_order,
660                                    process_sp->GetTarget()
661                                        .GetArchitecture()
662                                        .GetAddressByteSize());
663                 return_valobj_sp = ValueObjectConstResult::Create(
664                     &thread, return_compiler_type, ConstString(""), data);
665               }
666             }
667           }
668         } else if (*byte_size <= vec_reg->byte_size * 2) {
669           const RegisterInfo *vec_reg2 =
670               reg_ctx->GetRegisterInfoByName("xmm1", 0);
671           if (vec_reg2) {
672             ProcessSP process_sp(thread.GetProcess());
673             if (process_sp) {
674               std::unique_ptr<DataBufferHeap> heap_data_up(
675                   new DataBufferHeap(*byte_size, 0));
676               const ByteOrder byte_order = process_sp->GetByteOrder();
677               RegisterValue reg_value;
678               RegisterValue reg_value2;
679               if (reg_ctx->ReadRegister(vec_reg, reg_value) &&
680                   reg_ctx->ReadRegister(vec_reg2, reg_value2)) {
681
682                 Status error;
683                 if (reg_value.GetAsMemoryData(vec_reg, heap_data_up->GetBytes(),
684                                               vec_reg->byte_size, byte_order,
685                                               error) &&
686                     reg_value2.GetAsMemoryData(
687                         vec_reg2, heap_data_up->GetBytes() + vec_reg->byte_size,
688                         heap_data_up->GetByteSize() - vec_reg->byte_size,
689                         byte_order, error)) {
690                   DataExtractor data(DataBufferSP(heap_data_up.release()),
691                                      byte_order,
692                                      process_sp->GetTarget()
693                                          .GetArchitecture()
694                                          .GetAddressByteSize());
695                   return_valobj_sp = ValueObjectConstResult::Create(
696                       &thread, return_compiler_type, ConstString(""), data);
697                 }
698               }
699             }
700           }
701         }
702       }
703     }
704   } else // 'Decimal Floating Point'
705   {
706     // ToDo: Yet to be implemented
707   }
708   return return_valobj_sp;
709 }
710
711 ValueObjectSP ABISysV_i386::GetReturnValueObjectImpl(
712     Thread &thread, CompilerType &return_compiler_type) const {
713   ValueObjectSP return_valobj_sp;
714
715   if (!return_compiler_type)
716     return return_valobj_sp;
717
718   ExecutionContext exe_ctx(thread.shared_from_this());
719   return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
720   if (return_valobj_sp)
721     return return_valobj_sp;
722
723   RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
724   if (!reg_ctx_sp)
725     return return_valobj_sp;
726
727   if (return_compiler_type.IsAggregateType()) {
728     unsigned eax_id =
729         reg_ctx_sp->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
730     lldb::addr_t storage_addr = (uint32_t)(
731         thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
732         0xffffffff);
733     return_valobj_sp = ValueObjectMemory::Create(
734         &thread, "", Address(storage_addr, nullptr), return_compiler_type);
735   }
736
737   return return_valobj_sp;
738 }
739
740 // This defines CFA as esp+4
741 // The saved pc is at CFA-4 (i.e. esp+0)
742 // The saved esp is CFA+0
743
744 bool ABISysV_i386::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
745   unwind_plan.Clear();
746   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
747
748   uint32_t sp_reg_num = dwarf_esp;
749   uint32_t pc_reg_num = dwarf_eip;
750
751   UnwindPlan::RowSP row(new UnwindPlan::Row);
752   row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4);
753   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
754   row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
755   unwind_plan.AppendRow(row);
756   unwind_plan.SetSourceName("i386 at-func-entry default");
757   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
758   return true;
759 }
760
761 // This defines CFA as ebp+8
762 // The saved pc is at CFA-4 (i.e. ebp+4)
763 // The saved ebp is at CFA-8 (i.e. ebp+0)
764 // The saved esp is CFA+0
765
766 bool ABISysV_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
767   unwind_plan.Clear();
768   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
769
770   uint32_t fp_reg_num = dwarf_ebp;
771   uint32_t sp_reg_num = dwarf_esp;
772   uint32_t pc_reg_num = dwarf_eip;
773
774   UnwindPlan::RowSP row(new UnwindPlan::Row);
775   const int32_t ptr_size = 4;
776
777   row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
778   row->SetOffset(0);
779
780   row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
781   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
782   row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
783
784   unwind_plan.AppendRow(row);
785   unwind_plan.SetSourceName("i386 default unwind plan");
786   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
787   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
788   return true;
789 }
790
791 // According to "Register Usage" in reference document (specified on top of
792 // this source file) ebx, ebp, esi, edi and esp registers are preserved i.e.
793 // non-volatile i.e. callee-saved on i386
794 bool ABISysV_i386::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
795   if (!reg_info)
796     return false;
797
798   // Saved registers are ebx, ebp, esi, edi, esp, eip
799   const char *name = reg_info->name;
800   if (name[0] == 'e') {
801     switch (name[1]) {
802     case 'b':
803       if (name[2] == 'x' || name[2] == 'p')
804         return name[3] == '\0';
805       break;
806     case 'd':
807       if (name[2] == 'i')
808         return name[3] == '\0';
809       break;
810     case 'i':
811       if (name[2] == 'p')
812         return name[3] == '\0';
813       break;
814     case 's':
815       if (name[2] == 'i' || name[2] == 'p')
816         return name[3] == '\0';
817       break;
818     }
819   }
820
821   if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
822     return true;
823   if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
824     return true;
825   if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
826     return true;
827
828   return false;
829 }
830
831 void ABISysV_i386::Initialize() {
832   PluginManager::RegisterPlugin(
833       GetPluginNameStatic(), "System V ABI for i386 targets", CreateInstance);
834 }
835
836 void ABISysV_i386::Terminate() {
837   PluginManager::UnregisterPlugin(CreateInstance);
838 }
839
840 // PluginInterface protocol
841
842 lldb_private::ConstString ABISysV_i386::GetPluginNameStatic() {
843   static ConstString g_name("sysv-i386");
844   return g_name;
845 }
846
847 lldb_private::ConstString ABISysV_i386::GetPluginName() {
848   return GetPluginNameStatic();
849 }