1 //===-- ABIMacOSX_i386.cpp --------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "ABIMacOSX_i386.h"
16 // Other libraries and framework includes
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/Triple.h"
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"
35 using namespace lldb_private;
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
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
89 static RegisterInfo g_register_infos[] =
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 }
144 static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
145 static bool g_register_info_names_constified = false;
147 const lldb_private::RegisterInfo *
148 ABIMacOSX_i386::GetRegisterInfoArray (uint32_t &count)
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)
155 g_register_info_names_constified = true;
156 for (uint32_t i = 0; i < k_num_register_infos; ++i)
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();
164 count = k_num_register_infos;
165 return g_register_infos;
169 ABIMacOSX_i386::GetRedZoneSize () const
174 //------------------------------------------------------------------
176 //------------------------------------------------------------------
179 ABIMacOSX_i386::CreateInstance (const ArchSpec &arch)
181 static ABISP g_abi_sp;
182 if ((arch.GetTriple().getArch() == llvm::Triple::x86) &&
183 (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS() || arch.GetTriple().isWatchOS()))
186 g_abi_sp.reset (new ABIMacOSX_i386);
193 ABIMacOSX_i386::PrepareTrivialCall (Thread &thread,
197 llvm::ArrayRef<addr_t> args) const
199 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
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);
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");
211 return false; // TODO this should actually never happen
213 // Make room for the argument(s) on the stack
216 RegisterValue reg_value;
218 // Write any arguments onto the stack
219 sp -= 4 * args.size();
222 sp &= ~(16ull-1ull); // 16-byte alignment
226 for (addr_t arg : args)
228 reg_value.SetUInt32(arg);
229 error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
231 reg_info_32->byte_size,
238 // The return address is pushed onto the stack (yes after we just set the
239 // alignment above!).
241 reg_value.SetUInt32(return_addr);
242 error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
244 reg_info_32->byte_size,
249 // %esp is set to the actual stack value.
251 if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_num, sp))
254 // %eip is set to the address of the called function.
256 if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_num, func_addr))
263 ReadIntegerArgument (Scalar &scalar,
264 unsigned int bit_width,
267 addr_t ¤t_stack_argument)
270 uint32_t byte_size = (bit_width + (8-1))/8;
272 if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error))
274 current_stack_argument += byte_size;
281 ABIMacOSX_i386::GetArgumentValues (Thread &thread,
282 ValueList &values) const
284 unsigned int num_values = values.GetSize();
285 unsigned int value_index;
287 // Get the pointer to the first stack argument so we have a place to start
290 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
295 addr_t sp = reg_ctx->GetSP(0);
300 addr_t current_stack_argument = sp + 4; // jump over return address
302 for (value_index = 0;
303 value_index < num_values;
306 Value *value = values.GetValueAtIndex(value_index);
311 // We currently only support extracting values with Clang QualTypes.
312 // Do we care about others?
313 CompilerType compiler_type (value->GetCompilerType());
318 if (compiler_type.IsIntegerOrEnumerationType (is_signed))
320 ReadIntegerArgument(value->GetScalar(),
321 compiler_type.GetBitSize(&thread),
323 thread.GetProcess().get(),
324 current_stack_argument);
326 else if (compiler_type.IsPointerType())
328 ReadIntegerArgument(value->GetScalar(),
329 compiler_type.GetBitSize(&thread),
331 thread.GetProcess().get(),
332 current_stack_argument);
341 ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
346 error.SetErrorString("Empty value object for return value.");
350 CompilerType compiler_type = new_value_sp->GetCompilerType();
353 error.SetErrorString ("Null clang type for return value.");
357 Thread *thread = frame_sp->GetThread().get();
363 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
365 bool set_it_simple = false;
366 if (compiler_type.IsIntegerOrEnumerationType (is_signed) || compiler_type.IsPointerType())
370 size_t num_bytes = new_value_sp->GetData(data, data_error);
371 if (data_error.Fail())
373 error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
376 lldb::offset_t offset = 0;
379 const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
382 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
384 if (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value))
385 set_it_simple = true;
389 uint32_t raw_value = data.GetMaxU32(&offset, 4);
391 if (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value))
393 const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0);
394 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
396 if (reg_ctx->WriteRegisterFromUnsigned (edx_info, raw_value))
397 set_it_simple = true;
403 error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
406 else if (compiler_type.IsFloatingPointType (count, is_complex))
409 error.SetErrorString ("We don't support returning complex values at present");
411 error.SetErrorString ("We don't support returning float values at present");
415 error.SetErrorString ("We only support setting simple integer return types at present.");
421 ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
422 CompilerType &compiler_type) const
425 ValueObjectSP return_valobj_sp;
428 return return_valobj_sp;
430 //value.SetContext (Value::eContextTypeClangType, compiler_type.GetOpaqueQualType());
431 value.SetCompilerType (compiler_type);
433 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
435 return return_valobj_sp;
439 if (compiler_type.IsIntegerOrEnumerationType (is_signed))
441 size_t bit_width = compiler_type.GetBitSize(&thread);
443 unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
444 unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
450 // Scalar can't hold 128-bit literals, so we don't handle this
451 return return_valobj_sp;
454 raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
455 raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32;
457 value.GetScalar() = (int64_t)raw_value;
459 value.GetScalar() = (uint64_t)raw_value;
463 value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
465 value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
469 value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
471 value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
475 value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
477 value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
481 else if (compiler_type.IsPointerType ())
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;
490 return return_valobj_sp;
493 // If we get here, we have a valid Value, so make our ValueObject out of it:
495 return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
498 return return_valobj_sp;
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
506 ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
509 unwind_plan.SetRegisterKind (eRegisterKindDWARF);
511 uint32_t sp_reg_num = dwarf_esp;
512 uint32_t pc_reg_num = dwarf_eip;
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);
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
530 ABIMacOSX_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
532 unwind_plan.Clear ();
533 unwind_plan.SetRegisterKind (eRegisterKindDWARF);
535 uint32_t fp_reg_num = dwarf_ebp;
536 uint32_t sp_reg_num = dwarf_esp;
537 uint32_t pc_reg_num = dwarf_eip;
539 UnwindPlan::RowSP row(new UnwindPlan::Row);
540 const int32_t ptr_size = 4;
542 row->GetCFAValue().SetIsRegisterPlusOffset (fp_reg_num, 2 * ptr_size);
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);
549 unwind_plan.AppendRow (row);
550 unwind_plan.SetSourceName ("i386 default unwind plan");
551 unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
552 unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
557 ABIMacOSX_i386::RegisterIsVolatile (const RegisterInfo *reg_info)
559 return !RegisterIsCalleeSaved (reg_info);
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
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:
567 // ebx, ebp, esi, edi, esp
570 ABIMacOSX_i386::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
574 // Saved registers are ebx, ebp, esi, edi, esp, eip
575 const char *name = reg_info->name;
581 if (name[2] == 'x' || name[2] == 'p')
582 return name[3] == '\0';
586 return name[3] == '\0';
590 return name[3] == '\0';
593 if (name[2] == 'i' || name[2] == 'p')
594 return name[3] == '\0';
598 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
600 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
602 if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
609 ABIMacOSX_i386::Initialize()
611 PluginManager::RegisterPlugin (GetPluginNameStatic(),
612 "Mac OS X ABI for i386 targets",
617 ABIMacOSX_i386::Terminate()
619 PluginManager::UnregisterPlugin (CreateInstance);
622 lldb_private::ConstString
623 ABIMacOSX_i386::GetPluginNameStatic ()
625 static ConstString g_short_name("abi.macosx-i386");
630 //------------------------------------------------------------------
631 // PluginInterface protocol
632 //------------------------------------------------------------------
634 lldb_private::ConstString
635 ABIMacOSX_i386::GetPluginName()
637 return GetPluginNameStatic();
641 ABIMacOSX_i386::GetPluginVersion()