Coverage Report

Created: 2022-07-16 07:03

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