]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / source / Plugins / ABI / MacOSX-i386 / ABIMacOSX_i386.cpp
1 //===-- ABIMacOSX_i386.cpp --------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "ABIMacOSX_i386.h"
10
11 #include <vector>
12
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/ADT/Triple.h"
15
16 #include "lldb/Core/Module.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/ValueObjectConstResult.h"
19 #include "lldb/Symbol/UnwindPlan.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/RegisterContext.h"
22 #include "lldb/Target/Target.h"
23 #include "lldb/Target/Thread.h"
24 #include "lldb/Utility/ConstString.h"
25 #include "lldb/Utility/RegisterValue.h"
26 #include "lldb/Utility/Scalar.h"
27 #include "lldb/Utility/Status.h"
28
29 using namespace lldb;
30 using namespace lldb_private;
31
32 enum {
33   ehframe_eax = 0,
34   ehframe_ecx,
35   ehframe_edx,
36   ehframe_ebx,
37   ehframe_ebp, // Different from DWARF the regnums - eh_frame esp/ebp had their
38                // regnums switched on i386 darwin
39   ehframe_esp, // Different from DWARF the regnums - eh_frame esp/ebp had their
40                // regnums switched on i386 darwin
41   ehframe_esi,
42   ehframe_edi,
43   ehframe_eip,
44   ehframe_eflags
45 };
46
47 enum {
48   dwarf_eax = 0,
49   dwarf_ecx,
50   dwarf_edx,
51   dwarf_ebx,
52   dwarf_esp,
53   dwarf_ebp,
54   dwarf_esi,
55   dwarf_edi,
56   dwarf_eip,
57   dwarf_eflags,
58   dwarf_stmm0 = 11,
59   dwarf_stmm1,
60   dwarf_stmm2,
61   dwarf_stmm3,
62   dwarf_stmm4,
63   dwarf_stmm5,
64   dwarf_stmm6,
65   dwarf_stmm7,
66   dwarf_xmm0 = 21,
67   dwarf_xmm1,
68   dwarf_xmm2,
69   dwarf_xmm3,
70   dwarf_xmm4,
71   dwarf_xmm5,
72   dwarf_xmm6,
73   dwarf_xmm7,
74   dwarf_ymm0 = dwarf_xmm0,
75   dwarf_ymm1 = dwarf_xmm1,
76   dwarf_ymm2 = dwarf_xmm2,
77   dwarf_ymm3 = dwarf_xmm3,
78   dwarf_ymm4 = dwarf_xmm4,
79   dwarf_ymm5 = dwarf_xmm5,
80   dwarf_ymm6 = dwarf_xmm6,
81   dwarf_ymm7 = dwarf_xmm7
82 };
83
84 static RegisterInfo g_register_infos[] = {
85     //  NAME      ALT      SZ OFF ENCODING         FORMAT
86     //  EH_FRAME              DWARF                 GENERIC
87     //  PROCESS PLUGIN        LLDB NATIVE
88     //  ======    =======  == === =============    ============
89     //  ===================== ===================== ============================
90     //  ====================  ======================
91     {"eax",
92      nullptr,
93      4,
94      0,
95      eEncodingUint,
96      eFormatHex,
97      {ehframe_eax, dwarf_eax, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
98       LLDB_INVALID_REGNUM},
99      nullptr,
100      nullptr,
101      nullptr,
102      0},
103     {"ebx",
104      nullptr,
105      4,
106      0,
107      eEncodingUint,
108      eFormatHex,
109      {ehframe_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
110       LLDB_INVALID_REGNUM},
111      nullptr,
112      nullptr,
113      nullptr,
114      0},
115     {"ecx",
116      nullptr,
117      4,
118      0,
119      eEncodingUint,
120      eFormatHex,
121      {ehframe_ecx, dwarf_ecx, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,
122       LLDB_INVALID_REGNUM},
123      nullptr,
124      nullptr,
125      nullptr,
126      0},
127     {"edx",
128      nullptr,
129      4,
130      0,
131      eEncodingUint,
132      eFormatHex,
133      {ehframe_edx, dwarf_edx, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,
134       LLDB_INVALID_REGNUM},
135      nullptr,
136      nullptr,
137      nullptr,
138      0},
139     {"esi",
140      nullptr,
141      4,
142      0,
143      eEncodingUint,
144      eFormatHex,
145      {ehframe_esi, dwarf_esi, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,
146       LLDB_INVALID_REGNUM},
147      nullptr,
148      nullptr,
149      nullptr,
150      0},
151     {"edi",
152      nullptr,
153      4,
154      0,
155      eEncodingUint,
156      eFormatHex,
157      {ehframe_edi, dwarf_edi, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,
158       LLDB_INVALID_REGNUM},
159      nullptr,
160      nullptr,
161      nullptr,
162      0},
163     {"ebp",
164      "fp",
165      4,
166      0,
167      eEncodingUint,
168      eFormatHex,
169      {ehframe_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
170       LLDB_INVALID_REGNUM},
171      nullptr,
172      nullptr,
173      nullptr,
174      0},
175     {"esp",
176      "sp",
177      4,
178      0,
179      eEncodingUint,
180      eFormatHex,
181      {ehframe_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
182       LLDB_INVALID_REGNUM},
183      nullptr,
184      nullptr,
185      nullptr,
186      0},
187     {"eip",
188      "pc",
189      4,
190      0,
191      eEncodingUint,
192      eFormatHex,
193      {ehframe_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
194       LLDB_INVALID_REGNUM},
195      nullptr,
196      nullptr,
197      nullptr,
198      0},
199     {"eflags",
200      nullptr,
201      4,
202      0,
203      eEncodingUint,
204      eFormatHex,
205      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS,
206       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
207      nullptr,
208      nullptr,
209      nullptr,
210      0},
211     {"cs",
212      nullptr,
213      4,
214      0,
215      eEncodingUint,
216      eFormatHex,
217      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
218       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
219      nullptr,
220      nullptr,
221      nullptr,
222      0},
223     {"ss",
224      nullptr,
225      4,
226      0,
227      eEncodingUint,
228      eFormatHex,
229      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
230       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
231      nullptr,
232      nullptr,
233      nullptr,
234      0},
235     {"ds",
236      nullptr,
237      4,
238      0,
239      eEncodingUint,
240      eFormatHex,
241      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
242       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
243      nullptr,
244      nullptr,
245      nullptr,
246      0},
247     {"es",
248      nullptr,
249      4,
250      0,
251      eEncodingUint,
252      eFormatHex,
253      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
254       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
255      nullptr,
256      nullptr,
257      nullptr,
258      0},
259     {"fs",
260      nullptr,
261      4,
262      0,
263      eEncodingUint,
264      eFormatHex,
265      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
266       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
267      nullptr,
268      nullptr,
269      nullptr,
270      0},
271     {"gs",
272      nullptr,
273      4,
274      0,
275      eEncodingUint,
276      eFormatHex,
277      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
278       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
279      nullptr,
280      nullptr,
281      nullptr,
282      0},
283     {"stmm0",
284      nullptr,
285      10,
286      0,
287      eEncodingVector,
288      eFormatVectorOfUInt8,
289      {LLDB_INVALID_REGNUM, dwarf_stmm0, LLDB_INVALID_REGNUM,
290       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
291      nullptr,
292      nullptr,
293      nullptr,
294      0},
295     {"stmm1",
296      nullptr,
297      10,
298      0,
299      eEncodingVector,
300      eFormatVectorOfUInt8,
301      {LLDB_INVALID_REGNUM, dwarf_stmm1, LLDB_INVALID_REGNUM,
302       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
303      nullptr,
304      nullptr,
305      nullptr,
306      0},
307     {"stmm2",
308      nullptr,
309      10,
310      0,
311      eEncodingVector,
312      eFormatVectorOfUInt8,
313      {LLDB_INVALID_REGNUM, dwarf_stmm2, LLDB_INVALID_REGNUM,
314       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
315      nullptr,
316      nullptr,
317      nullptr,
318      0},
319     {"stmm3",
320      nullptr,
321      10,
322      0,
323      eEncodingVector,
324      eFormatVectorOfUInt8,
325      {LLDB_INVALID_REGNUM, dwarf_stmm3, LLDB_INVALID_REGNUM,
326       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
327      nullptr,
328      nullptr,
329      nullptr,
330      0},
331     {"stmm4",
332      nullptr,
333      10,
334      0,
335      eEncodingVector,
336      eFormatVectorOfUInt8,
337      {LLDB_INVALID_REGNUM, dwarf_stmm4, LLDB_INVALID_REGNUM,
338       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
339      nullptr,
340      nullptr,
341      nullptr,
342      0},
343     {"stmm5",
344      nullptr,
345      10,
346      0,
347      eEncodingVector,
348      eFormatVectorOfUInt8,
349      {LLDB_INVALID_REGNUM, dwarf_stmm5, LLDB_INVALID_REGNUM,
350       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
351      nullptr,
352      nullptr,
353      nullptr,
354      0},
355     {"stmm6",
356      nullptr,
357      10,
358      0,
359      eEncodingVector,
360      eFormatVectorOfUInt8,
361      {LLDB_INVALID_REGNUM, dwarf_stmm6, LLDB_INVALID_REGNUM,
362       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
363      nullptr,
364      nullptr,
365      nullptr,
366      0},
367     {"stmm7",
368      nullptr,
369      10,
370      0,
371      eEncodingVector,
372      eFormatVectorOfUInt8,
373      {LLDB_INVALID_REGNUM, dwarf_stmm7, LLDB_INVALID_REGNUM,
374       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
375      nullptr,
376      nullptr,
377      nullptr,
378      0},
379     {"fctrl",
380      nullptr,
381      4,
382      0,
383      eEncodingUint,
384      eFormatHex,
385      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
386       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
387      nullptr,
388      nullptr,
389      nullptr,
390      0},
391     {"fstat",
392      nullptr,
393      4,
394      0,
395      eEncodingUint,
396      eFormatHex,
397      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
398       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
399      nullptr,
400      nullptr,
401      nullptr,
402      0},
403     {"ftag",
404      nullptr,
405      4,
406      0,
407      eEncodingUint,
408      eFormatHex,
409      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
410       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
411      nullptr,
412      nullptr,
413      nullptr,
414      0},
415     {"fiseg",
416      nullptr,
417      4,
418      0,
419      eEncodingUint,
420      eFormatHex,
421      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
422       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
423      nullptr,
424      nullptr,
425      nullptr,
426      0},
427     {"fioff",
428      nullptr,
429      4,
430      0,
431      eEncodingUint,
432      eFormatHex,
433      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
434       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
435      nullptr,
436      nullptr,
437      nullptr,
438      0},
439     {"foseg",
440      nullptr,
441      4,
442      0,
443      eEncodingUint,
444      eFormatHex,
445      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
446       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
447      nullptr,
448      nullptr,
449      nullptr,
450      0},
451     {"fooff",
452      nullptr,
453      4,
454      0,
455      eEncodingUint,
456      eFormatHex,
457      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
458       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
459      nullptr,
460      nullptr,
461      nullptr,
462      0},
463     {"fop",
464      nullptr,
465      4,
466      0,
467      eEncodingUint,
468      eFormatHex,
469      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
470       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
471      nullptr,
472      nullptr,
473      nullptr,
474      0},
475     {"xmm0",
476      nullptr,
477      16,
478      0,
479      eEncodingVector,
480      eFormatVectorOfUInt8,
481      {LLDB_INVALID_REGNUM, dwarf_xmm0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
482       LLDB_INVALID_REGNUM},
483      nullptr,
484      nullptr,
485      nullptr,
486      0},
487     {"xmm1",
488      nullptr,
489      16,
490      0,
491      eEncodingVector,
492      eFormatVectorOfUInt8,
493      {LLDB_INVALID_REGNUM, dwarf_xmm1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
494       LLDB_INVALID_REGNUM},
495      nullptr,
496      nullptr,
497      nullptr,
498      0},
499     {"xmm2",
500      nullptr,
501      16,
502      0,
503      eEncodingVector,
504      eFormatVectorOfUInt8,
505      {LLDB_INVALID_REGNUM, dwarf_xmm2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
506       LLDB_INVALID_REGNUM},
507      nullptr,
508      nullptr,
509      nullptr,
510      0},
511     {"xmm3",
512      nullptr,
513      16,
514      0,
515      eEncodingVector,
516      eFormatVectorOfUInt8,
517      {LLDB_INVALID_REGNUM, dwarf_xmm3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
518       LLDB_INVALID_REGNUM},
519      nullptr,
520      nullptr,
521      nullptr,
522      0},
523     {"xmm4",
524      nullptr,
525      16,
526      0,
527      eEncodingVector,
528      eFormatVectorOfUInt8,
529      {LLDB_INVALID_REGNUM, dwarf_xmm4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
530       LLDB_INVALID_REGNUM},
531      nullptr,
532      nullptr,
533      nullptr,
534      0},
535     {"xmm5",
536      nullptr,
537      16,
538      0,
539      eEncodingVector,
540      eFormatVectorOfUInt8,
541      {LLDB_INVALID_REGNUM, dwarf_xmm5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
542       LLDB_INVALID_REGNUM},
543      nullptr,
544      nullptr,
545      nullptr,
546      0},
547     {"xmm6",
548      nullptr,
549      16,
550      0,
551      eEncodingVector,
552      eFormatVectorOfUInt8,
553      {LLDB_INVALID_REGNUM, dwarf_xmm6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
554       LLDB_INVALID_REGNUM},
555      nullptr,
556      nullptr,
557      nullptr,
558      0},
559     {"xmm7",
560      nullptr,
561      16,
562      0,
563      eEncodingVector,
564      eFormatVectorOfUInt8,
565      {LLDB_INVALID_REGNUM, dwarf_xmm7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
566       LLDB_INVALID_REGNUM},
567      nullptr,
568      nullptr,
569      nullptr,
570      0},
571     {"mxcsr",
572      nullptr,
573      4,
574      0,
575      eEncodingUint,
576      eFormatHex,
577      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
578       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
579      nullptr,
580      nullptr,
581      nullptr,
582      0},
583     {"ymm0",
584      nullptr,
585      32,
586      0,
587      eEncodingVector,
588      eFormatVectorOfUInt8,
589      {LLDB_INVALID_REGNUM, dwarf_ymm0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
590       LLDB_INVALID_REGNUM},
591      nullptr,
592      nullptr,
593      nullptr,
594      0},
595     {"ymm1",
596      nullptr,
597      32,
598      0,
599      eEncodingVector,
600      eFormatVectorOfUInt8,
601      {LLDB_INVALID_REGNUM, dwarf_ymm1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
602       LLDB_INVALID_REGNUM},
603      nullptr,
604      nullptr,
605      nullptr,
606      0},
607     {"ymm2",
608      nullptr,
609      32,
610      0,
611      eEncodingVector,
612      eFormatVectorOfUInt8,
613      {LLDB_INVALID_REGNUM, dwarf_ymm2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
614       LLDB_INVALID_REGNUM},
615      nullptr,
616      nullptr,
617      nullptr,
618      0},
619     {"ymm3",
620      nullptr,
621      32,
622      0,
623      eEncodingVector,
624      eFormatVectorOfUInt8,
625      {LLDB_INVALID_REGNUM, dwarf_ymm3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
626       LLDB_INVALID_REGNUM},
627      nullptr,
628      nullptr,
629      nullptr,
630      0},
631     {"ymm4",
632      nullptr,
633      32,
634      0,
635      eEncodingVector,
636      eFormatVectorOfUInt8,
637      {LLDB_INVALID_REGNUM, dwarf_ymm4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
638       LLDB_INVALID_REGNUM},
639      nullptr,
640      nullptr,
641      nullptr,
642      0},
643     {"ymm5",
644      nullptr,
645      32,
646      0,
647      eEncodingVector,
648      eFormatVectorOfUInt8,
649      {LLDB_INVALID_REGNUM, dwarf_ymm5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
650       LLDB_INVALID_REGNUM},
651      nullptr,
652      nullptr,
653      nullptr,
654      0},
655     {"ymm6",
656      nullptr,
657      32,
658      0,
659      eEncodingVector,
660      eFormatVectorOfUInt8,
661      {LLDB_INVALID_REGNUM, dwarf_ymm6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
662       LLDB_INVALID_REGNUM},
663      nullptr,
664      nullptr,
665      nullptr,
666      0},
667     {"ymm7",
668      nullptr,
669      32,
670      0,
671      eEncodingVector,
672      eFormatVectorOfUInt8,
673      {LLDB_INVALID_REGNUM, dwarf_ymm7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
674       LLDB_INVALID_REGNUM},
675      nullptr,
676      nullptr,
677      nullptr,
678      0}};
679
680 static const uint32_t k_num_register_infos =
681     llvm::array_lengthof(g_register_infos);
682 static bool g_register_info_names_constified = false;
683
684 const lldb_private::RegisterInfo *
685 ABIMacOSX_i386::GetRegisterInfoArray(uint32_t &count) {
686   // Make the C-string names and alt_names for the register infos into const
687   // C-string values by having the ConstString unique the names in the global
688   // constant C-string pool.
689   if (!g_register_info_names_constified) {
690     g_register_info_names_constified = true;
691     for (uint32_t i = 0; i < k_num_register_infos; ++i) {
692       if (g_register_infos[i].name)
693         g_register_infos[i].name =
694             ConstString(g_register_infos[i].name).GetCString();
695       if (g_register_infos[i].alt_name)
696         g_register_infos[i].alt_name =
697             ConstString(g_register_infos[i].alt_name).GetCString();
698     }
699   }
700   count = k_num_register_infos;
701   return g_register_infos;
702 }
703
704 size_t ABIMacOSX_i386::GetRedZoneSize() const { return 0; }
705
706 // Static Functions
707
708 ABISP
709 ABIMacOSX_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
710   if ((arch.GetTriple().getArch() == llvm::Triple::x86) &&
711       (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS() ||
712        arch.GetTriple().isWatchOS())) {
713     return ABISP(new ABIMacOSX_i386(process_sp));
714   }
715   return ABISP();
716 }
717
718 bool ABIMacOSX_i386::PrepareTrivialCall(Thread &thread, addr_t sp,
719                                         addr_t func_addr, addr_t return_addr,
720                                         llvm::ArrayRef<addr_t> args) const {
721   RegisterContext *reg_ctx = thread.GetRegisterContext().get();
722   if (!reg_ctx)
723     return false;
724   uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
725       eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
726   uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
727       eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
728
729   // When writing a register value down to memory, the register info used to
730   // write memory just needs to have the correct size of a 32 bit register, the
731   // actual register it pertains to is not important, just the size needs to be
732   // correct. Here we use "eax"...
733   const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
734   if (!reg_info_32)
735     return false; // TODO this should actually never happen
736
737   // Make room for the argument(s) on the stack
738
739   Status error;
740   RegisterValue reg_value;
741
742   // Write any arguments onto the stack
743   sp -= 4 * args.size();
744
745   // Align the SP
746   sp &= ~(16ull - 1ull); // 16-byte alignment
747
748   addr_t arg_pos = sp;
749
750   for (addr_t arg : args) {
751     reg_value.SetUInt32(arg);
752     error = reg_ctx->WriteRegisterValueToMemory(
753         reg_info_32, arg_pos, reg_info_32->byte_size, reg_value);
754     if (error.Fail())
755       return false;
756     arg_pos += 4;
757   }
758
759   // The return address is pushed onto the stack (yes after we just set the
760   // alignment above!).
761   sp -= 4;
762   reg_value.SetUInt32(return_addr);
763   error = reg_ctx->WriteRegisterValueToMemory(
764       reg_info_32, sp, reg_info_32->byte_size, reg_value);
765   if (error.Fail())
766     return false;
767
768   // %esp is set to the actual stack value.
769
770   if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp))
771     return false;
772
773   // %eip is set to the address of the called function.
774
775   if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr))
776     return false;
777
778   return true;
779 }
780
781 static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width,
782                                 bool is_signed, Process *process,
783                                 addr_t &current_stack_argument) {
784
785   uint32_t byte_size = (bit_width + (8 - 1)) / 8;
786   Status error;
787   if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size,
788                                            is_signed, scalar, error)) {
789     current_stack_argument += byte_size;
790     return true;
791   }
792   return false;
793 }
794
795 bool ABIMacOSX_i386::GetArgumentValues(Thread &thread,
796                                        ValueList &values) const {
797   unsigned int num_values = values.GetSize();
798   unsigned int value_index;
799
800   // Get the pointer to the first stack argument so we have a place to start
801   // when reading data
802
803   RegisterContext *reg_ctx = thread.GetRegisterContext().get();
804
805   if (!reg_ctx)
806     return false;
807
808   addr_t sp = reg_ctx->GetSP(0);
809
810   if (!sp)
811     return false;
812
813   addr_t current_stack_argument = sp + 4; // jump over return address
814
815   for (value_index = 0; value_index < num_values; ++value_index) {
816     Value *value = values.GetValueAtIndex(value_index);
817
818     if (!value)
819       return false;
820
821     // We currently only support extracting values with Clang QualTypes. Do we
822     // care about others?
823     CompilerType compiler_type(value->GetCompilerType());
824     llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
825     if (bit_size) {
826       bool is_signed;
827       if (compiler_type.IsIntegerOrEnumerationType(is_signed))
828         ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed,
829                             thread.GetProcess().get(), current_stack_argument);
830       else if (compiler_type.IsPointerType())
831         ReadIntegerArgument(value->GetScalar(), *bit_size, false,
832                             thread.GetProcess().get(), current_stack_argument);
833     }
834   }
835
836   return true;
837 }
838
839 Status ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
840                                             lldb::ValueObjectSP &new_value_sp) {
841   Status error;
842   if (!new_value_sp) {
843     error.SetErrorString("Empty value object for return value.");
844     return error;
845   }
846
847   CompilerType compiler_type = new_value_sp->GetCompilerType();
848   if (!compiler_type) {
849     error.SetErrorString("Null clang type for return value.");
850     return error;
851   }
852
853   Thread *thread = frame_sp->GetThread().get();
854
855   bool is_signed;
856   uint32_t count;
857   bool is_complex;
858
859   RegisterContext *reg_ctx = thread->GetRegisterContext().get();
860
861   bool set_it_simple = false;
862   if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
863       compiler_type.IsPointerType()) {
864     DataExtractor data;
865     Status data_error;
866     size_t num_bytes = new_value_sp->GetData(data, data_error);
867     if (data_error.Fail()) {
868       error.SetErrorStringWithFormat(
869           "Couldn't convert return value to raw data: %s",
870           data_error.AsCString());
871       return error;
872     }
873     lldb::offset_t offset = 0;
874     if (num_bytes <= 8) {
875       const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
876       if (num_bytes <= 4) {
877         uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
878
879         if (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value))
880           set_it_simple = true;
881       } else {
882         uint32_t raw_value = data.GetMaxU32(&offset, 4);
883
884         if (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value)) {
885           const RegisterInfo *edx_info =
886               reg_ctx->GetRegisterInfoByName("edx", 0);
887           uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
888
889           if (reg_ctx->WriteRegisterFromUnsigned(edx_info, raw_value))
890             set_it_simple = true;
891         }
892       }
893     } else {
894       error.SetErrorString("We don't support returning longer than 64 bit "
895                            "integer values at present.");
896     }
897   } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
898     if (is_complex)
899       error.SetErrorString(
900           "We don't support returning complex values at present");
901     else
902       error.SetErrorString(
903           "We don't support returning float values at present");
904   }
905
906   if (!set_it_simple)
907     error.SetErrorString(
908         "We only support setting simple integer return types at present.");
909
910   return error;
911 }
912
913 ValueObjectSP
914 ABIMacOSX_i386::GetReturnValueObjectImpl(Thread &thread,
915                                          CompilerType &compiler_type) const {
916   Value value;
917   ValueObjectSP return_valobj_sp;
918
919   if (!compiler_type)
920     return return_valobj_sp;
921
922   // value.SetContext (Value::eContextTypeClangType,
923   // compiler_type.GetOpaqueQualType());
924   value.SetCompilerType(compiler_type);
925
926   RegisterContext *reg_ctx = thread.GetRegisterContext().get();
927   if (!reg_ctx)
928     return return_valobj_sp;
929
930   bool is_signed;
931
932   if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
933     llvm::Optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread);
934     if (!bit_width)
935       return return_valobj_sp;
936     unsigned eax_id =
937         reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
938     unsigned edx_id =
939         reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
940
941     switch (*bit_width) {
942     default:
943     case 128:
944       // Scalar can't hold 128-bit literals, so we don't handle this
945       return return_valobj_sp;
946     case 64:
947       uint64_t raw_value;
948       raw_value =
949           thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
950           0xffffffff;
951       raw_value |=
952           (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) &
953            0xffffffff)
954           << 32;
955       if (is_signed)
956         value.GetScalar() = (int64_t)raw_value;
957       else
958         value.GetScalar() = (uint64_t)raw_value;
959       break;
960     case 32:
961       if (is_signed)
962         value.GetScalar() = (int32_t)(
963             thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
964             0xffffffff);
965       else
966         value.GetScalar() = (uint32_t)(
967             thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
968             0xffffffff);
969       break;
970     case 16:
971       if (is_signed)
972         value.GetScalar() = (int16_t)(
973             thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
974             0xffff);
975       else
976         value.GetScalar() = (uint16_t)(
977             thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
978             0xffff);
979       break;
980     case 8:
981       if (is_signed)
982         value.GetScalar() = (int8_t)(
983             thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
984             0xff);
985       else
986         value.GetScalar() = (uint8_t)(
987             thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
988             0xff);
989       break;
990     }
991   } else if (compiler_type.IsPointerType()) {
992     unsigned eax_id =
993         reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
994     uint32_t ptr =
995         thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
996         0xffffffff;
997     value.GetScalar() = ptr;
998   } else {
999     // not handled yet
1000     return return_valobj_sp;
1001   }
1002
1003   // If we get here, we have a valid Value, so make our ValueObject out of it:
1004
1005   return_valobj_sp = ValueObjectConstResult::Create(
1006       thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
1007   return return_valobj_sp;
1008 }
1009
1010 // This defines the CFA as esp+4
1011 // the saved pc is at CFA-4 (i.e. esp+0)
1012 // The saved esp is CFA+0
1013
1014 bool ABIMacOSX_i386::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
1015   unwind_plan.Clear();
1016   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1017
1018   uint32_t sp_reg_num = dwarf_esp;
1019   uint32_t pc_reg_num = dwarf_eip;
1020
1021   UnwindPlan::RowSP row(new UnwindPlan::Row);
1022   row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4);
1023   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
1024   row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
1025   unwind_plan.AppendRow(row);
1026   unwind_plan.SetSourceName("i386 at-func-entry default");
1027   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1028   return true;
1029 }
1030
1031 // This defines the CFA as ebp+8
1032 // The saved pc is at CFA-4 (i.e. ebp+4)
1033 // The saved ebp is at CFA-8 (i.e. ebp+0)
1034 // The saved esp is CFA+0
1035
1036 bool ABIMacOSX_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
1037   unwind_plan.Clear();
1038   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1039
1040   uint32_t fp_reg_num = dwarf_ebp;
1041   uint32_t sp_reg_num = dwarf_esp;
1042   uint32_t pc_reg_num = dwarf_eip;
1043
1044   UnwindPlan::RowSP row(new UnwindPlan::Row);
1045   const int32_t ptr_size = 4;
1046
1047   row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
1048   row->SetOffset(0);
1049
1050   row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
1051   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
1052   row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
1053
1054   unwind_plan.AppendRow(row);
1055   unwind_plan.SetSourceName("i386 default unwind plan");
1056   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1057   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
1058   return true;
1059 }
1060
1061 bool ABIMacOSX_i386::RegisterIsVolatile(const RegisterInfo *reg_info) {
1062   return !RegisterIsCalleeSaved(reg_info);
1063 }
1064
1065 // v.
1066 // http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130
1067 // -IA-
1068 // 32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4
1069 //
1070 // This document ("OS X ABI Function Call Guide", chapter "IA-32 Function
1071 // Calling Conventions") says that the following registers on i386 are
1072 // preserved aka non-volatile aka callee-saved:
1073 //
1074 // ebx, ebp, esi, edi, esp
1075
1076 bool ABIMacOSX_i386::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
1077   if (reg_info) {
1078     // Saved registers are ebx, ebp, esi, edi, esp, eip
1079     const char *name = reg_info->name;
1080     if (name[0] == 'e') {
1081       switch (name[1]) {
1082       case 'b':
1083         if (name[2] == 'x' || name[2] == 'p')
1084           return name[3] == '\0';
1085         break;
1086       case 'd':
1087         if (name[2] == 'i')
1088           return name[3] == '\0';
1089         break;
1090       case 'i':
1091         if (name[2] == 'p')
1092           return name[3] == '\0';
1093         break;
1094       case 's':
1095         if (name[2] == 'i' || name[2] == 'p')
1096           return name[3] == '\0';
1097         break;
1098       }
1099     }
1100     if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
1101       return true;
1102     if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
1103       return true;
1104     if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
1105       return true;
1106   }
1107   return false;
1108 }
1109
1110 void ABIMacOSX_i386::Initialize() {
1111   PluginManager::RegisterPlugin(
1112       GetPluginNameStatic(), "Mac OS X ABI for i386 targets", CreateInstance);
1113 }
1114
1115 void ABIMacOSX_i386::Terminate() {
1116   PluginManager::UnregisterPlugin(CreateInstance);
1117 }
1118
1119 lldb_private::ConstString ABIMacOSX_i386::GetPluginNameStatic() {
1120   static ConstString g_short_name("abi.macosx-i386");
1121   return g_short_name;
1122 }
1123
1124 // PluginInterface protocol
1125
1126 lldb_private::ConstString ABIMacOSX_i386::GetPluginName() {
1127   return GetPluginNameStatic();
1128 }
1129
1130 uint32_t ABIMacOSX_i386::GetPluginVersion() { return 1; }