]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
Import mandoc 1.4.1rc2
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Plugins / ABI / MacOSX-i386 / ABIMacOSX_i386.cpp
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 // C Includes
13 // C++ Includes
14 #include <vector>
15
16 // Other libraries and framework includes
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/Triple.h"
19
20 // Project includes
21 #include "lldb/Core/ConstString.h"
22 #include "lldb/Core/Error.h"
23 #include "lldb/Core/Module.h"
24 #include "lldb/Core/PluginManager.h"
25 #include "lldb/Core/RegisterValue.h"
26 #include "lldb/Core/Scalar.h"
27 #include "lldb/Core/ValueObjectConstResult.h"
28 #include "lldb/Symbol/UnwindPlan.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/RegisterContext.h"
31 #include "lldb/Target/Target.h"
32 #include "lldb/Target/Thread.h"
33
34 using namespace lldb;
35 using namespace lldb_private;
36
37 enum
38 {
39     ehframe_eax = 0,
40     ehframe_ecx,
41     ehframe_edx,
42     ehframe_ebx,
43     ehframe_ebp,   // Different from DWARF the regnums - eh_frame esp/ebp had their regnums switched on i386 darwin
44     ehframe_esp,   // Different from DWARF the regnums - eh_frame esp/ebp had their regnums switched on i386 darwin
45     ehframe_esi,
46     ehframe_edi,
47     ehframe_eip,
48     ehframe_eflags
49 };
50
51 enum
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
89 static RegisterInfo g_register_infos[] = 
90 {
91   //  NAME      ALT      SZ OFF ENCODING         FORMAT                EH_FRAME              DWARF                 GENERIC                      PROCESS PLUGIN        LLDB NATIVE            VALUE REGS    INVALIDATE REGS
92   //  ======    =======  == === =============    ============          ===================== ===================== ============================ ====================  ====================== ==========    ===============
93     { "eax",    nullptr, 4,  0, eEncodingUint  , eFormatHex          , { ehframe_eax         , dwarf_eax           , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
94     { "ebx"   , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { ehframe_ebx         , dwarf_ebx           , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
95     { "ecx"   , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { ehframe_ecx         , dwarf_ecx           , LLDB_REGNUM_GENERIC_ARG4  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
96     { "edx"   , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { ehframe_edx         , dwarf_edx           , LLDB_REGNUM_GENERIC_ARG3  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
97     { "esi"   , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { ehframe_esi         , dwarf_esi           , LLDB_REGNUM_GENERIC_ARG2  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
98     { "edi"   , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { ehframe_edi         , dwarf_edi           , LLDB_REGNUM_GENERIC_ARG1  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
99     { "ebp"   , "fp",    4,  0, eEncodingUint  , eFormatHex          , { ehframe_ebp         , dwarf_ebp           , LLDB_REGNUM_GENERIC_FP    , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
100     { "esp"   , "sp",    4,  0, eEncodingUint  , eFormatHex          , { ehframe_esp         , dwarf_esp           , LLDB_REGNUM_GENERIC_SP    , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
101     { "eip"   , "pc",    4,  0, eEncodingUint  , eFormatHex          , { ehframe_eip         , dwarf_eip           , LLDB_REGNUM_GENERIC_PC    , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
102     { "eflags", nullptr, 4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
103     { "cs"    , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
104     { "ss"    , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
105     { "ds"    , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
106     { "es"    , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
107     { "fs"    , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
108     { "gs"    , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
109     { "stmm0" , nullptr,10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm0         , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
110     { "stmm1" , nullptr,10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm1         , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
111     { "stmm2" , nullptr,10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm2         , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
112     { "stmm3" , nullptr,10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm3         , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
113     { "stmm4" , nullptr,10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm4         , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
114     { "stmm5" , nullptr,10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm5         , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
115     { "stmm6" , nullptr,10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm6         , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
116     { "stmm7" , nullptr,10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm7         , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
117     { "fctrl" , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
118     { "fstat" , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
119     { "ftag"  , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
120     { "fiseg" , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
121     { "fioff" , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
122     { "foseg" , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
123     { "fooff" , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
124     { "fop"   , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
125     { "xmm0"  , nullptr,16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
126     { "xmm1"  , nullptr,16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
127     { "xmm2"  , nullptr,16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
128     { "xmm3"  , nullptr,16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
129     { "xmm4"  , nullptr,16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
130     { "xmm5"  , nullptr,16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
131     { "xmm6"  , nullptr,16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
132     { "xmm7"  , nullptr,16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
133     { "mxcsr" , nullptr, 4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
134     { "ymm0"  , nullptr,32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
135     { "ymm1"  , nullptr,32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
136     { "ymm2"  , nullptr,32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
137     { "ymm3"  , nullptr,32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
138     { "ymm4"  , nullptr,32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
139     { "ymm5"  , nullptr,32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
140     { "ymm6"  , nullptr,32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr },
141     { "ymm7"  , nullptr,32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,           nullptr }
142 };
143
144 static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
145 static bool g_register_info_names_constified = false;
146
147 const lldb_private::RegisterInfo *
148 ABIMacOSX_i386::GetRegisterInfoArray (uint32_t &count)
149 {
150     // Make the C-string names and alt_names for the register infos into const 
151     // C-string values by having the ConstString unique the names in the global
152     // constant C-string pool.
153     if (!g_register_info_names_constified)
154     {
155         g_register_info_names_constified = true;
156         for (uint32_t i = 0; i < k_num_register_infos; ++i)
157         {
158             if (g_register_infos[i].name)
159                 g_register_infos[i].name = ConstString(g_register_infos[i].name).GetCString();
160             if (g_register_infos[i].alt_name)
161                 g_register_infos[i].alt_name = ConstString(g_register_infos[i].alt_name).GetCString();
162         }
163     }
164     count = k_num_register_infos;
165     return g_register_infos;
166 }
167
168 size_t
169 ABIMacOSX_i386::GetRedZoneSize () const
170 {
171     return 0;
172 }
173
174 //------------------------------------------------------------------
175 // Static Functions
176 //------------------------------------------------------------------
177
178 ABISP
179 ABIMacOSX_i386::CreateInstance (const ArchSpec &arch)
180 {
181     static ABISP g_abi_sp;
182      if ((arch.GetTriple().getArch() == llvm::Triple::x86) &&
183           (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS() || arch.GetTriple().isWatchOS()))
184      {
185         if (!g_abi_sp)
186             g_abi_sp.reset (new ABIMacOSX_i386);
187         return g_abi_sp;
188     }
189     return ABISP();
190 }
191
192 bool
193 ABIMacOSX_i386::PrepareTrivialCall (Thread &thread, 
194                                     addr_t sp, 
195                                     addr_t func_addr, 
196                                     addr_t return_addr, 
197                                     llvm::ArrayRef<addr_t> args) const
198 {
199     RegisterContext *reg_ctx = thread.GetRegisterContext().get();
200     if (!reg_ctx)
201         return false;    
202     uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
203     uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
204     
205     // When writing a register value down to memory, the register info used 
206     // to write memory just needs to have the correct size of a 32 bit register, 
207     // the actual register it pertains to is not important, just the size needs 
208     // to be correct. Here we use "eax"...
209     const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
210     if (!reg_info_32)
211         return false; // TODO this should actually never happen
212
213     // Make room for the argument(s) on the stack
214
215     Error error;
216     RegisterValue reg_value;
217     
218     // Write any arguments onto the stack
219     sp -= 4 * args.size();
220     
221     // Align the SP    
222     sp &= ~(16ull-1ull); // 16-byte alignment
223     
224     addr_t arg_pos = sp;
225     
226     for (addr_t arg : args)
227     {
228         reg_value.SetUInt32(arg);
229         error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
230                                                      arg_pos,
231                                                      reg_info_32->byte_size,
232                                                      reg_value);
233         if (error.Fail())
234             return false;
235         arg_pos += 4;
236     }
237     
238     // The return address is pushed onto the stack (yes after we just set the
239     // alignment above!).
240     sp -= 4;
241     reg_value.SetUInt32(return_addr);
242     error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 
243                                                  sp, 
244                                                  reg_info_32->byte_size, 
245                                                  reg_value);
246     if (error.Fail())
247         return false;
248     
249     // %esp is set to the actual stack value.
250     
251     if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_num, sp))
252         return false;
253     
254     // %eip is set to the address of the called function.
255     
256     if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_num, func_addr))
257         return false;
258     
259     return true;
260 }
261
262 static bool 
263 ReadIntegerArgument (Scalar           &scalar,
264                      unsigned int     bit_width,
265                      bool             is_signed,
266                      Process          *process,
267                      addr_t           &current_stack_argument)
268 {
269     
270     uint32_t byte_size = (bit_width + (8-1))/8;
271     Error error;
272     if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error))
273     {
274         current_stack_argument += byte_size;
275         return true;
276     }
277     return false;
278 }
279
280 bool
281 ABIMacOSX_i386::GetArgumentValues (Thread &thread,
282                                    ValueList &values) const
283 {
284     unsigned int num_values = values.GetSize();
285     unsigned int value_index;
286     
287     // Get the pointer to the first stack argument so we have a place to start 
288     // when reading data
289     
290     RegisterContext *reg_ctx = thread.GetRegisterContext().get();
291     
292     if (!reg_ctx)
293         return false;
294     
295     addr_t sp = reg_ctx->GetSP(0);
296     
297     if (!sp)
298         return false;
299     
300     addr_t current_stack_argument = sp + 4; // jump over return address
301     
302     for (value_index = 0;
303          value_index < num_values;
304          ++value_index)
305     {
306         Value *value = values.GetValueAtIndex(value_index);
307         
308         if (!value)
309             return false;
310         
311         // We currently only support extracting values with Clang QualTypes.
312         // Do we care about others?
313         CompilerType compiler_type (value->GetCompilerType());
314         if (compiler_type)
315         {
316             bool is_signed;
317             
318             if (compiler_type.IsIntegerOrEnumerationType (is_signed))
319             {
320                 ReadIntegerArgument(value->GetScalar(),
321                                     compiler_type.GetBitSize(&thread),
322                                     is_signed,
323                                     thread.GetProcess().get(), 
324                                     current_stack_argument);
325             }
326             else if (compiler_type.IsPointerType())
327             {
328                 ReadIntegerArgument(value->GetScalar(),
329                                     compiler_type.GetBitSize(&thread),
330                                     false,
331                                     thread.GetProcess().get(),
332                                     current_stack_argument);
333             }
334         }
335     }
336     
337     return true;
338 }
339
340 Error
341 ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
342 {
343     Error error;
344     if (!new_value_sp)
345     {
346         error.SetErrorString("Empty value object for return value.");
347         return error;
348     }
349     
350     CompilerType compiler_type = new_value_sp->GetCompilerType();
351     if (!compiler_type)
352     {
353         error.SetErrorString ("Null clang type for return value.");
354         return error;
355     }
356     
357     Thread *thread = frame_sp->GetThread().get();
358     
359     bool is_signed;
360     uint32_t count;
361     bool is_complex;
362     
363     RegisterContext *reg_ctx = thread->GetRegisterContext().get();
364
365     bool set_it_simple = false;
366     if (compiler_type.IsIntegerOrEnumerationType (is_signed) || compiler_type.IsPointerType())
367     {
368         DataExtractor data;
369         Error data_error;
370         size_t num_bytes = new_value_sp->GetData(data, data_error);
371         if (data_error.Fail())
372         {
373             error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
374             return error;
375         }
376         lldb::offset_t offset = 0;
377         if (num_bytes <= 8)
378         {
379             const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
380             if (num_bytes <= 4)
381             {
382                 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
383         
384                 if (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value))
385                     set_it_simple = true;
386             }
387             else
388             {
389                 uint32_t raw_value = data.GetMaxU32(&offset, 4);
390         
391                 if (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value))
392                 {
393                     const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0);
394                     uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
395                 
396                     if (reg_ctx->WriteRegisterFromUnsigned (edx_info, raw_value))
397                         set_it_simple = true;
398                 }
399             }
400         }
401         else
402         {
403             error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
404         }
405     }
406     else if (compiler_type.IsFloatingPointType (count, is_complex))
407     {
408         if (is_complex)
409             error.SetErrorString ("We don't support returning complex values at present");
410         else
411             error.SetErrorString ("We don't support returning float values at present");
412     }
413     
414     if (!set_it_simple)
415         error.SetErrorString ("We only support setting simple integer return types at present.");
416     
417     return error;
418 }
419
420 ValueObjectSP
421 ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
422                                           CompilerType &compiler_type) const
423 {
424     Value value;
425     ValueObjectSP return_valobj_sp;
426     
427     if (!compiler_type)
428         return return_valobj_sp;
429     
430     //value.SetContext (Value::eContextTypeClangType, compiler_type.GetOpaqueQualType());
431     value.SetCompilerType (compiler_type);
432     
433     RegisterContext *reg_ctx = thread.GetRegisterContext().get();
434         if (!reg_ctx)
435         return return_valobj_sp;
436         
437     bool is_signed;
438             
439     if (compiler_type.IsIntegerOrEnumerationType (is_signed))
440     {
441         size_t bit_width = compiler_type.GetBitSize(&thread);
442         
443         unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
444         unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
445         
446         switch (bit_width)
447         {
448             default:
449             case 128:
450                 // Scalar can't hold 128-bit literals, so we don't handle this
451                 return return_valobj_sp;
452             case 64:
453                 uint64_t raw_value;
454                 raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
455                 raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32;
456                 if (is_signed)
457                     value.GetScalar() = (int64_t)raw_value;
458                 else
459                     value.GetScalar() = (uint64_t)raw_value;
460                 break;
461             case 32:
462                 if (is_signed)
463                     value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
464                 else
465                     value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
466                 break;
467             case 16:
468                 if (is_signed)
469                     value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
470                 else
471                     value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
472                 break;
473             case 8:
474                 if (is_signed)
475                     value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
476                 else
477                     value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
478                 break;
479         }
480     }
481     else if (compiler_type.IsPointerType ())
482     {
483         unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
484         uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
485         value.GetScalar() = ptr;
486     }
487     else
488     {
489         // not handled yet
490         return return_valobj_sp;
491     }
492     
493     // If we get here, we have a valid Value, so make our ValueObject out of it:
494     
495     return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
496                                                       value,
497                                                       ConstString(""));
498     return return_valobj_sp;
499 }
500
501 // This defines the CFA as esp+4
502 // the saved pc is at CFA-4 (i.e. esp+0)
503 // The saved esp is CFA+0
504
505 bool
506 ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
507 {
508     unwind_plan.Clear();
509     unwind_plan.SetRegisterKind (eRegisterKindDWARF);
510
511     uint32_t sp_reg_num = dwarf_esp;
512     uint32_t pc_reg_num = dwarf_eip;
513     
514     UnwindPlan::RowSP row(new UnwindPlan::Row);
515     row->GetCFAValue().SetIsRegisterPlusOffset (sp_reg_num, 4);
516     row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
517     row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
518     unwind_plan.AppendRow (row);
519     unwind_plan.SetSourceName ("i386 at-func-entry default");
520     unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
521     return true;
522 }
523
524 // This defines the CFA as ebp+8
525 // The saved pc is at CFA-4 (i.e. ebp+4)
526 // The saved ebp is at CFA-8 (i.e. ebp+0)
527 // The saved esp is CFA+0
528
529 bool
530 ABIMacOSX_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
531 {
532     unwind_plan.Clear ();
533     unwind_plan.SetRegisterKind (eRegisterKindDWARF);
534
535     uint32_t fp_reg_num = dwarf_ebp;
536     uint32_t sp_reg_num = dwarf_esp;
537     uint32_t pc_reg_num = dwarf_eip;
538     
539     UnwindPlan::RowSP row(new UnwindPlan::Row);
540     const int32_t ptr_size = 4;
541
542     row->GetCFAValue().SetIsRegisterPlusOffset (fp_reg_num, 2 * ptr_size);
543     row->SetOffset (0);
544     
545     row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
546     row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
547     row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
548
549     unwind_plan.AppendRow (row);
550     unwind_plan.SetSourceName ("i386 default unwind plan");
551     unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
552     unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
553     return true;
554 }
555
556 bool
557 ABIMacOSX_i386::RegisterIsVolatile (const RegisterInfo *reg_info)
558 {
559     return !RegisterIsCalleeSaved (reg_info);
560 }
561
562 // 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
563 //
564 // This document ("OS X ABI Function Call Guide", chapter "IA-32 Function Calling Conventions")
565 // says that the following registers on i386 are preserved aka non-volatile aka callee-saved:
566 // 
567 // ebx, ebp, esi, edi, esp
568
569 bool
570 ABIMacOSX_i386::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
571 {
572     if (reg_info)
573     {
574         // Saved registers are ebx, ebp, esi, edi, esp, eip
575         const char *name = reg_info->name;
576         if (name[0] == 'e')
577         {
578             switch (name[1])
579             {
580             case 'b': 
581                 if (name[2] == 'x' || name[2] == 'p')
582                     return name[3] == '\0';
583                 break;
584             case 'd':
585                 if (name[2] == 'i')
586                     return name[3] == '\0';
587                 break;
588             case 'i': 
589                 if (name[2] == 'p')
590                     return name[3] == '\0';
591                 break;
592             case 's':
593                 if (name[2] == 'i' || name[2] == 'p')
594                     return name[3] == '\0';
595                 break;
596             }
597         }
598         if (name[0] == 's' && name[1] == 'p' && name[2] == '\0')   // sp
599             return true;
600         if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0')   // fp
601             return true;
602         if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0')   // pc
603             return true;
604     }
605     return false;
606 }
607
608 void
609 ABIMacOSX_i386::Initialize()
610 {
611     PluginManager::RegisterPlugin (GetPluginNameStatic(),
612                                    "Mac OS X ABI for i386 targets",
613                                    CreateInstance);    
614 }
615
616 void
617 ABIMacOSX_i386::Terminate()
618 {
619     PluginManager::UnregisterPlugin (CreateInstance);
620 }
621
622 lldb_private::ConstString
623 ABIMacOSX_i386::GetPluginNameStatic ()
624 {
625     static ConstString g_short_name("abi.macosx-i386");
626     return g_short_name;
627     
628 }
629
630 //------------------------------------------------------------------
631 // PluginInterface protocol
632 //------------------------------------------------------------------
633
634 lldb_private::ConstString
635 ABIMacOSX_i386::GetPluginName()
636 {
637     return GetPluginNameStatic();
638 }
639
640 uint32_t
641 ABIMacOSX_i386::GetPluginVersion()
642 {
643     return 1;
644 }