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