ABISysV_mips.cpp revision 360784
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
32using namespace lldb;
33using namespace lldb_private;
34
35enum 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
76static 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
541static const uint32_t k_num_register_infos =
542    llvm::array_lengthof(g_register_infos);
543
544const lldb_private::RegisterInfo *
545ABISysV_mips::GetRegisterInfoArray(uint32_t &count) {
546  count = k_num_register_infos;
547  return g_register_infos;
548}
549
550size_t ABISysV_mips::GetRedZoneSize() const { return 0; }
551
552// Static Functions
553
554ABISP
555ABISysV_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
565bool 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
693bool ABISysV_mips::GetArgumentValues(Thread &thread, ValueList &values) const {
694  return false;
695}
696
697Status 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
771ValueObjectSP ABISysV_mips::GetReturnValueObjectSimple(
772    Thread &thread, CompilerType &return_compiler_type) const {
773  ValueObjectSP return_valobj_sp;
774  return return_valobj_sp;
775}
776
777ValueObjectSP 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
959bool 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
980bool 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
998bool ABISysV_mips::RegisterIsVolatile(const RegisterInfo *reg_info) {
999  return !RegisterIsCalleeSaved(reg_info);
1000}
1001
1002bool ABISysV_mips::IsSoftFloat(uint32_t fp_flags) const {
1003  return (fp_flags == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);
1004}
1005
1006bool 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
1044void ABISysV_mips::Initialize() {
1045  PluginManager::RegisterPlugin(
1046      GetPluginNameStatic(), "System V ABI for mips targets", CreateInstance);
1047}
1048
1049void ABISysV_mips::Terminate() {
1050  PluginManager::UnregisterPlugin(CreateInstance);
1051}
1052
1053lldb_private::ConstString ABISysV_mips::GetPluginNameStatic() {
1054  static ConstString g_name("sysv-mips");
1055  return g_name;
1056}
1057
1058// PluginInterface protocol
1059
1060lldb_private::ConstString ABISysV_mips::GetPluginName() {
1061  return GetPluginNameStatic();
1062}
1063
1064uint32_t ABISysV_mips::GetPluginVersion() { return 1; }
1065