1 //===-- ABIMacOSX_arm64.cpp -----------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "ABIMacOSX_arm64.h"
10
11 #include <vector>
12
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/ADT/Triple.h"
15
16 #include "lldb/Core/Module.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/Value.h"
19 #include "lldb/Core/ValueObjectConstResult.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/LLDBLog.h"
27 #include "lldb/Utility/Log.h"
28 #include "lldb/Utility/RegisterValue.h"
29 #include "lldb/Utility/Scalar.h"
30 #include "lldb/Utility/Status.h"
31
32 #include "Utility/ARM64_DWARF_Registers.h"
33
34 using namespace lldb;
35 using namespace lldb_private;
36
37 static const char *pluginDesc = "Mac OS X ABI for arm64 targets";
38
GetRedZoneSize() const39 size_t ABIMacOSX_arm64::GetRedZoneSize() const { return 128; }
40
41 // Static Functions
42
43 ABISP
CreateInstance(ProcessSP process_sp,const ArchSpec & arch)44 ABIMacOSX_arm64::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) {
45 const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
46 const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor();
47
48 if (vendor_type == llvm::Triple::Apple) {
49 if (arch_type == llvm::Triple::aarch64 ||
50 arch_type == llvm::Triple::aarch64_32) {
51 return ABISP(
52 new ABIMacOSX_arm64(std::move(process_sp), MakeMCRegisterInfo(arch)));
53 }
54 }
55
56 return ABISP();
57 }
58
PrepareTrivialCall(Thread & thread,lldb::addr_t sp,lldb::addr_t func_addr,lldb::addr_t return_addr,llvm::ArrayRef<lldb::addr_t> args) const59 bool ABIMacOSX_arm64::PrepareTrivialCall(
60 Thread &thread, lldb::addr_t sp, lldb::addr_t func_addr,
61 lldb::addr_t return_addr, llvm::ArrayRef<lldb::addr_t> args) const {
62 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
63 if (!reg_ctx)
64 return false;
65
66 Log *log = GetLog(LLDBLog::Expressions);
67
68 if (log) {
69 StreamString s;
70 s.Printf("ABIMacOSX_arm64::PrepareTrivialCall (tid = 0x%" PRIx64
71 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
72 ", return_addr = 0x%" PRIx64,
73 thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
74 (uint64_t)return_addr);
75
76 for (size_t i = 0; i < args.size(); ++i)
77 s.Printf(", arg%d = 0x%" PRIx64, static_cast<int>(i + 1), args[i]);
78 s.PutCString(")");
79 log->PutString(s.GetString());
80 }
81
82 const uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
83 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
84 const uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
85 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
86 const uint32_t ra_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
87 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
88
89 // x0 - x7 contain first 8 simple args
90 if (args.size() > 8) // TODO handle more than 8 arguments
91 return false;
92
93 for (size_t i = 0; i < args.size(); ++i) {
94 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(
95 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
96 LLDB_LOGF(log, "About to write arg%d (0x%" PRIx64 ") into %s",
97 static_cast<int>(i + 1), args[i], reg_info->name);
98 if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
99 return false;
100 }
101
102 // Set "lr" to the return address
103 if (!reg_ctx->WriteRegisterFromUnsigned(
104 reg_ctx->GetRegisterInfoAtIndex(ra_reg_num), return_addr))
105 return false;
106
107 // Set "sp" to the requested value
108 if (!reg_ctx->WriteRegisterFromUnsigned(
109 reg_ctx->GetRegisterInfoAtIndex(sp_reg_num), sp))
110 return false;
111
112 // Set "pc" to the address requested
113 if (!reg_ctx->WriteRegisterFromUnsigned(
114 reg_ctx->GetRegisterInfoAtIndex(pc_reg_num), func_addr))
115 return false;
116
117 return true;
118 }
119
GetArgumentValues(Thread & thread,ValueList & values) const120 bool ABIMacOSX_arm64::GetArgumentValues(Thread &thread,
121 ValueList &values) const {
122 uint32_t num_values = values.GetSize();
123
124 ExecutionContext exe_ctx(thread.shared_from_this());
125
126 // Extract the register context so we can read arguments from registers
127
128 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
129
130 if (!reg_ctx)
131 return false;
132
133 addr_t sp = 0;
134
135 for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx) {
136 // We currently only support extracting values with Clang QualTypes. Do we
137 // care about others?
138 Value *value = values.GetValueAtIndex(value_idx);
139
140 if (!value)
141 return false;
142
143 CompilerType value_type = value->GetCompilerType();
144 llvm::Optional<uint64_t> bit_size = value_type.GetBitSize(&thread);
145 if (!bit_size)
146 return false;
147
148 bool is_signed = false;
149 size_t bit_width = 0;
150 if (value_type.IsIntegerOrEnumerationType(is_signed)) {
151 bit_width = *bit_size;
152 } else if (value_type.IsPointerOrReferenceType()) {
153 bit_width = *bit_size;
154 } else {
155 // We only handle integer, pointer and reference types currently...
156 return false;
157 }
158
159 if (bit_width <= (exe_ctx.GetProcessRef().GetAddressByteSize() * 8)) {
160 if (value_idx < 8) {
161 // Arguments 1-6 are in x0-x5...
162 const RegisterInfo *reg_info = nullptr;
163 // Search by generic ID first, then fall back to by name
164 uint32_t arg_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
165 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx);
166 if (arg_reg_num != LLDB_INVALID_REGNUM) {
167 reg_info = reg_ctx->GetRegisterInfoAtIndex(arg_reg_num);
168 } else {
169 switch (value_idx) {
170 case 0:
171 reg_info = reg_ctx->GetRegisterInfoByName("x0");
172 break;
173 case 1:
174 reg_info = reg_ctx->GetRegisterInfoByName("x1");
175 break;
176 case 2:
177 reg_info = reg_ctx->GetRegisterInfoByName("x2");
178 break;
179 case 3:
180 reg_info = reg_ctx->GetRegisterInfoByName("x3");
181 break;
182 case 4:
183 reg_info = reg_ctx->GetRegisterInfoByName("x4");
184 break;
185 case 5:
186 reg_info = reg_ctx->GetRegisterInfoByName("x5");
187 break;
188 case 6:
189 reg_info = reg_ctx->GetRegisterInfoByName("x6");
190 break;
191 case 7:
192 reg_info = reg_ctx->GetRegisterInfoByName("x7");
193 break;
194 }
195 }
196
197 if (reg_info) {
198 RegisterValue reg_value;
199
200 if (reg_ctx->ReadRegister(reg_info, reg_value)) {
201 if (is_signed)
202 reg_value.SignExtend(bit_width);
203 if (!reg_value.GetScalarValue(value->GetScalar()))
204 return false;
205 continue;
206 }
207 }
208 return false;
209 } else {
210 if (sp == 0) {
211 // Read the stack pointer if we already haven't read it
212 sp = reg_ctx->GetSP(0);
213 if (sp == 0)
214 return false;
215 }
216
217 // Arguments 5 on up are on the stack
218 const uint32_t arg_byte_size = (bit_width + (8 - 1)) / 8;
219 Status error;
220 if (!exe_ctx.GetProcessRef().ReadScalarIntegerFromMemory(
221 sp, arg_byte_size, is_signed, value->GetScalar(), error))
222 return false;
223
224 sp += arg_byte_size;
225 // Align up to the next 8 byte boundary if needed
226 if (sp % 8) {
227 sp >>= 3;
228 sp += 1;
229 sp <<= 3;
230 }
231 }
232 }
233 }
234 return true;
235 }
236
237 Status
SetReturnValueObject(lldb::StackFrameSP & frame_sp,lldb::ValueObjectSP & new_value_sp)238 ABIMacOSX_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
239 lldb::ValueObjectSP &new_value_sp) {
240 Status error;
241 if (!new_value_sp) {
242 error.SetErrorString("Empty value object for return value.");
243 return error;
244 }
245
246 CompilerType return_value_type = new_value_sp->GetCompilerType();
247 if (!return_value_type) {
248 error.SetErrorString("Null clang type for return value.");
249 return error;
250 }
251
252 Thread *thread = frame_sp->GetThread().get();
253
254 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
255
256 if (reg_ctx) {
257 DataExtractor data;
258 Status data_error;
259 const uint64_t byte_size = new_value_sp->GetData(data, data_error);
260 if (data_error.Fail()) {
261 error.SetErrorStringWithFormat(
262 "Couldn't convert return value to raw data: %s",
263 data_error.AsCString());
264 return error;
265 }
266
267 const uint32_t type_flags = return_value_type.GetTypeInfo(nullptr);
268 if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
269 if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
270 // Extract the register context so we can read arguments from registers
271 lldb::offset_t offset = 0;
272 if (byte_size <= 16) {
273 const RegisterInfo *x0_info = reg_ctx->GetRegisterInfoByName("x0", 0);
274 if (byte_size <= 8) {
275 uint64_t raw_value = data.GetMaxU64(&offset, byte_size);
276
277 if (!reg_ctx->WriteRegisterFromUnsigned(x0_info, raw_value))
278 error.SetErrorString("failed to write register x0");
279 } else {
280 uint64_t raw_value = data.GetMaxU64(&offset, 8);
281
282 if (reg_ctx->WriteRegisterFromUnsigned(x0_info, raw_value)) {
283 const RegisterInfo *x1_info =
284 reg_ctx->GetRegisterInfoByName("x1", 0);
285 raw_value = data.GetMaxU64(&offset, byte_size - offset);
286
287 if (!reg_ctx->WriteRegisterFromUnsigned(x1_info, raw_value))
288 error.SetErrorString("failed to write register x1");
289 }
290 }
291 } else {
292 error.SetErrorString("We don't support returning longer than 128 bit "
293 "integer values at present.");
294 }
295 } else if (type_flags & eTypeIsFloat) {
296 if (type_flags & eTypeIsComplex) {
297 // Don't handle complex yet.
298 error.SetErrorString(
299 "returning complex float values are not supported");
300 } else {
301 const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);
302
303 if (v0_info) {
304 if (byte_size <= 16) {
305 if (byte_size <= RegisterValue::GetMaxByteSize()) {
306 RegisterValue reg_value;
307 error = reg_value.SetValueFromData(v0_info, data, 0, true);
308 if (error.Success()) {
309 if (!reg_ctx->WriteRegister(v0_info, reg_value))
310 error.SetErrorString("failed to write register v0");
311 }
312 } else {
313 error.SetErrorStringWithFormat(
314 "returning float values with a byte size of %" PRIu64
315 " are not supported",
316 byte_size);
317 }
318 } else {
319 error.SetErrorString("returning float values longer than 128 "
320 "bits are not supported");
321 }
322 } else {
323 error.SetErrorString("v0 register is not available on this target");
324 }
325 }
326 }
327 } else if (type_flags & eTypeIsVector) {
328 if (byte_size > 0) {
329 const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);
330
331 if (v0_info) {
332 if (byte_size <= v0_info->byte_size) {
333 RegisterValue reg_value;
334 error = reg_value.SetValueFromData(v0_info, data, 0, true);
335 if (error.Success()) {
336 if (!reg_ctx->WriteRegister(v0_info, reg_value))
337 error.SetErrorString("failed to write register v0");
338 }
339 }
340 }
341 }
342 }
343 } else {
344 error.SetErrorString("no registers are available");
345 }
346
347 return error;
348 }
349
CreateFunctionEntryUnwindPlan(UnwindPlan & unwind_plan)350 bool ABIMacOSX_arm64::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
351 unwind_plan.Clear();
352 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
353
354 uint32_t lr_reg_num = arm64_dwarf::lr;
355 uint32_t sp_reg_num = arm64_dwarf::sp;
356 uint32_t pc_reg_num = arm64_dwarf::pc;
357
358 UnwindPlan::RowSP row(new UnwindPlan::Row);
359
360 // Our previous Call Frame Address is the stack pointer
361 row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0);
362
363 // Our previous PC is in the LR
364 row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
365
366 unwind_plan.AppendRow(row);
367
368 // All other registers are the same.
369
370 unwind_plan.SetSourceName("arm64 at-func-entry default");
371 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
372
373 return true;
374 }
375
CreateDefaultUnwindPlan(UnwindPlan & unwind_plan)376 bool ABIMacOSX_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
377 unwind_plan.Clear();
378 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
379
380 uint32_t fp_reg_num = arm64_dwarf::fp;
381 uint32_t pc_reg_num = arm64_dwarf::pc;
382
383 UnwindPlan::RowSP row(new UnwindPlan::Row);
384 const int32_t ptr_size = 8;
385
386 row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
387 row->SetOffset(0);
388 row->SetUnspecifiedRegistersAreUndefined(true);
389
390 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
391 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
392
393 unwind_plan.AppendRow(row);
394 unwind_plan.SetSourceName("arm64-apple-darwin default unwind plan");
395 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
396 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
397 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
398 return true;
399 }
400
401 // AAPCS64 (Procedure Call Standard for the ARM 64-bit Architecture) says
402 // registers x19 through x28 and sp are callee preserved. v8-v15 are non-
403 // volatile (and specifically only the lower 8 bytes of these regs), the rest
404 // of the fp/SIMD registers are volatile.
405 //
406 // v. https://github.com/ARM-software/abi-aa/blob/main/aapcs64/
407
408 // We treat x29 as callee preserved also, else the unwinder won't try to
409 // retrieve fp saves.
410
RegisterIsVolatile(const RegisterInfo * reg_info)411 bool ABIMacOSX_arm64::RegisterIsVolatile(const RegisterInfo *reg_info) {
412 if (reg_info) {
413 const char *name = reg_info->name;
414
415 // Sometimes we'll be called with the "alternate" name for these registers;
416 // recognize them as non-volatile.
417
418 if (name[0] == 'p' && name[1] == 'c') // pc
419 return false;
420 if (name[0] == 'f' && name[1] == 'p') // fp
421 return false;
422 if (name[0] == 's' && name[1] == 'p') // sp
423 return false;
424 if (name[0] == 'l' && name[1] == 'r') // lr
425 return false;
426
427 if (name[0] == 'x') {
428 // Volatile registers: x0-x18, x30 (lr)
429 // Return false for the non-volatile gpr regs, true for everything else
430 switch (name[1]) {
431 case '1':
432 switch (name[2]) {
433 case '9':
434 return false; // x19 is non-volatile
435 default:
436 return true;
437 }
438 break;
439 case '2':
440 switch (name[2]) {
441 case '0':
442 case '1':
443 case '2':
444 case '3':
445 case '4':
446 case '5':
447 case '6':
448 case '7':
449 case '8':
450 return false; // x20 - 28 are non-volatile
451 case '9':
452 return false; // x29 aka fp treat as non-volatile on Darwin
453 default:
454 return true;
455 }
456 case '3': // x30 aka lr treat as non-volatile
457 if (name[2] == '0')
458 return false;
459 break;
460 default:
461 return true;
462 }
463 } else if (name[0] == 'v' || name[0] == 's' || name[0] == 'd') {
464 // Volatile registers: v0-7, v16-v31
465 // Return false for non-volatile fp/SIMD regs, true for everything else
466 switch (name[1]) {
467 case '8':
468 case '9':
469 return false; // v8-v9 are non-volatile
470 case '1':
471 switch (name[2]) {
472 case '0':
473 case '1':
474 case '2':
475 case '3':
476 case '4':
477 case '5':
478 return false; // v10-v15 are non-volatile
479 default:
480 return true;
481 }
482 default:
483 return true;
484 }
485 }
486 }
487 return true;
488 }
489
LoadValueFromConsecutiveGPRRegisters(ExecutionContext & exe_ctx,RegisterContext * reg_ctx,const CompilerType & value_type,bool is_return_value,uint32_t & NGRN,uint32_t & NSRN,DataExtractor & data)490 static bool LoadValueFromConsecutiveGPRRegisters(
491 ExecutionContext &exe_ctx, RegisterContext *reg_ctx,
492 const CompilerType &value_type,
493 bool is_return_value, // false => parameter, true => return value
494 uint32_t &NGRN, // NGRN (see ABI documentation)
495 uint32_t &NSRN, // NSRN (see ABI documentation)
496 DataExtractor &data) {
497 llvm::Optional<uint64_t> byte_size =
498 value_type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
499 if (!byte_size || *byte_size == 0)
500 return false;
501
502 std::unique_ptr<DataBufferHeap> heap_data_up(
503 new DataBufferHeap(*byte_size, 0));
504 const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();
505 Status error;
506
507 CompilerType base_type;
508 const uint32_t homogeneous_count =
509 value_type.IsHomogeneousAggregate(&base_type);
510 if (homogeneous_count > 0 && homogeneous_count <= 8) {
511 // Make sure we have enough registers
512 if (NSRN < 8 && (8 - NSRN) >= homogeneous_count) {
513 if (!base_type)
514 return false;
515 llvm::Optional<uint64_t> base_byte_size =
516 base_type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
517 if (!base_byte_size)
518 return false;
519 uint32_t data_offset = 0;
520
521 for (uint32_t i = 0; i < homogeneous_count; ++i) {
522 char v_name[8];
523 ::snprintf(v_name, sizeof(v_name), "v%u", NSRN);
524 const RegisterInfo *reg_info =
525 reg_ctx->GetRegisterInfoByName(v_name, 0);
526 if (reg_info == nullptr)
527 return false;
528
529 if (*base_byte_size > reg_info->byte_size)
530 return false;
531
532 RegisterValue reg_value;
533
534 if (!reg_ctx->ReadRegister(reg_info, reg_value))
535 return false;
536
537 // Make sure we have enough room in "heap_data_up"
538 if ((data_offset + *base_byte_size) <= heap_data_up->GetByteSize()) {
539 const size_t bytes_copied = reg_value.GetAsMemoryData(
540 reg_info, heap_data_up->GetBytes() + data_offset, *base_byte_size,
541 byte_order, error);
542 if (bytes_copied != *base_byte_size)
543 return false;
544 data_offset += bytes_copied;
545 ++NSRN;
546 } else
547 return false;
548 }
549 data.SetByteOrder(byte_order);
550 data.SetAddressByteSize(exe_ctx.GetProcessRef().GetAddressByteSize());
551 data.SetData(DataBufferSP(heap_data_up.release()));
552 return true;
553 }
554 }
555
556 const size_t max_reg_byte_size = 16;
557 if (*byte_size <= max_reg_byte_size) {
558 size_t bytes_left = *byte_size;
559 uint32_t data_offset = 0;
560 while (data_offset < *byte_size) {
561 if (NGRN >= 8)
562 return false;
563
564 uint32_t reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
565 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + NGRN);
566 if (reg_num == LLDB_INVALID_REGNUM)
567 return false;
568
569 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
570 if (reg_info == nullptr)
571 return false;
572
573 RegisterValue reg_value;
574
575 if (!reg_ctx->ReadRegister(reg_info, reg_value))
576 return false;
577
578 const size_t curr_byte_size = std::min<size_t>(8, bytes_left);
579 const size_t bytes_copied = reg_value.GetAsMemoryData(
580 reg_info, heap_data_up->GetBytes() + data_offset, curr_byte_size,
581 byte_order, error);
582 if (bytes_copied == 0)
583 return false;
584 if (bytes_copied >= bytes_left)
585 break;
586 data_offset += bytes_copied;
587 bytes_left -= bytes_copied;
588 ++NGRN;
589 }
590 } else {
591 const RegisterInfo *reg_info = nullptr;
592 if (is_return_value) {
593 // The Darwin arm64 ABI doesn't write the return location back to x8
594 // before returning from the function the way the x86_64 ABI does. So
595 // we can't reconstruct stack based returns on exit from the function:
596 return false;
597 } else {
598 // We are assuming we are stopped at the first instruction in a function
599 // and that the ABI is being respected so all parameters appear where
600 // they should be (functions with no external linkage can legally violate
601 // the ABI).
602 if (NGRN >= 8)
603 return false;
604
605 uint32_t reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
606 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + NGRN);
607 if (reg_num == LLDB_INVALID_REGNUM)
608 return false;
609 reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
610 if (reg_info == nullptr)
611 return false;
612 ++NGRN;
613 }
614
615 if (reg_info == nullptr)
616 return false;
617
618 const lldb::addr_t value_addr =
619 reg_ctx->ReadRegisterAsUnsigned(reg_info, LLDB_INVALID_ADDRESS);
620
621 if (value_addr == LLDB_INVALID_ADDRESS)
622 return false;
623
624 if (exe_ctx.GetProcessRef().ReadMemory(
625 value_addr, heap_data_up->GetBytes(), heap_data_up->GetByteSize(),
626 error) != heap_data_up->GetByteSize()) {
627 return false;
628 }
629 }
630
631 data.SetByteOrder(byte_order);
632 data.SetAddressByteSize(exe_ctx.GetProcessRef().GetAddressByteSize());
633 data.SetData(DataBufferSP(heap_data_up.release()));
634 return true;
635 }
636
GetReturnValueObjectImpl(Thread & thread,CompilerType & return_compiler_type) const637 ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl(
638 Thread &thread, CompilerType &return_compiler_type) const {
639 ValueObjectSP return_valobj_sp;
640 Value value;
641
642 ExecutionContext exe_ctx(thread.shared_from_this());
643 if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
644 return return_valobj_sp;
645
646 // value.SetContext (Value::eContextTypeClangType, return_compiler_type);
647 value.SetCompilerType(return_compiler_type);
648
649 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
650 if (!reg_ctx)
651 return return_valobj_sp;
652
653 llvm::Optional<uint64_t> byte_size =
654 return_compiler_type.GetByteSize(&thread);
655 if (!byte_size)
656 return return_valobj_sp;
657
658 const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr);
659 if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
660 value.SetValueType(Value::ValueType::Scalar);
661
662 bool success = false;
663 if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
664 // Extract the register context so we can read arguments from registers
665 if (*byte_size <= 8) {
666 const RegisterInfo *x0_reg_info =
667 reg_ctx->GetRegisterInfoByName("x0", 0);
668 if (x0_reg_info) {
669 uint64_t raw_value =
670 thread.GetRegisterContext()->ReadRegisterAsUnsigned(x0_reg_info,
671 0);
672 const bool is_signed = (type_flags & eTypeIsSigned) != 0;
673 switch (*byte_size) {
674 default:
675 break;
676 case 16: // uint128_t
677 // In register x0 and x1
678 {
679 const RegisterInfo *x1_reg_info =
680 reg_ctx->GetRegisterInfoByName("x1", 0);
681
682 if (x1_reg_info) {
683 if (*byte_size <=
684 x0_reg_info->byte_size + x1_reg_info->byte_size) {
685 std::unique_ptr<DataBufferHeap> heap_data_up(
686 new DataBufferHeap(*byte_size, 0));
687 const ByteOrder byte_order =
688 exe_ctx.GetProcessRef().GetByteOrder();
689 RegisterValue x0_reg_value;
690 RegisterValue x1_reg_value;
691 if (reg_ctx->ReadRegister(x0_reg_info, x0_reg_value) &&
692 reg_ctx->ReadRegister(x1_reg_info, x1_reg_value)) {
693 Status error;
694 if (x0_reg_value.GetAsMemoryData(
695 x0_reg_info, heap_data_up->GetBytes() + 0, 8,
696 byte_order, error) &&
697 x1_reg_value.GetAsMemoryData(
698 x1_reg_info, heap_data_up->GetBytes() + 8, 8,
699 byte_order, error)) {
700 DataExtractor data(
701 DataBufferSP(heap_data_up.release()), byte_order,
702 exe_ctx.GetProcessRef().GetAddressByteSize());
703
704 return_valobj_sp = ValueObjectConstResult::Create(
705 &thread, return_compiler_type, ConstString(""), data);
706 return return_valobj_sp;
707 }
708 }
709 }
710 }
711 }
712 break;
713 case sizeof(uint64_t):
714 if (is_signed)
715 value.GetScalar() = (int64_t)(raw_value);
716 else
717 value.GetScalar() = (uint64_t)(raw_value);
718 success = true;
719 break;
720
721 case sizeof(uint32_t):
722 if (is_signed)
723 value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
724 else
725 value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
726 success = true;
727 break;
728
729 case sizeof(uint16_t):
730 if (is_signed)
731 value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
732 else
733 value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
734 success = true;
735 break;
736
737 case sizeof(uint8_t):
738 if (is_signed)
739 value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
740 else
741 value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
742 success = true;
743 break;
744 }
745 }
746 }
747 } else if (type_flags & eTypeIsFloat) {
748 if (type_flags & eTypeIsComplex) {
749 // Don't handle complex yet.
750 } else {
751 if (*byte_size <= sizeof(long double)) {
752 const RegisterInfo *v0_reg_info =
753 reg_ctx->GetRegisterInfoByName("v0", 0);
754 RegisterValue v0_value;
755 if (reg_ctx->ReadRegister(v0_reg_info, v0_value)) {
756 DataExtractor data;
757 if (v0_value.GetData(data)) {
758 lldb::offset_t offset = 0;
759 if (*byte_size == sizeof(float)) {
760 value.GetScalar() = data.GetFloat(&offset);
761 success = true;
762 } else if (*byte_size == sizeof(double)) {
763 value.GetScalar() = data.GetDouble(&offset);
764 success = true;
765 } else if (*byte_size == sizeof(long double)) {
766 value.GetScalar() = data.GetLongDouble(&offset);
767 success = true;
768 }
769 }
770 }
771 }
772 }
773 }
774
775 if (success)
776 return_valobj_sp = ValueObjectConstResult::Create(
777 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
778 } else if (type_flags & eTypeIsVector) {
779 if (*byte_size > 0) {
780
781 const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);
782
783 if (v0_info) {
784 if (*byte_size <= v0_info->byte_size) {
785 std::unique_ptr<DataBufferHeap> heap_data_up(
786 new DataBufferHeap(*byte_size, 0));
787 const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();
788 RegisterValue reg_value;
789 if (reg_ctx->ReadRegister(v0_info, reg_value)) {
790 Status error;
791 if (reg_value.GetAsMemoryData(v0_info, heap_data_up->GetBytes(),
792 heap_data_up->GetByteSize(),
793 byte_order, error)) {
794 DataExtractor data(DataBufferSP(heap_data_up.release()),
795 byte_order,
796 exe_ctx.GetProcessRef().GetAddressByteSize());
797 return_valobj_sp = ValueObjectConstResult::Create(
798 &thread, return_compiler_type, ConstString(""), data);
799 }
800 }
801 }
802 }
803 }
804 } else if (type_flags & eTypeIsStructUnion || type_flags & eTypeIsClass) {
805 DataExtractor data;
806
807 uint32_t NGRN = 0; // Search ABI docs for NGRN
808 uint32_t NSRN = 0; // Search ABI docs for NSRN
809 const bool is_return_value = true;
810 if (LoadValueFromConsecutiveGPRRegisters(
811 exe_ctx, reg_ctx, return_compiler_type, is_return_value, NGRN, NSRN,
812 data)) {
813 return_valobj_sp = ValueObjectConstResult::Create(
814 &thread, return_compiler_type, ConstString(""), data);
815 }
816 }
817 return return_valobj_sp;
818 }
819
FixAddress(addr_t pc,addr_t mask)820 lldb::addr_t ABIMacOSX_arm64::FixAddress(addr_t pc, addr_t mask) {
821 lldb::addr_t pac_sign_extension = 0x0080000000000000ULL;
822 // Darwin systems originally couldn't determine the proper value
823 // dynamically, so the most common value was hardcoded. This has
824 // largely been cleaned up, but there are still a handful of
825 // environments that assume the default value is set to this value
826 // and there's no dynamic value to correct it.
827 // When no mask is specified, set it to 39 bits of addressing (0..38).
828 if (mask == 0) {
829 // ~((1ULL<<39)-1)
830 mask = 0xffffff8000000000;
831 }
832 return (pc & pac_sign_extension) ? pc | mask : pc & (~mask);
833 }
834
Initialize()835 void ABIMacOSX_arm64::Initialize() {
836 PluginManager::RegisterPlugin(GetPluginNameStatic(), pluginDesc,
837 CreateInstance);
838 }
839
Terminate()840 void ABIMacOSX_arm64::Terminate() {
841 PluginManager::UnregisterPlugin(CreateInstance);
842 }
843