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/Module.h"
22 #include "lldb/Core/PluginManager.h"
23 #include "lldb/Core/RegisterValue.h"
24 #include "lldb/Core/Scalar.h"
25 #include "lldb/Core/ValueObjectConstResult.h"
26 #include "lldb/Symbol/UnwindPlan.h"
27 #include "lldb/Target/Process.h"
28 #include "lldb/Target/RegisterContext.h"
29 #include "lldb/Target/Target.h"
30 #include "lldb/Target/Thread.h"
31 #include "lldb/Utility/ConstString.h"
32 #include "lldb/Utility/Status.h"
35 using namespace lldb_private;
42 ehframe_ebp, // Different from DWARF the regnums - eh_frame esp/ebp had their
43 // regnums switched on i386 darwin
44 ehframe_esp, // Different from DWARF the regnums - eh_frame esp/ebp had their
45 // 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[] = {
90 // NAME ALT SZ OFF ENCODING FORMAT
91 // EH_FRAME DWARF GENERIC
92 // PROCESS PLUGIN LLDB NATIVE
93 // ====== ======= == === ============= ============
94 // ===================== ===================== ============================
95 // ==================== ======================
102 {ehframe_eax, dwarf_eax, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
103 LLDB_INVALID_REGNUM},
114 {ehframe_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
115 LLDB_INVALID_REGNUM},
126 {ehframe_ecx, dwarf_ecx, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,
127 LLDB_INVALID_REGNUM},
138 {ehframe_edx, dwarf_edx, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,
139 LLDB_INVALID_REGNUM},
150 {ehframe_esi, dwarf_esi, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,
151 LLDB_INVALID_REGNUM},
162 {ehframe_edi, dwarf_edi, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,
163 LLDB_INVALID_REGNUM},
174 {ehframe_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
175 LLDB_INVALID_REGNUM},
186 {ehframe_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
187 LLDB_INVALID_REGNUM},
198 {ehframe_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
199 LLDB_INVALID_REGNUM},
210 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS,
211 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
222 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
223 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
234 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
235 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
246 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
247 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
258 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
259 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
270 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
271 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
282 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
283 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
293 eFormatVectorOfUInt8,
294 {LLDB_INVALID_REGNUM, dwarf_stmm0, LLDB_INVALID_REGNUM,
295 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
305 eFormatVectorOfUInt8,
306 {LLDB_INVALID_REGNUM, dwarf_stmm1, LLDB_INVALID_REGNUM,
307 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
317 eFormatVectorOfUInt8,
318 {LLDB_INVALID_REGNUM, dwarf_stmm2, LLDB_INVALID_REGNUM,
319 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
329 eFormatVectorOfUInt8,
330 {LLDB_INVALID_REGNUM, dwarf_stmm3, LLDB_INVALID_REGNUM,
331 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
341 eFormatVectorOfUInt8,
342 {LLDB_INVALID_REGNUM, dwarf_stmm4, LLDB_INVALID_REGNUM,
343 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
353 eFormatVectorOfUInt8,
354 {LLDB_INVALID_REGNUM, dwarf_stmm5, LLDB_INVALID_REGNUM,
355 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
365 eFormatVectorOfUInt8,
366 {LLDB_INVALID_REGNUM, dwarf_stmm6, LLDB_INVALID_REGNUM,
367 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
377 eFormatVectorOfUInt8,
378 {LLDB_INVALID_REGNUM, dwarf_stmm7, LLDB_INVALID_REGNUM,
379 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
390 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
391 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
402 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
403 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
414 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
415 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
426 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
427 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
438 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
439 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
450 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
451 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
462 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
463 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
474 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
475 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
485 eFormatVectorOfUInt8,
486 {LLDB_INVALID_REGNUM, dwarf_xmm0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
487 LLDB_INVALID_REGNUM},
497 eFormatVectorOfUInt8,
498 {LLDB_INVALID_REGNUM, dwarf_xmm1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
499 LLDB_INVALID_REGNUM},
509 eFormatVectorOfUInt8,
510 {LLDB_INVALID_REGNUM, dwarf_xmm2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
511 LLDB_INVALID_REGNUM},
521 eFormatVectorOfUInt8,
522 {LLDB_INVALID_REGNUM, dwarf_xmm3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
523 LLDB_INVALID_REGNUM},
533 eFormatVectorOfUInt8,
534 {LLDB_INVALID_REGNUM, dwarf_xmm4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
535 LLDB_INVALID_REGNUM},
545 eFormatVectorOfUInt8,
546 {LLDB_INVALID_REGNUM, dwarf_xmm5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
547 LLDB_INVALID_REGNUM},
557 eFormatVectorOfUInt8,
558 {LLDB_INVALID_REGNUM, dwarf_xmm6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
559 LLDB_INVALID_REGNUM},
569 eFormatVectorOfUInt8,
570 {LLDB_INVALID_REGNUM, dwarf_xmm7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
571 LLDB_INVALID_REGNUM},
582 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
583 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
593 eFormatVectorOfUInt8,
594 {LLDB_INVALID_REGNUM, dwarf_ymm0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
595 LLDB_INVALID_REGNUM},
605 eFormatVectorOfUInt8,
606 {LLDB_INVALID_REGNUM, dwarf_ymm1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
607 LLDB_INVALID_REGNUM},
617 eFormatVectorOfUInt8,
618 {LLDB_INVALID_REGNUM, dwarf_ymm2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
619 LLDB_INVALID_REGNUM},
629 eFormatVectorOfUInt8,
630 {LLDB_INVALID_REGNUM, dwarf_ymm3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
631 LLDB_INVALID_REGNUM},
641 eFormatVectorOfUInt8,
642 {LLDB_INVALID_REGNUM, dwarf_ymm4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
643 LLDB_INVALID_REGNUM},
653 eFormatVectorOfUInt8,
654 {LLDB_INVALID_REGNUM, dwarf_ymm5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
655 LLDB_INVALID_REGNUM},
665 eFormatVectorOfUInt8,
666 {LLDB_INVALID_REGNUM, dwarf_ymm6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
667 LLDB_INVALID_REGNUM},
677 eFormatVectorOfUInt8,
678 {LLDB_INVALID_REGNUM, dwarf_ymm7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
679 LLDB_INVALID_REGNUM},
685 static const uint32_t k_num_register_infos =
686 llvm::array_lengthof(g_register_infos);
687 static bool g_register_info_names_constified = false;
689 const lldb_private::RegisterInfo *
690 ABIMacOSX_i386::GetRegisterInfoArray(uint32_t &count) {
691 // Make the C-string names and alt_names for the register infos into const
692 // C-string values by having the ConstString unique the names in the global
693 // constant C-string pool.
694 if (!g_register_info_names_constified) {
695 g_register_info_names_constified = true;
696 for (uint32_t i = 0; i < k_num_register_infos; ++i) {
697 if (g_register_infos[i].name)
698 g_register_infos[i].name =
699 ConstString(g_register_infos[i].name).GetCString();
700 if (g_register_infos[i].alt_name)
701 g_register_infos[i].alt_name =
702 ConstString(g_register_infos[i].alt_name).GetCString();
705 count = k_num_register_infos;
706 return g_register_infos;
709 size_t ABIMacOSX_i386::GetRedZoneSize() const { return 0; }
711 //------------------------------------------------------------------
713 //------------------------------------------------------------------
716 ABIMacOSX_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
717 static ABISP g_abi_sp;
718 if ((arch.GetTriple().getArch() == llvm::Triple::x86) &&
719 (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS() ||
720 arch.GetTriple().isWatchOS())) {
722 g_abi_sp.reset(new ABIMacOSX_i386(process_sp));
728 bool ABIMacOSX_i386::PrepareTrivialCall(Thread &thread, addr_t sp,
729 addr_t func_addr, addr_t return_addr,
730 llvm::ArrayRef<addr_t> args) const {
731 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
734 uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
735 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
736 uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
737 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
739 // When writing a register value down to memory, the register info used
740 // to write memory just needs to have the correct size of a 32 bit register,
741 // the actual register it pertains to is not important, just the size needs
742 // to be correct. Here we use "eax"...
743 const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
745 return false; // TODO this should actually never happen
747 // Make room for the argument(s) on the stack
750 RegisterValue reg_value;
752 // Write any arguments onto the stack
753 sp -= 4 * args.size();
756 sp &= ~(16ull - 1ull); // 16-byte alignment
760 for (addr_t arg : args) {
761 reg_value.SetUInt32(arg);
762 error = reg_ctx->WriteRegisterValueToMemory(
763 reg_info_32, arg_pos, reg_info_32->byte_size, reg_value);
769 // The return address is pushed onto the stack (yes after we just set the
770 // alignment above!).
772 reg_value.SetUInt32(return_addr);
773 error = reg_ctx->WriteRegisterValueToMemory(
774 reg_info_32, sp, reg_info_32->byte_size, reg_value);
778 // %esp is set to the actual stack value.
780 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp))
783 // %eip is set to the address of the called function.
785 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr))
791 static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width,
792 bool is_signed, Process *process,
793 addr_t ¤t_stack_argument) {
795 uint32_t byte_size = (bit_width + (8 - 1)) / 8;
797 if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size,
798 is_signed, scalar, error)) {
799 current_stack_argument += byte_size;
805 bool ABIMacOSX_i386::GetArgumentValues(Thread &thread,
806 ValueList &values) const {
807 unsigned int num_values = values.GetSize();
808 unsigned int value_index;
810 // Get the pointer to the first stack argument so we have a place to start
813 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
818 addr_t sp = reg_ctx->GetSP(0);
823 addr_t current_stack_argument = sp + 4; // jump over return address
825 for (value_index = 0; value_index < num_values; ++value_index) {
826 Value *value = values.GetValueAtIndex(value_index);
831 // We currently only support extracting values with Clang QualTypes.
832 // Do we care about others?
833 CompilerType compiler_type(value->GetCompilerType());
837 if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
838 ReadIntegerArgument(value->GetScalar(),
839 compiler_type.GetBitSize(&thread), is_signed,
840 thread.GetProcess().get(), current_stack_argument);
841 } else if (compiler_type.IsPointerType()) {
842 ReadIntegerArgument(value->GetScalar(),
843 compiler_type.GetBitSize(&thread), false,
844 thread.GetProcess().get(), current_stack_argument);
852 Status ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
853 lldb::ValueObjectSP &new_value_sp) {
856 error.SetErrorString("Empty value object for return value.");
860 CompilerType compiler_type = new_value_sp->GetCompilerType();
861 if (!compiler_type) {
862 error.SetErrorString("Null clang type for return value.");
866 Thread *thread = frame_sp->GetThread().get();
872 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
874 bool set_it_simple = false;
875 if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
876 compiler_type.IsPointerType()) {
879 size_t num_bytes = new_value_sp->GetData(data, data_error);
880 if (data_error.Fail()) {
881 error.SetErrorStringWithFormat(
882 "Couldn't convert return value to raw data: %s",
883 data_error.AsCString());
886 lldb::offset_t offset = 0;
887 if (num_bytes <= 8) {
888 const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
889 if (num_bytes <= 4) {
890 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
892 if (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value))
893 set_it_simple = true;
895 uint32_t raw_value = data.GetMaxU32(&offset, 4);
897 if (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value)) {
898 const RegisterInfo *edx_info =
899 reg_ctx->GetRegisterInfoByName("edx", 0);
900 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
902 if (reg_ctx->WriteRegisterFromUnsigned(edx_info, raw_value))
903 set_it_simple = true;
907 error.SetErrorString("We don't support returning longer than 64 bit "
908 "integer values at present.");
910 } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
912 error.SetErrorString(
913 "We don't support returning complex values at present");
915 error.SetErrorString(
916 "We don't support returning float values at present");
920 error.SetErrorString(
921 "We only support setting simple integer return types at present.");
927 ABIMacOSX_i386::GetReturnValueObjectImpl(Thread &thread,
928 CompilerType &compiler_type) const {
930 ValueObjectSP return_valobj_sp;
933 return return_valobj_sp;
935 // value.SetContext (Value::eContextTypeClangType,
936 // compiler_type.GetOpaqueQualType());
937 value.SetCompilerType(compiler_type);
939 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
941 return return_valobj_sp;
945 if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
946 size_t bit_width = compiler_type.GetBitSize(&thread);
949 reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
951 reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
956 // Scalar can't hold 128-bit literals, so we don't handle this
957 return return_valobj_sp;
961 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
964 (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) &
968 value.GetScalar() = (int64_t)raw_value;
970 value.GetScalar() = (uint64_t)raw_value;
974 value.GetScalar() = (int32_t)(
975 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
978 value.GetScalar() = (uint32_t)(
979 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
984 value.GetScalar() = (int16_t)(
985 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
988 value.GetScalar() = (uint16_t)(
989 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
994 value.GetScalar() = (int8_t)(
995 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
998 value.GetScalar() = (uint8_t)(
999 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
1003 } else if (compiler_type.IsPointerType()) {
1005 reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
1007 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
1009 value.GetScalar() = ptr;
1012 return return_valobj_sp;
1015 // If we get here, we have a valid Value, so make our ValueObject out of it:
1017 return_valobj_sp = ValueObjectConstResult::Create(
1018 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
1019 return return_valobj_sp;
1022 // This defines the CFA as esp+4
1023 // the saved pc is at CFA-4 (i.e. esp+0)
1024 // The saved esp is CFA+0
1026 bool ABIMacOSX_i386::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
1027 unwind_plan.Clear();
1028 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1030 uint32_t sp_reg_num = dwarf_esp;
1031 uint32_t pc_reg_num = dwarf_eip;
1033 UnwindPlan::RowSP row(new UnwindPlan::Row);
1034 row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4);
1035 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
1036 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
1037 unwind_plan.AppendRow(row);
1038 unwind_plan.SetSourceName("i386 at-func-entry default");
1039 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1043 // This defines the CFA as ebp+8
1044 // The saved pc is at CFA-4 (i.e. ebp+4)
1045 // The saved ebp is at CFA-8 (i.e. ebp+0)
1046 // The saved esp is CFA+0
1048 bool ABIMacOSX_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
1049 unwind_plan.Clear();
1050 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1052 uint32_t fp_reg_num = dwarf_ebp;
1053 uint32_t sp_reg_num = dwarf_esp;
1054 uint32_t pc_reg_num = dwarf_eip;
1056 UnwindPlan::RowSP row(new UnwindPlan::Row);
1057 const int32_t ptr_size = 4;
1059 row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
1062 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
1063 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
1064 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
1066 unwind_plan.AppendRow(row);
1067 unwind_plan.SetSourceName("i386 default unwind plan");
1068 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1069 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
1073 bool ABIMacOSX_i386::RegisterIsVolatile(const RegisterInfo *reg_info) {
1074 return !RegisterIsCalleeSaved(reg_info);
1078 // http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130-IA-32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4
1080 // This document ("OS X ABI Function Call Guide", chapter "IA-32 Function
1081 // Calling Conventions")
1082 // says that the following registers on i386 are preserved aka non-volatile aka
1085 // ebx, ebp, esi, edi, esp
1087 bool ABIMacOSX_i386::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
1089 // Saved registers are ebx, ebp, esi, edi, esp, eip
1090 const char *name = reg_info->name;
1091 if (name[0] == 'e') {
1094 if (name[2] == 'x' || name[2] == 'p')
1095 return name[3] == '\0';
1099 return name[3] == '\0';
1103 return name[3] == '\0';
1106 if (name[2] == 'i' || name[2] == 'p')
1107 return name[3] == '\0';
1111 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
1113 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
1115 if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
1121 void ABIMacOSX_i386::Initialize() {
1122 PluginManager::RegisterPlugin(
1123 GetPluginNameStatic(), "Mac OS X ABI for i386 targets", CreateInstance);
1126 void ABIMacOSX_i386::Terminate() {
1127 PluginManager::UnregisterPlugin(CreateInstance);
1130 lldb_private::ConstString ABIMacOSX_i386::GetPluginNameStatic() {
1131 static ConstString g_short_name("abi.macosx-i386");
1132 return g_short_name;
1135 //------------------------------------------------------------------
1136 // PluginInterface protocol
1137 //------------------------------------------------------------------
1139 lldb_private::ConstString ABIMacOSX_i386::GetPluginName() {
1140 return GetPluginNameStatic();
1143 uint32_t ABIMacOSX_i386::GetPluginVersion() { return 1; }