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