ABIMacOSX_i386.cpp revision 360784
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
29using namespace lldb;
30using namespace lldb_private;
31
32enum {
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
47enum {
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
84static 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
680static const uint32_t k_num_register_infos =
681    llvm::array_lengthof(g_register_infos);
682static bool g_register_info_names_constified = false;
683
684const lldb_private::RegisterInfo *
685ABIMacOSX_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
704size_t ABIMacOSX_i386::GetRedZoneSize() const { return 0; }
705
706// Static Functions
707
708ABISP
709ABIMacOSX_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(
714        new ABIMacOSX_i386(std::move(process_sp), MakeMCRegisterInfo(arch)));
715  }
716  return ABISP();
717}
718
719bool ABIMacOSX_i386::PrepareTrivialCall(Thread &thread, addr_t sp,
720                                        addr_t func_addr, addr_t return_addr,
721                                        llvm::ArrayRef<addr_t> args) const {
722  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
723  if (!reg_ctx)
724    return false;
725  uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
726      eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
727  uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
728      eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
729
730  // When writing a register value down to memory, the register info used to
731  // write memory just needs to have the correct size of a 32 bit register, the
732  // actual register it pertains to is not important, just the size needs to be
733  // correct. Here we use "eax"...
734  const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
735  if (!reg_info_32)
736    return false; // TODO this should actually never happen
737
738  // Make room for the argument(s) on the stack
739
740  Status error;
741  RegisterValue reg_value;
742
743  // Write any arguments onto the stack
744  sp -= 4 * args.size();
745
746  // Align the SP
747  sp &= ~(16ull - 1ull); // 16-byte alignment
748
749  addr_t arg_pos = sp;
750
751  for (addr_t arg : args) {
752    reg_value.SetUInt32(arg);
753    error = reg_ctx->WriteRegisterValueToMemory(
754        reg_info_32, arg_pos, reg_info_32->byte_size, reg_value);
755    if (error.Fail())
756      return false;
757    arg_pos += 4;
758  }
759
760  // The return address is pushed onto the stack (yes after we just set the
761  // alignment above!).
762  sp -= 4;
763  reg_value.SetUInt32(return_addr);
764  error = reg_ctx->WriteRegisterValueToMemory(
765      reg_info_32, sp, reg_info_32->byte_size, reg_value);
766  if (error.Fail())
767    return false;
768
769  // %esp is set to the actual stack value.
770
771  if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp))
772    return false;
773
774  // %eip is set to the address of the called function.
775
776  if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr))
777    return false;
778
779  return true;
780}
781
782static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width,
783                                bool is_signed, Process *process,
784                                addr_t &current_stack_argument) {
785
786  uint32_t byte_size = (bit_width + (8 - 1)) / 8;
787  Status error;
788  if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size,
789                                           is_signed, scalar, error)) {
790    current_stack_argument += byte_size;
791    return true;
792  }
793  return false;
794}
795
796bool ABIMacOSX_i386::GetArgumentValues(Thread &thread,
797                                       ValueList &values) const {
798  unsigned int num_values = values.GetSize();
799  unsigned int value_index;
800
801  // Get the pointer to the first stack argument so we have a place to start
802  // when reading data
803
804  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
805
806  if (!reg_ctx)
807    return false;
808
809  addr_t sp = reg_ctx->GetSP(0);
810
811  if (!sp)
812    return false;
813
814  addr_t current_stack_argument = sp + 4; // jump over return address
815
816  for (value_index = 0; value_index < num_values; ++value_index) {
817    Value *value = values.GetValueAtIndex(value_index);
818
819    if (!value)
820      return false;
821
822    // We currently only support extracting values with Clang QualTypes. Do we
823    // care about others?
824    CompilerType compiler_type(value->GetCompilerType());
825    llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
826    if (bit_size) {
827      bool is_signed;
828      if (compiler_type.IsIntegerOrEnumerationType(is_signed))
829        ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed,
830                            thread.GetProcess().get(), current_stack_argument);
831      else if (compiler_type.IsPointerType())
832        ReadIntegerArgument(value->GetScalar(), *bit_size, false,
833                            thread.GetProcess().get(), current_stack_argument);
834    }
835  }
836
837  return true;
838}
839
840Status ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
841                                            lldb::ValueObjectSP &new_value_sp) {
842  Status error;
843  if (!new_value_sp) {
844    error.SetErrorString("Empty value object for return value.");
845    return error;
846  }
847
848  CompilerType compiler_type = new_value_sp->GetCompilerType();
849  if (!compiler_type) {
850    error.SetErrorString("Null clang type for return value.");
851    return error;
852  }
853
854  Thread *thread = frame_sp->GetThread().get();
855
856  bool is_signed;
857  uint32_t count;
858  bool is_complex;
859
860  RegisterContext *reg_ctx = thread->GetRegisterContext().get();
861
862  bool set_it_simple = false;
863  if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
864      compiler_type.IsPointerType()) {
865    DataExtractor data;
866    Status data_error;
867    size_t num_bytes = new_value_sp->GetData(data, data_error);
868    if (data_error.Fail()) {
869      error.SetErrorStringWithFormat(
870          "Couldn't convert return value to raw data: %s",
871          data_error.AsCString());
872      return error;
873    }
874    lldb::offset_t offset = 0;
875    if (num_bytes <= 8) {
876      const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
877      if (num_bytes <= 4) {
878        uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
879
880        if (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value))
881          set_it_simple = true;
882      } else {
883        uint32_t raw_value = data.GetMaxU32(&offset, 4);
884
885        if (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value)) {
886          const RegisterInfo *edx_info =
887              reg_ctx->GetRegisterInfoByName("edx", 0);
888          uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
889
890          if (reg_ctx->WriteRegisterFromUnsigned(edx_info, raw_value))
891            set_it_simple = true;
892        }
893      }
894    } else {
895      error.SetErrorString("We don't support returning longer than 64 bit "
896                           "integer values at present.");
897    }
898  } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
899    if (is_complex)
900      error.SetErrorString(
901          "We don't support returning complex values at present");
902    else
903      error.SetErrorString(
904          "We don't support returning float values at present");
905  }
906
907  if (!set_it_simple)
908    error.SetErrorString(
909        "We only support setting simple integer return types at present.");
910
911  return error;
912}
913
914ValueObjectSP
915ABIMacOSX_i386::GetReturnValueObjectImpl(Thread &thread,
916                                         CompilerType &compiler_type) const {
917  Value value;
918  ValueObjectSP return_valobj_sp;
919
920  if (!compiler_type)
921    return return_valobj_sp;
922
923  // value.SetContext (Value::eContextTypeClangType,
924  // compiler_type.GetOpaqueQualType());
925  value.SetCompilerType(compiler_type);
926
927  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
928  if (!reg_ctx)
929    return return_valobj_sp;
930
931  bool is_signed;
932
933  if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
934    llvm::Optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread);
935    if (!bit_width)
936      return return_valobj_sp;
937    unsigned eax_id =
938        reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
939    unsigned edx_id =
940        reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
941
942    switch (*bit_width) {
943    default:
944    case 128:
945      // Scalar can't hold 128-bit literals, so we don't handle this
946      return return_valobj_sp;
947    case 64:
948      uint64_t raw_value;
949      raw_value =
950          thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
951          0xffffffff;
952      raw_value |=
953          (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) &
954           0xffffffff)
955          << 32;
956      if (is_signed)
957        value.GetScalar() = (int64_t)raw_value;
958      else
959        value.GetScalar() = (uint64_t)raw_value;
960      break;
961    case 32:
962      if (is_signed)
963        value.GetScalar() = (int32_t)(
964            thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
965            0xffffffff);
966      else
967        value.GetScalar() = (uint32_t)(
968            thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
969            0xffffffff);
970      break;
971    case 16:
972      if (is_signed)
973        value.GetScalar() = (int16_t)(
974            thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
975            0xffff);
976      else
977        value.GetScalar() = (uint16_t)(
978            thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
979            0xffff);
980      break;
981    case 8:
982      if (is_signed)
983        value.GetScalar() = (int8_t)(
984            thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
985            0xff);
986      else
987        value.GetScalar() = (uint8_t)(
988            thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
989            0xff);
990      break;
991    }
992  } else if (compiler_type.IsPointerType()) {
993    unsigned eax_id =
994        reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
995    uint32_t ptr =
996        thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
997        0xffffffff;
998    value.GetScalar() = ptr;
999  } else {
1000    // not handled yet
1001    return return_valobj_sp;
1002  }
1003
1004  // If we get here, we have a valid Value, so make our ValueObject out of it:
1005
1006  return_valobj_sp = ValueObjectConstResult::Create(
1007      thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
1008  return return_valobj_sp;
1009}
1010
1011// This defines the CFA as esp+4
1012// the saved pc is at CFA-4 (i.e. esp+0)
1013// The saved esp is CFA+0
1014
1015bool ABIMacOSX_i386::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
1016  unwind_plan.Clear();
1017  unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1018
1019  uint32_t sp_reg_num = dwarf_esp;
1020  uint32_t pc_reg_num = dwarf_eip;
1021
1022  UnwindPlan::RowSP row(new UnwindPlan::Row);
1023  row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4);
1024  row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
1025  row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
1026  unwind_plan.AppendRow(row);
1027  unwind_plan.SetSourceName("i386 at-func-entry default");
1028  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1029  return true;
1030}
1031
1032// This defines the CFA as ebp+8
1033// The saved pc is at CFA-4 (i.e. ebp+4)
1034// The saved ebp is at CFA-8 (i.e. ebp+0)
1035// The saved esp is CFA+0
1036
1037bool ABIMacOSX_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
1038  unwind_plan.Clear();
1039  unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1040
1041  uint32_t fp_reg_num = dwarf_ebp;
1042  uint32_t sp_reg_num = dwarf_esp;
1043  uint32_t pc_reg_num = dwarf_eip;
1044
1045  UnwindPlan::RowSP row(new UnwindPlan::Row);
1046  const int32_t ptr_size = 4;
1047
1048  row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
1049  row->SetOffset(0);
1050
1051  row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
1052  row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
1053  row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
1054
1055  unwind_plan.AppendRow(row);
1056  unwind_plan.SetSourceName("i386 default unwind plan");
1057  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1058  unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
1059  unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
1060  return true;
1061}
1062
1063bool ABIMacOSX_i386::RegisterIsVolatile(const RegisterInfo *reg_info) {
1064  return !RegisterIsCalleeSaved(reg_info);
1065}
1066
1067// v.
1068// http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130
1069// -IA-
1070// 32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4
1071//
1072// This document ("OS X ABI Function Call Guide", chapter "IA-32 Function
1073// Calling Conventions") says that the following registers on i386 are
1074// preserved aka non-volatile aka callee-saved:
1075//
1076// ebx, ebp, esi, edi, esp
1077
1078bool ABIMacOSX_i386::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
1079  if (reg_info) {
1080    // Saved registers are ebx, ebp, esi, edi, esp, eip
1081    const char *name = reg_info->name;
1082    if (name[0] == 'e') {
1083      switch (name[1]) {
1084      case 'b':
1085        if (name[2] == 'x' || name[2] == 'p')
1086          return name[3] == '\0';
1087        break;
1088      case 'd':
1089        if (name[2] == 'i')
1090          return name[3] == '\0';
1091        break;
1092      case 'i':
1093        if (name[2] == 'p')
1094          return name[3] == '\0';
1095        break;
1096      case 's':
1097        if (name[2] == 'i' || name[2] == 'p')
1098          return name[3] == '\0';
1099        break;
1100      }
1101    }
1102    if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
1103      return true;
1104    if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
1105      return true;
1106    if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
1107      return true;
1108  }
1109  return false;
1110}
1111
1112void ABIMacOSX_i386::Initialize() {
1113  PluginManager::RegisterPlugin(
1114      GetPluginNameStatic(), "Mac OS X ABI for i386 targets", CreateInstance);
1115}
1116
1117void ABIMacOSX_i386::Terminate() {
1118  PluginManager::UnregisterPlugin(CreateInstance);
1119}
1120
1121lldb_private::ConstString ABIMacOSX_i386::GetPluginNameStatic() {
1122  static ConstString g_short_name("abi.macosx-i386");
1123  return g_short_name;
1124}
1125
1126// PluginInterface protocol
1127
1128lldb_private::ConstString ABIMacOSX_i386::GetPluginName() {
1129  return GetPluginNameStatic();
1130}
1131
1132uint32_t ABIMacOSX_i386::GetPluginVersion() { return 1; }
1133