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