LLDB  mainline
ABISysV_mips.cpp
Go to the documentation of this file.
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"
16 #include "lldb/Core/Value.h"
20 #include "lldb/Symbol/UnwindPlan.h"
21 #include "lldb/Target/Process.h"
23 #include "lldb/Target/StackFrame.h"
24 #include "lldb/Target/Target.h"
25 #include "lldb/Target/Thread.h"
28 #include "lldb/Utility/Log.h"
30 #include "lldb/Utility/Status.h"
31 
32 using namespace lldb;
33 using namespace lldb_private;
34 
36  dwarf_r0 = 0,
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,
88  eFormatHex,
90  LLDB_INVALID_REGNUM},
91  nullptr,
92  nullptr,
93  nullptr,
94  0},
95  {"r1",
96  "AT",
97  4,
98  0,
100  eFormatHex,
102  LLDB_INVALID_REGNUM},
103  nullptr,
104  nullptr,
105  nullptr,
106  0},
107  {"r2",
108  "v0",
109  4,
110  0,
112  eFormatHex,
114  LLDB_INVALID_REGNUM},
115  nullptr,
116  nullptr,
117  nullptr,
118  0},
119  {"r3",
120  "v1",
121  4,
122  0,
124  eFormatHex,
126  LLDB_INVALID_REGNUM},
127  nullptr,
128  nullptr,
129  nullptr,
130  0},
131  {"r4",
132  "arg1",
133  4,
134  0,
136  eFormatHex,
138  LLDB_INVALID_REGNUM},
139  nullptr,
140  nullptr,
141  nullptr,
142  0},
143  {"r5",
144  "arg2",
145  4,
146  0,
148  eFormatHex,
150  LLDB_INVALID_REGNUM},
151  nullptr,
152  nullptr,
153  nullptr,
154  0},
155  {"r6",
156  "arg3",
157  4,
158  0,
160  eFormatHex,
162  LLDB_INVALID_REGNUM},
163  nullptr,
164  nullptr,
165  nullptr,
166  0},
167  {"r7",
168  "arg4",
169  4,
170  0,
172  eFormatHex,
174  LLDB_INVALID_REGNUM},
175  nullptr,
176  nullptr,
177  nullptr,
178  0},
179  {"r8",
180  "arg5",
181  4,
182  0,
184  eFormatHex,
186  LLDB_INVALID_REGNUM},
187  nullptr,
188  nullptr,
189  nullptr,
190  0},
191  {"r9",
192  "arg6",
193  4,
194  0,
196  eFormatHex,
198  LLDB_INVALID_REGNUM},
199  nullptr,
200  nullptr,
201  nullptr,
202  0},
203  {"r10",
204  "arg7",
205  4,
206  0,
208  eFormatHex,
210  LLDB_INVALID_REGNUM},
211  nullptr,
212  nullptr,
213  nullptr,
214  0},
215  {"r11",
216  "arg8",
217  4,
218  0,
220  eFormatHex,
222  LLDB_INVALID_REGNUM},
223  nullptr,
224  nullptr,
225  nullptr,
226  0},
227  {"r12",
228  nullptr,
229  4,
230  0,
232  eFormatHex,
234  LLDB_INVALID_REGNUM},
235  nullptr,
236  nullptr,
237  nullptr,
238  0},
239  {"r13",
240  nullptr,
241  4,
242  0,
244  eFormatHex,
246  LLDB_INVALID_REGNUM},
247  nullptr,
248  nullptr,
249  nullptr,
250  0},
251  {"r14",
252  nullptr,
253  4,
254  0,
256  eFormatHex,
258  LLDB_INVALID_REGNUM},
259  nullptr,
260  nullptr,
261  nullptr,
262  0},
263  {"r15",
264  nullptr,
265  4,
266  0,
268  eFormatHex,
270  LLDB_INVALID_REGNUM},
271  nullptr,
272  nullptr,
273  nullptr,
274  0},
275  {"r16",
276  nullptr,
277  4,
278  0,
280  eFormatHex,
282  LLDB_INVALID_REGNUM},
283  nullptr,
284  nullptr,
285  nullptr,
286  0},
287  {"r17",
288  nullptr,
289  4,
290  0,
292  eFormatHex,
294  LLDB_INVALID_REGNUM},
295  nullptr,
296  nullptr,
297  nullptr,
298  0},
299  {"r18",
300  nullptr,
301  4,
302  0,
304  eFormatHex,
306  LLDB_INVALID_REGNUM},
307  nullptr,
308  nullptr,
309  nullptr,
310  0},
311  {"r19",
312  nullptr,
313  4,
314  0,
316  eFormatHex,
318  LLDB_INVALID_REGNUM},
319  nullptr,
320  nullptr,
321  nullptr,
322  0},
323  {"r20",
324  nullptr,
325  4,
326  0,
328  eFormatHex,
330  LLDB_INVALID_REGNUM},
331  nullptr,
332  nullptr,
333  nullptr,
334  0},
335  {"r21",
336  nullptr,
337  4,
338  0,
340  eFormatHex,
342  LLDB_INVALID_REGNUM},
343  nullptr,
344  nullptr,
345  nullptr,
346  0},
347  {"r22",
348  nullptr,
349  4,
350  0,
352  eFormatHex,
354  LLDB_INVALID_REGNUM},
355  nullptr,
356  nullptr,
357  nullptr,
358  0},
359  {"r23",
360  nullptr,
361  4,
362  0,
364  eFormatHex,
366  LLDB_INVALID_REGNUM},
367  nullptr,
368  nullptr,
369  nullptr,
370  0},
371  {"r24",
372  nullptr,
373  4,
374  0,
376  eFormatHex,
378  LLDB_INVALID_REGNUM},
379  nullptr,
380  nullptr,
381  nullptr,
382  0},
383  {"r25",
384  nullptr,
385  4,
386  0,
388  eFormatHex,
390  LLDB_INVALID_REGNUM},
391  nullptr,
392  nullptr,
393  nullptr,
394  0},
395  {"r26",
396  nullptr,
397  4,
398  0,
400  eFormatHex,
402  LLDB_INVALID_REGNUM},
403  nullptr,
404  nullptr,
405  nullptr,
406  0},
407  {"r27",
408  nullptr,
409  4,
410  0,
412  eFormatHex,
414  LLDB_INVALID_REGNUM},
415  nullptr,
416  nullptr,
417  nullptr,
418  0},
419  {"r28",
420  "gp",
421  4,
422  0,
424  eFormatHex,
426  LLDB_INVALID_REGNUM},
427  nullptr,
428  nullptr,
429  nullptr,
430  0},
431  {"r29",
432  "sp",
433  4,
434  0,
436  eFormatHex,
438  LLDB_INVALID_REGNUM},
439  nullptr,
440  nullptr,
441  nullptr,
442  0},
443  {"r30",
444  "fp",
445  4,
446  0,
448  eFormatHex,
450  LLDB_INVALID_REGNUM},
451  nullptr,
452  nullptr,
453  nullptr,
454  0},
455  {"r31",
456  "ra",
457  4,
458  0,
460  eFormatHex,
462  LLDB_INVALID_REGNUM},
463  nullptr,
464  nullptr,
465  nullptr,
466  0},
467  {"sr",
468  nullptr,
469  4,
470  0,
472  eFormatHex,
474  LLDB_INVALID_REGNUM},
475  nullptr,
476  nullptr,
477  nullptr,
478  0},
479  {"lo",
480  nullptr,
481  4,
482  0,
484  eFormatHex,
486  LLDB_INVALID_REGNUM},
487  nullptr,
488  nullptr,
489  nullptr,
490  0},
491  {"hi",
492  nullptr,
493  4,
494  0,
496  eFormatHex,
498  LLDB_INVALID_REGNUM},
499  nullptr,
500  nullptr,
501  nullptr,
502  0},
503  {"bad",
504  nullptr,
505  4,
506  0,
508  eFormatHex,
510  LLDB_INVALID_REGNUM},
511  nullptr,
512  nullptr,
513  nullptr,
514  0},
515  {"cause",
516  nullptr,
517  4,
518  0,
520  eFormatHex,
522  LLDB_INVALID_REGNUM},
523  nullptr,
524  nullptr,
525  nullptr,
526  0},
527  {"pc",
528  nullptr,
529  4,
530  0,
532  eFormatHex,
534  LLDB_INVALID_REGNUM},
535  nullptr,
536  nullptr,
537  nullptr,
538  0},
539 };
540 
542  llvm::array_lengthof(g_register_infos);
543 
544 const lldb_private::RegisterInfo *
546  count = k_num_register_infos;
547  return g_register_infos;
548 }
549 
550 size_t ABISysV_mips::GetRedZoneSize() const { return 0; }
551 
552 // Static Functions
553 
554 ABISP
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(new ABISysV_mips(process_sp));
560  }
561  return ABISP();
562 }
563 
565  addr_t func_addr, addr_t return_addr,
566  llvm::ArrayRef<addr_t> args) const {
568 
569  if (log) {
570  StreamString s;
571  s.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64
572  ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
573  ", return_addr = 0x%" PRIx64,
574  thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
575  (uint64_t)return_addr);
576 
577  for (size_t i = 0; i < args.size(); ++i)
578  s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);
579  s.PutCString(")");
580  log->PutString(s.GetString());
581  }
582 
583  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
584  if (!reg_ctx)
585  return false;
586 
587  const RegisterInfo *reg_info = nullptr;
588 
589  RegisterValue reg_value;
590 
591  // Argument registers
592  const char *reg_names[] = {"r4", "r5", "r6", "r7"};
593 
594  llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
595 
596  // Write arguments to registers
597  for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i) {
598  if (ai == ae)
599  break;
600 
601  reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
603  if (log)
604  log->Printf("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(
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  if (log)
634  log->Printf("About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "",
635  i + 1, args[i], arg_pos);
636 
637  if (reg_ctx
638  ->WriteRegisterValueToMemory(reg_info, arg_pos,
639  reg_info->byte_size, reg_value)
640  .Fail())
641  return false;
642  arg_pos += reg_info->byte_size;
643  i++;
644  }
645  }
646 
647  Status error;
648  const RegisterInfo *pc_reg_info =
650  const RegisterInfo *sp_reg_info =
652  const RegisterInfo *ra_reg_info =
654  const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
655  const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);
656 
657  if (log)
658  log->Printf("Writing R0: 0x%" PRIx64, (uint64_t)0);
659 
660  /* Write r0 with 0, in case we are stopped in syscall,
661  * such setting prevents automatic decrement of the PC.
662  * This clears the bug 23659 for MIPS.
663  */
664  if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))
665  return false;
666 
667  if (log)
668  log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
669 
670  // Set "sp" to the requested value
671  if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))
672  return false;
673 
674  if (log)
675  log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
676 
677  // Set "ra" to the return address
678  if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))
679  return false;
680 
681  if (log)
682  log->Printf("Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
683 
684  // Set pc to the address of the called function.
685  if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))
686  return false;
687 
688  if (log)
689  log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
690 
691  // All callers of position independent functions must place the address of
692  // the called function in t9 (r25)
693  if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))
694  return false;
695 
696  return true;
697 }
698 
699 bool ABISysV_mips::GetArgumentValues(Thread &thread, ValueList &values) const {
700  return false;
701 }
702 
703 Status ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
704  lldb::ValueObjectSP &new_value_sp) {
705  Status error;
706  if (!new_value_sp) {
707  error.SetErrorString("Empty value object for return value.");
708  return error;
709  }
710 
711  CompilerType compiler_type = new_value_sp->GetCompilerType();
712  if (!compiler_type) {
713  error.SetErrorString("Null clang type for return value.");
714  return error;
715  }
716 
717  Thread *thread = frame_sp->GetThread().get();
718 
719  bool is_signed;
720  uint32_t count;
721  bool is_complex;
722 
723  RegisterContext *reg_ctx = thread->GetRegisterContext().get();
724 
725  bool set_it_simple = false;
726  if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
727  compiler_type.IsPointerType()) {
728  DataExtractor data;
729  Status data_error;
730  size_t num_bytes = new_value_sp->GetData(data, data_error);
731  if (data_error.Fail()) {
733  "Couldn't convert return value to raw data: %s",
734  data_error.AsCString());
735  return error;
736  }
737 
738  lldb::offset_t offset = 0;
739  if (num_bytes <= 8) {
740  const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
741  if (num_bytes <= 4) {
742  uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
743 
744  if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))
745  set_it_simple = true;
746  } else {
747  uint32_t raw_value = data.GetMaxU32(&offset, 4);
748 
749  if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {
750  const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
751  uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
752 
753  if (reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))
754  set_it_simple = true;
755  }
756  }
757  } else {
758  error.SetErrorString("We don't support returning longer than 64 bit "
759  "integer values at present.");
760  }
761  } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
762  if (is_complex)
763  error.SetErrorString(
764  "We don't support returning complex values at present");
765  else
766  error.SetErrorString(
767  "We don't support returning float values at present");
768  }
769 
770  if (!set_it_simple)
771  error.SetErrorString(
772  "We only support setting simple integer return types at present.");
773 
774  return error;
775 }
776 
778  Thread &thread, CompilerType &return_compiler_type) const {
779  ValueObjectSP return_valobj_sp;
780  return return_valobj_sp;
781 }
782 
784  Thread &thread, CompilerType &return_compiler_type) const {
785  ValueObjectSP return_valobj_sp;
786  Value value;
787 
788  if (!return_compiler_type)
789  return return_valobj_sp;
790 
791  ExecutionContext exe_ctx(thread.shared_from_this());
792  if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
793  return return_valobj_sp;
794 
795  Target *target = exe_ctx.GetTargetPtr();
796  const ArchSpec target_arch = target->GetArchitecture();
797  ByteOrder target_byte_order = target_arch.GetByteOrder();
798  value.SetCompilerType(return_compiler_type);
799  uint32_t fp_flag =
801 
802  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
803  if (!reg_ctx)
804  return return_valobj_sp;
805 
806  bool is_signed = false;
807  bool is_complex = false;
808  uint32_t count = 0;
809 
810  // In MIPS register "r2" (v0) holds the integer function return values
811  const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
812  llvm::Optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);
813  if (!bit_width)
814  return return_valobj_sp;
815  if (return_compiler_type.IsIntegerOrEnumerationType(is_signed)) {
816  switch (*bit_width) {
817  default:
818  return return_valobj_sp;
819  case 64: {
820  const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
821  uint64_t raw_value;
822  raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
823  raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) &
824  UINT32_MAX))
825  << 32;
826  if (is_signed)
827  value.GetScalar() = (int64_t)raw_value;
828  else
829  value.GetScalar() = (uint64_t)raw_value;
830  } break;
831  case 32:
832  if (is_signed)
833  value.GetScalar() = (int32_t)(
834  reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
835  else
836  value.GetScalar() = (uint32_t)(
837  reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
838  break;
839  case 16:
840  if (is_signed)
841  value.GetScalar() = (int16_t)(
842  reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
843  else
844  value.GetScalar() = (uint16_t)(
845  reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
846  break;
847  case 8:
848  if (is_signed)
849  value.GetScalar() = (int8_t)(
850  reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
851  else
852  value.GetScalar() = (uint8_t)(
853  reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
854  break;
855  }
856  } else if (return_compiler_type.IsPointerType()) {
857  uint32_t ptr =
858  thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) &
859  UINT32_MAX;
860  value.GetScalar() = ptr;
861  } else if (return_compiler_type.IsAggregateType()) {
862  // Structure/Vector is always passed in memory and pointer to that memory
863  // is passed in r2.
864  uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
865  reg_ctx->GetRegisterInfoByName("r2", 0), 0);
866  // We have got the address. Create a memory object out of it
867  return_valobj_sp = ValueObjectMemory::Create(
868  &thread, "", Address(mem_address, nullptr), return_compiler_type);
869  return return_valobj_sp;
870  } else if (return_compiler_type.IsFloatingPointType(count, is_complex)) {
871  if (IsSoftFloat(fp_flag)) {
872  uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0);
873  if (count != 1 && is_complex)
874  return return_valobj_sp;
875  switch (*bit_width) {
876  default:
877  return return_valobj_sp;
878  case 32:
879  static_assert(sizeof(float) == sizeof(uint32_t), "");
880  value.GetScalar() = *((float *)(&raw_value));
881  break;
882  case 64:
883  static_assert(sizeof(double) == sizeof(uint64_t), "");
884  const RegisterInfo *r3_reg_info =
885  reg_ctx->GetRegisterInfoByName("r3", 0);
886  if (target_byte_order == eByteOrderLittle)
887  raw_value =
888  ((reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0)) << 32) |
889  raw_value;
890  else
891  raw_value = (raw_value << 32) |
892  reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0);
893  value.GetScalar() = *((double *)(&raw_value));
894  break;
895  }
896  }
897 
898  else {
899  const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
900  RegisterValue f0_value;
901  DataExtractor f0_data;
902  reg_ctx->ReadRegister(f0_info, f0_value);
903  f0_value.GetData(f0_data);
904  lldb::offset_t offset = 0;
905 
906  if (count == 1 && !is_complex) {
907  switch (*bit_width) {
908  default:
909  return return_valobj_sp;
910  case 64: {
911  static_assert(sizeof(double) == sizeof(uint64_t), "");
912  const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
913  RegisterValue f1_value;
914  DataExtractor f1_data;
915  reg_ctx->ReadRegister(f1_info, f1_value);
916  DataExtractor *copy_from_extractor = nullptr;
917  DataBufferSP data_sp(new DataBufferHeap(8, 0));
918  DataExtractor return_ext(
919  data_sp, target_byte_order,
920  target->GetArchitecture().GetAddressByteSize());
921 
922  if (target_byte_order == eByteOrderLittle) {
923  copy_from_extractor = &f0_data;
924  copy_from_extractor->CopyByteOrderedData(
925  offset, 4, data_sp->GetBytes(), 4, target_byte_order);
926  f1_value.GetData(f1_data);
927  copy_from_extractor = &f1_data;
928  copy_from_extractor->CopyByteOrderedData(
929  offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
930  } else {
931  copy_from_extractor = &f0_data;
932  copy_from_extractor->CopyByteOrderedData(
933  offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
934  f1_value.GetData(f1_data);
935  copy_from_extractor = &f1_data;
936  copy_from_extractor->CopyByteOrderedData(
937  offset, 4, data_sp->GetBytes(), 4, target_byte_order);
938  }
939  value.GetScalar() = (double)return_ext.GetDouble(&offset);
940  break;
941  }
942  case 32: {
943  static_assert(sizeof(float) == sizeof(uint32_t), "");
944  value.GetScalar() = (float)f0_data.GetFloat(&offset);
945  break;
946  }
947  }
948  } else {
949  // not handled yet
950  return return_valobj_sp;
951  }
952  }
953  } else {
954  // not handled yet
955  return return_valobj_sp;
956  }
957 
958  // If we get here, we have a valid Value, so make our ValueObject out of it:
959 
960  return_valobj_sp = ValueObjectConstResult::Create(
961  thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
962  return return_valobj_sp;
963 }
964 
966  unwind_plan.Clear();
967  unwind_plan.SetRegisterKind(eRegisterKindDWARF);
968 
970 
971  // Our Call Frame Address is the stack pointer value
972  row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
973 
974  // The previous PC is in the RA
975  row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
976  unwind_plan.AppendRow(row);
977 
978  // All other registers are the same.
979 
980  unwind_plan.SetSourceName("mips at-func-entry default");
981  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
982  unwind_plan.SetReturnAddressRegister(dwarf_r31);
983  return true;
984 }
985 
987  unwind_plan.Clear();
988  unwind_plan.SetRegisterKind(eRegisterKindDWARF);
989 
991 
992  row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
993 
994  row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
995 
996  unwind_plan.AppendRow(row);
997  unwind_plan.SetSourceName("mips default unwind plan");
998  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1000  return true;
1001 }
1002 
1003 bool ABISysV_mips::RegisterIsVolatile(const RegisterInfo *reg_info) {
1004  return !RegisterIsCalleeSaved(reg_info);
1005 }
1006 
1007 bool ABISysV_mips::IsSoftFloat(uint32_t fp_flags) const {
1008  return (fp_flags == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);
1009 }
1010 
1011 bool ABISysV_mips::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
1012  if (reg_info) {
1013  // Preserved registers are :
1014  // r16-r23, r28, r29, r30, r31
1015  const char *name = reg_info->name;
1016 
1017  if (name[0] == 'r') {
1018  switch (name[1]) {
1019  case '1':
1020  if (name[2] == '6' || name[2] == '7' || name[2] == '8' ||
1021  name[2] == '9') // r16-r19
1022  return name[3] == '\0';
1023  break;
1024  case '2':
1025  if (name[2] == '0' || name[2] == '1' || name[2] == '2' ||
1026  name[2] == '3' // r20-r23
1027  || name[2] == '8' || name[2] == '9') // r28 and r29
1028  return name[3] == '\0';
1029  break;
1030  case '3':
1031  if (name[2] == '0' || name[2] == '1') // r30 and r31
1032  return name[3] == '\0';
1033  break;
1034  }
1035 
1036  if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28)
1037  return true;
1038  if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29)
1039  return true;
1040  if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30)
1041  return true;
1042  if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31)
1043  return true;
1044  }
1045  }
1046  return false;
1047 }
1048 
1050  PluginManager::RegisterPlugin(
1051  GetPluginNameStatic(), "System V ABI for mips targets", CreateInstance);
1052 }
1053 
1055  PluginManager::UnregisterPlugin(CreateInstance);
1056 }
1057 
1059  static ConstString g_name("sysv-mips");
1060  return g_name;
1061 }
1062 
1063 // PluginInterface protocol
1064 
1066  return GetPluginNameStatic();
1067 }
1068 
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:61
uint32_t GetFlags() const
Definition: ArchSpec.h:501
#define LLDB_REGNUM_GENERIC_PC
Definition: lldb-defines.h:63
An data extractor class.
Definition: DataExtractor.h:47
void SetSourceName(const char *)
Definition: UnwindPlan.cpp:542
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
const ArchSpec & GetArchitecture() const
Definition: Target.h:941
bool CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override
bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info)
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
Definition: ArchSpec.cpp:742
#define LLDB_REGNUM_GENERIC_RA
Definition: lldb-defines.h:66
uint64_t ReadRegisterAsUnsigned(uint32_t reg, uint64_t fail_value)
uint32_t GetPluginVersion() override
#define LLDB_REGNUM_GENERIC_ARG4
Definition: lldb-defines.h:74
bool IsIntegerOrEnumerationType(bool &is_signed) const
static lldb_private::ConstString GetPluginNameStatic()
void PutString(llvm::StringRef str)
Definition: Log.cpp:110
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition: UserID.h:49
An architecture specification class.
Definition: ArchSpec.h:32
lldb_private::ConstString GetPluginName() override
#define LLDB_REGNUM_GENERIC_ARG2
Definition: lldb-defines.h:70
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
#define LLDB_REGNUM_GENERIC_SP
Definition: lldb-defines.h:64
bool CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override
static void Initialize()
lldb::ValueObjectSP GetReturnValueObjectSimple(lldb_private::Thread &thread, lldb_private::CompilerType &ast_type) const
float GetFloat(lldb::offset_t *offset_ptr) const
Extract a float from *offset_ptr.
static lldb::ABISP CreateInstance(lldb::ProcessSP process_sp, const lldb_private::ArchSpec &arch)
A subclass of DataBuffer that stores a data buffer on the heap.
#define LLDB_REGNUM_GENERIC_ARG1
Definition: lldb-defines.h:68
bool IsPointerType(CompilerType *pointee_type=nullptr) const
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:431
lldb_private::Status SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override
bool PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, lldb::addr_t functionAddress, lldb::addr_t returnAddress, llvm::ArrayRef< lldb::addr_t > args) const override
#define LLDB_REGNUM_GENERIC_FP
Definition: lldb-defines.h:65
#define UINT32_MAX
Definition: lldb-defines.h:31
bool IsFloatingPointType(uint32_t &count, bool &is_complex) const
bool GetArgumentValues(lldb_private::Thread &thread, lldb_private::ValueList &values) const override
uint64_t offset_t
Definition: lldb-types.h:87
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:57
std::shared_ptr< Row > RowSP
Definition: UnwindPlan.h:366
void AppendRow(const RowSP &row_sp)
Definition: UnwindPlan.cpp:355
llvm::StringRef GetString() const
virtual lldb::RegisterContextSP GetRegisterContext()=0
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:241
virtual bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)=0
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
Definition: ArchSpec.cpp:788
#define LLDB_REGNUM_GENERIC_FLAGS
Definition: lldb-defines.h:67
const RegisterInfo * GetRegisterInfoByName(llvm::StringRef reg_name, uint32_t start_idx=0)
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
void SetRegisterKind(lldb::RegisterKind kind)
Definition: UnwindPlan.h:408
A section + offset based address class.
Definition: Address.h:80
static const RegisterInfo g_register_infos[]
void SetUInt32(uint32_t uint, Type t=eTypeUInt32)
bool WriteRegisterFromUnsigned(uint32_t reg, uint64_t uval)
dwarf_regnums
lldb::ValueObjectSP GetReturnValueObjectImpl(lldb_private::Thread &thread, lldb_private::CompilerType &type) const override
const RegisterInfo * GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num)
void SetUnwindPlanValidAtAllInstructions(lldb_private::LazyBool valid_at_all_insn)
Definition: UnwindPlan.h:461
lldb::offset_t CopyByteOrderedData(lldb::offset_t src_offset, lldb::offset_t src_len, void *dst, lldb::offset_t dst_len, lldb::ByteOrder dst_byte_order) const
Copy dst_len bytes from *offset_ptr and ensure the copied data is treated as a value that can be swap...
uint64_t addr_t
Definition: lldb-types.h:83
bool GetData(DataExtractor &data) const
static void Terminate()
A uniqued constant string class.
Definition: ConstString.h:38
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
llvm::Optional< uint64_t > GetBitSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bits.
uint32_t GetMaxU32(lldb::offset_t *offset_ptr, size_t byte_size) const
Extract an integer of size byte_size from *offset_ptr.
#define LLDB_REGNUM_GENERIC_ARG3
Definition: lldb-defines.h:72
Definition: SBAddress.h:15
size_t GetRedZoneSize() const override
bool IsSoftFloat(uint32_t fp_flag) const
bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
Definition: Status.cpp:255
void SetCompilerType(const CompilerType &compiler_type)
Definition: Value.cpp:268
#define LIBLLDB_LOG_EXPRESSIONS
Definition: Logging.h:22
const Scalar & GetScalar() const
Definition: Value.h:178
static const uint32_t k_num_register_infos
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:130
virtual lldb::StackFrameSP GetStackFrameAtIndex(uint32_t idx)
Definition: Thread.h:395
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler)
Definition: UnwindPlan.h:449
const lldb_private::RegisterInfo * GetRegisterInfoArray(uint32_t &count) override
void SetReturnAddressRegister(uint32_t regnum)
Definition: UnwindPlan.h:410
An error handling class.
Definition: Status.h:44
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:90