LLDB  mainline
ABIMacOSX_i386.cpp
Go to the documentation of this file.
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"
19 #include "lldb/Symbol/UnwindPlan.h"
20 #include "lldb/Target/Process.h"
22 #include "lldb/Target/Target.h"
23 #include "lldb/Target/Thread.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 {
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
45 };
46 
47 enum {
48  dwarf_eax = 0,
66  dwarf_xmm0 = 21,
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,
96  eFormatHex,
98  LLDB_INVALID_REGNUM},
99  nullptr,
100  nullptr,
101  nullptr,
102  0},
103  {"ebx",
104  nullptr,
105  4,
106  0,
108  eFormatHex,
110  LLDB_INVALID_REGNUM},
111  nullptr,
112  nullptr,
113  nullptr,
114  0},
115  {"ecx",
116  nullptr,
117  4,
118  0,
120  eFormatHex,
122  LLDB_INVALID_REGNUM},
123  nullptr,
124  nullptr,
125  nullptr,
126  0},
127  {"edx",
128  nullptr,
129  4,
130  0,
132  eFormatHex,
134  LLDB_INVALID_REGNUM},
135  nullptr,
136  nullptr,
137  nullptr,
138  0},
139  {"esi",
140  nullptr,
141  4,
142  0,
144  eFormatHex,
146  LLDB_INVALID_REGNUM},
147  nullptr,
148  nullptr,
149  nullptr,
150  0},
151  {"edi",
152  nullptr,
153  4,
154  0,
156  eFormatHex,
158  LLDB_INVALID_REGNUM},
159  nullptr,
160  nullptr,
161  nullptr,
162  0},
163  {"ebp",
164  "fp",
165  4,
166  0,
168  eFormatHex,
170  LLDB_INVALID_REGNUM},
171  nullptr,
172  nullptr,
173  nullptr,
174  0},
175  {"esp",
176  "sp",
177  4,
178  0,
180  eFormatHex,
182  LLDB_INVALID_REGNUM},
183  nullptr,
184  nullptr,
185  nullptr,
186  0},
187  {"eip",
188  "pc",
189  4,
190  0,
192  eFormatHex,
194  LLDB_INVALID_REGNUM},
195  nullptr,
196  nullptr,
197  nullptr,
198  0},
199  {"eflags",
200  nullptr,
201  4,
202  0,
204  eFormatHex,
206  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
207  nullptr,
208  nullptr,
209  nullptr,
210  0},
211  {"cs",
212  nullptr,
213  4,
214  0,
216  eFormatHex,
218  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
219  nullptr,
220  nullptr,
221  nullptr,
222  0},
223  {"ss",
224  nullptr,
225  4,
226  0,
228  eFormatHex,
230  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
231  nullptr,
232  nullptr,
233  nullptr,
234  0},
235  {"ds",
236  nullptr,
237  4,
238  0,
240  eFormatHex,
242  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
243  nullptr,
244  nullptr,
245  nullptr,
246  0},
247  {"es",
248  nullptr,
249  4,
250  0,
252  eFormatHex,
254  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
255  nullptr,
256  nullptr,
257  nullptr,
258  0},
259  {"fs",
260  nullptr,
261  4,
262  0,
264  eFormatHex,
266  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
267  nullptr,
268  nullptr,
269  nullptr,
270  0},
271  {"gs",
272  nullptr,
273  4,
274  0,
276  eFormatHex,
278  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
279  nullptr,
280  nullptr,
281  nullptr,
282  0},
283  {"stmm0",
284  nullptr,
285  10,
286  0,
290  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
291  nullptr,
292  nullptr,
293  nullptr,
294  0},
295  {"stmm1",
296  nullptr,
297  10,
298  0,
302  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
303  nullptr,
304  nullptr,
305  nullptr,
306  0},
307  {"stmm2",
308  nullptr,
309  10,
310  0,
314  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
315  nullptr,
316  nullptr,
317  nullptr,
318  0},
319  {"stmm3",
320  nullptr,
321  10,
322  0,
326  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
327  nullptr,
328  nullptr,
329  nullptr,
330  0},
331  {"stmm4",
332  nullptr,
333  10,
334  0,
338  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
339  nullptr,
340  nullptr,
341  nullptr,
342  0},
343  {"stmm5",
344  nullptr,
345  10,
346  0,
350  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
351  nullptr,
352  nullptr,
353  nullptr,
354  0},
355  {"stmm6",
356  nullptr,
357  10,
358  0,
362  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
363  nullptr,
364  nullptr,
365  nullptr,
366  0},
367  {"stmm7",
368  nullptr,
369  10,
370  0,
374  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
375  nullptr,
376  nullptr,
377  nullptr,
378  0},
379  {"fctrl",
380  nullptr,
381  4,
382  0,
384  eFormatHex,
386  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
387  nullptr,
388  nullptr,
389  nullptr,
390  0},
391  {"fstat",
392  nullptr,
393  4,
394  0,
396  eFormatHex,
398  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
399  nullptr,
400  nullptr,
401  nullptr,
402  0},
403  {"ftag",
404  nullptr,
405  4,
406  0,
408  eFormatHex,
410  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
411  nullptr,
412  nullptr,
413  nullptr,
414  0},
415  {"fiseg",
416  nullptr,
417  4,
418  0,
420  eFormatHex,
422  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
423  nullptr,
424  nullptr,
425  nullptr,
426  0},
427  {"fioff",
428  nullptr,
429  4,
430  0,
432  eFormatHex,
434  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
435  nullptr,
436  nullptr,
437  nullptr,
438  0},
439  {"foseg",
440  nullptr,
441  4,
442  0,
444  eFormatHex,
446  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
447  nullptr,
448  nullptr,
449  nullptr,
450  0},
451  {"fooff",
452  nullptr,
453  4,
454  0,
456  eFormatHex,
458  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
459  nullptr,
460  nullptr,
461  nullptr,
462  0},
463  {"fop",
464  nullptr,
465  4,
466  0,
468  eFormatHex,
470  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
471  nullptr,
472  nullptr,
473  nullptr,
474  0},
475  {"xmm0",
476  nullptr,
477  16,
478  0,
482  LLDB_INVALID_REGNUM},
483  nullptr,
484  nullptr,
485  nullptr,
486  0},
487  {"xmm1",
488  nullptr,
489  16,
490  0,
494  LLDB_INVALID_REGNUM},
495  nullptr,
496  nullptr,
497  nullptr,
498  0},
499  {"xmm2",
500  nullptr,
501  16,
502  0,
506  LLDB_INVALID_REGNUM},
507  nullptr,
508  nullptr,
509  nullptr,
510  0},
511  {"xmm3",
512  nullptr,
513  16,
514  0,
518  LLDB_INVALID_REGNUM},
519  nullptr,
520  nullptr,
521  nullptr,
522  0},
523  {"xmm4",
524  nullptr,
525  16,
526  0,
530  LLDB_INVALID_REGNUM},
531  nullptr,
532  nullptr,
533  nullptr,
534  0},
535  {"xmm5",
536  nullptr,
537  16,
538  0,
542  LLDB_INVALID_REGNUM},
543  nullptr,
544  nullptr,
545  nullptr,
546  0},
547  {"xmm6",
548  nullptr,
549  16,
550  0,
554  LLDB_INVALID_REGNUM},
555  nullptr,
556  nullptr,
557  nullptr,
558  0},
559  {"xmm7",
560  nullptr,
561  16,
562  0,
566  LLDB_INVALID_REGNUM},
567  nullptr,
568  nullptr,
569  nullptr,
570  0},
571  {"mxcsr",
572  nullptr,
573  4,
574  0,
576  eFormatHex,
578  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
579  nullptr,
580  nullptr,
581  nullptr,
582  0},
583  {"ymm0",
584  nullptr,
585  32,
586  0,
590  LLDB_INVALID_REGNUM},
591  nullptr,
592  nullptr,
593  nullptr,
594  0},
595  {"ymm1",
596  nullptr,
597  32,
598  0,
602  LLDB_INVALID_REGNUM},
603  nullptr,
604  nullptr,
605  nullptr,
606  0},
607  {"ymm2",
608  nullptr,
609  32,
610  0,
614  LLDB_INVALID_REGNUM},
615  nullptr,
616  nullptr,
617  nullptr,
618  0},
619  {"ymm3",
620  nullptr,
621  32,
622  0,
626  LLDB_INVALID_REGNUM},
627  nullptr,
628  nullptr,
629  nullptr,
630  0},
631  {"ymm4",
632  nullptr,
633  32,
634  0,
638  LLDB_INVALID_REGNUM},
639  nullptr,
640  nullptr,
641  nullptr,
642  0},
643  {"ymm5",
644  nullptr,
645  32,
646  0,
650  LLDB_INVALID_REGNUM},
651  nullptr,
652  nullptr,
653  nullptr,
654  0},
655  {"ymm6",
656  nullptr,
657  32,
658  0,
662  LLDB_INVALID_REGNUM},
663  nullptr,
664  nullptr,
665  nullptr,
666  0},
667  {"ymm7",
668  nullptr,
669  32,
670  0,
674  LLDB_INVALID_REGNUM},
675  nullptr,
676  nullptr,
677  nullptr,
678  0}};
679 
681  llvm::array_lengthof(g_register_infos);
683 
684 const lldb_private::RegisterInfo *
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.
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 =
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 
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(
726  uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
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 
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()) {
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
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 
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 
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 
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 
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);
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 
1111  PluginManager::RegisterPlugin(
1112  GetPluginNameStatic(), "Mac OS X ABI for i386 targets", CreateInstance);
1113 }
1114 
1116  PluginManager::UnregisterPlugin(CreateInstance);
1117 }
1118 
1120  static ConstString g_short_name("abi.macosx-i386");
1121  return g_short_name;
1122 }
1123 
1124 // PluginInterface protocol
1125 
1127  return GetPluginNameStatic();
1128 }
1129 
static void Terminate()
#define LLDB_REGNUM_GENERIC_PC
Definition: lldb-defines.h:63
An data extractor class.
Definition: DataExtractor.h:47
void SetSourceName(const char *)
Definition: UnwindPlan.cpp:542
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
static lldb::ABISP CreateInstance(lldb::ProcessSP process_sp, const lldb_private::ArchSpec &arch)
#define LLDB_REGNUM_GENERIC_ARG4
Definition: lldb-defines.h:74
bool IsIntegerOrEnumerationType(bool &is_signed) const
uint64_t GetSP(uint64_t fail_value=LLDB_INVALID_ADDRESS)
lldb_private::ConstString GetPluginName() override
uint32_t GetPluginVersion() override
virtual uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num)=0
Convert from a given register numbering scheme to the lldb register numbering scheme.
An architecture specification class.
Definition: ArchSpec.h:32
#define LLDB_REGNUM_GENERIC_ARG2
Definition: lldb-defines.h:70
Value * GetValueAtIndex(size_t idx)
Definition: Value.cpp:701
#define LLDB_REGNUM_GENERIC_SP
Definition: lldb-defines.h:64
virtual Status WriteRegisterValueToMemory(const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len, const RegisterValue &reg_value)
#define LLDB_REGNUM_GENERIC_ARG1
Definition: lldb-defines.h:68
bool IsPointerType(CompilerType *pointee_type=nullptr) const
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:431
bool PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, lldb::addr_t func_addr, lldb::addr_t return_addr, llvm::ArrayRef< lldb::addr_t > args) const override
#define LLDB_REGNUM_GENERIC_FP
Definition: lldb-defines.h:65
bool IsFloatingPointType(uint32_t &count, bool &is_complex) const
lldb_private::Status SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override
static lldb_private::ConstString GetPluginNameStatic()
bool GetArgumentValues(lldb_private::Thread &thread, lldb_private::ValueList &values) const override
uint64_t offset_t
Definition: lldb-types.h:87
static RegisterInfo g_register_infos[]
std::shared_ptr< Row > RowSP
Definition: UnwindPlan.h:366
void AppendRow(const RowSP &row_sp)
Definition: UnwindPlan.cpp:355
bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info)
virtual lldb::RegisterContextSP GetRegisterContext()=0
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:241
A plug-in interface definition class for debugging a process.
Definition: Process.h:353
size_t GetRedZoneSize() const override
#define LLDB_REGNUM_GENERIC_FLAGS
Definition: lldb-defines.h:67
const RegisterInfo * GetRegisterInfoByName(llvm::StringRef reg_name, uint32_t start_idx=0)
const CompilerType & GetCompilerType()
Definition: Value.cpp:239
void SetRegisterKind(lldb::RegisterKind kind)
Definition: UnwindPlan.h:408
void SetUInt32(uint32_t uint, Type t=eTypeUInt32)
bool WriteRegisterFromUnsigned(uint32_t reg, uint64_t uval)
lldb::ProcessSP GetProcess() const
Definition: Thread.h:154
const lldb_private::RegisterInfo * GetRegisterInfoArray(uint32_t &count) override
static bool g_register_info_names_constified
static const uint32_t k_num_register_infos
bool CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override
bool CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override
void SetUnwindPlanValidAtAllInstructions(lldb_private::LazyBool valid_at_all_insn)
Definition: UnwindPlan.h:461
uint64_t addr_t
Definition: lldb-types.h:83
bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override
A uniqued constant string class.
Definition: ConstString.h:38
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:247
llvm::Optional< uint64_t > GetBitSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bits.
uint32_t GetMaxU32(lldb::offset_t *offset_ptr, size_t byte_size) const
Extract an integer of size byte_size from *offset_ptr.
#define LLDB_REGNUM_GENERIC_ARG3
Definition: lldb-defines.h:72
Definition: SBAddress.h:15
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
Definition: Status.cpp:255
void SetCompilerType(const CompilerType &compiler_type)
Definition: Value.cpp:268
const Scalar & GetScalar() const
Definition: Value.h:178
static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width, bool is_signed, Process *process, addr_t &current_stack_argument)
size_t ReadScalarIntegerFromMemory(lldb::addr_t addr, uint32_t byte_size, bool is_signed, Scalar &scalar, Status &error)
Definition: Process.cpp:2302
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:130
virtual lldb::StackFrameSP GetStackFrameAtIndex(uint32_t idx)
Definition: Thread.h:395
void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler)
Definition: UnwindPlan.h:449
lldb::ValueObjectSP GetReturnValueObjectImpl(lldb_private::Thread &thread, lldb_private::CompilerType &ast_type) const override
static void Initialize()
An error handling class.
Definition: Status.h:44
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:90