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