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/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_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 },
98 {"r1",
99 "AT",
100 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 "arg5",
177 4,
178 0,
179 eEncodingUint,
180 eFormatHex,
181 {dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
182 LLDB_INVALID_REGNUM},
183 nullptr,
184 nullptr,
185 },
186 {"r9",
187 "arg6",
188 4,
189 0,
190 eEncodingUint,
191 eFormatHex,
192 {dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
193 LLDB_INVALID_REGNUM},
194 nullptr,
195 nullptr,
196 },
197 {"r10",
198 "arg7",
199 4,
200 0,
201 eEncodingUint,
202 eFormatHex,
203 {dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
204 LLDB_INVALID_REGNUM},
205 nullptr,
206 nullptr,
207 },
208 {"r11",
209 "arg8",
210 4,
211 0,
212 eEncodingUint,
213 eFormatHex,
214 {dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
215 LLDB_INVALID_REGNUM},
216 nullptr,
217 nullptr,
218 },
219 {"r12",
220 nullptr,
221 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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 4,
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);
508
509 const lldb_private::RegisterInfo *
GetRegisterInfoArray(uint32_t & count)510 ABISysV_mips::GetRegisterInfoArray(uint32_t &count) {
511 count = k_num_register_infos;
512 return g_register_infos;
513 }
514
GetRedZoneSize() const515 size_t ABISysV_mips::GetRedZoneSize() const { return 0; }
516
517 // Static Functions
518
519 ABISP
CreateInstance(lldb::ProcessSP process_sp,const ArchSpec & arch)520 ABISysV_mips::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
521 const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
522 if ((arch_type == llvm::Triple::mips) ||
523 (arch_type == llvm::Triple::mipsel)) {
524 return ABISP(
525 new ABISysV_mips(std::move(process_sp), MakeMCRegisterInfo(arch)));
526 }
527 return ABISP();
528 }
529
PrepareTrivialCall(Thread & thread,addr_t sp,addr_t func_addr,addr_t return_addr,llvm::ArrayRef<addr_t> args) const530 bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp,
531 addr_t func_addr, addr_t return_addr,
532 llvm::ArrayRef<addr_t> args) const {
533 Log *log = GetLog(LLDBLog::Expressions);
534
535 if (log) {
536 StreamString s;
537 s.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64
538 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
539 ", return_addr = 0x%" PRIx64,
540 thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
541 (uint64_t)return_addr);
542
543 for (size_t i = 0; i < args.size(); ++i)
544 s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);
545 s.PutCString(")");
546 log->PutString(s.GetString());
547 }
548
549 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
550 if (!reg_ctx)
551 return false;
552
553 const RegisterInfo *reg_info = nullptr;
554
555 RegisterValue reg_value;
556
557 // Argument registers
558 const char *reg_names[] = {"r4", "r5", "r6", "r7"};
559
560 llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
561
562 // Write arguments to registers
563 for (size_t i = 0; i < std::size(reg_names); ++i) {
564 if (ai == ae)
565 break;
566
567 reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
568 LLDB_REGNUM_GENERIC_ARG1 + i);
569 LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1,
570 args[i], reg_info->name);
571
572 if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
573 return false;
574
575 ++ai;
576 }
577
578 // If we have more than 4 arguments --Spill onto the stack
579 if (ai != ae) {
580 // No of arguments to go on stack
581 size_t num_stack_regs = args.size();
582
583 // Allocate needed space for args on the stack
584 sp -= (num_stack_regs * 4);
585
586 // Keep the stack 8 byte aligned
587 sp &= ~(8ull - 1ull);
588
589 // just using arg1 to get the right size
590 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(
591 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
592
593 addr_t arg_pos = sp + 16;
594
595 size_t i = 4;
596 for (; ai != ae; ++ai) {
597 reg_value.SetUInt32(*ai);
598 LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "",
599 i + 1, args[i], arg_pos);
600
601 if (reg_ctx
602 ->WriteRegisterValueToMemory(reg_info, arg_pos,
603 reg_info->byte_size, reg_value)
604 .Fail())
605 return false;
606 arg_pos += reg_info->byte_size;
607 i++;
608 }
609 }
610
611 Status error;
612 const RegisterInfo *pc_reg_info =
613 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
614 const RegisterInfo *sp_reg_info =
615 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
616 const RegisterInfo *ra_reg_info =
617 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
618 const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
619 const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);
620
621 LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0);
622
623 /* Write r0 with 0, in case we are stopped in syscall,
624 * such setting prevents automatic decrement of the PC.
625 * This clears the bug 23659 for MIPS.
626 */
627 if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))
628 return false;
629
630 LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);
631
632 // Set "sp" to the requested value
633 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))
634 return false;
635
636 LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
637
638 // Set "ra" to the return address
639 if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))
640 return false;
641
642 LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
643
644 // Set pc to the address of the called function.
645 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))
646 return false;
647
648 LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
649
650 // All callers of position independent functions must place the address of
651 // the called function in t9 (r25)
652 if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))
653 return false;
654
655 return true;
656 }
657
GetArgumentValues(Thread & thread,ValueList & values) const658 bool ABISysV_mips::GetArgumentValues(Thread &thread, ValueList &values) const {
659 return false;
660 }
661
SetReturnValueObject(lldb::StackFrameSP & frame_sp,lldb::ValueObjectSP & new_value_sp)662 Status ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
663 lldb::ValueObjectSP &new_value_sp) {
664 Status error;
665 if (!new_value_sp) {
666 error.SetErrorString("Empty value object for return value.");
667 return error;
668 }
669
670 CompilerType compiler_type = new_value_sp->GetCompilerType();
671 if (!compiler_type) {
672 error.SetErrorString("Null clang type for return value.");
673 return error;
674 }
675
676 Thread *thread = frame_sp->GetThread().get();
677
678 bool is_signed;
679 uint32_t count;
680 bool is_complex;
681
682 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
683
684 bool set_it_simple = false;
685 if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
686 compiler_type.IsPointerType()) {
687 DataExtractor data;
688 Status data_error;
689 size_t num_bytes = new_value_sp->GetData(data, data_error);
690 if (data_error.Fail()) {
691 error.SetErrorStringWithFormat(
692 "Couldn't convert return value to raw data: %s",
693 data_error.AsCString());
694 return error;
695 }
696
697 lldb::offset_t offset = 0;
698 if (num_bytes <= 8) {
699 const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
700 if (num_bytes <= 4) {
701 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
702
703 if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))
704 set_it_simple = true;
705 } else {
706 uint32_t raw_value = data.GetMaxU32(&offset, 4);
707
708 if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {
709 const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
710 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
711
712 if (reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))
713 set_it_simple = true;
714 }
715 }
716 } else {
717 error.SetErrorString("We don't support returning longer than 64 bit "
718 "integer values at present.");
719 }
720 } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
721 if (is_complex)
722 error.SetErrorString(
723 "We don't support returning complex values at present");
724 else
725 error.SetErrorString(
726 "We don't support returning float values at present");
727 }
728
729 if (!set_it_simple)
730 error.SetErrorString(
731 "We only support setting simple integer return types at present.");
732
733 return error;
734 }
735
GetReturnValueObjectSimple(Thread & thread,CompilerType & return_compiler_type) const736 ValueObjectSP ABISysV_mips::GetReturnValueObjectSimple(
737 Thread &thread, CompilerType &return_compiler_type) const {
738 ValueObjectSP return_valobj_sp;
739 return return_valobj_sp;
740 }
741
GetReturnValueObjectImpl(Thread & thread,CompilerType & return_compiler_type) const742 ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(
743 Thread &thread, CompilerType &return_compiler_type) const {
744 ValueObjectSP return_valobj_sp;
745 Value value;
746
747 if (!return_compiler_type)
748 return return_valobj_sp;
749
750 ExecutionContext exe_ctx(thread.shared_from_this());
751 if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
752 return return_valobj_sp;
753
754 Target *target = exe_ctx.GetTargetPtr();
755 const ArchSpec target_arch = target->GetArchitecture();
756 ByteOrder target_byte_order = target_arch.GetByteOrder();
757 value.SetCompilerType(return_compiler_type);
758 uint32_t fp_flag =
759 target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;
760
761 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
762 if (!reg_ctx)
763 return return_valobj_sp;
764
765 bool is_signed = false;
766 bool is_complex = false;
767 uint32_t count = 0;
768
769 // In MIPS register "r2" (v0) holds the integer function return values
770 const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
771 std::optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);
772 if (!bit_width)
773 return return_valobj_sp;
774 if (return_compiler_type.IsIntegerOrEnumerationType(is_signed)) {
775 switch (*bit_width) {
776 default:
777 return return_valobj_sp;
778 case 64: {
779 const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
780 uint64_t raw_value;
781 raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
782 raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) &
783 UINT32_MAX))
784 << 32;
785 if (is_signed)
786 value.GetScalar() = (int64_t)raw_value;
787 else
788 value.GetScalar() = (uint64_t)raw_value;
789 } break;
790 case 32:
791 if (is_signed)
792 value.GetScalar() = (int32_t)(
793 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
794 else
795 value.GetScalar() = (uint32_t)(
796 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
797 break;
798 case 16:
799 if (is_signed)
800 value.GetScalar() = (int16_t)(
801 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
802 else
803 value.GetScalar() = (uint16_t)(
804 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
805 break;
806 case 8:
807 if (is_signed)
808 value.GetScalar() = (int8_t)(
809 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
810 else
811 value.GetScalar() = (uint8_t)(
812 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
813 break;
814 }
815 } else if (return_compiler_type.IsPointerType()) {
816 uint32_t ptr =
817 thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) &
818 UINT32_MAX;
819 value.GetScalar() = ptr;
820 } else if (return_compiler_type.IsAggregateType()) {
821 // Structure/Vector is always passed in memory and pointer to that memory
822 // is passed in r2.
823 uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
824 reg_ctx->GetRegisterInfoByName("r2", 0), 0);
825 // We have got the address. Create a memory object out of it
826 return_valobj_sp = ValueObjectMemory::Create(
827 &thread, "", Address(mem_address, nullptr), return_compiler_type);
828 return return_valobj_sp;
829 } else if (return_compiler_type.IsFloatingPointType(count, is_complex)) {
830 if (IsSoftFloat(fp_flag)) {
831 uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0);
832 if (count != 1 && is_complex)
833 return return_valobj_sp;
834 switch (*bit_width) {
835 default:
836 return return_valobj_sp;
837 case 32:
838 static_assert(sizeof(float) == sizeof(uint32_t));
839 value.GetScalar() = *((float *)(&raw_value));
840 break;
841 case 64:
842 static_assert(sizeof(double) == sizeof(uint64_t));
843 const RegisterInfo *r3_reg_info =
844 reg_ctx->GetRegisterInfoByName("r3", 0);
845 if (target_byte_order == eByteOrderLittle)
846 raw_value =
847 ((reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0)) << 32) |
848 raw_value;
849 else
850 raw_value = (raw_value << 32) |
851 reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0);
852 value.GetScalar() = *((double *)(&raw_value));
853 break;
854 }
855 }
856
857 else {
858 const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
859 RegisterValue f0_value;
860 DataExtractor f0_data;
861 reg_ctx->ReadRegister(f0_info, f0_value);
862 f0_value.GetData(f0_data);
863 lldb::offset_t offset = 0;
864
865 if (count == 1 && !is_complex) {
866 switch (*bit_width) {
867 default:
868 return return_valobj_sp;
869 case 64: {
870 static_assert(sizeof(double) == sizeof(uint64_t));
871 const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
872 RegisterValue f1_value;
873 DataExtractor f1_data;
874 reg_ctx->ReadRegister(f1_info, f1_value);
875 DataExtractor *copy_from_extractor = nullptr;
876 WritableDataBufferSP data_sp(new DataBufferHeap(8, 0));
877 DataExtractor return_ext(
878 data_sp, target_byte_order,
879 target->GetArchitecture().GetAddressByteSize());
880
881 if (target_byte_order == eByteOrderLittle) {
882 copy_from_extractor = &f0_data;
883 copy_from_extractor->CopyByteOrderedData(
884 offset, 4, data_sp->GetBytes(), 4, target_byte_order);
885 f1_value.GetData(f1_data);
886 copy_from_extractor = &f1_data;
887 copy_from_extractor->CopyByteOrderedData(
888 offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
889 } else {
890 copy_from_extractor = &f0_data;
891 copy_from_extractor->CopyByteOrderedData(
892 offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
893 f1_value.GetData(f1_data);
894 copy_from_extractor = &f1_data;
895 copy_from_extractor->CopyByteOrderedData(
896 offset, 4, data_sp->GetBytes(), 4, target_byte_order);
897 }
898 value.GetScalar() = (double)return_ext.GetDouble(&offset);
899 break;
900 }
901 case 32: {
902 static_assert(sizeof(float) == sizeof(uint32_t));
903 value.GetScalar() = (float)f0_data.GetFloat(&offset);
904 break;
905 }
906 }
907 } else {
908 // not handled yet
909 return return_valobj_sp;
910 }
911 }
912 } else {
913 // not handled yet
914 return return_valobj_sp;
915 }
916
917 // If we get here, we have a valid Value, so make our ValueObject out of it:
918
919 return_valobj_sp = ValueObjectConstResult::Create(
920 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
921 return return_valobj_sp;
922 }
923
CreateFunctionEntryUnwindPlan(UnwindPlan & unwind_plan)924 bool ABISysV_mips::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
925 unwind_plan.Clear();
926 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
927
928 UnwindPlan::RowSP row(new UnwindPlan::Row);
929
930 // Our Call Frame Address is the stack pointer value
931 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
932
933 // The previous PC is in the RA
934 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
935 unwind_plan.AppendRow(row);
936
937 // All other registers are the same.
938
939 unwind_plan.SetSourceName("mips at-func-entry default");
940 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
941 unwind_plan.SetReturnAddressRegister(dwarf_r31);
942 return true;
943 }
944
CreateDefaultUnwindPlan(UnwindPlan & unwind_plan)945 bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
946 unwind_plan.Clear();
947 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
948
949 UnwindPlan::RowSP row(new UnwindPlan::Row);
950
951 row->SetUnspecifiedRegistersAreUndefined(true);
952 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
953
954 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
955
956 unwind_plan.AppendRow(row);
957 unwind_plan.SetSourceName("mips default unwind plan");
958 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
959 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
960 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
961 return true;
962 }
963
RegisterIsVolatile(const RegisterInfo * reg_info)964 bool ABISysV_mips::RegisterIsVolatile(const RegisterInfo *reg_info) {
965 return !RegisterIsCalleeSaved(reg_info);
966 }
967
IsSoftFloat(uint32_t fp_flags) const968 bool ABISysV_mips::IsSoftFloat(uint32_t fp_flags) const {
969 return (fp_flags == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);
970 }
971
RegisterIsCalleeSaved(const RegisterInfo * reg_info)972 bool ABISysV_mips::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
973 if (reg_info) {
974 // Preserved registers are :
975 // r16-r23, r28, r29, r30, r31
976 const char *name = reg_info->name;
977
978 if (name[0] == 'r') {
979 switch (name[1]) {
980 case '1':
981 if (name[2] == '6' || name[2] == '7' || name[2] == '8' ||
982 name[2] == '9') // r16-r19
983 return name[3] == '\0';
984 break;
985 case '2':
986 if (name[2] == '0' || name[2] == '1' || name[2] == '2' ||
987 name[2] == '3' // r20-r23
988 || name[2] == '8' || name[2] == '9') // r28 and r29
989 return name[3] == '\0';
990 break;
991 case '3':
992 if (name[2] == '0' || name[2] == '1') // r30 and r31
993 return name[3] == '\0';
994 break;
995 }
996
997 if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28)
998 return true;
999 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29)
1000 return true;
1001 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30)
1002 return true;
1003 if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31)
1004 return true;
1005 }
1006 }
1007 return false;
1008 }
1009
Initialize()1010 void ABISysV_mips::Initialize() {
1011 PluginManager::RegisterPlugin(
1012 GetPluginNameStatic(), "System V ABI for mips targets", CreateInstance);
1013 }
1014
Terminate()1015 void ABISysV_mips::Terminate() {
1016 PluginManager::UnregisterPlugin(CreateInstance);
1017 }
1018