LLDB mainline
ABISysV_mips64.cpp
Go to the documentation of this file.
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"
16#include "lldb/Core/Value.h"
21#include "lldb/Target/Process.h"
24#include "lldb/Target/Target.h"
25#include "lldb/Target/Thread.h"
29#include "lldb/Utility/Log.h"
31#include "lldb/Utility/Status.h"
32#include <optional>
33
34using namespace lldb;
35using namespace lldb_private;
36
38
78};
79
80static 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,
95 nullptr,
96 nullptr,
97 },
98 {"r1",
99 "AT",
100 8,
101 0,
106 nullptr,
107 nullptr,
108 },
109 {"r2",
110 "v0",
111 8,
112 0,
117 nullptr,
118 nullptr,
119 },
120 {"r3",
121 "v1",
122 8,
123 0,
128 nullptr,
129 nullptr,
130 },
131 {"r4",
132 nullptr,
133 8,
134 0,
139 nullptr,
140 nullptr,
141 },
142 {"r5",
143 nullptr,
144 8,
145 0,
150 nullptr,
151 nullptr,
152 },
153 {"r6",
154 nullptr,
155 8,
156 0,
161 nullptr,
162 nullptr,
163 },
164 {"r7",
165 nullptr,
166 8,
167 0,
172 nullptr,
173 nullptr,
174 },
175 {"r8",
176 nullptr,
177 8,
178 0,
183 nullptr,
184 nullptr,
185 },
186 {"r9",
187 nullptr,
188 8,
189 0,
194 nullptr,
195 nullptr,
196 },
197 {"r10",
198 nullptr,
199 8,
200 0,
205 nullptr,
206 nullptr,
207 },
208 {"r11",
209 nullptr,
210 8,
211 0,
216 nullptr,
217 nullptr,
218 },
219 {"r12",
220 nullptr,
221 8,
222 0,
227 nullptr,
228 nullptr,
229 },
230 {"r13",
231 nullptr,
232 8,
233 0,
238 nullptr,
239 nullptr,
240 },
241 {"r14",
242 nullptr,
243 8,
244 0,
249 nullptr,
250 nullptr,
251 },
252 {"r15",
253 nullptr,
254 8,
255 0,
260 nullptr,
261 nullptr,
262 },
263 {"r16",
264 nullptr,
265 8,
266 0,
271 nullptr,
272 nullptr,
273 },
274 {"r17",
275 nullptr,
276 8,
277 0,
282 nullptr,
283 nullptr,
284 },
285 {"r18",
286 nullptr,
287 8,
288 0,
293 nullptr,
294 nullptr,
295 },
296 {"r19",
297 nullptr,
298 8,
299 0,
304 nullptr,
305 nullptr,
306 },
307 {"r20",
308 nullptr,
309 8,
310 0,
315 nullptr,
316 nullptr,
317 },
318 {"r21",
319 nullptr,
320 8,
321 0,
326 nullptr,
327 nullptr,
328 },
329 {"r22",
330 nullptr,
331 8,
332 0,
337 nullptr,
338 nullptr,
339 },
340 {"r23",
341 nullptr,
342 8,
343 0,
348 nullptr,
349 nullptr,
350 },
351 {"r24",
352 nullptr,
353 8,
354 0,
359 nullptr,
360 nullptr,
361 },
362 {"r25",
363 nullptr,
364 8,
365 0,
370 nullptr,
371 nullptr,
372 },
373 {"r26",
374 nullptr,
375 8,
376 0,
381 nullptr,
382 nullptr,
383 },
384 {"r27",
385 nullptr,
386 8,
387 0,
392 nullptr,
393 nullptr,
394 },
395 {"r28",
396 "gp",
397 8,
398 0,
403 nullptr,
404 nullptr,
405 },
406 {"r29",
407 nullptr,
408 8,
409 0,
414 nullptr,
415 nullptr,
416 },
417 {"r30",
418 nullptr,
419 8,
420 0,
425 nullptr,
426 nullptr,
427 },
428 {"r31",
429 nullptr,
430 8,
431 0,
436 nullptr,
437 nullptr,
438 },
439 {"sr",
440 nullptr,
441 4,
442 0,
447 nullptr,
448 nullptr,
449 },
450 {"lo",
451 nullptr,
452 8,
453 0,
458 nullptr,
459 nullptr,
460 },
461 {"hi",
462 nullptr,
463 8,
464 0,
469 nullptr,
470 nullptr,
471 },
472 {"bad",
473 nullptr,
474 8,
475 0,
480 nullptr,
481 nullptr,
482 },
483 {"cause",
484 nullptr,
485 8,
486 0,
491 nullptr,
492 nullptr,
493 },
494 {"pc",
495 nullptr,
496 8,
497 0,
502 nullptr,
503 nullptr,
504 },
505};
506
508
509const lldb_private::RegisterInfo *
511 count = k_num_register_infos;
513}
514
515size_t ABISysV_mips64::GetRedZoneSize() const { return 0; }
516
517// Static Functions
518
519ABISP
520ABISysV_mips64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
521 if (arch.GetTriple().isMIPS64())
522 return ABISP(
523 new ABISysV_mips64(std::move(process_sp), MakeMCRegisterInfo(arch)));
524 return ABISP();
525}
526
528 addr_t func_addr, addr_t return_addr,
529 llvm::ArrayRef<addr_t> args) const {
530 Log *log = GetLog(LLDBLog::Expressions);
531
532 if (log) {
533 StreamString s;
534 s.Printf("ABISysV_mips64::PrepareTrivialCall (tid = 0x%" PRIx64
535 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
536 ", return_addr = 0x%" PRIx64,
537 thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
538 (uint64_t)return_addr);
539
540 for (size_t i = 0; i < args.size(); ++i)
541 s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);
542 s.PutCString(")");
543 log->PutString(s.GetString());
544 }
545
546 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
547 if (!reg_ctx)
548 return false;
549
550 const RegisterInfo *reg_info = nullptr;
551
552 if (args.size() > 8) // TODO handle more than 8 arguments
553 return false;
554
555 for (size_t i = 0; i < args.size(); ++i) {
556 reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
558 LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1,
559 args[i], reg_info->name);
560 if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
561 return false;
562 }
563
564 // First, align the SP
565
566 LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64,
567 (uint64_t)sp, (uint64_t)(sp & ~0xfull));
568
569 sp &= ~(0xfull); // 16-byte alignment
570
572 const RegisterInfo *pc_reg_info =
574 const RegisterInfo *sp_reg_info =
576 const RegisterInfo *ra_reg_info =
578 const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
579 const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);
580
581 LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0);
582
583 /* Write r0 with 0, in case we are stopped in syscall,
584 * such setting prevents automatic decrement of the PC.
585 * This clears the bug 23659 for MIPS.
586 */
587 if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))
588 return false;
589
590 LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);
591
592 // Set "sp" to the requested value
593 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))
594 return false;
595
596 LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
597
598 // Set "ra" to the return address
599 if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))
600 return false;
601
602 LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
603
604 // Set pc to the address of the called function.
605 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))
606 return false;
607
608 LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
609
610 // All callers of position independent functions must place the address of
611 // the called function in t9 (r25)
612 if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))
613 return false;
614
615 return true;
616}
617
619 ValueList &values) const {
620 return false;
621}
622
623Status ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
624 lldb::ValueObjectSP &new_value_sp) {
626 if (!new_value_sp) {
627 error.SetErrorString("Empty value object for return value.");
628 return error;
629 }
630
631 CompilerType compiler_type = new_value_sp->GetCompilerType();
632 if (!compiler_type) {
633 error.SetErrorString("Null clang type for return value.");
634 return error;
635 }
636
637 Thread *thread = frame_sp->GetThread().get();
638
639 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
640
641 if (!reg_ctx)
642 error.SetErrorString("no registers are available");
643
644 DataExtractor data;
645 Status data_error;
646 size_t num_bytes = new_value_sp->GetData(data, data_error);
647 if (data_error.Fail()) {
648 error.SetErrorStringWithFormat(
649 "Couldn't convert return value to raw data: %s",
650 data_error.AsCString());
651 return error;
652 }
653
654 const uint32_t type_flags = compiler_type.GetTypeInfo(nullptr);
655
656 if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
657 if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
658 lldb::offset_t offset = 0;
659
660 if (num_bytes <= 16) {
661 const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
662 if (num_bytes <= 8) {
663 uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
664
665 if (!reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))
666 error.SetErrorString("failed to write register r2");
667 } else {
668 uint64_t raw_value = data.GetMaxU64(&offset, 8);
669 if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {
670 const RegisterInfo *r3_info =
671 reg_ctx->GetRegisterInfoByName("r3", 0);
672 raw_value = data.GetMaxU64(&offset, num_bytes - offset);
673
674 if (!reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))
675 error.SetErrorString("failed to write register r3");
676 } else
677 error.SetErrorString("failed to write register r2");
678 }
679 } else {
680 error.SetErrorString("We don't support returning longer than 128 bit "
681 "integer values at present.");
682 }
683 } else if (type_flags & eTypeIsFloat) {
684 error.SetErrorString("TODO: Handle Float Types.");
685 }
686 } else if (type_flags & eTypeIsVector) {
687 error.SetErrorString("returning vector values are not supported");
688 }
689
690 return error;
691}
692
694 Thread &thread, CompilerType &return_compiler_type) const {
695 ValueObjectSP return_valobj_sp;
696 return return_valobj_sp;
697}
698
700 Thread &thread, CompilerType &return_compiler_type) const {
701 ValueObjectSP return_valobj_sp;
702 Value value;
704
705 ExecutionContext exe_ctx(thread.shared_from_this());
706 if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
707 return return_valobj_sp;
708
709 value.SetCompilerType(return_compiler_type);
710
711 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
712 if (!reg_ctx)
713 return return_valobj_sp;
714
715 Target *target = exe_ctx.GetTargetPtr();
716 const ArchSpec target_arch = target->GetArchitecture();
717 ByteOrder target_byte_order = target_arch.GetByteOrder();
718 std::optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread);
719 if (!byte_size)
720 return return_valobj_sp;
721 const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr);
722 uint32_t fp_flag =
724
725 const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
726 const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
727 assert(r2_info && r3_info && "Basic registers should always be present.");
728
729 if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
730 value.SetValueType(Value::ValueType::Scalar);
731
732 bool success = false;
733 if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
734 // Extract the register context so we can read arguments from registers
735 // In MIPS register "r2" (v0) holds the integer function return values
736
737 uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0);
738
739 const bool is_signed = (type_flags & eTypeIsSigned) != 0;
740 switch (*byte_size) {
741 default:
742 break;
743
744 case sizeof(uint64_t):
745 if (is_signed)
746 value.GetScalar() = (int64_t)(raw_value);
747 else
748 value.GetScalar() = (uint64_t)(raw_value);
749 success = true;
750 break;
751
752 case sizeof(uint32_t):
753 if (is_signed)
754 value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
755 else
756 value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
757 success = true;
758 break;
759
760 case sizeof(uint16_t):
761 if (is_signed)
762 value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
763 else
764 value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
765 success = true;
766 break;
767
768 case sizeof(uint8_t):
769 if (is_signed)
770 value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
771 else
772 value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
773 success = true;
774 break;
775 }
776 } else if (type_flags & eTypeIsFloat) {
777 if (type_flags & eTypeIsComplex) {
778 // Don't handle complex yet.
779 } else if (IsSoftFloat(fp_flag)) {
780 uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0);
781 switch (*byte_size) {
782 case 4:
783 value.GetScalar() = *((float *)(&raw_value));
784 success = true;
785 break;
786 case 8:
787 value.GetScalar() = *((double *)(&raw_value));
788 success = true;
789 break;
790 case 16:
791 uint64_t result[2];
792 if (target_byte_order == eByteOrderLittle) {
793 result[0] = raw_value;
794 result[1] = reg_ctx->ReadRegisterAsUnsigned(r3_info, 0);
795 value.GetScalar() = *((long double *)(result));
796 } else {
797 result[0] = reg_ctx->ReadRegisterAsUnsigned(r3_info, 0);
798 result[1] = raw_value;
799 value.GetScalar() = *((long double *)(result));
800 }
801 success = true;
802 break;
803 }
804
805 } else {
806 if (*byte_size <= sizeof(long double)) {
807 const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
808
809 RegisterValue f0_value;
810 DataExtractor f0_data;
811
812 reg_ctx->ReadRegister(f0_info, f0_value);
813
814 f0_value.GetData(f0_data);
815
816 lldb::offset_t offset = 0;
817 if (*byte_size == sizeof(float)) {
818 value.GetScalar() = (float)f0_data.GetFloat(&offset);
819 success = true;
820 } else if (*byte_size == sizeof(double)) {
821 value.GetScalar() = (double)f0_data.GetDouble(&offset);
822 success = true;
823 } else if (*byte_size == sizeof(long double)) {
824 const RegisterInfo *f2_info =
825 reg_ctx->GetRegisterInfoByName("f2", 0);
826 RegisterValue f2_value;
827 DataExtractor f2_data;
828 reg_ctx->ReadRegister(f2_info, f2_value);
829 DataExtractor *copy_from_extractor = nullptr;
830 WritableDataBufferSP data_sp(new DataBufferHeap(16, 0));
831 DataExtractor return_ext(
832 data_sp, target_byte_order,
834
835 if (target_byte_order == eByteOrderLittle) {
836 copy_from_extractor = &f0_data;
837 copy_from_extractor->CopyByteOrderedData(
838 0, 8, data_sp->GetBytes(), *byte_size - 8, target_byte_order);
839 f2_value.GetData(f2_data);
840 copy_from_extractor = &f2_data;
841 copy_from_extractor->CopyByteOrderedData(
842 0, 8, data_sp->GetBytes() + 8, *byte_size - 8,
843 target_byte_order);
844 } else {
845 copy_from_extractor = &f0_data;
846 copy_from_extractor->CopyByteOrderedData(
847 0, 8, data_sp->GetBytes() + 8, *byte_size - 8,
848 target_byte_order);
849 f2_value.GetData(f2_data);
850 copy_from_extractor = &f2_data;
851 copy_from_extractor->CopyByteOrderedData(
852 0, 8, data_sp->GetBytes(), *byte_size - 8, target_byte_order);
853 }
854
855 return_valobj_sp = ValueObjectConstResult::Create(
856 &thread, return_compiler_type, ConstString(""), return_ext);
857 return return_valobj_sp;
858 }
859 }
860 }
861 }
862
863 if (success)
864 return_valobj_sp = ValueObjectConstResult::Create(
865 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
866 } else if (type_flags & eTypeIsStructUnion || type_flags & eTypeIsClass ||
867 type_flags & eTypeIsVector) {
868 // Any structure of up to 16 bytes in size is returned in the registers.
869 if (*byte_size <= 16) {
870 WritableDataBufferSP data_sp(new DataBufferHeap(16, 0));
871 DataExtractor return_ext(data_sp, target_byte_order,
873
874 RegisterValue r2_value, r3_value, f0_value, f1_value, f2_value;
875 // Tracks how much bytes of r2 and r3 registers we've consumed so far
876 uint32_t integer_bytes = 0;
877
878 // True if return values are in FP return registers.
879 bool use_fp_regs = false;
880 // True if we found any non floating point field in structure.
881 bool found_non_fp_field = false;
882 // True if return values are in r2 register.
883 bool use_r2 = false;
884 // True if return values are in r3 register.
885 bool use_r3 = false;
886 // True if the result is copied into our data buffer
887 bool sucess = false;
888 std::string name;
889 bool is_complex;
890 uint32_t count;
891 const uint32_t num_children = return_compiler_type.GetNumFields();
892
893 // A structure consisting of one or two FP values (and nothing else) will
894 // be returned in the two FP return-value registers i.e fp0 and fp2.
895 if (num_children <= 2) {
896 uint64_t field_bit_offset = 0;
897
898 // Check if this structure contains only floating point fields
899 for (uint32_t idx = 0; idx < num_children; idx++) {
900 CompilerType field_compiler_type =
901 return_compiler_type.GetFieldAtIndex(idx, name, &field_bit_offset,
902 nullptr, nullptr);
903
904 if (field_compiler_type.IsFloatingPointType(count, is_complex))
905 use_fp_regs = true;
906 else
907 found_non_fp_field = true;
908 }
909
910 if (use_fp_regs && !found_non_fp_field) {
911 // We have one or two FP-only values in this structure. Get it from
912 // f0/f2 registers.
913 DataExtractor f0_data, f1_data, f2_data;
914 const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
915 const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
916 const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0);
917
918 reg_ctx->ReadRegister(f0_info, f0_value);
919 reg_ctx->ReadRegister(f2_info, f2_value);
920
921 f0_value.GetData(f0_data);
922
923 for (uint32_t idx = 0; idx < num_children; idx++) {
924 CompilerType field_compiler_type =
925 return_compiler_type.GetFieldAtIndex(
926 idx, name, &field_bit_offset, nullptr, nullptr);
927 std::optional<uint64_t> field_byte_width =
928 field_compiler_type.GetByteSize(&thread);
929 if (!field_byte_width)
930 return return_valobj_sp;
931
932 DataExtractor *copy_from_extractor = nullptr;
933 uint64_t return_value[2];
934 offset_t offset = 0;
935
936 if (idx == 0) {
937 // This case is for long double type.
938 if (*field_byte_width == 16) {
939
940 // If structure contains long double type, then it is returned
941 // in fp0/fp1 registers.
942 if (target_byte_order == eByteOrderLittle) {
943 return_value[0] = f0_data.GetU64(&offset);
944 reg_ctx->ReadRegister(f1_info, f1_value);
945 f1_value.GetData(f1_data);
946 offset = 0;
947 return_value[1] = f1_data.GetU64(&offset);
948 } else {
949 return_value[1] = f0_data.GetU64(&offset);
950 reg_ctx->ReadRegister(f1_info, f1_value);
951 f1_value.GetData(f1_data);
952 offset = 0;
953 return_value[0] = f1_data.GetU64(&offset);
954 }
955
956 f0_data.SetData(return_value, *field_byte_width,
957 target_byte_order);
958 }
959 copy_from_extractor = &f0_data; // This is in f0, copy from
960 // register to our result
961 // structure
962 } else {
963 f2_value.GetData(f2_data);
964 // This is in f2, copy from register to our result structure
965 copy_from_extractor = &f2_data;
966 }
967
968 // Sanity check to avoid crash
969 if (!copy_from_extractor ||
970 *field_byte_width > copy_from_extractor->GetByteSize())
971 return return_valobj_sp;
972
973 // copy the register contents into our data buffer
974 copy_from_extractor->CopyByteOrderedData(
975 0, *field_byte_width,
976 data_sp->GetBytes() + (field_bit_offset / 8), *field_byte_width,
977 target_byte_order);
978 }
979
980 // The result is in our data buffer. Create a variable object out of
981 // it
982 return_valobj_sp = ValueObjectConstResult::Create(
983 &thread, return_compiler_type, ConstString(""), return_ext);
984
985 return return_valobj_sp;
986 }
987 }
988
989 // If we reach here, it means this structure either contains more than
990 // two fields or it contains at least one non floating point type. In
991 // that case, all fields are returned in GP return registers.
992 for (uint32_t idx = 0; idx < num_children; idx++) {
993 uint64_t field_bit_offset = 0;
994 bool is_signed;
995 uint32_t padding;
996
997 CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(
998 idx, name, &field_bit_offset, nullptr, nullptr);
999 std::optional<uint64_t> field_byte_width =
1000 field_compiler_type.GetByteSize(&thread);
1001
1002 // if we don't know the size of the field (e.g. invalid type), just
1003 // bail out
1004 if (!field_byte_width || *field_byte_width == 0)
1005 break;
1006
1007 uint32_t field_byte_offset = field_bit_offset / 8;
1008
1009 if (field_compiler_type.IsIntegerOrEnumerationType(is_signed) ||
1010 field_compiler_type.IsPointerType() ||
1011 field_compiler_type.IsFloatingPointType(count, is_complex)) {
1012 padding = field_byte_offset - integer_bytes;
1013
1014 if (integer_bytes < 8) {
1015 // We have not yet consumed r2 completely.
1016 if (integer_bytes + *field_byte_width + padding <= 8) {
1017 // This field fits in r2, copy its value from r2 to our result
1018 // structure
1019 integer_bytes = integer_bytes + *field_byte_width +
1020 padding; // Increase the consumed bytes.
1021 use_r2 = true;
1022 } else {
1023 // There isn't enough space left in r2 for this field, so this
1024 // will be in r3.
1025 integer_bytes = integer_bytes + *field_byte_width +
1026 padding; // Increase the consumed bytes.
1027 use_r3 = true;
1028 }
1029 }
1030 // We already have consumed at-least 8 bytes that means r2 is done,
1031 // and this field will be in r3. Check if this field can fit in r3.
1032 else if (integer_bytes + *field_byte_width + padding <= 16) {
1033 integer_bytes = integer_bytes + *field_byte_width + padding;
1034 use_r3 = true;
1035 } else {
1036 // There isn't any space left for this field, this should not
1037 // happen as we have already checked the overall size is not
1038 // greater than 16 bytes. For now, return a nullptr return value
1039 // object.
1040 return return_valobj_sp;
1041 }
1042 }
1043 }
1044 // Vector types up to 16 bytes are returned in GP return registers
1045 if (type_flags & eTypeIsVector) {
1046 if (*byte_size <= 8)
1047 use_r2 = true;
1048 else {
1049 use_r2 = true;
1050 use_r3 = true;
1051 }
1052 }
1053
1054 if (use_r2) {
1055 reg_ctx->ReadRegister(r2_info, r2_value);
1056
1057 const size_t bytes_copied = r2_value.GetAsMemoryData(
1058 *r2_info, data_sp->GetBytes(), r2_info->byte_size,
1059 target_byte_order, error);
1060 if (bytes_copied != r2_info->byte_size)
1061 return return_valobj_sp;
1062 sucess = true;
1063 }
1064 if (use_r3) {
1065 reg_ctx->ReadRegister(r3_info, r3_value);
1066 const size_t bytes_copied = r3_value.GetAsMemoryData(
1067 *r3_info, data_sp->GetBytes() + r2_info->byte_size,
1068 r3_info->byte_size, target_byte_order, error);
1069
1070 if (bytes_copied != r3_info->byte_size)
1071 return return_valobj_sp;
1072 sucess = true;
1073 }
1074 if (sucess) {
1075 // The result is in our data buffer. Create a variable object out of
1076 // it
1077 return_valobj_sp = ValueObjectConstResult::Create(
1078 &thread, return_compiler_type, ConstString(""), return_ext);
1079 }
1080 return return_valobj_sp;
1081 }
1082
1083 // Any structure/vector greater than 16 bytes in size is returned in
1084 // memory. The pointer to that memory is returned in r2.
1085 uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
1086 reg_ctx->GetRegisterInfoByName("r2", 0), 0);
1087
1088 // We have got the address. Create a memory object out of it
1089 return_valobj_sp = ValueObjectMemory::Create(
1090 &thread, "", Address(mem_address, nullptr), return_compiler_type);
1091 }
1092 return return_valobj_sp;
1093}
1094
1096 unwind_plan.Clear();
1098
1100
1101 // Our Call Frame Address is the stack pointer value
1102 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
1103
1104 // The previous PC is in the RA
1105 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
1106 unwind_plan.AppendRow(row);
1107
1108 // All other registers are the same.
1109
1110 unwind_plan.SetSourceName("mips64 at-func-entry default");
1113 return true;
1114}
1115
1117 unwind_plan.Clear();
1119
1121
1122 row->SetUnspecifiedRegistersAreUndefined(true);
1123 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
1124
1125 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
1126
1127 unwind_plan.AppendRow(row);
1128 unwind_plan.SetSourceName("mips64 default unwind plan");
1132 return true;
1133}
1134
1135bool ABISysV_mips64::RegisterIsVolatile(const RegisterInfo *reg_info) {
1136 return !RegisterIsCalleeSaved(reg_info);
1137}
1138
1141}
1142
1143bool ABISysV_mips64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
1144 if (reg_info) {
1145 // Preserved registers are :
1146 // r16-r23, r28, r29, r30, r31
1147
1148 int reg = ((reg_info->byte_offset) / 8);
1149
1150 bool save = (reg >= 16) && (reg <= 23);
1151 save |= (reg >= 28) && (reg <= 31);
1152
1153 return save;
1154 }
1155 return false;
1156}
1157
1160 GetPluginNameStatic(), "System V ABI for mips64 targets", CreateInstance);
1161}
1162
1165}
static const uint32_t k_num_register_infos
@ dwarf_r7
@ dwarf_r21
@ dwarf_r24
@ dwarf_r12
@ dwarf_hi
@ dwarf_r3
@ dwarf_r13
@ dwarf_r2
@ dwarf_r8
@ dwarf_r28
@ dwarf_bad
@ dwarf_r11
@ dwarf_r31
@ dwarf_sr
@ dwarf_r19
@ dwarf_r1
@ dwarf_r26
@ dwarf_r9
@ dwarf_pc
@ dwarf_r29
@ dwarf_r16
@ dwarf_r18
@ dwarf_r17
@ dwarf_r15
@ dwarf_lo
@ dwarf_r23
@ dwarf_r10
@ dwarf_cause
@ dwarf_r14
@ dwarf_r6
@ dwarf_r25
@ dwarf_r30
@ dwarf_r0
@ dwarf_r5
@ dwarf_r20
@ dwarf_r27
@ dwarf_r4
@ dwarf_r22
static const uint32_t k_num_register_infos
static const RegisterInfo g_register_infos_mips64[]
dwarf_regnums
@ dwarf_r31
@ dwarf_pc
@ dwarf_r29
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOGF(log,...)
Definition: Log.h:344
#define LLDB_PLUGIN_DEFINE(PluginName)
Definition: PluginManager.h:31
static llvm::StringRef GetPluginNameStatic()
bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info)
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
lldb_private::Status SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override
bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override
static void Initialize()
const lldb_private::RegisterInfo * GetRegisterInfoArray(uint32_t &count) override
static void Terminate()
lldb::ValueObjectSP GetReturnValueObjectSimple(lldb_private::Thread &thread, lldb_private::CompilerType &ast_type) const
bool GetArgumentValues(lldb_private::Thread &thread, lldb_private::ValueList &values) const override
lldb::ValueObjectSP GetReturnValueObjectImpl(lldb_private::Thread &thread, lldb_private::CompilerType &type) const override
bool IsSoftFloat(uint32_t fp_flag) const
bool CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override
size_t GetRedZoneSize() const override
static lldb::ABISP CreateInstance(lldb::ProcessSP process_sp, const lldb_private::ArchSpec &arch)
bool CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override
static std::unique_ptr< llvm::MCRegisterInfo > MakeMCRegisterInfo(const ArchSpec &arch)
Utility function to construct a MCRegisterInfo using the ArchSpec triple.
Definition: ABI.cpp:201
A section + offset based address class.
Definition: Address.h:59
An architecture specification class.
Definition: ArchSpec.h:32
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
Definition: ArchSpec.cpp:694
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:463
uint32_t GetFlags() const
Definition: ArchSpec.h:539
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
Definition: ArchSpec.cpp:741
Generic representation of a type in a programming language.
Definition: CompilerType.h:36
std::optional< uint64_t > GetByteSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bytes.
CompilerType GetFieldAtIndex(size_t idx, std::string &name, uint64_t *bit_offset_ptr, uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) const
bool IsFloatingPointType(uint32_t &count, bool &is_complex) const
uint32_t GetNumFields() const
bool IsIntegerOrEnumerationType(bool &is_signed) const
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
bool IsPointerType(CompilerType *pointee_type=nullptr) const
A uniqued constant string class.
Definition: ConstString.h:39
A subclass of DataBuffer that stores a data buffer on the heap.
An data extractor class.
Definition: DataExtractor.h:48
float GetFloat(lldb::offset_t *offset_ptr) const
Extract a float from *offset_ptr.
uint64_t GetU64(lldb::offset_t *offset_ptr) const
Extract a uint64_t value from *offset_ptr.
uint64_t GetByteSize() const
Get the number of bytes contained in this object.
lldb::offset_t SetData(const void *bytes, lldb::offset_t length, lldb::ByteOrder byte_order)
Set data with a buffer that is caller owned.
uint64_t GetMaxU64(lldb::offset_t *offset_ptr, size_t byte_size) const
Extract an unsigned integer of size byte_size from *offset_ptr.
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...
double GetDouble(lldb::offset_t *offset_ptr) const
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
Target * GetTargetPtr() const
Returns a pointer to the target object.
Process * GetProcessPtr() const
Returns a pointer to the process object.
void PutString(llvm::StringRef str)
Definition: Log.cpp:135
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
uint64_t ReadRegisterAsUnsigned(uint32_t reg, uint64_t fail_value)
const RegisterInfo * GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num)
bool WriteRegisterFromUnsigned(uint32_t reg, uint64_t uval)
const RegisterInfo * GetRegisterInfoByName(llvm::StringRef reg_name, uint32_t start_idx=0)
virtual bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)=0
bool GetData(DataExtractor &data) const
uint32_t GetAsMemoryData(const RegisterInfo &reg_info, void *dst, uint32_t dst_len, lldb::ByteOrder dst_byte_order, Status &error) const
An error handling class.
Definition: Status.h:44
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:130
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:63
const ArchSpec & GetArchitecture() const
Definition: Target.h:990
virtual lldb::StackFrameSP GetStackFrameAtIndex(uint32_t idx)
Definition: Thread.h:399
virtual lldb::RegisterContextSP GetRegisterContext()=0
void SetUnwindPlanForSignalTrap(lldb_private::LazyBool is_for_signal_trap)
Definition: UnwindPlan.h:502
void SetRegisterKind(lldb::RegisterKind kind)
Definition: UnwindPlan.h:437
void SetReturnAddressRegister(uint32_t regnum)
Definition: UnwindPlan.h:439
void AppendRow(const RowSP &row_sp)
Definition: UnwindPlan.cpp:362
std::shared_ptr< Row > RowSP
Definition: UnwindPlan.h:395
void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler)
Definition: UnwindPlan.h:478
void SetSourceName(const char *)
Definition: UnwindPlan.cpp:564
void SetUnwindPlanValidAtAllInstructions(lldb_private::LazyBool valid_at_all_insn)
Definition: UnwindPlan.h:490
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size, lldb::addr_t address=LLDB_INVALID_ADDRESS)
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, llvm::StringRef name, const Address &address, lldb::TypeSP &type_sp)
const Scalar & GetScalar() const
Definition: Value.h:112
void SetCompilerType(const CompilerType &compiler_type)
Definition: Value.cpp:252
void SetValueType(ValueType value_type)
Definition: Value.h:89
#define LLDB_REGNUM_GENERIC_RA
Definition: lldb-defines.h:54
#define LLDB_REGNUM_GENERIC_ARG8
Definition: lldb-defines.h:70
#define LLDB_REGNUM_GENERIC_ARG6
Definition: lldb-defines.h:66
#define LLDB_REGNUM_GENERIC_SP
Definition: lldb-defines.h:52
#define LLDB_REGNUM_GENERIC_ARG4
Definition: lldb-defines.h:62
#define LLDB_REGNUM_GENERIC_ARG3
Definition: lldb-defines.h:60
#define LLDB_REGNUM_GENERIC_ARG1
Definition: lldb-defines.h:56
#define LLDB_REGNUM_GENERIC_ARG7
Definition: lldb-defines.h:68
#define LLDB_REGNUM_GENERIC_FLAGS
Definition: lldb-defines.h:55
#define UINT32_MAX
Definition: lldb-defines.h:19
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:79
#define LLDB_REGNUM_GENERIC_ARG2
Definition: lldb-defines.h:58
#define LLDB_REGNUM_GENERIC_PC
Definition: lldb-defines.h:51
#define LLDB_REGNUM_GENERIC_FP
Definition: lldb-defines.h:53
#define LLDB_REGNUM_GENERIC_ARG5
Definition: lldb-defines.h:64
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:309
Definition: SBAddress.h:15
uint64_t offset_t
Definition: lldb-types.h:83
@ eEncodingUint
unsigned integer
ByteOrder
Byte ordering definitions.
@ eByteOrderLittle
uint64_t addr_t
Definition: lldb-types.h:79
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target
@ eRegisterKindDWARF
the register numbers seen DWARF
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition: UserID.h:47