1 //===-- ABISysV_mips.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_mips.h"
10
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/TargetParser/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_mips)
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[] = {
81 // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME
82 // DWARF GENERIC PROCESS PLUGINS
83 // LLDB NATIVE VALUE REGS INVALIDATE REGS
84 // ======== ====== == === ============= =========== ============
85 // ============== ============ =================
86 // =================== ========== =================
87 {"r0",
88 "zero",
89 4,
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 nullptr,
98 },
99 {"r1",
100 "AT",
101 4,
102 0,
103 eEncodingUint,
104 eFormatHex,
105 {dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
106 LLDB_INVALID_REGNUM},
107 nullptr,
108 nullptr,
109 nullptr,
110 },
111 {"r2",
112 "v0",
113 4,
114 0,
115 eEncodingUint,
116 eFormatHex,
117 {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
118 LLDB_INVALID_REGNUM},
119 nullptr,
120 nullptr,
121 nullptr,
122 },
123 {"r3",
124 "v1",
125 4,
126 0,
127 eEncodingUint,
128 eFormatHex,
129 {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
130 LLDB_INVALID_REGNUM},
131 nullptr,
132 nullptr,
133 nullptr,
134 },
135 {"r4",
136 nullptr,
137 4,
138 0,
139 eEncodingUint,
140 eFormatHex,
141 {dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,
142 LLDB_INVALID_REGNUM},
143 nullptr,
144 nullptr,
145 nullptr,
146 },
147 {"r5",
148 nullptr,
149 4,
150 0,
151 eEncodingUint,
152 eFormatHex,
153 {dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,
154 LLDB_INVALID_REGNUM},
155 nullptr,
156 nullptr,
157 nullptr,
158 },
159 {"r6",
160 nullptr,
161 4,
162 0,
163 eEncodingUint,
164 eFormatHex,
165 {dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,
166 LLDB_INVALID_REGNUM},
167 nullptr,
168 nullptr,
169 nullptr,
170 },
171 {"r7",
172 nullptr,
173 4,
174 0,
175 eEncodingUint,
176 eFormatHex,
177 {dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,
178 LLDB_INVALID_REGNUM},
179 nullptr,
180 nullptr,
181 nullptr,
182 },
183 {"r8",
184 "arg5",
185 4,
186 0,
187 eEncodingUint,
188 eFormatHex,
189 {dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
190 LLDB_INVALID_REGNUM},
191 nullptr,
192 nullptr,
193 nullptr,
194 },
195 {"r9",
196 "arg6",
197 4,
198 0,
199 eEncodingUint,
200 eFormatHex,
201 {dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
202 LLDB_INVALID_REGNUM},
203 nullptr,
204 nullptr,
205 nullptr,
206 },
207 {"r10",
208 "arg7",
209 4,
210 0,
211 eEncodingUint,
212 eFormatHex,
213 {dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
214 LLDB_INVALID_REGNUM},
215 nullptr,
216 nullptr,
217 nullptr,
218 },
219 {"r11",
220 "arg8",
221 4,
222 0,
223 eEncodingUint,
224 eFormatHex,
225 {dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
226 LLDB_INVALID_REGNUM},
227 nullptr,
228 nullptr,
229 nullptr,
230 },
231 {"r12",
232 nullptr,
233 4,
234 0,
235 eEncodingUint,
236 eFormatHex,
237 {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
238 LLDB_INVALID_REGNUM},
239 nullptr,
240 nullptr,
241 nullptr,
242 },
243 {"r13",
244 nullptr,
245 4,
246 0,
247 eEncodingUint,
248 eFormatHex,
249 {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
250 LLDB_INVALID_REGNUM},
251 nullptr,
252 nullptr,
253 nullptr,
254 },
255 {"r14",
256 nullptr,
257 4,
258 0,
259 eEncodingUint,
260 eFormatHex,
261 {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
262 LLDB_INVALID_REGNUM},
263 nullptr,
264 nullptr,
265 nullptr,
266 },
267 {"r15",
268 nullptr,
269 4,
270 0,
271 eEncodingUint,
272 eFormatHex,
273 {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
274 LLDB_INVALID_REGNUM},
275 nullptr,
276 nullptr,
277 nullptr,
278 },
279 {"r16",
280 nullptr,
281 4,
282 0,
283 eEncodingUint,
284 eFormatHex,
285 {dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
286 LLDB_INVALID_REGNUM},
287 nullptr,
288 nullptr,
289 nullptr,
290 },
291 {"r17",
292 nullptr,
293 4,
294 0,
295 eEncodingUint,
296 eFormatHex,
297 {dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
298 LLDB_INVALID_REGNUM},
299 nullptr,
300 nullptr,
301 nullptr,
302 },
303 {"r18",
304 nullptr,
305 4,
306 0,
307 eEncodingUint,
308 eFormatHex,
309 {dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
310 LLDB_INVALID_REGNUM},
311 nullptr,
312 nullptr,
313 nullptr,
314 },
315 {"r19",
316 nullptr,
317 4,
318 0,
319 eEncodingUint,
320 eFormatHex,
321 {dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
322 LLDB_INVALID_REGNUM},
323 nullptr,
324 nullptr,
325 nullptr,
326 },
327 {"r20",
328 nullptr,
329 4,
330 0,
331 eEncodingUint,
332 eFormatHex,
333 {dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
334 LLDB_INVALID_REGNUM},
335 nullptr,
336 nullptr,
337 nullptr,
338 },
339 {"r21",
340 nullptr,
341 4,
342 0,
343 eEncodingUint,
344 eFormatHex,
345 {dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
346 LLDB_INVALID_REGNUM},
347 nullptr,
348 nullptr,
349 nullptr,
350 },
351 {"r22",
352 nullptr,
353 4,
354 0,
355 eEncodingUint,
356 eFormatHex,
357 {dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
358 LLDB_INVALID_REGNUM},
359 nullptr,
360 nullptr,
361 nullptr,
362 },
363 {"r23",
364 nullptr,
365 4,
366 0,
367 eEncodingUint,
368 eFormatHex,
369 {dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
370 LLDB_INVALID_REGNUM},
371 nullptr,
372 nullptr,
373 nullptr,
374 },
375 {"r24",
376 nullptr,
377 4,
378 0,
379 eEncodingUint,
380 eFormatHex,
381 {dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
382 LLDB_INVALID_REGNUM},
383 nullptr,
384 nullptr,
385 nullptr,
386 },
387 {"r25",
388 nullptr,
389 4,
390 0,
391 eEncodingUint,
392 eFormatHex,
393 {dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
394 LLDB_INVALID_REGNUM},
395 nullptr,
396 nullptr,
397 nullptr,
398 },
399 {"r26",
400 nullptr,
401 4,
402 0,
403 eEncodingUint,
404 eFormatHex,
405 {dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
406 LLDB_INVALID_REGNUM},
407 nullptr,
408 nullptr,
409 nullptr,
410 },
411 {"r27",
412 nullptr,
413 4,
414 0,
415 eEncodingUint,
416 eFormatHex,
417 {dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
418 LLDB_INVALID_REGNUM},
419 nullptr,
420 nullptr,
421 nullptr,
422 },
423 {"r28",
424 "gp",
425 4,
426 0,
427 eEncodingUint,
428 eFormatHex,
429 {dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
430 LLDB_INVALID_REGNUM},
431 nullptr,
432 nullptr,
433 nullptr,
434 },
435 {"r29",
436 nullptr,
437 4,
438 0,
439 eEncodingUint,
440 eFormatHex,
441 {dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
442 LLDB_INVALID_REGNUM},
443 nullptr,
444 nullptr,
445 nullptr,
446 },
447 {"r30",
448 nullptr,
449 4,
450 0,
451 eEncodingUint,
452 eFormatHex,
453 {dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
454 LLDB_INVALID_REGNUM},
455 nullptr,
456 nullptr,
457 nullptr,
458 },
459 {"r31",
460 nullptr,
461 4,
462 0,
463 eEncodingUint,
464 eFormatHex,
465 {dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM,
466 LLDB_INVALID_REGNUM},
467 nullptr,
468 nullptr,
469 nullptr,
470 },
471 {"sr",
472 nullptr,
473 4,
474 0,
475 eEncodingUint,
476 eFormatHex,
477 {dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,
478 LLDB_INVALID_REGNUM},
479 nullptr,
480 nullptr,
481 nullptr,
482 },
483 {"lo",
484 nullptr,
485 4,
486 0,
487 eEncodingUint,
488 eFormatHex,
489 {dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
490 LLDB_INVALID_REGNUM},
491 nullptr,
492 nullptr,
493 nullptr,
494 },
495 {"hi",
496 nullptr,
497 4,
498 0,
499 eEncodingUint,
500 eFormatHex,
501 {dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
502 LLDB_INVALID_REGNUM},
503 nullptr,
504 nullptr,
505 nullptr,
506 },
507 {"bad",
508 nullptr,
509 4,
510 0,
511 eEncodingUint,
512 eFormatHex,
513 {dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
514 LLDB_INVALID_REGNUM},
515 nullptr,
516 nullptr,
517 nullptr,
518 },
519 {"cause",
520 nullptr,
521 4,
522 0,
523 eEncodingUint,
524 eFormatHex,
525 {dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
526 LLDB_INVALID_REGNUM},
527 nullptr,
528 nullptr,
529 nullptr,
530 },
531 {"pc",
532 nullptr,
533 4,
534 0,
535 eEncodingUint,
536 eFormatHex,
537 {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
538 LLDB_INVALID_REGNUM},
539 nullptr,
540 nullptr,
541 nullptr,
542 },
543 };
544
545 static const uint32_t k_num_register_infos = std::size(g_register_infos);
546
547 const lldb_private::RegisterInfo *
GetRegisterInfoArray(uint32_t & count)548 ABISysV_mips::GetRegisterInfoArray(uint32_t &count) {
549 count = k_num_register_infos;
550 return g_register_infos;
551 }
552
GetRedZoneSize() const553 size_t ABISysV_mips::GetRedZoneSize() const { return 0; }
554
555 // Static Functions
556
557 ABISP
CreateInstance(lldb::ProcessSP process_sp,const ArchSpec & arch)558 ABISysV_mips::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
559 const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
560 if ((arch_type == llvm::Triple::mips) ||
561 (arch_type == llvm::Triple::mipsel)) {
562 return ABISP(
563 new ABISysV_mips(std::move(process_sp), MakeMCRegisterInfo(arch)));
564 }
565 return ABISP();
566 }
567
PrepareTrivialCall(Thread & thread,addr_t sp,addr_t func_addr,addr_t return_addr,llvm::ArrayRef<addr_t> args) const568 bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp,
569 addr_t func_addr, addr_t return_addr,
570 llvm::ArrayRef<addr_t> args) const {
571 Log *log = GetLog(LLDBLog::Expressions);
572
573 if (log) {
574 StreamString s;
575 s.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64
576 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
577 ", return_addr = 0x%" PRIx64,
578 thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
579 (uint64_t)return_addr);
580
581 for (size_t i = 0; i < args.size(); ++i)
582 s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);
583 s.PutCString(")");
584 log->PutString(s.GetString());
585 }
586
587 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
588 if (!reg_ctx)
589 return false;
590
591 const RegisterInfo *reg_info = nullptr;
592
593 RegisterValue reg_value;
594
595 // Argument registers
596 const char *reg_names[] = {"r4", "r5", "r6", "r7"};
597
598 llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
599
600 // Write arguments to registers
601 for (size_t i = 0; i < std::size(reg_names); ++i) {
602 if (ai == ae)
603 break;
604
605 reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
606 LLDB_REGNUM_GENERIC_ARG1 + i);
607 LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1,
608 args[i], reg_info->name);
609
610 if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
611 return false;
612
613 ++ai;
614 }
615
616 // If we have more than 4 arguments --Spill onto the stack
617 if (ai != ae) {
618 // No of arguments to go on stack
619 size_t num_stack_regs = args.size();
620
621 // Allocate needed space for args on the stack
622 sp -= (num_stack_regs * 4);
623
624 // Keep the stack 8 byte aligned
625 sp &= ~(8ull - 1ull);
626
627 // just using arg1 to get the right size
628 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(
629 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
630
631 addr_t arg_pos = sp + 16;
632
633 size_t i = 4;
634 for (; ai != ae; ++ai) {
635 reg_value.SetUInt32(*ai);
636 LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "",
637 i + 1, args[i], arg_pos);
638
639 if (reg_ctx
640 ->WriteRegisterValueToMemory(reg_info, arg_pos,
641 reg_info->byte_size, reg_value)
642 .Fail())
643 return false;
644 arg_pos += reg_info->byte_size;
645 i++;
646 }
647 }
648
649 Status error;
650 const RegisterInfo *pc_reg_info =
651 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
652 const RegisterInfo *sp_reg_info =
653 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
654 const RegisterInfo *ra_reg_info =
655 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
656 const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
657 const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);
658
659 LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0);
660
661 /* Write r0 with 0, in case we are stopped in syscall,
662 * such setting prevents automatic decrement of the PC.
663 * This clears the bug 23659 for MIPS.
664 */
665 if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))
666 return false;
667
668 LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);
669
670 // Set "sp" to the requested value
671 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))
672 return false;
673
674 LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
675
676 // Set "ra" to the return address
677 if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))
678 return false;
679
680 LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
681
682 // Set pc to the address of the called function.
683 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))
684 return false;
685
686 LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
687
688 // All callers of position independent functions must place the address of
689 // the called function in t9 (r25)
690 if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))
691 return false;
692
693 return true;
694 }
695
GetArgumentValues(Thread & thread,ValueList & values) const696 bool ABISysV_mips::GetArgumentValues(Thread &thread, ValueList &values) const {
697 return false;
698 }
699
SetReturnValueObject(lldb::StackFrameSP & frame_sp,lldb::ValueObjectSP & new_value_sp)700 Status ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
701 lldb::ValueObjectSP &new_value_sp) {
702 Status error;
703 if (!new_value_sp) {
704 error.SetErrorString("Empty value object for return value.");
705 return error;
706 }
707
708 CompilerType compiler_type = new_value_sp->GetCompilerType();
709 if (!compiler_type) {
710 error.SetErrorString("Null clang type for return value.");
711 return error;
712 }
713
714 Thread *thread = frame_sp->GetThread().get();
715
716 bool is_signed;
717 uint32_t count;
718 bool is_complex;
719
720 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
721
722 bool set_it_simple = false;
723 if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
724 compiler_type.IsPointerType()) {
725 DataExtractor data;
726 Status data_error;
727 size_t num_bytes = new_value_sp->GetData(data, data_error);
728 if (data_error.Fail()) {
729 error.SetErrorStringWithFormat(
730 "Couldn't convert return value to raw data: %s",
731 data_error.AsCString());
732 return error;
733 }
734
735 lldb::offset_t offset = 0;
736 if (num_bytes <= 8) {
737 const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
738 if (num_bytes <= 4) {
739 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
740
741 if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))
742 set_it_simple = true;
743 } else {
744 uint32_t raw_value = data.GetMaxU32(&offset, 4);
745
746 if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {
747 const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
748 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
749
750 if (reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))
751 set_it_simple = true;
752 }
753 }
754 } else {
755 error.SetErrorString("We don't support returning longer than 64 bit "
756 "integer values at present.");
757 }
758 } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
759 if (is_complex)
760 error.SetErrorString(
761 "We don't support returning complex values at present");
762 else
763 error.SetErrorString(
764 "We don't support returning float values at present");
765 }
766
767 if (!set_it_simple)
768 error.SetErrorString(
769 "We only support setting simple integer return types at present.");
770
771 return error;
772 }
773
GetReturnValueObjectSimple(Thread & thread,CompilerType & return_compiler_type) const774 ValueObjectSP ABISysV_mips::GetReturnValueObjectSimple(
775 Thread &thread, CompilerType &return_compiler_type) const {
776 ValueObjectSP return_valobj_sp;
777 return return_valobj_sp;
778 }
779
GetReturnValueObjectImpl(Thread & thread,CompilerType & return_compiler_type) const780 ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(
781 Thread &thread, CompilerType &return_compiler_type) const {
782 ValueObjectSP return_valobj_sp;
783 Value value;
784
785 if (!return_compiler_type)
786 return return_valobj_sp;
787
788 ExecutionContext exe_ctx(thread.shared_from_this());
789 if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
790 return return_valobj_sp;
791
792 Target *target = exe_ctx.GetTargetPtr();
793 const ArchSpec target_arch = target->GetArchitecture();
794 ByteOrder target_byte_order = target_arch.GetByteOrder();
795 value.SetCompilerType(return_compiler_type);
796 uint32_t fp_flag =
797 target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;
798
799 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
800 if (!reg_ctx)
801 return return_valobj_sp;
802
803 bool is_signed = false;
804 bool is_complex = false;
805 uint32_t count = 0;
806
807 // In MIPS register "r2" (v0) holds the integer function return values
808 const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
809 std::optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);
810 if (!bit_width)
811 return return_valobj_sp;
812 if (return_compiler_type.IsIntegerOrEnumerationType(is_signed)) {
813 switch (*bit_width) {
814 default:
815 return return_valobj_sp;
816 case 64: {
817 const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
818 uint64_t raw_value;
819 raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
820 raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) &
821 UINT32_MAX))
822 << 32;
823 if (is_signed)
824 value.GetScalar() = (int64_t)raw_value;
825 else
826 value.GetScalar() = (uint64_t)raw_value;
827 } break;
828 case 32:
829 if (is_signed)
830 value.GetScalar() = (int32_t)(
831 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
832 else
833 value.GetScalar() = (uint32_t)(
834 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
835 break;
836 case 16:
837 if (is_signed)
838 value.GetScalar() = (int16_t)(
839 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
840 else
841 value.GetScalar() = (uint16_t)(
842 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
843 break;
844 case 8:
845 if (is_signed)
846 value.GetScalar() = (int8_t)(
847 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
848 else
849 value.GetScalar() = (uint8_t)(
850 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
851 break;
852 }
853 } else if (return_compiler_type.IsPointerType()) {
854 uint32_t ptr =
855 thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) &
856 UINT32_MAX;
857 value.GetScalar() = ptr;
858 } else if (return_compiler_type.IsAggregateType()) {
859 // Structure/Vector is always passed in memory and pointer to that memory
860 // is passed in r2.
861 uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
862 reg_ctx->GetRegisterInfoByName("r2", 0), 0);
863 // We have got the address. Create a memory object out of it
864 return_valobj_sp = ValueObjectMemory::Create(
865 &thread, "", Address(mem_address, nullptr), return_compiler_type);
866 return return_valobj_sp;
867 } else if (return_compiler_type.IsFloatingPointType(count, is_complex)) {
868 if (IsSoftFloat(fp_flag)) {
869 uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0);
870 if (count != 1 && is_complex)
871 return return_valobj_sp;
872 switch (*bit_width) {
873 default:
874 return return_valobj_sp;
875 case 32:
876 static_assert(sizeof(float) == sizeof(uint32_t));
877 value.GetScalar() = *((float *)(&raw_value));
878 break;
879 case 64:
880 static_assert(sizeof(double) == sizeof(uint64_t));
881 const RegisterInfo *r3_reg_info =
882 reg_ctx->GetRegisterInfoByName("r3", 0);
883 if (target_byte_order == eByteOrderLittle)
884 raw_value =
885 ((reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0)) << 32) |
886 raw_value;
887 else
888 raw_value = (raw_value << 32) |
889 reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0);
890 value.GetScalar() = *((double *)(&raw_value));
891 break;
892 }
893 }
894
895 else {
896 const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
897 RegisterValue f0_value;
898 DataExtractor f0_data;
899 reg_ctx->ReadRegister(f0_info, f0_value);
900 f0_value.GetData(f0_data);
901 lldb::offset_t offset = 0;
902
903 if (count == 1 && !is_complex) {
904 switch (*bit_width) {
905 default:
906 return return_valobj_sp;
907 case 64: {
908 static_assert(sizeof(double) == sizeof(uint64_t));
909 const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
910 RegisterValue f1_value;
911 DataExtractor f1_data;
912 reg_ctx->ReadRegister(f1_info, f1_value);
913 DataExtractor *copy_from_extractor = nullptr;
914 WritableDataBufferSP data_sp(new DataBufferHeap(8, 0));
915 DataExtractor return_ext(
916 data_sp, target_byte_order,
917 target->GetArchitecture().GetAddressByteSize());
918
919 if (target_byte_order == eByteOrderLittle) {
920 copy_from_extractor = &f0_data;
921 copy_from_extractor->CopyByteOrderedData(
922 offset, 4, data_sp->GetBytes(), 4, target_byte_order);
923 f1_value.GetData(f1_data);
924 copy_from_extractor = &f1_data;
925 copy_from_extractor->CopyByteOrderedData(
926 offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
927 } else {
928 copy_from_extractor = &f0_data;
929 copy_from_extractor->CopyByteOrderedData(
930 offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
931 f1_value.GetData(f1_data);
932 copy_from_extractor = &f1_data;
933 copy_from_extractor->CopyByteOrderedData(
934 offset, 4, data_sp->GetBytes(), 4, target_byte_order);
935 }
936 value.GetScalar() = (double)return_ext.GetDouble(&offset);
937 break;
938 }
939 case 32: {
940 static_assert(sizeof(float) == sizeof(uint32_t));
941 value.GetScalar() = (float)f0_data.GetFloat(&offset);
942 break;
943 }
944 }
945 } else {
946 // not handled yet
947 return return_valobj_sp;
948 }
949 }
950 } else {
951 // not handled yet
952 return return_valobj_sp;
953 }
954
955 // If we get here, we have a valid Value, so make our ValueObject out of it:
956
957 return_valobj_sp = ValueObjectConstResult::Create(
958 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
959 return return_valobj_sp;
960 }
961
CreateFunctionEntryUnwindPlan(UnwindPlan & unwind_plan)962 bool ABISysV_mips::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
963 unwind_plan.Clear();
964 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
965
966 UnwindPlan::RowSP row(new UnwindPlan::Row);
967
968 // Our Call Frame Address is the stack pointer value
969 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
970
971 // The previous PC is in the RA
972 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
973 unwind_plan.AppendRow(row);
974
975 // All other registers are the same.
976
977 unwind_plan.SetSourceName("mips at-func-entry default");
978 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
979 unwind_plan.SetReturnAddressRegister(dwarf_r31);
980 return true;
981 }
982
CreateDefaultUnwindPlan(UnwindPlan & unwind_plan)983 bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
984 unwind_plan.Clear();
985 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
986
987 UnwindPlan::RowSP row(new UnwindPlan::Row);
988
989 row->SetUnspecifiedRegistersAreUndefined(true);
990 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
991
992 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
993
994 unwind_plan.AppendRow(row);
995 unwind_plan.SetSourceName("mips default unwind plan");
996 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
997 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
998 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
999 return true;
1000 }
1001
RegisterIsVolatile(const RegisterInfo * reg_info)1002 bool ABISysV_mips::RegisterIsVolatile(const RegisterInfo *reg_info) {
1003 return !RegisterIsCalleeSaved(reg_info);
1004 }
1005
IsSoftFloat(uint32_t fp_flags) const1006 bool ABISysV_mips::IsSoftFloat(uint32_t fp_flags) const {
1007 return (fp_flags == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);
1008 }
1009
RegisterIsCalleeSaved(const RegisterInfo * reg_info)1010 bool ABISysV_mips::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
1011 if (reg_info) {
1012 // Preserved registers are :
1013 // r16-r23, r28, r29, r30, r31
1014 const char *name = reg_info->name;
1015
1016 if (name[0] == 'r') {
1017 switch (name[1]) {
1018 case '1':
1019 if (name[2] == '6' || name[2] == '7' || name[2] == '8' ||
1020 name[2] == '9') // r16-r19
1021 return name[3] == '\0';
1022 break;
1023 case '2':
1024 if (name[2] == '0' || name[2] == '1' || name[2] == '2' ||
1025 name[2] == '3' // r20-r23
1026 || name[2] == '8' || name[2] == '9') // r28 and r29
1027 return name[3] == '\0';
1028 break;
1029 case '3':
1030 if (name[2] == '0' || name[2] == '1') // r30 and r31
1031 return name[3] == '\0';
1032 break;
1033 }
1034
1035 if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28)
1036 return true;
1037 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29)
1038 return true;
1039 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30)
1040 return true;
1041 if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31)
1042 return true;
1043 }
1044 }
1045 return false;
1046 }
1047
Initialize()1048 void ABISysV_mips::Initialize() {
1049 PluginManager::RegisterPlugin(
1050 GetPluginNameStatic(), "System V ABI for mips targets", CreateInstance);
1051 }
1052
Terminate()1053 void ABISysV_mips::Terminate() {
1054 PluginManager::UnregisterPlugin(CreateInstance);
1055 }
1056