1//===-- ABISysV_i386.cpp --------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//===----------------------------------------------------------------------===//
7
8#include "ABISysV_i386.h"
9
10#include "llvm/ADT/STLExtras.h"
11#include "llvm/TargetParser/Triple.h"
12
13#include "lldb/Core/Module.h"
14#include "lldb/Core/PluginManager.h"
15#include "lldb/Core/Value.h"
16#include "lldb/Core/ValueObjectConstResult.h"
17#include "lldb/Core/ValueObjectMemory.h"
18#include "lldb/Core/ValueObjectRegister.h"
19#include "lldb/Symbol/UnwindPlan.h"
20#include "lldb/Target/Process.h"
21#include "lldb/Target/RegisterContext.h"
22#include "lldb/Target/StackFrame.h"
23#include "lldb/Target/Target.h"
24#include "lldb/Target/Thread.h"
25#include "lldb/Utility/ConstString.h"
26#include "lldb/Utility/DataExtractor.h"
27#include "lldb/Utility/Log.h"
28#include "lldb/Utility/RegisterValue.h"
29#include "lldb/Utility/Status.h"
30#include <optional>
31
32using namespace lldb;
33using namespace lldb_private;
34
35LLDB_PLUGIN_DEFINE(ABISysV_i386)
36
37//   This source file uses the following document as a reference:
38//====================================================================
39//             System V Application Binary Interface
40//    Intel386 Architecture Processor Supplement, Version 1.0
41//                         Edited by
42//      H.J. Lu, David L Kreitzer, Milind Girkar, Zia Ansari
43//
44//                        (Based on
45//           System V Application Binary Interface,
46//          AMD64 Architecture Processor Supplement,
47//                         Edited by
48//     H.J. Lu, Michael Matz, Milind Girkar, Jan Hubicka,
49//               Andreas Jaeger, Mark Mitchell)
50//
51//                     February 3, 2015
52//====================================================================
53
54// DWARF Register Number Mapping
55// See Table 2.14 of the reference document (specified on top of this file)
56// Comment: Table 2.14 is followed till 'mm' entries. After that, all entries
57// are ignored here.
58
59enum dwarf_regnums {
60  dwarf_eax = 0,
61  dwarf_ecx,
62  dwarf_edx,
63  dwarf_ebx,
64  dwarf_esp,
65  dwarf_ebp,
66  dwarf_esi,
67  dwarf_edi,
68  dwarf_eip,
69};
70
71// Static Functions
72
73ABISP
74ABISysV_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
75  if (arch.GetTriple().getVendor() != llvm::Triple::Apple) {
76    if (arch.GetTriple().getArch() == llvm::Triple::x86) {
77      return ABISP(
78          new ABISysV_i386(std::move(process_sp), MakeMCRegisterInfo(arch)));
79    }
80  }
81  return ABISP();
82}
83
84bool ABISysV_i386::PrepareTrivialCall(Thread &thread, addr_t sp,
85                                      addr_t func_addr, addr_t return_addr,
86                                      llvm::ArrayRef<addr_t> args) const {
87  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
88
89  if (!reg_ctx)
90    return false;
91
92  uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
93      eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
94  uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
95      eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
96
97  // While using register info to write a register value to memory, the
98  // register info just needs to have the correct size of a 32 bit register,
99  // the actual register it pertains to is not important, just the size needs
100  // to be correct. "eax" is used here for this purpose.
101  const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
102  if (!reg_info_32)
103    return false; // TODO this should actually never happen
104
105  Status error;
106  RegisterValue reg_value;
107
108  // Make room for the argument(s) on the stack
109  sp -= 4 * args.size();
110
111  // SP Alignment
112  sp &= ~(16ull - 1ull); // 16-byte alignment
113
114  // Write arguments onto the stack
115  addr_t arg_pos = sp;
116  for (addr_t arg : args) {
117    reg_value.SetUInt32(arg);
118    error = reg_ctx->WriteRegisterValueToMemory(
119        reg_info_32, arg_pos, reg_info_32->byte_size, reg_value);
120    if (error.Fail())
121      return false;
122    arg_pos += 4;
123  }
124
125  // The return address is pushed onto the stack
126  sp -= 4;
127  reg_value.SetUInt32(return_addr);
128  error = reg_ctx->WriteRegisterValueToMemory(
129      reg_info_32, sp, reg_info_32->byte_size, reg_value);
130  if (error.Fail())
131    return false;
132
133  // Setting %esp to the actual stack value.
134  if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp))
135    return false;
136
137  // Setting %eip to the address of the called function.
138  if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr))
139    return false;
140
141  return true;
142}
143
144static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width,
145                                bool is_signed, Process *process,
146                                addr_t &current_stack_argument) {
147  uint32_t byte_size = (bit_width + (8 - 1)) / 8;
148  Status error;
149
150  if (!process)
151    return false;
152
153  if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size,
154                                           is_signed, scalar, error)) {
155    current_stack_argument += byte_size;
156    return true;
157  }
158  return false;
159}
160
161bool ABISysV_i386::GetArgumentValues(Thread &thread, ValueList &values) const {
162  unsigned int num_values = values.GetSize();
163  unsigned int value_index;
164
165  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
166
167  if (!reg_ctx)
168    return false;
169
170  // Get pointer to the first stack argument
171  addr_t sp = reg_ctx->GetSP(0);
172  if (!sp)
173    return false;
174
175  addr_t current_stack_argument = sp + 4; // jump over return address
176
177  for (value_index = 0; value_index < num_values; ++value_index) {
178    Value *value = values.GetValueAtIndex(value_index);
179
180    if (!value)
181      return false;
182
183    // Currently: Support for extracting values with Clang QualTypes only.
184    CompilerType compiler_type(value->GetCompilerType());
185    std::optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
186    if (bit_size) {
187      bool is_signed;
188      if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
189        ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed,
190                            thread.GetProcess().get(), current_stack_argument);
191      } else if (compiler_type.IsPointerType()) {
192        ReadIntegerArgument(value->GetScalar(), *bit_size, false,
193                            thread.GetProcess().get(), current_stack_argument);
194      }
195    }
196  }
197  return true;
198}
199
200Status ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
201                                          lldb::ValueObjectSP &new_value_sp) {
202  Status error;
203  if (!new_value_sp) {
204    error.SetErrorString("Empty value object for return value.");
205    return error;
206  }
207
208  CompilerType compiler_type = new_value_sp->GetCompilerType();
209  if (!compiler_type) {
210    error.SetErrorString("Null clang type for return value.");
211    return error;
212  }
213
214  const uint32_t type_flags = compiler_type.GetTypeInfo();
215  Thread *thread = frame_sp->GetThread().get();
216  RegisterContext *reg_ctx = thread->GetRegisterContext().get();
217  DataExtractor data;
218  Status data_error;
219  size_t num_bytes = new_value_sp->GetData(data, data_error);
220  bool register_write_successful = true;
221
222  if (data_error.Fail()) {
223    error.SetErrorStringWithFormat(
224        "Couldn't convert return value to raw data: %s",
225        data_error.AsCString());
226    return error;
227  }
228
229  // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
230  // The terminology 'Fundamental Data Types' used here is adopted from Table
231  // 2.1 of the reference document (specified on top of this file)
232
233  if (type_flags & eTypeIsPointer) // 'Pointer'
234  {
235    if (num_bytes != sizeof(uint32_t)) {
236      error.SetErrorString("Pointer to be returned is not 4 bytes wide");
237      return error;
238    }
239    lldb::offset_t offset = 0;
240    const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
241    uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
242    register_write_successful =
243        reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
244  } else if ((type_flags & eTypeIsScalar) ||
245             (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
246  {
247    lldb::offset_t offset = 0;
248    const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
249
250    if (type_flags & eTypeIsInteger) // 'Integral' except enum
251    {
252      switch (num_bytes) {
253      default:
254        break;
255      case 16:
256        // For clang::BuiltinType::UInt128 & Int128 ToDo: Need to decide how to
257        // handle it
258        break;
259      case 8: {
260        uint32_t raw_value_low = data.GetMaxU32(&offset, 4);
261        const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0);
262        uint32_t raw_value_high = data.GetMaxU32(&offset, num_bytes - offset);
263        register_write_successful =
264            (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value_low) &&
265             reg_ctx->WriteRegisterFromUnsigned(edx_info, raw_value_high));
266        break;
267      }
268      case 4:
269      case 2:
270      case 1: {
271        uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
272        register_write_successful =
273            reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
274        break;
275      }
276      }
277    } else if (type_flags & eTypeIsEnumeration) // handles enum
278    {
279      uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
280      register_write_successful =
281          reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
282    } else if (type_flags & eTypeIsFloat) // 'Floating Point'
283    {
284      RegisterValue st0_value, fstat_value, ftag_value;
285      const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
286      const RegisterInfo *fstat_info =
287          reg_ctx->GetRegisterInfoByName("fstat", 0);
288      const RegisterInfo *ftag_info = reg_ctx->GetRegisterInfoByName("ftag", 0);
289
290      /* According to Page 3-12 of document
291      System V Application Binary Interface, Intel386 Architecture Processor
292      Supplement, Fourth Edition
293      To return Floating Point values, all st% registers except st0 should be
294      empty after exiting from
295      a function. This requires setting fstat and ftag registers to specific
296      values.
297      fstat: The TOP field of fstat should be set to a value [0,7]. ABI doesn't
298      specify the specific
299      value of TOP in case of function return. Hence, we set the TOP field to 7
300      by our choice. */
301      uint32_t value_fstat_u32 = 0x00003800;
302
303      /* ftag: Implication of setting TOP to 7 and indicating all st% registers
304      empty except st0 is to set
305      7th bit of 4th byte of FXSAVE area to 1 and all other bits of this byte to
306      0. This is in accordance
307      with the document Intel 64 and IA-32 Architectures Software Developer's
308      Manual, January 2015 */
309      uint32_t value_ftag_u32 = 0x00000080;
310
311      if (num_bytes <= 12) // handles float, double, long double, __float80
312      {
313        long double value_long_dbl = 0.0;
314        if (num_bytes == 4)
315          value_long_dbl = data.GetFloat(&offset);
316        else if (num_bytes == 8)
317          value_long_dbl = data.GetDouble(&offset);
318        else if (num_bytes == 12)
319          value_long_dbl = data.GetLongDouble(&offset);
320        else {
321          error.SetErrorString("Invalid number of bytes for this return type");
322          return error;
323        }
324        st0_value.SetLongDouble(value_long_dbl);
325        fstat_value.SetUInt32(value_fstat_u32);
326        ftag_value.SetUInt32(value_ftag_u32);
327        register_write_successful =
328            reg_ctx->WriteRegister(st0_info, st0_value) &&
329            reg_ctx->WriteRegister(fstat_info, fstat_value) &&
330            reg_ctx->WriteRegister(ftag_info, ftag_value);
331      } else if (num_bytes == 16) // handles __float128
332      {
333        error.SetErrorString("Implementation is missing for this clang type.");
334      }
335    } else {
336      // Neither 'Integral' nor 'Floating Point'. If flow reaches here then
337      // check type_flags. This type_flags is not a valid type.
338      error.SetErrorString("Invalid clang type");
339    }
340  } else {
341    /* 'Complex Floating Point', 'Packed', 'Decimal Floating Point' and
342    'Aggregate' data types
343    are yet to be implemented */
344    error.SetErrorString("Currently only Integral and Floating Point clang "
345                         "types are supported.");
346  }
347  if (!register_write_successful)
348    error.SetErrorString("Register writing failed");
349  return error;
350}
351
352ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
353    Thread &thread, CompilerType &return_compiler_type) const {
354  ValueObjectSP return_valobj_sp;
355  Value value;
356
357  if (!return_compiler_type)
358    return return_valobj_sp;
359
360  value.SetCompilerType(return_compiler_type);
361
362  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
363  if (!reg_ctx)
364    return return_valobj_sp;
365
366  const uint32_t type_flags = return_compiler_type.GetTypeInfo();
367
368  unsigned eax_id =
369      reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
370  unsigned edx_id =
371      reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
372
373  // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
374  // The terminology 'Fundamental Data Types' used here is adopted from Table
375  // 2.1 of the reference document (specified on top of this file)
376
377  if (type_flags & eTypeIsPointer) // 'Pointer'
378  {
379    uint32_t ptr =
380        thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
381        0xffffffff;
382    value.SetValueType(Value::ValueType::Scalar);
383    value.GetScalar() = ptr;
384    return_valobj_sp = ValueObjectConstResult::Create(
385        thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
386  } else if ((type_flags & eTypeIsScalar) ||
387             (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
388  {
389    value.SetValueType(Value::ValueType::Scalar);
390    std::optional<uint64_t> byte_size =
391        return_compiler_type.GetByteSize(&thread);
392    if (!byte_size)
393      return return_valobj_sp;
394    bool success = false;
395
396    if (type_flags & eTypeIsInteger) // 'Integral' except enum
397    {
398      const bool is_signed = ((type_flags & eTypeIsSigned) != 0);
399      uint64_t raw_value =
400          thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
401          0xffffffff;
402      raw_value |=
403          (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) &
404           0xffffffff)
405          << 32;
406
407      switch (*byte_size) {
408      default:
409        break;
410
411      case 16:
412        // For clang::BuiltinType::UInt128 & Int128 ToDo: Need to decide how to
413        // handle it
414        break;
415
416      case 8:
417        if (is_signed)
418          value.GetScalar() = (int64_t)(raw_value);
419        else
420          value.GetScalar() = (uint64_t)(raw_value);
421        success = true;
422        break;
423
424      case 4:
425        if (is_signed)
426          value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
427        else
428          value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
429        success = true;
430        break;
431
432      case 2:
433        if (is_signed)
434          value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
435        else
436          value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
437        success = true;
438        break;
439
440      case 1:
441        if (is_signed)
442          value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
443        else
444          value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
445        success = true;
446        break;
447      }
448
449      if (success)
450        return_valobj_sp = ValueObjectConstResult::Create(
451            thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
452    } else if (type_flags & eTypeIsEnumeration) // handles enum
453    {
454      uint32_t enm =
455          thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
456          0xffffffff;
457      value.SetValueType(Value::ValueType::Scalar);
458      value.GetScalar() = enm;
459      return_valobj_sp = ValueObjectConstResult::Create(
460          thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
461    } else if (type_flags & eTypeIsFloat) // 'Floating Point'
462    {
463      if (*byte_size <= 12) // handles float, double, long double, __float80
464      {
465        const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
466        RegisterValue st0_value;
467
468        if (reg_ctx->ReadRegister(st0_info, st0_value)) {
469          DataExtractor data;
470          if (st0_value.GetData(data)) {
471            lldb::offset_t offset = 0;
472            long double value_long_double = data.GetLongDouble(&offset);
473
474            // float is 4 bytes.
475            if (*byte_size == 4) {
476              float value_float = (float)value_long_double;
477              value.GetScalar() = value_float;
478              success = true;
479            } else if (*byte_size == 8) {
480              // double is 8 bytes
481              // On Android Platform: long double is also 8 bytes It will be
482              // handled here only.
483              double value_double = (double)value_long_double;
484              value.GetScalar() = value_double;
485              success = true;
486            } else if (*byte_size == 12) {
487              // long double and __float80 are 12 bytes on i386.
488              value.GetScalar() = value_long_double;
489              success = true;
490            }
491          }
492        }
493
494        if (success)
495          return_valobj_sp = ValueObjectConstResult::Create(
496              thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
497      } else if (*byte_size == 16) // handles __float128
498      {
499        lldb::addr_t storage_addr = (uint32_t)(
500            thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
501            0xffffffff);
502        return_valobj_sp = ValueObjectMemory::Create(
503            &thread, "", Address(storage_addr, nullptr), return_compiler_type);
504      }
505    } else // Neither 'Integral' nor 'Floating Point'
506    {
507      // If flow reaches here then check type_flags This type_flags is
508      // unhandled
509    }
510  } else if (type_flags & eTypeIsComplex) // 'Complex Floating Point'
511  {
512    // ToDo: Yet to be implemented
513  } else if (type_flags & eTypeIsVector) // 'Packed'
514  {
515    std::optional<uint64_t> byte_size =
516        return_compiler_type.GetByteSize(&thread);
517    if (byte_size && *byte_size > 0) {
518      const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
519      if (vec_reg == nullptr)
520        vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
521
522      if (vec_reg) {
523        if (*byte_size <= vec_reg->byte_size) {
524          ProcessSP process_sp(thread.GetProcess());
525          if (process_sp) {
526            std::unique_ptr<DataBufferHeap> heap_data_up(
527                new DataBufferHeap(*byte_size, 0));
528            const ByteOrder byte_order = process_sp->GetByteOrder();
529            RegisterValue reg_value;
530            if (reg_ctx->ReadRegister(vec_reg, reg_value)) {
531              Status error;
532              if (reg_value.GetAsMemoryData(*vec_reg, heap_data_up->GetBytes(),
533                                            heap_data_up->GetByteSize(),
534                                            byte_order, error)) {
535                DataExtractor data(DataBufferSP(heap_data_up.release()),
536                                   byte_order,
537                                   process_sp->GetTarget()
538                                       .GetArchitecture()
539                                       .GetAddressByteSize());
540                return_valobj_sp = ValueObjectConstResult::Create(
541                    &thread, return_compiler_type, ConstString(""), data);
542              }
543            }
544          }
545        } else if (*byte_size <= vec_reg->byte_size * 2) {
546          const RegisterInfo *vec_reg2 =
547              reg_ctx->GetRegisterInfoByName("xmm1", 0);
548          if (vec_reg2) {
549            ProcessSP process_sp(thread.GetProcess());
550            if (process_sp) {
551              std::unique_ptr<DataBufferHeap> heap_data_up(
552                  new DataBufferHeap(*byte_size, 0));
553              const ByteOrder byte_order = process_sp->GetByteOrder();
554              RegisterValue reg_value;
555              RegisterValue reg_value2;
556              if (reg_ctx->ReadRegister(vec_reg, reg_value) &&
557                  reg_ctx->ReadRegister(vec_reg2, reg_value2)) {
558
559                Status error;
560                if (reg_value.GetAsMemoryData(
561                        *vec_reg, heap_data_up->GetBytes(), vec_reg->byte_size,
562                        byte_order, error) &&
563                    reg_value2.GetAsMemoryData(
564                        *vec_reg2,
565                        heap_data_up->GetBytes() + vec_reg->byte_size,
566                        heap_data_up->GetByteSize() - vec_reg->byte_size,
567                        byte_order, error)) {
568                  DataExtractor data(DataBufferSP(heap_data_up.release()),
569                                     byte_order,
570                                     process_sp->GetTarget()
571                                         .GetArchitecture()
572                                         .GetAddressByteSize());
573                  return_valobj_sp = ValueObjectConstResult::Create(
574                      &thread, return_compiler_type, ConstString(""), data);
575                }
576              }
577            }
578          }
579        }
580      }
581    }
582  } else // 'Decimal Floating Point'
583  {
584    // ToDo: Yet to be implemented
585  }
586  return return_valobj_sp;
587}
588
589ValueObjectSP ABISysV_i386::GetReturnValueObjectImpl(
590    Thread &thread, CompilerType &return_compiler_type) const {
591  ValueObjectSP return_valobj_sp;
592
593  if (!return_compiler_type)
594    return return_valobj_sp;
595
596  ExecutionContext exe_ctx(thread.shared_from_this());
597  return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
598  if (return_valobj_sp)
599    return return_valobj_sp;
600
601  RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
602  if (!reg_ctx_sp)
603    return return_valobj_sp;
604
605  if (return_compiler_type.IsAggregateType()) {
606    unsigned eax_id =
607        reg_ctx_sp->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
608    lldb::addr_t storage_addr = (uint32_t)(
609        thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
610        0xffffffff);
611    return_valobj_sp = ValueObjectMemory::Create(
612        &thread, "", Address(storage_addr, nullptr), return_compiler_type);
613  }
614
615  return return_valobj_sp;
616}
617
618// This defines CFA as esp+4
619// The saved pc is at CFA-4 (i.e. esp+0)
620// The saved esp is CFA+0
621
622bool ABISysV_i386::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
623  unwind_plan.Clear();
624  unwind_plan.SetRegisterKind(eRegisterKindDWARF);
625
626  uint32_t sp_reg_num = dwarf_esp;
627  uint32_t pc_reg_num = dwarf_eip;
628
629  UnwindPlan::RowSP row(new UnwindPlan::Row);
630  row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4);
631  row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
632  row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
633  unwind_plan.AppendRow(row);
634  unwind_plan.SetSourceName("i386 at-func-entry default");
635  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
636  return true;
637}
638
639// This defines CFA as ebp+8
640// The saved pc is at CFA-4 (i.e. ebp+4)
641// The saved ebp is at CFA-8 (i.e. ebp+0)
642// The saved esp is CFA+0
643
644bool ABISysV_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
645  unwind_plan.Clear();
646  unwind_plan.SetRegisterKind(eRegisterKindDWARF);
647
648  uint32_t fp_reg_num = dwarf_ebp;
649  uint32_t sp_reg_num = dwarf_esp;
650  uint32_t pc_reg_num = dwarf_eip;
651
652  UnwindPlan::RowSP row(new UnwindPlan::Row);
653  const int32_t ptr_size = 4;
654
655  row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
656  row->SetOffset(0);
657  row->SetUnspecifiedRegistersAreUndefined(true);
658
659  row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
660  row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
661  row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
662
663  unwind_plan.AppendRow(row);
664  unwind_plan.SetSourceName("i386 default unwind plan");
665  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
666  unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
667  unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
668  return true;
669}
670
671// According to "Register Usage" in reference document (specified on top of
672// this source file) ebx, ebp, esi, edi and esp registers are preserved i.e.
673// non-volatile i.e. callee-saved on i386
674bool ABISysV_i386::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
675  if (!reg_info)
676    return false;
677
678  // Saved registers are ebx, ebp, esi, edi, esp, eip
679  const char *name = reg_info->name;
680  if (name[0] == 'e') {
681    switch (name[1]) {
682    case 'b':
683      if (name[2] == 'x' || name[2] == 'p')
684        return name[3] == '\0';
685      break;
686    case 'd':
687      if (name[2] == 'i')
688        return name[3] == '\0';
689      break;
690    case 'i':
691      if (name[2] == 'p')
692        return name[3] == '\0';
693      break;
694    case 's':
695      if (name[2] == 'i' || name[2] == 'p')
696        return name[3] == '\0';
697      break;
698    }
699  }
700
701  if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
702    return true;
703  if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
704    return true;
705  if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
706    return true;
707
708  return false;
709}
710
711void ABISysV_i386::Initialize() {
712  PluginManager::RegisterPlugin(
713      GetPluginNameStatic(), "System V ABI for i386 targets", CreateInstance);
714}
715
716void ABISysV_i386::Terminate() {
717  PluginManager::UnregisterPlugin(CreateInstance);
718}
719