1 //===-- ABIMacOSX_arm.cpp -------------------------------------------------===//
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_arm.h"
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/TargetParser/Triple.h"
17 #include "lldb/Core/Module.h"
18 #include "lldb/Core/PluginManager.h"
19 #include "lldb/Core/Value.h"
20 #include "lldb/Symbol/UnwindPlan.h"
21 #include "lldb/Target/Process.h"
22 #include "lldb/Target/RegisterContext.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Target/Thread.h"
25 #include "lldb/Utility/ConstString.h"
26 #include "lldb/Utility/RegisterValue.h"
27 #include "lldb/Utility/Scalar.h"
28 #include "lldb/Utility/Status.h"
29 #include "lldb/ValueObject/ValueObjectConstResult.h"
31 #include "Plugins/Process/Utility/ARMDefines.h"
32 #include "Utility/ARM_DWARF_Registers.h"
33 #include "Utility/ARM_ehframe_Registers.h"
36 using namespace lldb_private
;
38 static const RegisterInfo g_register_infos
[] = {
45 {ehframe_r0
, dwarf_r0
, LLDB_REGNUM_GENERIC_ARG1
, LLDB_INVALID_REGNUM
,
57 {ehframe_r1
, dwarf_r1
, LLDB_REGNUM_GENERIC_ARG2
, LLDB_INVALID_REGNUM
,
69 {ehframe_r2
, dwarf_r2
, LLDB_REGNUM_GENERIC_ARG3
, LLDB_INVALID_REGNUM
,
81 {ehframe_r3
, dwarf_r3
, LLDB_REGNUM_GENERIC_ARG4
, LLDB_INVALID_REGNUM
,
93 {ehframe_r4
, dwarf_r4
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
105 {ehframe_r5
, dwarf_r5
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
106 LLDB_INVALID_REGNUM
},
117 {ehframe_r6
, dwarf_r6
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
118 LLDB_INVALID_REGNUM
},
129 {ehframe_r7
, dwarf_r7
, LLDB_REGNUM_GENERIC_FP
, LLDB_INVALID_REGNUM
,
130 LLDB_INVALID_REGNUM
},
141 {ehframe_r8
, dwarf_r8
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
142 LLDB_INVALID_REGNUM
},
153 {ehframe_r9
, dwarf_r9
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
154 LLDB_INVALID_REGNUM
},
165 {ehframe_r10
, dwarf_r10
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
166 LLDB_INVALID_REGNUM
},
177 {ehframe_r11
, dwarf_r11
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
178 LLDB_INVALID_REGNUM
},
189 {ehframe_r12
, dwarf_r12
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
190 LLDB_INVALID_REGNUM
},
201 {ehframe_sp
, dwarf_sp
, LLDB_REGNUM_GENERIC_SP
, LLDB_INVALID_REGNUM
,
202 LLDB_INVALID_REGNUM
},
213 {ehframe_lr
, dwarf_lr
, LLDB_REGNUM_GENERIC_RA
, LLDB_INVALID_REGNUM
,
214 LLDB_INVALID_REGNUM
},
225 {ehframe_pc
, dwarf_pc
, LLDB_REGNUM_GENERIC_PC
, LLDB_INVALID_REGNUM
,
226 LLDB_INVALID_REGNUM
},
237 {ehframe_cpsr
, dwarf_cpsr
, LLDB_REGNUM_GENERIC_FLAGS
, LLDB_INVALID_REGNUM
,
238 LLDB_INVALID_REGNUM
},
249 {LLDB_INVALID_REGNUM
, dwarf_s0
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
250 LLDB_INVALID_REGNUM
},
261 {LLDB_INVALID_REGNUM
, dwarf_s1
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
262 LLDB_INVALID_REGNUM
},
273 {LLDB_INVALID_REGNUM
, dwarf_s2
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
274 LLDB_INVALID_REGNUM
},
285 {LLDB_INVALID_REGNUM
, dwarf_s3
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
286 LLDB_INVALID_REGNUM
},
297 {LLDB_INVALID_REGNUM
, dwarf_s4
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
298 LLDB_INVALID_REGNUM
},
309 {LLDB_INVALID_REGNUM
, dwarf_s5
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
310 LLDB_INVALID_REGNUM
},
321 {LLDB_INVALID_REGNUM
, dwarf_s6
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
322 LLDB_INVALID_REGNUM
},
333 {LLDB_INVALID_REGNUM
, dwarf_s7
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
334 LLDB_INVALID_REGNUM
},
345 {LLDB_INVALID_REGNUM
, dwarf_s8
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
346 LLDB_INVALID_REGNUM
},
357 {LLDB_INVALID_REGNUM
, dwarf_s9
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
358 LLDB_INVALID_REGNUM
},
369 {LLDB_INVALID_REGNUM
, dwarf_s10
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
370 LLDB_INVALID_REGNUM
},
381 {LLDB_INVALID_REGNUM
, dwarf_s11
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
382 LLDB_INVALID_REGNUM
},
393 {LLDB_INVALID_REGNUM
, dwarf_s12
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
394 LLDB_INVALID_REGNUM
},
405 {LLDB_INVALID_REGNUM
, dwarf_s13
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
406 LLDB_INVALID_REGNUM
},
417 {LLDB_INVALID_REGNUM
, dwarf_s14
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
418 LLDB_INVALID_REGNUM
},
429 {LLDB_INVALID_REGNUM
, dwarf_s15
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
430 LLDB_INVALID_REGNUM
},
441 {LLDB_INVALID_REGNUM
, dwarf_s16
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
442 LLDB_INVALID_REGNUM
},
453 {LLDB_INVALID_REGNUM
, dwarf_s17
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
454 LLDB_INVALID_REGNUM
},
465 {LLDB_INVALID_REGNUM
, dwarf_s18
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
466 LLDB_INVALID_REGNUM
},
477 {LLDB_INVALID_REGNUM
, dwarf_s19
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
478 LLDB_INVALID_REGNUM
},
489 {LLDB_INVALID_REGNUM
, dwarf_s20
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
490 LLDB_INVALID_REGNUM
},
501 {LLDB_INVALID_REGNUM
, dwarf_s21
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
502 LLDB_INVALID_REGNUM
},
513 {LLDB_INVALID_REGNUM
, dwarf_s22
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
514 LLDB_INVALID_REGNUM
},
525 {LLDB_INVALID_REGNUM
, dwarf_s23
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
526 LLDB_INVALID_REGNUM
},
537 {LLDB_INVALID_REGNUM
, dwarf_s24
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
538 LLDB_INVALID_REGNUM
},
549 {LLDB_INVALID_REGNUM
, dwarf_s25
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
550 LLDB_INVALID_REGNUM
},
561 {LLDB_INVALID_REGNUM
, dwarf_s26
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
562 LLDB_INVALID_REGNUM
},
573 {LLDB_INVALID_REGNUM
, dwarf_s27
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
574 LLDB_INVALID_REGNUM
},
585 {LLDB_INVALID_REGNUM
, dwarf_s28
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
586 LLDB_INVALID_REGNUM
},
597 {LLDB_INVALID_REGNUM
, dwarf_s29
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
598 LLDB_INVALID_REGNUM
},
609 {LLDB_INVALID_REGNUM
, dwarf_s30
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
610 LLDB_INVALID_REGNUM
},
621 {LLDB_INVALID_REGNUM
, dwarf_s31
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
622 LLDB_INVALID_REGNUM
},
633 {LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
634 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
645 {LLDB_INVALID_REGNUM
, dwarf_d0
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
646 LLDB_INVALID_REGNUM
},
657 {LLDB_INVALID_REGNUM
, dwarf_d1
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
658 LLDB_INVALID_REGNUM
},
669 {LLDB_INVALID_REGNUM
, dwarf_d2
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
670 LLDB_INVALID_REGNUM
},
681 {LLDB_INVALID_REGNUM
, dwarf_d3
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
682 LLDB_INVALID_REGNUM
},
693 {LLDB_INVALID_REGNUM
, dwarf_d4
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
694 LLDB_INVALID_REGNUM
},
705 {LLDB_INVALID_REGNUM
, dwarf_d5
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
706 LLDB_INVALID_REGNUM
},
717 {LLDB_INVALID_REGNUM
, dwarf_d6
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
718 LLDB_INVALID_REGNUM
},
729 {LLDB_INVALID_REGNUM
, dwarf_d7
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
730 LLDB_INVALID_REGNUM
},
741 {LLDB_INVALID_REGNUM
, dwarf_d8
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
742 LLDB_INVALID_REGNUM
},
753 {LLDB_INVALID_REGNUM
, dwarf_d9
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
754 LLDB_INVALID_REGNUM
},
765 {LLDB_INVALID_REGNUM
, dwarf_d10
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
766 LLDB_INVALID_REGNUM
},
777 {LLDB_INVALID_REGNUM
, dwarf_d11
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
778 LLDB_INVALID_REGNUM
},
789 {LLDB_INVALID_REGNUM
, dwarf_d12
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
790 LLDB_INVALID_REGNUM
},
801 {LLDB_INVALID_REGNUM
, dwarf_d13
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
802 LLDB_INVALID_REGNUM
},
813 {LLDB_INVALID_REGNUM
, dwarf_d14
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
814 LLDB_INVALID_REGNUM
},
825 {LLDB_INVALID_REGNUM
, dwarf_d15
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
826 LLDB_INVALID_REGNUM
},
837 {LLDB_INVALID_REGNUM
, dwarf_d16
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
838 LLDB_INVALID_REGNUM
},
849 {LLDB_INVALID_REGNUM
, dwarf_d17
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
850 LLDB_INVALID_REGNUM
},
861 {LLDB_INVALID_REGNUM
, dwarf_d18
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
862 LLDB_INVALID_REGNUM
},
873 {LLDB_INVALID_REGNUM
, dwarf_d19
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
874 LLDB_INVALID_REGNUM
},
885 {LLDB_INVALID_REGNUM
, dwarf_d20
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
886 LLDB_INVALID_REGNUM
},
897 {LLDB_INVALID_REGNUM
, dwarf_d21
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
898 LLDB_INVALID_REGNUM
},
909 {LLDB_INVALID_REGNUM
, dwarf_d22
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
910 LLDB_INVALID_REGNUM
},
921 {LLDB_INVALID_REGNUM
, dwarf_d23
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
922 LLDB_INVALID_REGNUM
},
933 {LLDB_INVALID_REGNUM
, dwarf_d24
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
934 LLDB_INVALID_REGNUM
},
945 {LLDB_INVALID_REGNUM
, dwarf_d25
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
946 LLDB_INVALID_REGNUM
},
957 {LLDB_INVALID_REGNUM
, dwarf_d26
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
958 LLDB_INVALID_REGNUM
},
969 {LLDB_INVALID_REGNUM
, dwarf_d27
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
970 LLDB_INVALID_REGNUM
},
981 {LLDB_INVALID_REGNUM
, dwarf_d28
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
982 LLDB_INVALID_REGNUM
},
993 {LLDB_INVALID_REGNUM
, dwarf_d29
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
994 LLDB_INVALID_REGNUM
},
1005 {LLDB_INVALID_REGNUM
, dwarf_d30
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
1006 LLDB_INVALID_REGNUM
},
1017 {LLDB_INVALID_REGNUM
, dwarf_d31
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
1018 LLDB_INVALID_REGNUM
},
1029 {LLDB_INVALID_REGNUM
, dwarf_r8_usr
, LLDB_INVALID_REGNUM
,
1030 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1041 {LLDB_INVALID_REGNUM
, dwarf_r9_usr
, LLDB_INVALID_REGNUM
,
1042 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1053 {LLDB_INVALID_REGNUM
, dwarf_r10_usr
, LLDB_INVALID_REGNUM
,
1054 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1065 {LLDB_INVALID_REGNUM
, dwarf_r11_usr
, LLDB_INVALID_REGNUM
,
1066 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1077 {LLDB_INVALID_REGNUM
, dwarf_r12_usr
, LLDB_INVALID_REGNUM
,
1078 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1089 {LLDB_INVALID_REGNUM
, dwarf_r13_usr
, LLDB_INVALID_REGNUM
,
1090 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1101 {LLDB_INVALID_REGNUM
, dwarf_r14_usr
, LLDB_INVALID_REGNUM
,
1102 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1113 {LLDB_INVALID_REGNUM
, dwarf_r8_fiq
, LLDB_INVALID_REGNUM
,
1114 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1125 {LLDB_INVALID_REGNUM
, dwarf_r9_fiq
, LLDB_INVALID_REGNUM
,
1126 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1137 {LLDB_INVALID_REGNUM
, dwarf_r10_fiq
, LLDB_INVALID_REGNUM
,
1138 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1149 {LLDB_INVALID_REGNUM
, dwarf_r11_fiq
, LLDB_INVALID_REGNUM
,
1150 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1161 {LLDB_INVALID_REGNUM
, dwarf_r12_fiq
, LLDB_INVALID_REGNUM
,
1162 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1173 {LLDB_INVALID_REGNUM
, dwarf_r13_fiq
, LLDB_INVALID_REGNUM
,
1174 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1185 {LLDB_INVALID_REGNUM
, dwarf_r14_fiq
, LLDB_INVALID_REGNUM
,
1186 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1197 {LLDB_INVALID_REGNUM
, dwarf_r13_irq
, LLDB_INVALID_REGNUM
,
1198 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1209 {LLDB_INVALID_REGNUM
, dwarf_r14_irq
, LLDB_INVALID_REGNUM
,
1210 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1221 {LLDB_INVALID_REGNUM
, dwarf_r13_abt
, LLDB_INVALID_REGNUM
,
1222 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1233 {LLDB_INVALID_REGNUM
, dwarf_r14_abt
, LLDB_INVALID_REGNUM
,
1234 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1245 {LLDB_INVALID_REGNUM
, dwarf_r13_und
, LLDB_INVALID_REGNUM
,
1246 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1257 {LLDB_INVALID_REGNUM
, dwarf_r14_und
, LLDB_INVALID_REGNUM
,
1258 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1269 {LLDB_INVALID_REGNUM
, dwarf_r13_svc
, LLDB_INVALID_REGNUM
,
1270 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1281 {LLDB_INVALID_REGNUM
, dwarf_r14_svc
, LLDB_INVALID_REGNUM
,
1282 LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
},
1288 static const uint32_t k_num_register_infos
= std::size(g_register_infos
);
1290 const lldb_private::RegisterInfo
*
1291 ABIMacOSX_arm::GetRegisterInfoArray(uint32_t &count
) {
1292 count
= k_num_register_infos
;
1293 return g_register_infos
;
1296 size_t ABIMacOSX_arm::GetRedZoneSize() const { return 0; }
1301 ABIMacOSX_arm::CreateInstance(ProcessSP process_sp
, const ArchSpec
&arch
) {
1302 const llvm::Triple::ArchType arch_type
= arch
.GetTriple().getArch();
1303 const llvm::Triple::VendorType vendor_type
= arch
.GetTriple().getVendor();
1305 if (vendor_type
== llvm::Triple::Apple
) {
1306 if ((arch_type
== llvm::Triple::arm
) ||
1307 (arch_type
== llvm::Triple::thumb
)) {
1309 new ABIMacOSX_arm(std::move(process_sp
), MakeMCRegisterInfo(arch
)));
1316 bool ABIMacOSX_arm::PrepareTrivialCall(Thread
&thread
, addr_t sp
,
1317 addr_t function_addr
, addr_t return_addr
,
1318 llvm::ArrayRef
<addr_t
> args
) const {
1319 RegisterContext
*reg_ctx
= thread
.GetRegisterContext().get();
1323 const uint32_t pc_reg_num
= reg_ctx
->ConvertRegisterKindToRegisterNumber(
1324 eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_PC
);
1325 const uint32_t sp_reg_num
= reg_ctx
->ConvertRegisterKindToRegisterNumber(
1326 eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_SP
);
1327 const uint32_t ra_reg_num
= reg_ctx
->ConvertRegisterKindToRegisterNumber(
1328 eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_RA
);
1330 RegisterValue reg_value
;
1332 const char *reg_names
[] = {"r0", "r1", "r2", "r3"};
1334 llvm::ArrayRef
<addr_t
>::iterator ai
= args
.begin(), ae
= args
.end();
1336 for (size_t i
= 0; i
< std::size(reg_names
); ++i
) {
1340 reg_value
.SetUInt32(*ai
);
1341 if (!reg_ctx
->WriteRegister(reg_ctx
->GetRegisterInfoByName(reg_names
[i
]),
1349 // Spill onto the stack
1350 size_t num_stack_regs
= ae
- ai
;
1352 sp
-= (num_stack_regs
* 4);
1353 // Keep the stack 16 byte aligned
1354 sp
&= ~(16ull - 1ull);
1356 // just using arg1 to get the right size
1357 const RegisterInfo
*reg_info
= reg_ctx
->GetRegisterInfo(
1358 eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_ARG1
);
1360 addr_t arg_pos
= sp
;
1362 for (; ai
!= ae
; ++ai
) {
1363 reg_value
.SetUInt32(*ai
);
1365 ->WriteRegisterValueToMemory(reg_info
, arg_pos
,
1366 reg_info
->byte_size
, reg_value
)
1369 arg_pos
+= reg_info
->byte_size
;
1373 TargetSP
target_sp(thread
.CalculateTarget());
1376 // Figure out if our return address is ARM or Thumb by using the
1377 // Address::GetCallableLoadAddress(Target*) which will figure out the ARM
1378 // thumb-ness and set the correct address bits for us.
1379 so_addr
.SetLoadAddress(return_addr
, target_sp
.get());
1380 return_addr
= so_addr
.GetCallableLoadAddress(target_sp
.get());
1382 // Set "lr" to the return address
1383 if (!reg_ctx
->WriteRegisterFromUnsigned(ra_reg_num
, return_addr
))
1386 // If bit zero or 1 is set, this must be a thumb function, no need to figure
1387 // this out from the symbols.
1388 so_addr
.SetLoadAddress(function_addr
, target_sp
.get());
1389 function_addr
= so_addr
.GetCallableLoadAddress(target_sp
.get());
1391 const RegisterInfo
*cpsr_reg_info
= reg_ctx
->GetRegisterInfoByName("cpsr");
1392 const uint32_t curr_cpsr
= reg_ctx
->ReadRegisterAsUnsigned(cpsr_reg_info
, 0);
1394 // Make a new CPSR and mask out any Thumb IT (if/then) bits
1395 uint32_t new_cpsr
= curr_cpsr
& ~MASK_CPSR_IT_MASK
;
1396 // If bit zero or 1 is set, this must be thumb...
1397 if (function_addr
& 1ull)
1398 new_cpsr
|= MASK_CPSR_T
; // Set T bit in CPSR
1400 new_cpsr
&= ~MASK_CPSR_T
; // Clear T bit in CPSR
1402 if (new_cpsr
!= curr_cpsr
) {
1403 if (!reg_ctx
->WriteRegisterFromUnsigned(cpsr_reg_info
, new_cpsr
))
1408 ~1ull; // clear bit zero since the CPSR will take care of the mode for us
1410 // Update the sp - stack pointer - to be aligned to 16-bytes
1412 if (!reg_ctx
->WriteRegisterFromUnsigned(sp_reg_num
, sp
))
1415 // Set "pc" to the address requested
1416 if (!reg_ctx
->WriteRegisterFromUnsigned(pc_reg_num
, function_addr
))
1422 bool ABIMacOSX_arm::GetArgumentValues(Thread
&thread
, ValueList
&values
) const {
1423 uint32_t num_values
= values
.GetSize();
1425 ExecutionContext
exe_ctx(thread
.shared_from_this());
1426 // For now, assume that the types in the AST values come from the Target's
1429 // Extract the register context so we can read arguments from registers
1431 RegisterContext
*reg_ctx
= thread
.GetRegisterContext().get();
1438 for (uint32_t value_idx
= 0; value_idx
< num_values
; ++value_idx
) {
1439 // We currently only support extracting values with Clang QualTypes. Do we
1440 // care about others?
1441 Value
*value
= values
.GetValueAtIndex(value_idx
);
1446 CompilerType compiler_type
= value
->GetCompilerType();
1447 if (compiler_type
) {
1448 bool is_signed
= false;
1449 size_t bit_width
= 0;
1450 std::optional
<uint64_t> bit_size
= compiler_type
.GetBitSize(&thread
);
1453 if (compiler_type
.IsIntegerOrEnumerationType(is_signed
))
1454 bit_width
= *bit_size
;
1455 else if (compiler_type
.IsPointerOrReferenceType())
1456 bit_width
= *bit_size
;
1458 // We only handle integer, pointer and reference types currently...
1461 if (bit_width
<= (exe_ctx
.GetProcessRef().GetAddressByteSize() * 8)) {
1462 if (value_idx
< 4) {
1463 // Arguments 1-4 are in r0-r3...
1464 const RegisterInfo
*arg_reg_info
= nullptr;
1465 // Search by generic ID first, then fall back to by name
1466 uint32_t arg_reg_num
= reg_ctx
->ConvertRegisterKindToRegisterNumber(
1467 eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_ARG1
+ value_idx
);
1468 if (arg_reg_num
!= LLDB_INVALID_REGNUM
) {
1469 arg_reg_info
= reg_ctx
->GetRegisterInfoAtIndex(arg_reg_num
);
1471 switch (value_idx
) {
1473 arg_reg_info
= reg_ctx
->GetRegisterInfoByName("r0");
1476 arg_reg_info
= reg_ctx
->GetRegisterInfoByName("r1");
1479 arg_reg_info
= reg_ctx
->GetRegisterInfoByName("r2");
1482 arg_reg_info
= reg_ctx
->GetRegisterInfoByName("r3");
1488 RegisterValue reg_value
;
1490 if (reg_ctx
->ReadRegister(arg_reg_info
, reg_value
)) {
1492 reg_value
.SignExtend(bit_width
);
1493 if (!reg_value
.GetScalarValue(value
->GetScalar()))
1501 // Read the stack pointer if it already hasn't been read
1502 sp
= reg_ctx
->GetSP(0);
1507 // Arguments 5 on up are on the stack
1508 const uint32_t arg_byte_size
= (bit_width
+ (8 - 1)) / 8;
1510 if (!exe_ctx
.GetProcessRef().ReadScalarIntegerFromMemory(
1511 sp
, arg_byte_size
, is_signed
, value
->GetScalar(), error
))
1514 sp
+= arg_byte_size
;
1522 bool ABIMacOSX_arm::IsArmv7kProcess() const {
1523 bool is_armv7k
= false;
1524 ProcessSP
process_sp(GetProcessSP());
1526 const ArchSpec
&arch(process_sp
->GetTarget().GetArchitecture());
1527 const ArchSpec::Core system_core
= arch
.GetCore();
1528 if (system_core
== ArchSpec::eCore_arm_armv7k
) {
1535 ValueObjectSP
ABIMacOSX_arm::GetReturnValueObjectImpl(
1536 Thread
&thread
, lldb_private::CompilerType
&compiler_type
) const {
1538 ValueObjectSP return_valobj_sp
;
1541 return return_valobj_sp
;
1543 value
.SetCompilerType(compiler_type
);
1545 RegisterContext
*reg_ctx
= thread
.GetRegisterContext().get();
1547 return return_valobj_sp
;
1551 // Get the pointer to the first stack argument so we have a place to start
1552 // when reading data
1554 const RegisterInfo
*r0_reg_info
= reg_ctx
->GetRegisterInfoByName("r0", 0);
1555 if (compiler_type
.IsIntegerOrEnumerationType(is_signed
)) {
1556 std::optional
<uint64_t> bit_width
= compiler_type
.GetBitSize(&thread
);
1558 return return_valobj_sp
;
1560 switch (*bit_width
) {
1562 return return_valobj_sp
;
1564 if (IsArmv7kProcess()) {
1565 // "A composite type not larger than 16 bytes is returned in r0-r3. The
1566 // format is as if the result had been stored in memory at a word-
1567 // aligned address and then loaded into r0-r3 with an ldm instruction"
1569 const RegisterInfo
*r1_reg_info
=
1570 reg_ctx
->GetRegisterInfoByName("r1", 0);
1571 const RegisterInfo
*r2_reg_info
=
1572 reg_ctx
->GetRegisterInfoByName("r2", 0);
1573 const RegisterInfo
*r3_reg_info
=
1574 reg_ctx
->GetRegisterInfoByName("r3", 0);
1575 if (r1_reg_info
&& r2_reg_info
&& r3_reg_info
) {
1576 std::optional
<uint64_t> byte_size
=
1577 compiler_type
.GetByteSize(&thread
);
1579 return return_valobj_sp
;
1580 ProcessSP
process_sp(thread
.GetProcess());
1581 if (*byte_size
<= r0_reg_info
->byte_size
+ r1_reg_info
->byte_size
+
1582 r2_reg_info
->byte_size
+
1583 r3_reg_info
->byte_size
&&
1585 std::unique_ptr
<DataBufferHeap
> heap_data_up(
1586 new DataBufferHeap(*byte_size
, 0));
1587 const ByteOrder byte_order
= process_sp
->GetByteOrder();
1588 RegisterValue r0_reg_value
;
1589 RegisterValue r1_reg_value
;
1590 RegisterValue r2_reg_value
;
1591 RegisterValue r3_reg_value
;
1592 if (reg_ctx
->ReadRegister(r0_reg_info
, r0_reg_value
) &&
1593 reg_ctx
->ReadRegister(r1_reg_info
, r1_reg_value
) &&
1594 reg_ctx
->ReadRegister(r2_reg_info
, r2_reg_value
) &&
1595 reg_ctx
->ReadRegister(r3_reg_info
, r3_reg_value
)) {
1597 if (r0_reg_value
.GetAsMemoryData(*r0_reg_info
,
1598 heap_data_up
->GetBytes() + 0,
1599 4, byte_order
, error
) &&
1600 r1_reg_value
.GetAsMemoryData(*r1_reg_info
,
1601 heap_data_up
->GetBytes() + 4,
1602 4, byte_order
, error
) &&
1603 r2_reg_value
.GetAsMemoryData(*r2_reg_info
,
1604 heap_data_up
->GetBytes() + 8,
1605 4, byte_order
, error
) &&
1606 r3_reg_value
.GetAsMemoryData(*r3_reg_info
,
1607 heap_data_up
->GetBytes() + 12,
1608 4, byte_order
, error
)) {
1609 DataExtractor
data(DataBufferSP(heap_data_up
.release()),
1611 process_sp
->GetAddressByteSize());
1613 return_valobj_sp
= ValueObjectConstResult::Create(
1614 &thread
, compiler_type
, ConstString(""), data
);
1615 return return_valobj_sp
;
1622 return return_valobj_sp
;
1626 const RegisterInfo
*r1_reg_info
= reg_ctx
->GetRegisterInfoByName("r1", 0);
1628 raw_value
= reg_ctx
->ReadRegisterAsUnsigned(r0_reg_info
, 0) & UINT32_MAX
;
1629 raw_value
|= ((uint64_t)(reg_ctx
->ReadRegisterAsUnsigned(r1_reg_info
, 0) &
1633 value
.GetScalar() = (int64_t)raw_value
;
1635 value
.GetScalar() = (uint64_t)raw_value
;
1639 value
.GetScalar() = (int32_t)(
1640 reg_ctx
->ReadRegisterAsUnsigned(r0_reg_info
, 0) & UINT32_MAX
);
1642 value
.GetScalar() = (uint32_t)(
1643 reg_ctx
->ReadRegisterAsUnsigned(r0_reg_info
, 0) & UINT32_MAX
);
1647 value
.GetScalar() = (int16_t)(
1648 reg_ctx
->ReadRegisterAsUnsigned(r0_reg_info
, 0) & UINT16_MAX
);
1650 value
.GetScalar() = (uint16_t)(
1651 reg_ctx
->ReadRegisterAsUnsigned(r0_reg_info
, 0) & UINT16_MAX
);
1655 value
.GetScalar() = (int8_t)(
1656 reg_ctx
->ReadRegisterAsUnsigned(r0_reg_info
, 0) & UINT8_MAX
);
1658 value
.GetScalar() = (uint8_t)(
1659 reg_ctx
->ReadRegisterAsUnsigned(r0_reg_info
, 0) & UINT8_MAX
);
1662 } else if (compiler_type
.IsPointerType()) {
1664 thread
.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info
, 0) &
1666 value
.GetScalar() = ptr
;
1669 return return_valobj_sp
;
1672 // If we get here, we have a valid Value, so make our ValueObject out of it:
1674 return_valobj_sp
= ValueObjectConstResult::Create(
1675 thread
.GetStackFrameAtIndex(0).get(), value
, ConstString(""));
1676 return return_valobj_sp
;
1679 Status
ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP
&frame_sp
,
1680 lldb::ValueObjectSP
&new_value_sp
) {
1682 if (!new_value_sp
) {
1683 error
= Status::FromErrorString("Empty value object for return value.");
1687 CompilerType compiler_type
= new_value_sp
->GetCompilerType();
1688 if (!compiler_type
) {
1689 error
= Status::FromErrorString("Null clang type for return value.");
1693 Thread
*thread
= frame_sp
->GetThread().get();
1699 RegisterContext
*reg_ctx
= thread
->GetRegisterContext().get();
1701 bool set_it_simple
= false;
1702 if (compiler_type
.IsIntegerOrEnumerationType(is_signed
) ||
1703 compiler_type
.IsPointerType()) {
1706 size_t num_bytes
= new_value_sp
->GetData(data
, data_error
);
1707 if (data_error
.Fail()) {
1708 error
= Status::FromErrorStringWithFormat(
1709 "Couldn't convert return value to raw data: %s",
1710 data_error
.AsCString());
1713 lldb::offset_t offset
= 0;
1714 if (num_bytes
<= 8) {
1715 const RegisterInfo
*r0_info
= reg_ctx
->GetRegisterInfoByName("r0", 0);
1716 if (num_bytes
<= 4) {
1717 uint32_t raw_value
= data
.GetMaxU32(&offset
, num_bytes
);
1719 if (reg_ctx
->WriteRegisterFromUnsigned(r0_info
, raw_value
))
1720 set_it_simple
= true;
1722 uint32_t raw_value
= data
.GetMaxU32(&offset
, 4);
1724 if (reg_ctx
->WriteRegisterFromUnsigned(r0_info
, raw_value
)) {
1725 const RegisterInfo
*r1_info
= reg_ctx
->GetRegisterInfoByName("r1", 0);
1726 uint32_t raw_value
= data
.GetMaxU32(&offset
, num_bytes
- offset
);
1728 if (reg_ctx
->WriteRegisterFromUnsigned(r1_info
, raw_value
))
1729 set_it_simple
= true;
1732 } else if (num_bytes
<= 16 && IsArmv7kProcess()) {
1733 // "A composite type not larger than 16 bytes is returned in r0-r3. The
1734 // format is as if the result had been stored in memory at a word-aligned
1735 // address and then loaded into r0-r3 with an ldm instruction"
1737 const RegisterInfo
*r0_info
= reg_ctx
->GetRegisterInfoByName("r0", 0);
1738 const RegisterInfo
*r1_info
= reg_ctx
->GetRegisterInfoByName("r1", 0);
1739 const RegisterInfo
*r2_info
= reg_ctx
->GetRegisterInfoByName("r2", 0);
1740 const RegisterInfo
*r3_info
= reg_ctx
->GetRegisterInfoByName("r3", 0);
1741 lldb::offset_t offset
= 0;
1742 uint32_t bytes_written
= 4;
1743 uint32_t raw_value
= data
.GetMaxU64(&offset
, 4);
1744 if (reg_ctx
->WriteRegisterFromUnsigned(r0_info
, raw_value
) &&
1745 bytes_written
<= num_bytes
) {
1747 raw_value
= data
.GetMaxU64(&offset
, 4);
1748 if (bytes_written
<= num_bytes
&&
1749 reg_ctx
->WriteRegisterFromUnsigned(r1_info
, raw_value
)) {
1751 raw_value
= data
.GetMaxU64(&offset
, 4);
1752 if (bytes_written
<= num_bytes
&&
1753 reg_ctx
->WriteRegisterFromUnsigned(r2_info
, raw_value
)) {
1755 raw_value
= data
.GetMaxU64(&offset
, 4);
1756 if (bytes_written
<= num_bytes
&&
1757 reg_ctx
->WriteRegisterFromUnsigned(r3_info
, raw_value
)) {
1758 set_it_simple
= true;
1764 error
= Status::FromErrorString(
1765 "We don't support returning longer than 64 bit "
1766 "integer values at present.");
1768 } else if (compiler_type
.IsFloatingPointType(count
, is_complex
)) {
1770 error
= Status::FromErrorString(
1771 "We don't support returning complex values at present");
1773 error
= Status::FromErrorString(
1774 "We don't support returning float values at present");
1778 error
= Status::FromErrorString(
1779 "We only support setting simple integer return types at present.");
1784 bool ABIMacOSX_arm::CreateFunctionEntryUnwindPlan(UnwindPlan
&unwind_plan
) {
1785 unwind_plan
.Clear();
1786 unwind_plan
.SetRegisterKind(eRegisterKindDWARF
);
1788 uint32_t lr_reg_num
= dwarf_lr
;
1789 uint32_t sp_reg_num
= dwarf_sp
;
1790 uint32_t pc_reg_num
= dwarf_pc
;
1792 UnwindPlan::RowSP
row(new UnwindPlan::Row
);
1794 // Our Call Frame Address is the stack pointer value
1795 row
->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num
, 0);
1797 // The previous PC is in the LR
1798 row
->SetRegisterLocationToRegister(pc_reg_num
, lr_reg_num
, true);
1799 unwind_plan
.AppendRow(row
);
1801 // All other registers are the same.
1803 unwind_plan
.SetSourceName("arm at-func-entry default");
1804 unwind_plan
.SetSourcedFromCompiler(eLazyBoolNo
);
1809 bool ABIMacOSX_arm::CreateDefaultUnwindPlan(UnwindPlan
&unwind_plan
) {
1810 unwind_plan
.Clear();
1811 unwind_plan
.SetRegisterKind(eRegisterKindDWARF
);
1813 uint32_t fp_reg_num
=
1814 dwarf_r7
; // apple uses r7 for all frames. Normal arm uses r11
1815 uint32_t pc_reg_num
= dwarf_pc
;
1817 UnwindPlan::RowSP
row(new UnwindPlan::Row
);
1818 const int32_t ptr_size
= 4;
1820 row
->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num
, 2 * ptr_size
);
1822 row
->SetUnspecifiedRegistersAreUndefined(true);
1824 row
->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num
, ptr_size
* -2, true);
1825 row
->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num
, ptr_size
* -1, true);
1827 unwind_plan
.AppendRow(row
);
1828 unwind_plan
.SetSourceName("arm-apple-ios default unwind plan");
1829 unwind_plan
.SetSourcedFromCompiler(eLazyBoolNo
);
1830 unwind_plan
.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo
);
1831 unwind_plan
.SetUnwindPlanForSignalTrap(eLazyBoolNo
);
1836 // cf. "ARMv6 Function Calling Conventions"
1837 // https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARMv6FunctionCallingConventions.html
1838 // and "ARMv7 Function Calling Conventions"
1839 // https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARMv7FunctionCallingConventions.html
1841 // ARMv7 on iOS general purpose reg rules:
1842 // r0-r3 not preserved (used for argument passing)
1844 // r7 preserved (frame pointer)
1846 // r9 not preserved (usable as volatile scratch register with iOS 3.x and
1848 // r10-r11 preserved
1850 // r13 preserved (stack pointer)
1851 // r14 not preserved (link register)
1852 // r15 preserved (pc)
1853 // cpsr not preserved (different rules for different bits)
1855 // ARMv7 on iOS floating point rules:
1856 // d0-d7 not preserved (aka s0-s15, q0-q3)
1857 // d8-d15 preserved (aka s16-s31, q4-q7)
1858 // d16-d31 not preserved (aka q8-q15)
1860 bool ABIMacOSX_arm::RegisterIsVolatile(const RegisterInfo
*reg_info
) {
1862 // Volatile registers are: r0, r1, r2, r3, r9, r12, r13 (aka sp)
1863 const char *name
= reg_info
->name
;
1864 if (name
[0] == 'r') {
1867 return name
[2] == '\0'; // r0
1874 return name
[3] == '\0'; // r12, r13 (sp)
1881 return name
[2] == '\0'; // r2
1883 return name
[2] == '\0'; // r3
1885 return name
[2] == '\0'; // r9 (apple-ios only...)
1889 } else if (name
[0] == 'd') {
1892 return name
[2] == '\0'; // d0 is volatile
1897 return true; // d1 is volatile
1902 return name
[3] == '\0'; // d16 - d19 are volatile
1911 return true; // d2 is volatile
1922 return name
[3] == '\0'; // d20 - d29 are volatile
1931 return true; // d3 is volatile
1934 return name
[3] == '\0'; // d30 - d31 are volatile
1943 return name
[2] == '\0'; // d4 - d7 are volatile
1948 } else if (name
[0] == 's') {
1951 return name
[2] == '\0'; // s0 is volatile
1956 return true; // s1 is volatile
1963 return name
[3] == '\0'; // s10 - s15 are volatile
1977 return name
[2] == '\0'; // s2 - s9 are volatile
1982 } else if (name
[0] == 'q') {
1987 return true; // q1 is volatile
1994 return true; // q10-q15 are volatile
2002 return name
[2] == '\0'; // q0-q3 are volatile
2005 return name
[2] == '\0'; // q8-q9 are volatile
2009 } else if (name
[0] == 's' && name
[1] == 'p' && name
[2] == '\0')
2015 void ABIMacOSX_arm::Initialize() {
2016 PluginManager::RegisterPlugin(GetPluginNameStatic(),
2017 "Mac OS X ABI for arm targets", CreateInstance
);
2020 void ABIMacOSX_arm::Terminate() {
2021 PluginManager::UnregisterPlugin(CreateInstance
);