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