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