1 //===-- ABIMacOSX_i386.cpp --------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "ABIMacOSX_i386.h"
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/ADT/Triple.h"
16 #include "lldb/Core/Module.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/ValueObjectConstResult.h"
19 #include "lldb/Symbol/UnwindPlan.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/RegisterContext.h"
22 #include "lldb/Target/Target.h"
23 #include "lldb/Target/Thread.h"
24 #include "lldb/Utility/ConstString.h"
25 #include "lldb/Utility/RegisterValue.h"
26 #include "lldb/Utility/Scalar.h"
27 #include "lldb/Utility/Status.h"
30 using namespace lldb_private;
37 ehframe_ebp, // Different from DWARF the regnums - eh_frame esp/ebp had their
38 // regnums switched on i386 darwin
39 ehframe_esp, // Different from DWARF the regnums - eh_frame esp/ebp had their
40 // regnums switched on i386 darwin
74 dwarf_ymm0 = dwarf_xmm0,
75 dwarf_ymm1 = dwarf_xmm1,
76 dwarf_ymm2 = dwarf_xmm2,
77 dwarf_ymm3 = dwarf_xmm3,
78 dwarf_ymm4 = dwarf_xmm4,
79 dwarf_ymm5 = dwarf_xmm5,
80 dwarf_ymm6 = dwarf_xmm6,
81 dwarf_ymm7 = dwarf_xmm7
84 static RegisterInfo g_register_infos[] = {
85 // NAME ALT SZ OFF ENCODING FORMAT
86 // EH_FRAME DWARF GENERIC
87 // PROCESS PLUGIN LLDB NATIVE
88 // ====== ======= == === ============= ============
89 // ===================== ===================== ============================
90 // ==================== ======================
97 {ehframe_eax, dwarf_eax, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
109 {ehframe_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
110 LLDB_INVALID_REGNUM},
121 {ehframe_ecx, dwarf_ecx, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,
122 LLDB_INVALID_REGNUM},
133 {ehframe_edx, dwarf_edx, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,
134 LLDB_INVALID_REGNUM},
145 {ehframe_esi, dwarf_esi, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,
146 LLDB_INVALID_REGNUM},
157 {ehframe_edi, dwarf_edi, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,
158 LLDB_INVALID_REGNUM},
169 {ehframe_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
170 LLDB_INVALID_REGNUM},
181 {ehframe_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
182 LLDB_INVALID_REGNUM},
193 {ehframe_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
194 LLDB_INVALID_REGNUM},
205 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS,
206 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
217 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
218 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
229 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
230 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
241 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
242 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
253 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
254 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
265 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
266 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
277 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
278 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
288 eFormatVectorOfUInt8,
289 {LLDB_INVALID_REGNUM, dwarf_stmm0, LLDB_INVALID_REGNUM,
290 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
300 eFormatVectorOfUInt8,
301 {LLDB_INVALID_REGNUM, dwarf_stmm1, LLDB_INVALID_REGNUM,
302 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
312 eFormatVectorOfUInt8,
313 {LLDB_INVALID_REGNUM, dwarf_stmm2, LLDB_INVALID_REGNUM,
314 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
324 eFormatVectorOfUInt8,
325 {LLDB_INVALID_REGNUM, dwarf_stmm3, LLDB_INVALID_REGNUM,
326 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
336 eFormatVectorOfUInt8,
337 {LLDB_INVALID_REGNUM, dwarf_stmm4, LLDB_INVALID_REGNUM,
338 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
348 eFormatVectorOfUInt8,
349 {LLDB_INVALID_REGNUM, dwarf_stmm5, LLDB_INVALID_REGNUM,
350 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
360 eFormatVectorOfUInt8,
361 {LLDB_INVALID_REGNUM, dwarf_stmm6, LLDB_INVALID_REGNUM,
362 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
372 eFormatVectorOfUInt8,
373 {LLDB_INVALID_REGNUM, dwarf_stmm7, LLDB_INVALID_REGNUM,
374 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
385 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
386 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
397 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
398 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
409 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
410 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
421 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
422 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
433 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
434 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
445 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
446 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
457 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
458 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
469 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
470 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
480 eFormatVectorOfUInt8,
481 {LLDB_INVALID_REGNUM, dwarf_xmm0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
482 LLDB_INVALID_REGNUM},
492 eFormatVectorOfUInt8,
493 {LLDB_INVALID_REGNUM, dwarf_xmm1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
494 LLDB_INVALID_REGNUM},
504 eFormatVectorOfUInt8,
505 {LLDB_INVALID_REGNUM, dwarf_xmm2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
506 LLDB_INVALID_REGNUM},
516 eFormatVectorOfUInt8,
517 {LLDB_INVALID_REGNUM, dwarf_xmm3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
518 LLDB_INVALID_REGNUM},
528 eFormatVectorOfUInt8,
529 {LLDB_INVALID_REGNUM, dwarf_xmm4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
530 LLDB_INVALID_REGNUM},
540 eFormatVectorOfUInt8,
541 {LLDB_INVALID_REGNUM, dwarf_xmm5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
542 LLDB_INVALID_REGNUM},
552 eFormatVectorOfUInt8,
553 {LLDB_INVALID_REGNUM, dwarf_xmm6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
554 LLDB_INVALID_REGNUM},
564 eFormatVectorOfUInt8,
565 {LLDB_INVALID_REGNUM, dwarf_xmm7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
566 LLDB_INVALID_REGNUM},
577 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
578 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
588 eFormatVectorOfUInt8,
589 {LLDB_INVALID_REGNUM, dwarf_ymm0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
590 LLDB_INVALID_REGNUM},
600 eFormatVectorOfUInt8,
601 {LLDB_INVALID_REGNUM, dwarf_ymm1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
602 LLDB_INVALID_REGNUM},
612 eFormatVectorOfUInt8,
613 {LLDB_INVALID_REGNUM, dwarf_ymm2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
614 LLDB_INVALID_REGNUM},
624 eFormatVectorOfUInt8,
625 {LLDB_INVALID_REGNUM, dwarf_ymm3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
626 LLDB_INVALID_REGNUM},
636 eFormatVectorOfUInt8,
637 {LLDB_INVALID_REGNUM, dwarf_ymm4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
638 LLDB_INVALID_REGNUM},
648 eFormatVectorOfUInt8,
649 {LLDB_INVALID_REGNUM, dwarf_ymm5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
650 LLDB_INVALID_REGNUM},
660 eFormatVectorOfUInt8,
661 {LLDB_INVALID_REGNUM, dwarf_ymm6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
662 LLDB_INVALID_REGNUM},
672 eFormatVectorOfUInt8,
673 {LLDB_INVALID_REGNUM, dwarf_ymm7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
674 LLDB_INVALID_REGNUM},
680 static const uint32_t k_num_register_infos =
681 llvm::array_lengthof(g_register_infos);
682 static bool g_register_info_names_constified = false;
684 const lldb_private::RegisterInfo *
685 ABIMacOSX_i386::GetRegisterInfoArray(uint32_t &count) {
686 // Make the C-string names and alt_names for the register infos into const
687 // C-string values by having the ConstString unique the names in the global
688 // constant C-string pool.
689 if (!g_register_info_names_constified) {
690 g_register_info_names_constified = true;
691 for (uint32_t i = 0; i < k_num_register_infos; ++i) {
692 if (g_register_infos[i].name)
693 g_register_infos[i].name =
694 ConstString(g_register_infos[i].name).GetCString();
695 if (g_register_infos[i].alt_name)
696 g_register_infos[i].alt_name =
697 ConstString(g_register_infos[i].alt_name).GetCString();
700 count = k_num_register_infos;
701 return g_register_infos;
704 size_t ABIMacOSX_i386::GetRedZoneSize() const { return 0; }
709 ABIMacOSX_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
710 if ((arch.GetTriple().getArch() == llvm::Triple::x86) &&
711 (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS() ||
712 arch.GetTriple().isWatchOS())) {
713 return ABISP(new ABIMacOSX_i386(process_sp));
718 bool ABIMacOSX_i386::PrepareTrivialCall(Thread &thread, addr_t sp,
719 addr_t func_addr, addr_t return_addr,
720 llvm::ArrayRef<addr_t> args) const {
721 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
724 uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
725 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
726 uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
727 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
729 // When writing a register value down to memory, the register info used to
730 // write memory just needs to have the correct size of a 32 bit register, the
731 // actual register it pertains to is not important, just the size needs to be
732 // correct. Here we use "eax"...
733 const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
735 return false; // TODO this should actually never happen
737 // Make room for the argument(s) on the stack
740 RegisterValue reg_value;
742 // Write any arguments onto the stack
743 sp -= 4 * args.size();
746 sp &= ~(16ull - 1ull); // 16-byte alignment
750 for (addr_t arg : args) {
751 reg_value.SetUInt32(arg);
752 error = reg_ctx->WriteRegisterValueToMemory(
753 reg_info_32, arg_pos, reg_info_32->byte_size, reg_value);
759 // The return address is pushed onto the stack (yes after we just set the
760 // alignment above!).
762 reg_value.SetUInt32(return_addr);
763 error = reg_ctx->WriteRegisterValueToMemory(
764 reg_info_32, sp, reg_info_32->byte_size, reg_value);
768 // %esp is set to the actual stack value.
770 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp))
773 // %eip is set to the address of the called function.
775 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr))
781 static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width,
782 bool is_signed, Process *process,
783 addr_t ¤t_stack_argument) {
785 uint32_t byte_size = (bit_width + (8 - 1)) / 8;
787 if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size,
788 is_signed, scalar, error)) {
789 current_stack_argument += byte_size;
795 bool ABIMacOSX_i386::GetArgumentValues(Thread &thread,
796 ValueList &values) const {
797 unsigned int num_values = values.GetSize();
798 unsigned int value_index;
800 // Get the pointer to the first stack argument so we have a place to start
803 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
808 addr_t sp = reg_ctx->GetSP(0);
813 addr_t current_stack_argument = sp + 4; // jump over return address
815 for (value_index = 0; value_index < num_values; ++value_index) {
816 Value *value = values.GetValueAtIndex(value_index);
821 // We currently only support extracting values with Clang QualTypes. Do we
822 // care about others?
823 CompilerType compiler_type(value->GetCompilerType());
824 llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
827 if (compiler_type.IsIntegerOrEnumerationType(is_signed))
828 ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed,
829 thread.GetProcess().get(), current_stack_argument);
830 else if (compiler_type.IsPointerType())
831 ReadIntegerArgument(value->GetScalar(), *bit_size, false,
832 thread.GetProcess().get(), current_stack_argument);
839 Status ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
840 lldb::ValueObjectSP &new_value_sp) {
843 error.SetErrorString("Empty value object for return value.");
847 CompilerType compiler_type = new_value_sp->GetCompilerType();
848 if (!compiler_type) {
849 error.SetErrorString("Null clang type for return value.");
853 Thread *thread = frame_sp->GetThread().get();
859 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
861 bool set_it_simple = false;
862 if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
863 compiler_type.IsPointerType()) {
866 size_t num_bytes = new_value_sp->GetData(data, data_error);
867 if (data_error.Fail()) {
868 error.SetErrorStringWithFormat(
869 "Couldn't convert return value to raw data: %s",
870 data_error.AsCString());
873 lldb::offset_t offset = 0;
874 if (num_bytes <= 8) {
875 const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
876 if (num_bytes <= 4) {
877 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
879 if (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value))
880 set_it_simple = true;
882 uint32_t raw_value = data.GetMaxU32(&offset, 4);
884 if (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value)) {
885 const RegisterInfo *edx_info =
886 reg_ctx->GetRegisterInfoByName("edx", 0);
887 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
889 if (reg_ctx->WriteRegisterFromUnsigned(edx_info, raw_value))
890 set_it_simple = true;
894 error.SetErrorString("We don't support returning longer than 64 bit "
895 "integer values at present.");
897 } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
899 error.SetErrorString(
900 "We don't support returning complex values at present");
902 error.SetErrorString(
903 "We don't support returning float values at present");
907 error.SetErrorString(
908 "We only support setting simple integer return types at present.");
914 ABIMacOSX_i386::GetReturnValueObjectImpl(Thread &thread,
915 CompilerType &compiler_type) const {
917 ValueObjectSP return_valobj_sp;
920 return return_valobj_sp;
922 // value.SetContext (Value::eContextTypeClangType,
923 // compiler_type.GetOpaqueQualType());
924 value.SetCompilerType(compiler_type);
926 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
928 return return_valobj_sp;
932 if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
933 llvm::Optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread);
935 return return_valobj_sp;
937 reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
939 reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
941 switch (*bit_width) {
944 // Scalar can't hold 128-bit literals, so we don't handle this
945 return return_valobj_sp;
949 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
952 (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) &
956 value.GetScalar() = (int64_t)raw_value;
958 value.GetScalar() = (uint64_t)raw_value;
962 value.GetScalar() = (int32_t)(
963 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
966 value.GetScalar() = (uint32_t)(
967 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
972 value.GetScalar() = (int16_t)(
973 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
976 value.GetScalar() = (uint16_t)(
977 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
982 value.GetScalar() = (int8_t)(
983 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
986 value.GetScalar() = (uint8_t)(
987 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
991 } else if (compiler_type.IsPointerType()) {
993 reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
995 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
997 value.GetScalar() = ptr;
1000 return return_valobj_sp;
1003 // If we get here, we have a valid Value, so make our ValueObject out of it:
1005 return_valobj_sp = ValueObjectConstResult::Create(
1006 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
1007 return return_valobj_sp;
1010 // This defines the CFA as esp+4
1011 // the saved pc is at CFA-4 (i.e. esp+0)
1012 // The saved esp is CFA+0
1014 bool ABIMacOSX_i386::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
1015 unwind_plan.Clear();
1016 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1018 uint32_t sp_reg_num = dwarf_esp;
1019 uint32_t pc_reg_num = dwarf_eip;
1021 UnwindPlan::RowSP row(new UnwindPlan::Row);
1022 row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4);
1023 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
1024 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
1025 unwind_plan.AppendRow(row);
1026 unwind_plan.SetSourceName("i386 at-func-entry default");
1027 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1031 // This defines the CFA as ebp+8
1032 // The saved pc is at CFA-4 (i.e. ebp+4)
1033 // The saved ebp is at CFA-8 (i.e. ebp+0)
1034 // The saved esp is CFA+0
1036 bool ABIMacOSX_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
1037 unwind_plan.Clear();
1038 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1040 uint32_t fp_reg_num = dwarf_ebp;
1041 uint32_t sp_reg_num = dwarf_esp;
1042 uint32_t pc_reg_num = dwarf_eip;
1044 UnwindPlan::RowSP row(new UnwindPlan::Row);
1045 const int32_t ptr_size = 4;
1047 row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
1050 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
1051 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
1052 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
1054 unwind_plan.AppendRow(row);
1055 unwind_plan.SetSourceName("i386 default unwind plan");
1056 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1057 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
1061 bool ABIMacOSX_i386::RegisterIsVolatile(const RegisterInfo *reg_info) {
1062 return !RegisterIsCalleeSaved(reg_info);
1066 // http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130
1068 // 32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4
1070 // This document ("OS X ABI Function Call Guide", chapter "IA-32 Function
1071 // Calling Conventions") says that the following registers on i386 are
1072 // preserved aka non-volatile aka callee-saved:
1074 // ebx, ebp, esi, edi, esp
1076 bool ABIMacOSX_i386::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
1078 // Saved registers are ebx, ebp, esi, edi, esp, eip
1079 const char *name = reg_info->name;
1080 if (name[0] == 'e') {
1083 if (name[2] == 'x' || name[2] == 'p')
1084 return name[3] == '\0';
1088 return name[3] == '\0';
1092 return name[3] == '\0';
1095 if (name[2] == 'i' || name[2] == 'p')
1096 return name[3] == '\0';
1100 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
1102 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
1104 if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
1110 void ABIMacOSX_i386::Initialize() {
1111 PluginManager::RegisterPlugin(
1112 GetPluginNameStatic(), "Mac OS X ABI for i386 targets", CreateInstance);
1115 void ABIMacOSX_i386::Terminate() {
1116 PluginManager::UnregisterPlugin(CreateInstance);
1119 lldb_private::ConstString ABIMacOSX_i386::GetPluginNameStatic() {
1120 static ConstString g_short_name("abi.macosx-i386");
1121 return g_short_name;
1124 // PluginInterface protocol
1126 lldb_private::ConstString ABIMacOSX_i386::GetPluginName() {
1127 return GetPluginNameStatic();
1130 uint32_t ABIMacOSX_i386::GetPluginVersion() { return 1; }