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