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