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