1 //===-- ABIMacOSX_i386.cpp --------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "ABIMacOSX_i386.h"
11 
12 #include "lldb/Core/ConstString.h"
13 #include "lldb/Core/Error.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Core/RegisterValue.h"
17 #include "lldb/Core/Scalar.h"
18 #include "lldb/Core/ValueObjectConstResult.h"
19 #include "lldb/Symbol/ClangASTContext.h"
20 #include "lldb/Symbol/UnwindPlan.h"
21 #include "lldb/Target/Process.h"
22 #include "lldb/Target/RegisterContext.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Target/Thread.h"
25 
26 #include "llvm/ADT/Triple.h"
27 
28 #include <vector>
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 enum
34 {
35     gcc_eax = 0,
36     gcc_ecx,
37     gcc_edx,
38     gcc_ebx,
39     gcc_ebp,
40     gcc_esp,
41     gcc_esi,
42     gcc_edi,
43     gcc_eip,
44     gcc_eflags
45 };
46 
47 enum
48 {
49     dwarf_eax = 0,
50     dwarf_ecx,
51     dwarf_edx,
52     dwarf_ebx,
53     dwarf_esp,
54     dwarf_ebp,
55     dwarf_esi,
56     dwarf_edi,
57     dwarf_eip,
58     dwarf_eflags,
59     dwarf_stmm0 = 11,
60     dwarf_stmm1,
61     dwarf_stmm2,
62     dwarf_stmm3,
63     dwarf_stmm4,
64     dwarf_stmm5,
65     dwarf_stmm6,
66     dwarf_stmm7,
67     dwarf_xmm0 = 21,
68     dwarf_xmm1,
69     dwarf_xmm2,
70     dwarf_xmm3,
71     dwarf_xmm4,
72     dwarf_xmm5,
73     dwarf_xmm6,
74     dwarf_xmm7,
75     dwarf_ymm0 = dwarf_xmm0,
76     dwarf_ymm1 = dwarf_xmm1,
77     dwarf_ymm2 = dwarf_xmm2,
78     dwarf_ymm3 = dwarf_xmm3,
79     dwarf_ymm4 = dwarf_xmm4,
80     dwarf_ymm5 = dwarf_xmm5,
81     dwarf_ymm6 = dwarf_xmm6,
82     dwarf_ymm7 = dwarf_xmm7
83 };
84 
85 enum
86 {
87     gdb_eax        =  0,
88     gdb_ecx        =  1,
89     gdb_edx        =  2,
90     gdb_ebx        =  3,
91     gdb_esp        =  4,
92     gdb_ebp        =  5,
93     gdb_esi        =  6,
94     gdb_edi        =  7,
95     gdb_eip        =  8,
96     gdb_eflags     =  9,
97     gdb_cs         = 10,
98     gdb_ss         = 11,
99     gdb_ds         = 12,
100     gdb_es         = 13,
101     gdb_fs         = 14,
102     gdb_gs         = 15,
103     gdb_stmm0      = 16,
104     gdb_stmm1      = 17,
105     gdb_stmm2      = 18,
106     gdb_stmm3      = 19,
107     gdb_stmm4      = 20,
108     gdb_stmm5      = 21,
109     gdb_stmm6      = 22,
110     gdb_stmm7      = 23,
111     gdb_fctrl      = 24,    gdb_fcw     = gdb_fctrl,
112     gdb_fstat      = 25,    gdb_fsw     = gdb_fstat,
113     gdb_ftag       = 26,    gdb_ftw     = gdb_ftag,
114     gdb_fiseg      = 27,    gdb_fpu_cs  = gdb_fiseg,
115     gdb_fioff      = 28,    gdb_ip      = gdb_fioff,
116     gdb_foseg      = 29,    gdb_fpu_ds  = gdb_foseg,
117     gdb_fooff      = 30,    gdb_dp      = gdb_fooff,
118     gdb_fop        = 31,
119     gdb_xmm0       = 32,
120     gdb_xmm1       = 33,
121     gdb_xmm2       = 34,
122     gdb_xmm3       = 35,
123     gdb_xmm4       = 36,
124     gdb_xmm5       = 37,
125     gdb_xmm6       = 38,
126     gdb_xmm7       = 39,
127     gdb_mxcsr      = 40,
128     gdb_mm0        = 41,
129     gdb_mm1        = 42,
130     gdb_mm2        = 43,
131     gdb_mm3        = 44,
132     gdb_mm4        = 45,
133     gdb_mm5        = 46,
134     gdb_mm6        = 47,
135     gdb_mm7        = 48,
136     gdb_ymm0       = gdb_xmm0,
137     gdb_ymm1       = gdb_xmm1,
138     gdb_ymm2       = gdb_xmm2,
139     gdb_ymm3       = gdb_xmm3,
140     gdb_ymm4       = gdb_xmm4,
141     gdb_ymm5       = gdb_xmm5,
142     gdb_ymm6       = gdb_xmm6,
143     gdb_ymm7       = gdb_xmm7
144 };
145 
146 
147 static RegisterInfo g_register_infos[] =
148 {
149   //  NAME      ALT      SZ OFF ENCODING         FORMAT                COMPILER              DWARF                 GENERIC                      GDB                   LLDB NATIVE            VALUE REGS    INVALIDATE REGS
150   //  ======    =======  == === =============    ============          ===================== ===================== ============================ ====================  ====================== ==========    ===============
151     { "eax",    NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_eax             , dwarf_eax           , LLDB_INVALID_REGNUM       , gdb_eax            , LLDB_INVALID_REGNUM },      NULL,              NULL},
152     { "ebx"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_ebx             , dwarf_ebx           , LLDB_INVALID_REGNUM       , gdb_ebx            , LLDB_INVALID_REGNUM },      NULL,              NULL},
153     { "ecx"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_ecx             , dwarf_ecx           , LLDB_REGNUM_GENERIC_ARG4  , gdb_ecx            , LLDB_INVALID_REGNUM },      NULL,              NULL},
154     { "edx"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_edx             , dwarf_edx           , LLDB_REGNUM_GENERIC_ARG3  , gdb_edx            , LLDB_INVALID_REGNUM },      NULL,              NULL},
155     { "esi"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_esi             , dwarf_esi           , LLDB_REGNUM_GENERIC_ARG2  , gdb_esi            , LLDB_INVALID_REGNUM },      NULL,              NULL},
156     { "edi"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_edi             , dwarf_edi           , LLDB_REGNUM_GENERIC_ARG1  , gdb_edi            , LLDB_INVALID_REGNUM },      NULL,              NULL},
157     { "ebp"   , "fp",    4,  0, eEncodingUint  , eFormatHex          , { gcc_ebp             , dwarf_ebp           , LLDB_REGNUM_GENERIC_FP    , gdb_ebp            , LLDB_INVALID_REGNUM },      NULL,              NULL},
158     { "esp"   , "sp",    4,  0, eEncodingUint  , eFormatHex          , { gcc_esp             , dwarf_esp           , LLDB_REGNUM_GENERIC_SP    , gdb_esp            , LLDB_INVALID_REGNUM },      NULL,              NULL},
159     { "eip"   , "pc",    4,  0, eEncodingUint  , eFormatHex          , { gcc_eip             , dwarf_eip           , LLDB_REGNUM_GENERIC_PC    , gdb_eip            , LLDB_INVALID_REGNUM },      NULL,              NULL},
160     { "eflags", NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags         , LLDB_INVALID_REGNUM },      NULL,              NULL},
161     { "cs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_cs             , LLDB_INVALID_REGNUM },      NULL,              NULL},
162     { "ss"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ss             , LLDB_INVALID_REGNUM },      NULL,              NULL},
163     { "ds"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ds             , LLDB_INVALID_REGNUM },      NULL,              NULL},
164     { "es"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_es             , LLDB_INVALID_REGNUM },      NULL,              NULL},
165     { "fs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fs             , LLDB_INVALID_REGNUM },      NULL,              NULL},
166     { "gs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_gs             , LLDB_INVALID_REGNUM },      NULL,              NULL},
167     { "stmm0" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm0         , LLDB_INVALID_REGNUM       , gdb_stmm0          , LLDB_INVALID_REGNUM },      NULL,              NULL},
168     { "stmm1" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm1         , LLDB_INVALID_REGNUM       , gdb_stmm1          , LLDB_INVALID_REGNUM },      NULL,              NULL},
169     { "stmm2" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm2         , LLDB_INVALID_REGNUM       , gdb_stmm2          , LLDB_INVALID_REGNUM },      NULL,              NULL},
170     { "stmm3" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm3         , LLDB_INVALID_REGNUM       , gdb_stmm3          , LLDB_INVALID_REGNUM },      NULL,              NULL},
171     { "stmm4" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm4         , LLDB_INVALID_REGNUM       , gdb_stmm4          , LLDB_INVALID_REGNUM },      NULL,              NULL},
172     { "stmm5" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm5         , LLDB_INVALID_REGNUM       , gdb_stmm5          , LLDB_INVALID_REGNUM },      NULL,              NULL},
173     { "stmm6" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm6         , LLDB_INVALID_REGNUM       , gdb_stmm6          , LLDB_INVALID_REGNUM },      NULL,              NULL},
174     { "stmm7" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm7         , LLDB_INVALID_REGNUM       , gdb_stmm7          , LLDB_INVALID_REGNUM },      NULL,              NULL},
175     { "fctrl" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fctrl          , LLDB_INVALID_REGNUM },      NULL,              NULL},
176     { "fstat" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fstat          , LLDB_INVALID_REGNUM },      NULL,              NULL},
177     { "ftag"  , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ftag           , LLDB_INVALID_REGNUM },      NULL,              NULL},
178     { "fiseg" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fiseg          , LLDB_INVALID_REGNUM },      NULL,              NULL},
179     { "fioff" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fioff          , LLDB_INVALID_REGNUM },      NULL,              NULL},
180     { "foseg" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_foseg          , LLDB_INVALID_REGNUM },      NULL,              NULL},
181     { "fooff" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fooff          , LLDB_INVALID_REGNUM },      NULL,              NULL},
182     { "fop"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fop            , LLDB_INVALID_REGNUM },      NULL,              NULL},
183     { "xmm0"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0          , LLDB_INVALID_REGNUM       , gdb_xmm0           , LLDB_INVALID_REGNUM },      NULL,              NULL},
184     { "xmm1"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1          , LLDB_INVALID_REGNUM       , gdb_xmm1           , LLDB_INVALID_REGNUM },      NULL,              NULL},
185     { "xmm2"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2          , LLDB_INVALID_REGNUM       , gdb_xmm2           , LLDB_INVALID_REGNUM },      NULL,              NULL},
186     { "xmm3"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3          , LLDB_INVALID_REGNUM       , gdb_xmm3           , LLDB_INVALID_REGNUM },      NULL,              NULL},
187     { "xmm4"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4          , LLDB_INVALID_REGNUM       , gdb_xmm4           , LLDB_INVALID_REGNUM },      NULL,              NULL},
188     { "xmm5"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5          , LLDB_INVALID_REGNUM       , gdb_xmm5           , LLDB_INVALID_REGNUM },      NULL,              NULL},
189     { "xmm6"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6          , LLDB_INVALID_REGNUM       , gdb_xmm6           , LLDB_INVALID_REGNUM },      NULL,              NULL},
190     { "xmm7"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7          , LLDB_INVALID_REGNUM       , gdb_xmm7           , LLDB_INVALID_REGNUM },      NULL,              NULL},
191     { "mxcsr" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_mxcsr          , LLDB_INVALID_REGNUM },      NULL,              NULL},
192     { "ymm0"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0          , LLDB_INVALID_REGNUM       , gdb_ymm0           , LLDB_INVALID_REGNUM },      NULL,              NULL},
193     { "ymm1"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1          , LLDB_INVALID_REGNUM       , gdb_ymm1           , LLDB_INVALID_REGNUM },      NULL,              NULL},
194     { "ymm2"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2          , LLDB_INVALID_REGNUM       , gdb_ymm2           , LLDB_INVALID_REGNUM },      NULL,              NULL},
195     { "ymm3"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3          , LLDB_INVALID_REGNUM       , gdb_ymm3           , LLDB_INVALID_REGNUM },      NULL,              NULL},
196     { "ymm4"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4          , LLDB_INVALID_REGNUM       , gdb_ymm4           , LLDB_INVALID_REGNUM },      NULL,              NULL},
197     { "ymm5"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5          , LLDB_INVALID_REGNUM       , gdb_ymm5           , LLDB_INVALID_REGNUM },      NULL,              NULL},
198     { "ymm6"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6          , LLDB_INVALID_REGNUM       , gdb_ymm6           , LLDB_INVALID_REGNUM },      NULL,              NULL},
199     { "ymm7"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7          , LLDB_INVALID_REGNUM       , gdb_ymm7           , LLDB_INVALID_REGNUM },      NULL,              NULL}
200 };
201 
202 static const uint32_t k_num_register_infos = sizeof(g_register_infos)/sizeof(RegisterInfo);
203 static bool g_register_info_names_constified = false;
204 
205 const lldb_private::RegisterInfo *
GetRegisterInfoArray(uint32_t & count)206 ABIMacOSX_i386::GetRegisterInfoArray (uint32_t &count)
207 {
208     // Make the C-string names and alt_names for the register infos into const
209     // C-string values by having the ConstString unique the names in the global
210     // constant C-string pool.
211     if (!g_register_info_names_constified)
212     {
213         g_register_info_names_constified = true;
214         for (uint32_t i=0; i<k_num_register_infos; ++i)
215         {
216             if (g_register_infos[i].name)
217                 g_register_infos[i].name = ConstString(g_register_infos[i].name).GetCString();
218             if (g_register_infos[i].alt_name)
219                 g_register_infos[i].alt_name = ConstString(g_register_infos[i].alt_name).GetCString();
220         }
221     }
222     count = k_num_register_infos;
223     return g_register_infos;
224 }
225 
226 size_t
GetRedZoneSize() const227 ABIMacOSX_i386::GetRedZoneSize () const
228 {
229     return 0;
230 }
231 
232 //------------------------------------------------------------------
233 // Static Functions
234 //------------------------------------------------------------------
235 ABISP
CreateInstance(const ArchSpec & arch)236 ABIMacOSX_i386::CreateInstance (const ArchSpec &arch)
237 {
238     static ABISP g_abi_sp;
239     if (arch.GetTriple().getArch() == llvm::Triple::x86)
240     {
241         if (!g_abi_sp)
242             g_abi_sp.reset (new ABIMacOSX_i386);
243         return g_abi_sp;
244     }
245     return ABISP();
246 }
247 
248 bool
PrepareTrivialCall(Thread & thread,addr_t sp,addr_t func_addr,addr_t return_addr,addr_t * arg1_ptr,addr_t * arg2_ptr,addr_t * arg3_ptr,addr_t * arg4_ptr,addr_t * arg5_ptr,addr_t * arg6_ptr) const249 ABIMacOSX_i386::PrepareTrivialCall (Thread &thread,
250                                     addr_t sp,
251                                     addr_t func_addr,
252                                     addr_t return_addr,
253                                     addr_t *arg1_ptr,
254                                     addr_t *arg2_ptr,
255                                     addr_t *arg3_ptr,
256                                     addr_t *arg4_ptr,
257                                     addr_t *arg5_ptr,
258                                     addr_t *arg6_ptr) const
259 {
260     RegisterContext *reg_ctx = thread.GetRegisterContext().get();
261     if (!reg_ctx)
262         return false;
263     uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
264     uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
265 
266     // When writing a register value down to memory, the register info used
267     // to write memory just needs to have the correct size of a 32 bit register,
268     // the actual register it pertains to is not important, just the size needs
269     // to be correct. Here we use "eax"...
270     const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
271     if (!reg_info_32)
272         return false; // TODO this should actually never happen
273 
274     // Make room for the argument(s) on the stack
275 
276     Error error;
277     RegisterValue reg_value;
278 
279     // Write any arguments onto the stack
280     if (arg1_ptr)
281     {
282         sp -= 4;
283         if (arg2_ptr)
284         {
285             sp -= 4;
286             if (arg3_ptr)
287             {
288                 sp -= 4;
289                 if (arg4_ptr)
290                 {
291                     sp -= 4;
292                     if (arg5_ptr)
293                     {
294                         sp -= 4;
295                         if (arg6_ptr)
296                         {
297                             sp -= 4;
298                         }
299                     }
300                 }
301             }
302         }
303     }
304 
305     // Align the SP
306     sp &= ~(16ull-1ull); // 16-byte alignment
307 
308     if (arg1_ptr)
309     {
310         reg_value.SetUInt32(*arg1_ptr);
311         error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
312                                                      sp,
313                                                      reg_info_32->byte_size,
314                                                      reg_value);
315         if (error.Fail())
316             return false;
317 
318         if (arg2_ptr)
319         {
320             reg_value.SetUInt32(*arg2_ptr);
321             // The register info used to write memory just needs to have the correct
322             // size of a 32 bit register, the actual register it pertains to is not
323             // important, just the size needs to be correct. Here we use "eax"...
324             error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
325                                                          sp + 4,
326                                                          reg_info_32->byte_size,
327                                                          reg_value);
328             if (error.Fail())
329                 return false;
330 
331             if (arg3_ptr)
332             {
333                 reg_value.SetUInt32(*arg3_ptr);
334                 // The register info used to write memory just needs to have the correct
335                 // size of a 32 bit register, the actual register it pertains to is not
336                 // important, just the size needs to be correct. Here we use "eax"...
337                 error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
338                                                              sp + 8,
339                                                              reg_info_32->byte_size,
340                                                              reg_value);
341                 if (error.Fail())
342                     return false;
343 
344                 if (arg4_ptr)
345                 {
346                     reg_value.SetUInt32(*arg4_ptr);
347                     // The register info used to write memory just needs to have the correct
348                     // size of a 32 bit register, the actual register it pertains to is not
349                     // important, just the size needs to be correct. Here we use "eax"...
350                     error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
351                                                                  sp + 12,
352                                                                  reg_info_32->byte_size,
353                                                                  reg_value);
354                     if (error.Fail())
355                         return false;
356                     if (arg5_ptr)
357                     {
358                         reg_value.SetUInt32(*arg5_ptr);
359                         // The register info used to write memory just needs to have the correct
360                         // size of a 32 bit register, the actual register it pertains to is not
361                         // important, just the size needs to be correct. Here we use "eax"...
362                         error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
363                                                                      sp + 16,
364                                                                      reg_info_32->byte_size,
365                                                                      reg_value);
366                         if (error.Fail())
367                             return false;
368                         if (arg6_ptr)
369                         {
370                             reg_value.SetUInt32(*arg6_ptr);
371                             // The register info used to write memory just needs to have the correct
372                             // size of a 32 bit register, the actual register it pertains to is not
373                             // important, just the size needs to be correct. Here we use "eax"...
374                             error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
375                                                                          sp + 20,
376                                                                          reg_info_32->byte_size,
377                                                                          reg_value);
378                             if (error.Fail())
379                                 return false;
380                         }
381                     }
382                 }
383             }
384         }
385     }
386 
387 
388     // The return address is pushed onto the stack (yes after we just set the
389     // alignment above!).
390     sp -= 4;
391     reg_value.SetUInt32(return_addr);
392     error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
393                                                  sp,
394                                                  reg_info_32->byte_size,
395                                                  reg_value);
396     if (error.Fail())
397         return false;
398 
399     // %esp is set to the actual stack value.
400 
401     if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_num, sp))
402         return false;
403 
404     // %eip is set to the address of the called function.
405 
406     if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_num, func_addr))
407         return false;
408 
409     return true;
410 }
411 
412 bool
PrepareNormalCall(Thread & thread,addr_t sp,addr_t func_addr,addr_t return_addr,ValueList & args) const413 ABIMacOSX_i386::PrepareNormalCall (Thread &thread,
414                                    addr_t sp,
415                                    addr_t func_addr,
416                                    addr_t return_addr,
417                                    ValueList &args) const
418 {
419     ExecutionContext exe_ctx (thread.shared_from_this());
420     RegisterContext *reg_ctx = thread.GetRegisterContext().get();
421     if (!reg_ctx)
422         return false;
423 
424     Process *process = exe_ctx.GetProcessPtr();
425     Error error;
426     uint32_t fp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
427     uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
428     uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
429 
430     // Do the argument layout
431 
432     std::vector <uint32_t> argLayout;   // 4-byte chunks, as discussed in the ABI Function Call Guide
433 
434     size_t numArgs = args.GetSize();
435     size_t index;
436 
437     for (index = 0; index < numArgs; ++index)
438     {
439         Value *val = args.GetValueAtIndex(index);
440 
441         if (!val)
442             return false;
443 
444         switch (val->GetValueType())
445         {
446         case Value::eValueTypeScalar:
447             {
448                 Scalar &scalar = val->GetScalar();
449                 switch (scalar.GetType())
450                 {
451                 case Scalar::e_void:
452                     return false;
453                 case Scalar::e_sint:
454                 case Scalar::e_uint:
455                 case Scalar::e_slong:
456                 case Scalar::e_ulong:
457                 case Scalar::e_slonglong:
458                 case Scalar::e_ulonglong:
459                     {
460                         uint64_t data = scalar.ULongLong();
461 
462                         switch (scalar.GetByteSize())
463                         {
464                         default:
465                             return false;
466                         case 1:
467                             argLayout.push_back((uint32_t)(data & 0xffull));
468                             break;
469                         case 2:
470                             argLayout.push_back((uint32_t)(data & 0xffffull));
471                             break;
472                         case 4:
473                             argLayout.push_back((uint32_t)(data & 0xffffffffull));
474                             break;
475                         case 8:
476                             argLayout.push_back((uint32_t)(data & 0xffffffffull));
477                             argLayout.push_back((uint32_t)(data >> 32));
478                             break;
479                         }
480                     }
481                     break;
482                 case Scalar::e_float:
483                     {
484                         float data = scalar.Float();
485                         uint32_t dataRaw = *((uint32_t*)(&data));
486                         argLayout.push_back(dataRaw);
487                     }
488                     break;
489                 case Scalar::e_double:
490                     {
491                         double data = scalar.Double();
492                         uint32_t *dataRaw = ((uint32_t*)(&data));
493                         argLayout.push_back(dataRaw[0]);
494                         argLayout.push_back(dataRaw[1]);
495                     }
496                     break;
497                 case Scalar::e_long_double:
498                     {
499                         long double data = scalar.Double();
500                         uint32_t *dataRaw = ((uint32_t*)(&data));
501                         while ((argLayout.size() * 4) & 0xf)
502                             argLayout.push_back(0);
503                         argLayout.push_back(dataRaw[0]);
504                         argLayout.push_back(dataRaw[1]);
505                         argLayout.push_back(dataRaw[2]);
506                         argLayout.push_back(dataRaw[3]);
507                     }
508                     break;
509                 }
510             }
511             break;
512         case Value::eValueTypeHostAddress:
513             {
514                 ClangASTType clang_type (val->GetClangType());
515                 if (clang_type)
516                 {
517                     uint32_t cstr_length = 0;
518                     if (clang_type.IsCStringType (cstr_length))
519                     {
520                         const char *cstr = (const char*)val->GetScalar().ULongLong();
521                         cstr_length = strlen(cstr);
522 
523                         // Push the string onto the stack immediately.
524 
525                         sp -= (cstr_length + 1);
526 
527                         if (process->WriteMemory(sp, cstr, cstr_length + 1, error) != (cstr_length + 1))
528                             return false;
529 
530                         // Put the address of the string into the argument array.
531 
532                         argLayout.push_back((uint32_t)(sp & 0xffffffff));
533                     }
534                     else
535                     {
536                         return false;
537                     }
538                 }
539                 break;
540             }
541             break;
542         case Value::eValueTypeFileAddress:
543         case Value::eValueTypeLoadAddress:
544         default:
545             return false;
546         }
547     }
548 
549     // Make room for the arguments on the stack
550 
551     sp -= 4 * argLayout.size();
552 
553     // Align the SP
554 
555     sp &= ~(16ull-1ull); // 16-byte alignment
556 
557     // Write the arguments on the stack
558 
559     size_t numChunks = argLayout.size();
560 
561     for (index = 0; index < numChunks; ++index)
562         if (process->WriteMemory(sp + (index * 4), &argLayout[index], sizeof(uint32_t), error) != sizeof(uint32_t))
563             return false;
564 
565     // The return address is pushed onto the stack.
566 
567     sp -= 4;
568     uint32_t returnAddressU32 = return_addr;
569     if (process->WriteMemory (sp, &returnAddressU32, sizeof(returnAddressU32), error) != sizeof(returnAddressU32))
570         return false;
571 
572     // %esp is set to the actual stack value.
573 
574     if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp))
575         return false;
576 
577     // %ebp is set to a fake value, in our case 0x0x00000000
578 
579     if (!reg_ctx->WriteRegisterFromUnsigned(fp_reg_num, 0x00000000))
580         return false;
581 
582     // %eip is set to the address of the called function.
583 
584     if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr))
585         return false;
586 
587     return true;
588 }
589 
590 static bool
ReadIntegerArgument(Scalar & scalar,unsigned int bit_width,bool is_signed,Process * process,addr_t & current_stack_argument)591 ReadIntegerArgument (Scalar           &scalar,
592                      unsigned int     bit_width,
593                      bool             is_signed,
594                      Process          *process,
595                      addr_t           &current_stack_argument)
596 {
597 
598     uint32_t byte_size = (bit_width + (8-1))/8;
599     Error error;
600     if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error))
601     {
602         current_stack_argument += byte_size;
603         return true;
604     }
605     return false;
606 }
607 
608 bool
GetArgumentValues(Thread & thread,ValueList & values) const609 ABIMacOSX_i386::GetArgumentValues (Thread &thread,
610                                    ValueList &values) const
611 {
612     unsigned int num_values = values.GetSize();
613     unsigned int value_index;
614 
615     // Get the pointer to the first stack argument so we have a place to start
616     // when reading data
617 
618     RegisterContext *reg_ctx = thread.GetRegisterContext().get();
619 
620     if (!reg_ctx)
621         return false;
622 
623     addr_t sp = reg_ctx->GetSP(0);
624 
625     if (!sp)
626         return false;
627 
628     addr_t current_stack_argument = sp + 4; // jump over return address
629 
630     for (value_index = 0;
631          value_index < num_values;
632          ++value_index)
633     {
634         Value *value = values.GetValueAtIndex(value_index);
635 
636         if (!value)
637             return false;
638 
639         // We currently only support extracting values with Clang QualTypes.
640         // Do we care about others?
641         ClangASTType clang_type (value->GetClangType());
642         if (clang_type)
643         {
644             bool is_signed;
645 
646             if (clang_type.IsIntegerType (is_signed))
647             {
648                 ReadIntegerArgument(value->GetScalar(),
649                                     clang_type.GetBitSize(),
650                                     is_signed,
651                                     thread.GetProcess().get(),
652                                     current_stack_argument);
653             }
654             else if (clang_type.IsPointerType())
655             {
656                 ReadIntegerArgument(value->GetScalar(),
657                                     clang_type.GetBitSize(),
658                                     false,
659                                     thread.GetProcess().get(),
660                                     current_stack_argument);
661             }
662         }
663     }
664 
665     return true;
666 }
667 
668 Error
SetReturnValueObject(lldb::StackFrameSP & frame_sp,lldb::ValueObjectSP & new_value_sp)669 ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
670 {
671     Error error;
672     if (!new_value_sp)
673     {
674         error.SetErrorString("Empty value object for return value.");
675         return error;
676     }
677 
678     ClangASTType clang_type = new_value_sp->GetClangType();
679     if (!clang_type)
680     {
681         error.SetErrorString ("Null clang type for return value.");
682         return error;
683     }
684 
685     Thread *thread = frame_sp->GetThread().get();
686 
687     bool is_signed;
688     uint32_t count;
689     bool is_complex;
690 
691     RegisterContext *reg_ctx = thread->GetRegisterContext().get();
692 
693     bool set_it_simple = false;
694     if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
695     {
696         DataExtractor data;
697         size_t num_bytes = new_value_sp->GetData(data);
698         lldb::offset_t offset = 0;
699         if (num_bytes <= 8)
700         {
701             const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
702             if (num_bytes <= 4)
703             {
704                 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
705 
706                 if (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value))
707                     set_it_simple = true;
708             }
709             else
710             {
711                 uint32_t raw_value = data.GetMaxU32(&offset, 4);
712 
713                 if (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value))
714                 {
715                     const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0);
716                     uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
717 
718                     if (reg_ctx->WriteRegisterFromUnsigned (edx_info, raw_value))
719                         set_it_simple = true;
720                 }
721             }
722         }
723         else
724         {
725             error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
726         }
727     }
728     else if (clang_type.IsFloatingPointType (count, is_complex))
729     {
730         if (is_complex)
731             error.SetErrorString ("We don't support returning complex values at present");
732         else
733             error.SetErrorString ("We don't support returning float values at present");
734     }
735 
736     if (!set_it_simple)
737         error.SetErrorString ("We only support setting simple integer return types at present.");
738 
739     return error;
740 }
741 
742 ValueObjectSP
GetReturnValueObjectImpl(Thread & thread,ClangASTType & clang_type) const743 ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
744                                           ClangASTType &clang_type) const
745 {
746     Value value;
747     ValueObjectSP return_valobj_sp;
748 
749     if (!clang_type)
750         return return_valobj_sp;
751 
752     //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType());
753     value.SetClangType (clang_type);
754 
755     RegisterContext *reg_ctx = thread.GetRegisterContext().get();
756         if (!reg_ctx)
757         return return_valobj_sp;
758 
759     bool is_signed;
760 
761     if (clang_type.IsIntegerType (is_signed))
762     {
763         size_t bit_width = clang_type.GetBitSize();
764 
765         unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
766         unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
767 
768         switch (bit_width)
769         {
770             default:
771             case 128:
772                 // Scalar can't hold 128-bit literals, so we don't handle this
773                 return return_valobj_sp;
774             case 64:
775                 uint64_t raw_value;
776                 raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
777                 raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32;
778                 if (is_signed)
779                     value.GetScalar() = (int64_t)raw_value;
780                 else
781                     value.GetScalar() = (uint64_t)raw_value;
782                 break;
783             case 32:
784                 if (is_signed)
785                     value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
786                 else
787                     value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
788                 break;
789             case 16:
790                 if (is_signed)
791                     value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
792                 else
793                     value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
794                 break;
795             case 8:
796                 if (is_signed)
797                     value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
798                 else
799                     value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
800                 break;
801         }
802     }
803     else if (clang_type.IsPointerType ())
804     {
805         unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
806         uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
807         value.GetScalar() = ptr;
808     }
809     else
810     {
811         // not handled yet
812         return return_valobj_sp;
813     }
814 
815     // If we get here, we have a valid Value, so make our ValueObject out of it:
816 
817     return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
818                                                       value,
819                                                       ConstString(""));
820     return return_valobj_sp;
821 }
822 
823 bool
CreateFunctionEntryUnwindPlan(UnwindPlan & unwind_plan)824 ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
825 {
826     uint32_t reg_kind = unwind_plan.GetRegisterKind();
827     uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
828     uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
829 
830     switch (reg_kind)
831     {
832         case eRegisterKindDWARF:
833             sp_reg_num = dwarf_esp;
834             pc_reg_num = dwarf_eip;
835             break;
836 
837         case eRegisterKindGCC:
838             sp_reg_num = gcc_esp;
839             pc_reg_num = gcc_eip;
840             break;
841 
842         case eRegisterKindGDB:
843             sp_reg_num = gdb_esp;
844             pc_reg_num = gdb_eip;
845             break;
846 
847         case eRegisterKindGeneric:
848             sp_reg_num = LLDB_REGNUM_GENERIC_SP;
849             pc_reg_num = LLDB_REGNUM_GENERIC_PC;
850             break;
851     }
852 
853     if (sp_reg_num == LLDB_INVALID_REGNUM ||
854         pc_reg_num == LLDB_INVALID_REGNUM)
855         return false;
856 
857     UnwindPlan::RowSP row(new UnwindPlan::Row);
858     row->SetCFARegister (sp_reg_num);
859     row->SetCFAOffset (4);
860     row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
861     unwind_plan.AppendRow (row);
862     unwind_plan.SetSourceName ("i386 at-func-entry default");
863     unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
864     return true;
865 }
866 
867 bool
CreateDefaultUnwindPlan(UnwindPlan & unwind_plan)868 ABIMacOSX_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
869 {
870     uint32_t fp_reg_num = dwarf_ebp;
871     uint32_t sp_reg_num = dwarf_esp;
872     uint32_t pc_reg_num = dwarf_eip;
873 
874     UnwindPlan::RowSP row(new UnwindPlan::Row);
875     const int32_t ptr_size = 4;
876 
877     unwind_plan.Clear ();
878     unwind_plan.SetRegisterKind (eRegisterKindDWARF);
879     row->SetCFARegister (fp_reg_num);
880     row->SetCFAOffset (2 * ptr_size);
881     row->SetOffset (0);
882 
883     row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
884     row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
885     row->SetRegisterLocationToAtCFAPlusOffset(sp_reg_num, ptr_size *  0, true);
886 
887     unwind_plan.AppendRow (row);
888     unwind_plan.SetSourceName ("i386 default unwind plan");
889     unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
890     unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
891     return true;
892 }
893 
894 bool
RegisterIsVolatile(const RegisterInfo * reg_info)895 ABIMacOSX_i386::RegisterIsVolatile (const RegisterInfo *reg_info)
896 {
897     return !RegisterIsCalleeSaved (reg_info);
898 }
899 
900 // v. http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130-IA-32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4
901 
902 bool
RegisterIsCalleeSaved(const RegisterInfo * reg_info)903 ABIMacOSX_i386::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
904 {
905     if (reg_info)
906     {
907         // Saved registers are ebx, ebp, esi, edi, esp, eip
908         const char *name = reg_info->name;
909         if (name[0] == 'e')
910         {
911             switch (name[1])
912             {
913             case 'b':
914                 if (name[2] == 'x' || name[2] == 'p')
915                     return name[3] == '\0';
916                 break;
917             case 'd':
918                 if (name[2] == 'i')
919                     return name[3] == '\0';
920                 break;
921             case 'i':
922                 if (name[2] == 'p')
923                     return name[3] == '\0';
924                 break;
925             case 's':
926                 if (name[2] == 'i' || name[2] == 'p')
927                     return name[3] == '\0';
928                 break;
929             }
930         }
931         if (name[0] == 's' && name[1] == 'p' && name[2] == '\0')   // sp
932             return true;
933         if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0')   // fp
934             return true;
935         if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0')   // pc
936             return true;
937     }
938     return false;
939 }
940 
941 void
Initialize()942 ABIMacOSX_i386::Initialize()
943 {
944     PluginManager::RegisterPlugin (GetPluginNameStatic(),
945                                    "Mac OS X ABI for i386 targets",
946                                    CreateInstance);
947 }
948 
949 void
Terminate()950 ABIMacOSX_i386::Terminate()
951 {
952     PluginManager::UnregisterPlugin (CreateInstance);
953 }
954 
955 lldb_private::ConstString
GetPluginNameStatic()956 ABIMacOSX_i386::GetPluginNameStatic ()
957 {
958     static ConstString g_short_name("abi.macosx-i386");
959     return g_short_name;
960 
961 }
962 
963 //------------------------------------------------------------------
964 // PluginInterface protocol
965 //------------------------------------------------------------------
966 lldb_private::ConstString
GetPluginName()967 ABIMacOSX_i386::GetPluginName()
968 {
969     return GetPluginNameStatic();
970 }
971 
972 uint32_t
GetPluginVersion()973 ABIMacOSX_i386::GetPluginVersion()
974 {
975     return 1;
976 }
977 
978