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
30using namespace lldb;
31using namespace lldb_private;
32
33enum
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
47enum
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
85enum
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
147static 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
202static const uint32_t k_num_register_infos = sizeof(g_register_infos)/sizeof(RegisterInfo);
203static bool g_register_info_names_constified = false;
204
205const lldb_private::RegisterInfo *
206ABIMacOSX_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
226size_t
227ABIMacOSX_i386::GetRedZoneSize () const
228{
229    return 0;
230}
231
232//------------------------------------------------------------------
233// Static Functions
234//------------------------------------------------------------------
235ABISP
236ABIMacOSX_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
248bool
249ABIMacOSX_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
412bool
413ABIMacOSX_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
590static bool
591ReadIntegerArgument (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
608bool
609ABIMacOSX_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
668Error
669ABIMacOSX_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
742ValueObjectSP
743ABIMacOSX_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
823bool
824ABIMacOSX_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
867bool
868ABIMacOSX_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
894bool
895ABIMacOSX_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
902bool
903ABIMacOSX_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
941void
942ABIMacOSX_i386::Initialize()
943{
944    PluginManager::RegisterPlugin (GetPluginNameStatic(),
945                                   "Mac OS X ABI for i386 targets",
946                                   CreateInstance);
947}
948
949void
950ABIMacOSX_i386::Terminate()
951{
952    PluginManager::UnregisterPlugin (CreateInstance);
953}
954
955lldb_private::ConstString
956ABIMacOSX_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//------------------------------------------------------------------
966lldb_private::ConstString
967ABIMacOSX_i386::GetPluginName()
968{
969    return GetPluginNameStatic();
970}
971
972uint32_t
973ABIMacOSX_i386::GetPluginVersion()
974{
975    return 1;
976}
977
978