1 //===-- ABISysV_mips64.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 "ABISysV_mips64.h"
10
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/Triple.h"
13
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Core/Value.h"
17 #include "lldb/Core/ValueObjectConstResult.h"
18 #include "lldb/Core/ValueObjectMemory.h"
19 #include "lldb/Core/ValueObjectRegister.h"
20 #include "lldb/Symbol/UnwindPlan.h"
21 #include "lldb/Target/Process.h"
22 #include "lldb/Target/RegisterContext.h"
23 #include "lldb/Target/StackFrame.h"
24 #include "lldb/Target/Target.h"
25 #include "lldb/Target/Thread.h"
26 #include "lldb/Utility/ConstString.h"
27 #include "lldb/Utility/DataExtractor.h"
28 #include "lldb/Utility/LLDBLog.h"
29 #include "lldb/Utility/Log.h"
30 #include "lldb/Utility/RegisterValue.h"
31 #include "lldb/Utility/Status.h"
32 #include <optional>
33
34 using namespace lldb;
35 using namespace lldb_private;
36
37 LLDB_PLUGIN_DEFINE(ABISysV_mips64)
38
39 enum dwarf_regnums {
40 dwarf_r0 = 0,
41 dwarf_r1,
42 dwarf_r2,
43 dwarf_r3,
44 dwarf_r4,
45 dwarf_r5,
46 dwarf_r6,
47 dwarf_r7,
48 dwarf_r8,
49 dwarf_r9,
50 dwarf_r10,
51 dwarf_r11,
52 dwarf_r12,
53 dwarf_r13,
54 dwarf_r14,
55 dwarf_r15,
56 dwarf_r16,
57 dwarf_r17,
58 dwarf_r18,
59 dwarf_r19,
60 dwarf_r20,
61 dwarf_r21,
62 dwarf_r22,
63 dwarf_r23,
64 dwarf_r24,
65 dwarf_r25,
66 dwarf_r26,
67 dwarf_r27,
68 dwarf_r28,
69 dwarf_r29,
70 dwarf_r30,
71 dwarf_r31,
72 dwarf_sr,
73 dwarf_lo,
74 dwarf_hi,
75 dwarf_bad,
76 dwarf_cause,
77 dwarf_pc
78 };
79
80 static const RegisterInfo g_register_infos_mips64[] = {
81 // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME
82 // DWARF GENERIC PROCESS PLUGIN
83 // LLDB NATIVE
84 // ======== ====== == === ============= ========== =============
85 // ================= ==================== =================
86 // ====================
87 {"r0",
88 "zero",
89 8,
90 0,
91 eEncodingUint,
92 eFormatHex,
93 {dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
94 LLDB_INVALID_REGNUM},
95 nullptr,
96 nullptr,
97 },
98 {"r1",
99 "AT",
100 8,
101 0,
102 eEncodingUint,
103 eFormatHex,
104 {dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
105 LLDB_INVALID_REGNUM},
106 nullptr,
107 nullptr,
108 },
109 {"r2",
110 "v0",
111 8,
112 0,
113 eEncodingUint,
114 eFormatHex,
115 {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
116 LLDB_INVALID_REGNUM},
117 nullptr,
118 nullptr,
119 },
120 {"r3",
121 "v1",
122 8,
123 0,
124 eEncodingUint,
125 eFormatHex,
126 {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
127 LLDB_INVALID_REGNUM},
128 nullptr,
129 nullptr,
130 },
131 {"r4",
132 nullptr,
133 8,
134 0,
135 eEncodingUint,
136 eFormatHex,
137 {dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,
138 LLDB_INVALID_REGNUM},
139 nullptr,
140 nullptr,
141 },
142 {"r5",
143 nullptr,
144 8,
145 0,
146 eEncodingUint,
147 eFormatHex,
148 {dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,
149 LLDB_INVALID_REGNUM},
150 nullptr,
151 nullptr,
152 },
153 {"r6",
154 nullptr,
155 8,
156 0,
157 eEncodingUint,
158 eFormatHex,
159 {dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,
160 LLDB_INVALID_REGNUM},
161 nullptr,
162 nullptr,
163 },
164 {"r7",
165 nullptr,
166 8,
167 0,
168 eEncodingUint,
169 eFormatHex,
170 {dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,
171 LLDB_INVALID_REGNUM},
172 nullptr,
173 nullptr,
174 },
175 {"r8",
176 nullptr,
177 8,
178 0,
179 eEncodingUint,
180 eFormatHex,
181 {dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM,
182 LLDB_INVALID_REGNUM},
183 nullptr,
184 nullptr,
185 },
186 {"r9",
187 nullptr,
188 8,
189 0,
190 eEncodingUint,
191 eFormatHex,
192 {dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM,
193 LLDB_INVALID_REGNUM},
194 nullptr,
195 nullptr,
196 },
197 {"r10",
198 nullptr,
199 8,
200 0,
201 eEncodingUint,
202 eFormatHex,
203 {dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM,
204 LLDB_INVALID_REGNUM},
205 nullptr,
206 nullptr,
207 },
208 {"r11",
209 nullptr,
210 8,
211 0,
212 eEncodingUint,
213 eFormatHex,
214 {dwarf_r11, dwarf_r11, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM,
215 LLDB_INVALID_REGNUM},
216 nullptr,
217 nullptr,
218 },
219 {"r12",
220 nullptr,
221 8,
222 0,
223 eEncodingUint,
224 eFormatHex,
225 {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
226 LLDB_INVALID_REGNUM},
227 nullptr,
228 nullptr,
229 },
230 {"r13",
231 nullptr,
232 8,
233 0,
234 eEncodingUint,
235 eFormatHex,
236 {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
237 LLDB_INVALID_REGNUM},
238 nullptr,
239 nullptr,
240 },
241 {"r14",
242 nullptr,
243 8,
244 0,
245 eEncodingUint,
246 eFormatHex,
247 {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
248 LLDB_INVALID_REGNUM},
249 nullptr,
250 nullptr,
251 },
252 {"r15",
253 nullptr,
254 8,
255 0,
256 eEncodingUint,
257 eFormatHex,
258 {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
259 LLDB_INVALID_REGNUM},
260 nullptr,
261 nullptr,
262 },
263 {"r16",
264 nullptr,
265 8,
266 0,
267 eEncodingUint,
268 eFormatHex,
269 {dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
270 LLDB_INVALID_REGNUM},
271 nullptr,
272 nullptr,
273 },
274 {"r17",
275 nullptr,
276 8,
277 0,
278 eEncodingUint,
279 eFormatHex,
280 {dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
281 LLDB_INVALID_REGNUM},
282 nullptr,
283 nullptr,
284 },
285 {"r18",
286 nullptr,
287 8,
288 0,
289 eEncodingUint,
290 eFormatHex,
291 {dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
292 LLDB_INVALID_REGNUM},
293 nullptr,
294 nullptr,
295 },
296 {"r19",
297 nullptr,
298 8,
299 0,
300 eEncodingUint,
301 eFormatHex,
302 {dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
303 LLDB_INVALID_REGNUM},
304 nullptr,
305 nullptr,
306 },
307 {"r20",
308 nullptr,
309 8,
310 0,
311 eEncodingUint,
312 eFormatHex,
313 {dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
314 LLDB_INVALID_REGNUM},
315 nullptr,
316 nullptr,
317 },
318 {"r21",
319 nullptr,
320 8,
321 0,
322 eEncodingUint,
323 eFormatHex,
324 {dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
325 LLDB_INVALID_REGNUM},
326 nullptr,
327 nullptr,
328 },
329 {"r22",
330 nullptr,
331 8,
332 0,
333 eEncodingUint,
334 eFormatHex,
335 {dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
336 LLDB_INVALID_REGNUM},
337 nullptr,
338 nullptr,
339 },
340 {"r23",
341 nullptr,
342 8,
343 0,
344 eEncodingUint,
345 eFormatHex,
346 {dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
347 LLDB_INVALID_REGNUM},
348 nullptr,
349 nullptr,
350 },
351 {"r24",
352 nullptr,
353 8,
354 0,
355 eEncodingUint,
356 eFormatHex,
357 {dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
358 LLDB_INVALID_REGNUM},
359 nullptr,
360 nullptr,
361 },
362 {"r25",
363 nullptr,
364 8,
365 0,
366 eEncodingUint,
367 eFormatHex,
368 {dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
369 LLDB_INVALID_REGNUM},
370 nullptr,
371 nullptr,
372 },
373 {"r26",
374 nullptr,
375 8,
376 0,
377 eEncodingUint,
378 eFormatHex,
379 {dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
380 LLDB_INVALID_REGNUM},
381 nullptr,
382 nullptr,
383 },
384 {"r27",
385 nullptr,
386 8,
387 0,
388 eEncodingUint,
389 eFormatHex,
390 {dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
391 LLDB_INVALID_REGNUM},
392 nullptr,
393 nullptr,
394 },
395 {"r28",
396 "gp",
397 8,
398 0,
399 eEncodingUint,
400 eFormatHex,
401 {dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
402 LLDB_INVALID_REGNUM},
403 nullptr,
404 nullptr,
405 },
406 {"r29",
407 nullptr,
408 8,
409 0,
410 eEncodingUint,
411 eFormatHex,
412 {dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
413 LLDB_INVALID_REGNUM},
414 nullptr,
415 nullptr,
416 },
417 {"r30",
418 nullptr,
419 8,
420 0,
421 eEncodingUint,
422 eFormatHex,
423 {dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
424 LLDB_INVALID_REGNUM},
425 nullptr,
426 nullptr,
427 },
428 {"r31",
429 nullptr,
430 8,
431 0,
432 eEncodingUint,
433 eFormatHex,
434 {dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM,
435 LLDB_INVALID_REGNUM},
436 nullptr,
437 nullptr,
438 },
439 {"sr",
440 nullptr,
441 4,
442 0,
443 eEncodingUint,
444 eFormatHex,
445 {dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,
446 LLDB_INVALID_REGNUM},
447 nullptr,
448 nullptr,
449 },
450 {"lo",
451 nullptr,
452 8,
453 0,
454 eEncodingUint,
455 eFormatHex,
456 {dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
457 LLDB_INVALID_REGNUM},
458 nullptr,
459 nullptr,
460 },
461 {"hi",
462 nullptr,
463 8,
464 0,
465 eEncodingUint,
466 eFormatHex,
467 {dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
468 LLDB_INVALID_REGNUM},
469 nullptr,
470 nullptr,
471 },
472 {"bad",
473 nullptr,
474 8,
475 0,
476 eEncodingUint,
477 eFormatHex,
478 {dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
479 LLDB_INVALID_REGNUM},
480 nullptr,
481 nullptr,
482 },
483 {"cause",
484 nullptr,
485 8,
486 0,
487 eEncodingUint,
488 eFormatHex,
489 {dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
490 LLDB_INVALID_REGNUM},
491 nullptr,
492 nullptr,
493 },
494 {"pc",
495 nullptr,
496 8,
497 0,
498 eEncodingUint,
499 eFormatHex,
500 {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
501 LLDB_INVALID_REGNUM},
502 nullptr,
503 nullptr,
504 },
505 };
506
507 static const uint32_t k_num_register_infos = std::size(g_register_infos_mips64);
508
509 const lldb_private::RegisterInfo *
GetRegisterInfoArray(uint32_t & count)510 ABISysV_mips64::GetRegisterInfoArray(uint32_t &count) {
511 count = k_num_register_infos;
512 return g_register_infos_mips64;
513 }
514
GetRedZoneSize() const515 size_t ABISysV_mips64::GetRedZoneSize() const { return 0; }
516
517 // Static Functions
518
519 ABISP
CreateInstance(lldb::ProcessSP process_sp,const ArchSpec & arch)520 ABISysV_mips64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
521 if (arch.GetTriple().isMIPS64())
522 return ABISP(
523 new ABISysV_mips64(std::move(process_sp), MakeMCRegisterInfo(arch)));
524 return ABISP();
525 }
526
PrepareTrivialCall(Thread & thread,addr_t sp,addr_t func_addr,addr_t return_addr,llvm::ArrayRef<addr_t> args) const527 bool ABISysV_mips64::PrepareTrivialCall(Thread &thread, addr_t sp,
528 addr_t func_addr, addr_t return_addr,
529 llvm::ArrayRef<addr_t> args) const {
530 Log *log = GetLog(LLDBLog::Expressions);
531
532 if (log) {
533 StreamString s;
534 s.Printf("ABISysV_mips64::PrepareTrivialCall (tid = 0x%" PRIx64
535 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
536 ", return_addr = 0x%" PRIx64,
537 thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
538 (uint64_t)return_addr);
539
540 for (size_t i = 0; i < args.size(); ++i)
541 s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);
542 s.PutCString(")");
543 log->PutString(s.GetString());
544 }
545
546 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
547 if (!reg_ctx)
548 return false;
549
550 const RegisterInfo *reg_info = nullptr;
551
552 if (args.size() > 8) // TODO handle more than 8 arguments
553 return false;
554
555 for (size_t i = 0; i < args.size(); ++i) {
556 reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
557 LLDB_REGNUM_GENERIC_ARG1 + i);
558 LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1,
559 args[i], reg_info->name);
560 if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
561 return false;
562 }
563
564 // First, align the SP
565
566 LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64,
567 (uint64_t)sp, (uint64_t)(sp & ~0xfull));
568
569 sp &= ~(0xfull); // 16-byte alignment
570
571 Status error;
572 const RegisterInfo *pc_reg_info =
573 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
574 const RegisterInfo *sp_reg_info =
575 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
576 const RegisterInfo *ra_reg_info =
577 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
578 const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
579 const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);
580
581 LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0);
582
583 /* Write r0 with 0, in case we are stopped in syscall,
584 * such setting prevents automatic decrement of the PC.
585 * This clears the bug 23659 for MIPS.
586 */
587 if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))
588 return false;
589
590 LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);
591
592 // Set "sp" to the requested value
593 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))
594 return false;
595
596 LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
597
598 // Set "ra" to the return address
599 if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))
600 return false;
601
602 LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
603
604 // Set pc to the address of the called function.
605 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))
606 return false;
607
608 LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
609
610 // All callers of position independent functions must place the address of
611 // the called function in t9 (r25)
612 if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))
613 return false;
614
615 return true;
616 }
617
GetArgumentValues(Thread & thread,ValueList & values) const618 bool ABISysV_mips64::GetArgumentValues(Thread &thread,
619 ValueList &values) const {
620 return false;
621 }
622
SetReturnValueObject(lldb::StackFrameSP & frame_sp,lldb::ValueObjectSP & new_value_sp)623 Status ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
624 lldb::ValueObjectSP &new_value_sp) {
625 Status error;
626 if (!new_value_sp) {
627 error.SetErrorString("Empty value object for return value.");
628 return error;
629 }
630
631 CompilerType compiler_type = new_value_sp->GetCompilerType();
632 if (!compiler_type) {
633 error.SetErrorString("Null clang type for return value.");
634 return error;
635 }
636
637 Thread *thread = frame_sp->GetThread().get();
638
639 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
640
641 if (!reg_ctx)
642 error.SetErrorString("no registers are available");
643
644 DataExtractor data;
645 Status data_error;
646 size_t num_bytes = new_value_sp->GetData(data, data_error);
647 if (data_error.Fail()) {
648 error.SetErrorStringWithFormat(
649 "Couldn't convert return value to raw data: %s",
650 data_error.AsCString());
651 return error;
652 }
653
654 const uint32_t type_flags = compiler_type.GetTypeInfo(nullptr);
655
656 if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
657 if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
658 lldb::offset_t offset = 0;
659
660 if (num_bytes <= 16) {
661 const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
662 if (num_bytes <= 8) {
663 uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
664
665 if (!reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))
666 error.SetErrorString("failed to write register r2");
667 } else {
668 uint64_t raw_value = data.GetMaxU64(&offset, 8);
669 if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {
670 const RegisterInfo *r3_info =
671 reg_ctx->GetRegisterInfoByName("r3", 0);
672 raw_value = data.GetMaxU64(&offset, num_bytes - offset);
673
674 if (!reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))
675 error.SetErrorString("failed to write register r3");
676 } else
677 error.SetErrorString("failed to write register r2");
678 }
679 } else {
680 error.SetErrorString("We don't support returning longer than 128 bit "
681 "integer values at present.");
682 }
683 } else if (type_flags & eTypeIsFloat) {
684 error.SetErrorString("TODO: Handle Float Types.");
685 }
686 } else if (type_flags & eTypeIsVector) {
687 error.SetErrorString("returning vector values are not supported");
688 }
689
690 return error;
691 }
692
GetReturnValueObjectSimple(Thread & thread,CompilerType & return_compiler_type) const693 ValueObjectSP ABISysV_mips64::GetReturnValueObjectSimple(
694 Thread &thread, CompilerType &return_compiler_type) const {
695 ValueObjectSP return_valobj_sp;
696 return return_valobj_sp;
697 }
698
GetReturnValueObjectImpl(Thread & thread,CompilerType & return_compiler_type) const699 ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
700 Thread &thread, CompilerType &return_compiler_type) const {
701 ValueObjectSP return_valobj_sp;
702 Value value;
703 Status error;
704
705 ExecutionContext exe_ctx(thread.shared_from_this());
706 if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
707 return return_valobj_sp;
708
709 value.SetCompilerType(return_compiler_type);
710
711 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
712 if (!reg_ctx)
713 return return_valobj_sp;
714
715 Target *target = exe_ctx.GetTargetPtr();
716 const ArchSpec target_arch = target->GetArchitecture();
717 ByteOrder target_byte_order = target_arch.GetByteOrder();
718 std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread);
719 if (!byte_size)
720 return return_valobj_sp;
721 const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr);
722 uint32_t fp_flag =
723 target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;
724
725 const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
726 const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
727 assert(r2_info && r3_info && "Basic registers should always be present.");
728
729 if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
730 value.SetValueType(Value::ValueType::Scalar);
731
732 bool success = false;
733 if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
734 // Extract the register context so we can read arguments from registers
735 // In MIPS register "r2" (v0) holds the integer function return values
736
737 uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0);
738
739 const bool is_signed = (type_flags & eTypeIsSigned) != 0;
740 switch (*byte_size) {
741 default:
742 break;
743
744 case sizeof(uint64_t):
745 if (is_signed)
746 value.GetScalar() = (int64_t)(raw_value);
747 else
748 value.GetScalar() = (uint64_t)(raw_value);
749 success = true;
750 break;
751
752 case sizeof(uint32_t):
753 if (is_signed)
754 value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
755 else
756 value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
757 success = true;
758 break;
759
760 case sizeof(uint16_t):
761 if (is_signed)
762 value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
763 else
764 value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
765 success = true;
766 break;
767
768 case sizeof(uint8_t):
769 if (is_signed)
770 value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
771 else
772 value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
773 success = true;
774 break;
775 }
776 } else if (type_flags & eTypeIsFloat) {
777 if (type_flags & eTypeIsComplex) {
778 // Don't handle complex yet.
779 } else if (IsSoftFloat(fp_flag)) {
780 uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0);
781 switch (*byte_size) {
782 case 4:
783 value.GetScalar() = *((float *)(&raw_value));
784 success = true;
785 break;
786 case 8:
787 value.GetScalar() = *((double *)(&raw_value));
788 success = true;
789 break;
790 case 16:
791 uint64_t result[2];
792 if (target_byte_order == eByteOrderLittle) {
793 result[0] = raw_value;
794 result[1] = reg_ctx->ReadRegisterAsUnsigned(r3_info, 0);
795 value.GetScalar() = *((long double *)(result));
796 } else {
797 result[0] = reg_ctx->ReadRegisterAsUnsigned(r3_info, 0);
798 result[1] = raw_value;
799 value.GetScalar() = *((long double *)(result));
800 }
801 success = true;
802 break;
803 }
804
805 } else {
806 if (*byte_size <= sizeof(long double)) {
807 const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
808
809 RegisterValue f0_value;
810 DataExtractor f0_data;
811
812 reg_ctx->ReadRegister(f0_info, f0_value);
813
814 f0_value.GetData(f0_data);
815
816 lldb::offset_t offset = 0;
817 if (*byte_size == sizeof(float)) {
818 value.GetScalar() = (float)f0_data.GetFloat(&offset);
819 success = true;
820 } else if (*byte_size == sizeof(double)) {
821 value.GetScalar() = (double)f0_data.GetDouble(&offset);
822 success = true;
823 } else if (*byte_size == sizeof(long double)) {
824 const RegisterInfo *f2_info =
825 reg_ctx->GetRegisterInfoByName("f2", 0);
826 RegisterValue f2_value;
827 DataExtractor f2_data;
828 reg_ctx->ReadRegister(f2_info, f2_value);
829 DataExtractor *copy_from_extractor = nullptr;
830 WritableDataBufferSP data_sp(new DataBufferHeap(16, 0));
831 DataExtractor return_ext(
832 data_sp, target_byte_order,
833 target->GetArchitecture().GetAddressByteSize());
834
835 if (target_byte_order == eByteOrderLittle) {
836 copy_from_extractor = &f0_data;
837 copy_from_extractor->CopyByteOrderedData(
838 0, 8, data_sp->GetBytes(), *byte_size - 8, target_byte_order);
839 f2_value.GetData(f2_data);
840 copy_from_extractor = &f2_data;
841 copy_from_extractor->CopyByteOrderedData(
842 0, 8, data_sp->GetBytes() + 8, *byte_size - 8,
843 target_byte_order);
844 } else {
845 copy_from_extractor = &f0_data;
846 copy_from_extractor->CopyByteOrderedData(
847 0, 8, data_sp->GetBytes() + 8, *byte_size - 8,
848 target_byte_order);
849 f2_value.GetData(f2_data);
850 copy_from_extractor = &f2_data;
851 copy_from_extractor->CopyByteOrderedData(
852 0, 8, data_sp->GetBytes(), *byte_size - 8, target_byte_order);
853 }
854
855 return_valobj_sp = ValueObjectConstResult::Create(
856 &thread, return_compiler_type, ConstString(""), return_ext);
857 return return_valobj_sp;
858 }
859 }
860 }
861 }
862
863 if (success)
864 return_valobj_sp = ValueObjectConstResult::Create(
865 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
866 } else if (type_flags & eTypeIsStructUnion || type_flags & eTypeIsClass ||
867 type_flags & eTypeIsVector) {
868 // Any structure of up to 16 bytes in size is returned in the registers.
869 if (*byte_size <= 16) {
870 WritableDataBufferSP data_sp(new DataBufferHeap(16, 0));
871 DataExtractor return_ext(data_sp, target_byte_order,
872 target->GetArchitecture().GetAddressByteSize());
873
874 RegisterValue r2_value, r3_value, f0_value, f1_value, f2_value;
875 // Tracks how much bytes of r2 and r3 registers we've consumed so far
876 uint32_t integer_bytes = 0;
877
878 // True if return values are in FP return registers.
879 bool use_fp_regs = false;
880 // True if we found any non floating point field in structure.
881 bool found_non_fp_field = false;
882 // True if return values are in r2 register.
883 bool use_r2 = false;
884 // True if return values are in r3 register.
885 bool use_r3 = false;
886 // True if the result is copied into our data buffer
887 bool sucess = false;
888 std::string name;
889 bool is_complex;
890 uint32_t count;
891 const uint32_t num_children = return_compiler_type.GetNumFields();
892
893 // A structure consisting of one or two FP values (and nothing else) will
894 // be returned in the two FP return-value registers i.e fp0 and fp2.
895 if (num_children <= 2) {
896 uint64_t field_bit_offset = 0;
897
898 // Check if this structure contains only floating point fields
899 for (uint32_t idx = 0; idx < num_children; idx++) {
900 CompilerType field_compiler_type =
901 return_compiler_type.GetFieldAtIndex(idx, name, &field_bit_offset,
902 nullptr, nullptr);
903
904 if (field_compiler_type.IsFloatingPointType(count, is_complex))
905 use_fp_regs = true;
906 else
907 found_non_fp_field = true;
908 }
909
910 if (use_fp_regs && !found_non_fp_field) {
911 // We have one or two FP-only values in this structure. Get it from
912 // f0/f2 registers.
913 DataExtractor f0_data, f1_data, f2_data;
914 const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
915 const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
916 const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0);
917
918 reg_ctx->ReadRegister(f0_info, f0_value);
919 reg_ctx->ReadRegister(f2_info, f2_value);
920
921 f0_value.GetData(f0_data);
922
923 for (uint32_t idx = 0; idx < num_children; idx++) {
924 CompilerType field_compiler_type =
925 return_compiler_type.GetFieldAtIndex(
926 idx, name, &field_bit_offset, nullptr, nullptr);
927 std::optional<uint64_t> field_byte_width =
928 field_compiler_type.GetByteSize(&thread);
929 if (!field_byte_width)
930 return return_valobj_sp;
931
932 DataExtractor *copy_from_extractor = nullptr;
933 uint64_t return_value[2];
934 offset_t offset = 0;
935
936 if (idx == 0) {
937 // This case is for long double type.
938 if (*field_byte_width == 16) {
939
940 // If structure contains long double type, then it is returned
941 // in fp0/fp1 registers.
942 if (target_byte_order == eByteOrderLittle) {
943 return_value[0] = f0_data.GetU64(&offset);
944 reg_ctx->ReadRegister(f1_info, f1_value);
945 f1_value.GetData(f1_data);
946 offset = 0;
947 return_value[1] = f1_data.GetU64(&offset);
948 } else {
949 return_value[1] = f0_data.GetU64(&offset);
950 reg_ctx->ReadRegister(f1_info, f1_value);
951 f1_value.GetData(f1_data);
952 offset = 0;
953 return_value[0] = f1_data.GetU64(&offset);
954 }
955
956 f0_data.SetData(return_value, *field_byte_width,
957 target_byte_order);
958 }
959 copy_from_extractor = &f0_data; // This is in f0, copy from
960 // register to our result
961 // structure
962 } else {
963 f2_value.GetData(f2_data);
964 // This is in f2, copy from register to our result structure
965 copy_from_extractor = &f2_data;
966 }
967
968 // Sanity check to avoid crash
969 if (!copy_from_extractor ||
970 *field_byte_width > copy_from_extractor->GetByteSize())
971 return return_valobj_sp;
972
973 // copy the register contents into our data buffer
974 copy_from_extractor->CopyByteOrderedData(
975 0, *field_byte_width,
976 data_sp->GetBytes() + (field_bit_offset / 8), *field_byte_width,
977 target_byte_order);
978 }
979
980 // The result is in our data buffer. Create a variable object out of
981 // it
982 return_valobj_sp = ValueObjectConstResult::Create(
983 &thread, return_compiler_type, ConstString(""), return_ext);
984
985 return return_valobj_sp;
986 }
987 }
988
989 // If we reach here, it means this structure either contains more than
990 // two fields or it contains at least one non floating point type. In
991 // that case, all fields are returned in GP return registers.
992 for (uint32_t idx = 0; idx < num_children; idx++) {
993 uint64_t field_bit_offset = 0;
994 bool is_signed;
995 uint32_t padding;
996
997 CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(
998 idx, name, &field_bit_offset, nullptr, nullptr);
999 std::optional<uint64_t> field_byte_width =
1000 field_compiler_type.GetByteSize(&thread);
1001
1002 // if we don't know the size of the field (e.g. invalid type), just
1003 // bail out
1004 if (!field_byte_width || *field_byte_width == 0)
1005 break;
1006
1007 uint32_t field_byte_offset = field_bit_offset / 8;
1008
1009 if (field_compiler_type.IsIntegerOrEnumerationType(is_signed) ||
1010 field_compiler_type.IsPointerType() ||
1011 field_compiler_type.IsFloatingPointType(count, is_complex)) {
1012 padding = field_byte_offset - integer_bytes;
1013
1014 if (integer_bytes < 8) {
1015 // We have not yet consumed r2 completely.
1016 if (integer_bytes + *field_byte_width + padding <= 8) {
1017 // This field fits in r2, copy its value from r2 to our result
1018 // structure
1019 integer_bytes = integer_bytes + *field_byte_width +
1020 padding; // Increase the consumed bytes.
1021 use_r2 = true;
1022 } else {
1023 // There isn't enough space left in r2 for this field, so this
1024 // will be in r3.
1025 integer_bytes = integer_bytes + *field_byte_width +
1026 padding; // Increase the consumed bytes.
1027 use_r3 = true;
1028 }
1029 }
1030 // We already have consumed at-least 8 bytes that means r2 is done,
1031 // and this field will be in r3. Check if this field can fit in r3.
1032 else if (integer_bytes + *field_byte_width + padding <= 16) {
1033 integer_bytes = integer_bytes + *field_byte_width + padding;
1034 use_r3 = true;
1035 } else {
1036 // There isn't any space left for this field, this should not
1037 // happen as we have already checked the overall size is not
1038 // greater than 16 bytes. For now, return a nullptr return value
1039 // object.
1040 return return_valobj_sp;
1041 }
1042 }
1043 }
1044 // Vector types up to 16 bytes are returned in GP return registers
1045 if (type_flags & eTypeIsVector) {
1046 if (*byte_size <= 8)
1047 use_r2 = true;
1048 else {
1049 use_r2 = true;
1050 use_r3 = true;
1051 }
1052 }
1053
1054 if (use_r2) {
1055 reg_ctx->ReadRegister(r2_info, r2_value);
1056
1057 const size_t bytes_copied = r2_value.GetAsMemoryData(
1058 *r2_info, data_sp->GetBytes(), r2_info->byte_size,
1059 target_byte_order, error);
1060 if (bytes_copied != r2_info->byte_size)
1061 return return_valobj_sp;
1062 sucess = true;
1063 }
1064 if (use_r3) {
1065 reg_ctx->ReadRegister(r3_info, r3_value);
1066 const size_t bytes_copied = r3_value.GetAsMemoryData(
1067 *r3_info, data_sp->GetBytes() + r2_info->byte_size,
1068 r3_info->byte_size, target_byte_order, error);
1069
1070 if (bytes_copied != r3_info->byte_size)
1071 return return_valobj_sp;
1072 sucess = true;
1073 }
1074 if (sucess) {
1075 // The result is in our data buffer. Create a variable object out of
1076 // it
1077 return_valobj_sp = ValueObjectConstResult::Create(
1078 &thread, return_compiler_type, ConstString(""), return_ext);
1079 }
1080 return return_valobj_sp;
1081 }
1082
1083 // Any structure/vector greater than 16 bytes in size is returned in
1084 // memory. The pointer to that memory is returned in r2.
1085 uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
1086 reg_ctx->GetRegisterInfoByName("r2", 0), 0);
1087
1088 // We have got the address. Create a memory object out of it
1089 return_valobj_sp = ValueObjectMemory::Create(
1090 &thread, "", Address(mem_address, nullptr), return_compiler_type);
1091 }
1092 return return_valobj_sp;
1093 }
1094
CreateFunctionEntryUnwindPlan(UnwindPlan & unwind_plan)1095 bool ABISysV_mips64::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
1096 unwind_plan.Clear();
1097 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1098
1099 UnwindPlan::RowSP row(new UnwindPlan::Row);
1100
1101 // Our Call Frame Address is the stack pointer value
1102 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
1103
1104 // The previous PC is in the RA
1105 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
1106 unwind_plan.AppendRow(row);
1107
1108 // All other registers are the same.
1109
1110 unwind_plan.SetSourceName("mips64 at-func-entry default");
1111 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1112 unwind_plan.SetReturnAddressRegister(dwarf_r31);
1113 return true;
1114 }
1115
CreateDefaultUnwindPlan(UnwindPlan & unwind_plan)1116 bool ABISysV_mips64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
1117 unwind_plan.Clear();
1118 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1119
1120 UnwindPlan::RowSP row(new UnwindPlan::Row);
1121
1122 row->SetUnspecifiedRegistersAreUndefined(true);
1123 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
1124
1125 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
1126
1127 unwind_plan.AppendRow(row);
1128 unwind_plan.SetSourceName("mips64 default unwind plan");
1129 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1130 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
1131 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
1132 return true;
1133 }
1134
RegisterIsVolatile(const RegisterInfo * reg_info)1135 bool ABISysV_mips64::RegisterIsVolatile(const RegisterInfo *reg_info) {
1136 return !RegisterIsCalleeSaved(reg_info);
1137 }
1138
IsSoftFloat(uint32_t fp_flag) const1139 bool ABISysV_mips64::IsSoftFloat(uint32_t fp_flag) const {
1140 return (fp_flag == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);
1141 }
1142
RegisterIsCalleeSaved(const RegisterInfo * reg_info)1143 bool ABISysV_mips64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
1144 if (reg_info) {
1145 // Preserved registers are :
1146 // r16-r23, r28, r29, r30, r31
1147
1148 int reg = ((reg_info->byte_offset) / 8);
1149
1150 bool save = (reg >= 16) && (reg <= 23);
1151 save |= (reg >= 28) && (reg <= 31);
1152
1153 return save;
1154 }
1155 return false;
1156 }
1157
Initialize()1158 void ABISysV_mips64::Initialize() {
1159 PluginManager::RegisterPlugin(
1160 GetPluginNameStatic(), "System V ABI for mips64 targets", CreateInstance);
1161 }
1162
Terminate()1163 void ABISysV_mips64::Terminate() {
1164 PluginManager::UnregisterPlugin(CreateInstance);
1165 }
1166