Coverage Report

Created: 2023-09-30 09:22

/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/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
32
using namespace lldb;
33
using namespace lldb_private;
34
35
LLDB_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
59
enum 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
73
ABISP
74
4.66k
ABISysV_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
75
4.66k
  if (arch.GetTriple().getVendor() != llvm::Triple::Apple) {
76
347
    if (arch.GetTriple().getArch() == llvm::Triple::x86) {
77
34
      return ABISP(
78
34
          new ABISysV_i386(std::move(process_sp), MakeMCRegisterInfo(arch)));
79
34
    }
80
347
  }
81
4.63k
  return ABISP();
82
4.66k
}
83
84
bool ABISysV_i386::PrepareTrivialCall(Thread &thread, addr_t sp,
85
                                      addr_t func_addr, addr_t return_addr,
86
0
                                      llvm::ArrayRef<addr_t> args) const {
87
0
  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
88
89
0
  if (!reg_ctx)
90
0
    return false;
91
92
0
  uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
93
0
      eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
94
0
  uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
95
0
      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
0
  const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
102
0
  if (!reg_info_32)
103
0
    return false; // TODO this should actually never happen
104
105
0
  Status error;
106
0
  RegisterValue reg_value;
107
108
  // Make room for the argument(s) on the stack
109
0
  sp -= 4 * args.size();
110
111
  // SP Alignment
112
0
  sp &= ~(16ull - 1ull); // 16-byte alignment
113
114
  // Write arguments onto the stack
115
0
  addr_t arg_pos = sp;
116
0
  for (addr_t arg : args) {
117
0
    reg_value.SetUInt32(arg);
118
0
    error = reg_ctx->WriteRegisterValueToMemory(
119
0
        reg_info_32, arg_pos, reg_info_32->byte_size, reg_value);
120
0
    if (error.Fail())
121
0
      return false;
122
0
    arg_pos += 4;
123
0
  }
124
125
  // The return address is pushed onto the stack
126
0
  sp -= 4;
127
0
  reg_value.SetUInt32(return_addr);
128
0
  error = reg_ctx->WriteRegisterValueToMemory(
129
0
      reg_info_32, sp, reg_info_32->byte_size, reg_value);
130
0
  if (error.Fail())
131
0
    return false;
132
133
  // Setting %esp to the actual stack value.
134
0
  if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp))
135
0
    return false;
136
137
  // Setting %eip to the address of the called function.
138
0
  if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr))
139
0
    return false;
140
141
0
  return true;
142
0
}
143
144
static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width,
145
                                bool is_signed, Process *process,
146
0
                                addr_t &current_stack_argument) {
147
0
  uint32_t byte_size = (bit_width + (8 - 1)) / 8;
148
0
  Status error;
149
150
0
  if (!process)
151
0
    return false;
152
153
0
  if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size,
154
0
                                           is_signed, scalar, error)) {
155
0
    current_stack_argument += byte_size;
156
0
    return true;
157
0
  }
158
0
  return false;
159
0
}
160
161
0
bool ABISysV_i386::GetArgumentValues(Thread &thread, ValueList &values) const {
162
0
  unsigned int num_values = values.GetSize();
163
0
  unsigned int value_index;
164
165
0
  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
166
167
0
  if (!reg_ctx)
168
0
    return false;
169
170
  // Get pointer to the first stack argument
171
0
  addr_t sp = reg_ctx->GetSP(0);
172
0
  if (!sp)
173
0
    return false;
174
175
0
  addr_t current_stack_argument = sp + 4; // jump over return address
176
177
0
  for (value_index = 0; value_index < num_values; ++value_index) {
178
0
    Value *value = values.GetValueAtIndex(value_index);
179
180
0
    if (!value)
181
0
      return false;
182
183
    // Currently: Support for extracting values with Clang QualTypes only.
184
0
    CompilerType compiler_type(value->GetCompilerType());
185
0
    std::optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
186
0
    if (bit_size) {
187
0
      bool is_signed;
188
0
      if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
189
0
        ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed,
190
0
                            thread.GetProcess().get(), current_stack_argument);
191
0
      } else if (compiler_type.IsPointerType()) {
192
0
        ReadIntegerArgument(value->GetScalar(), *bit_size, false,
193
0
                            thread.GetProcess().get(), current_stack_argument);
194
0
      }
195
0
    }
196
0
  }
197
0
  return true;
198
0
}
199
200
Status ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
201
0
                                          lldb::ValueObjectSP &new_value_sp) {
202
0
  Status error;
203
0
  if (!new_value_sp) {
204
0
    error.SetErrorString("Empty value object for return value.");
205
0
    return error;
206
0
  }
207
208
0
  CompilerType compiler_type = new_value_sp->GetCompilerType();
209
0
  if (!compiler_type) {
210
0
    error.SetErrorString("Null clang type for return value.");
211
0
    return error;
212
0
  }
213
214
0
  const uint32_t type_flags = compiler_type.GetTypeInfo();
215
0
  Thread *thread = frame_sp->GetThread().get();
216
0
  RegisterContext *reg_ctx = thread->GetRegisterContext().get();
217
0
  DataExtractor data;
218
0
  Status data_error;
219
0
  size_t num_bytes = new_value_sp->GetData(data, data_error);
220
0
  bool register_write_successful = true;
221
222
0
  if (data_error.Fail()) {
223
0
    error.SetErrorStringWithFormat(
224
0
        "Couldn't convert return value to raw data: %s",
225
0
        data_error.AsCString());
226
0
    return error;
227
0
  }
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
0
  if (type_flags & eTypeIsPointer) // 'Pointer'
234
0
  {
235
0
    if (num_bytes != sizeof(uint32_t)) {
236
0
      error.SetErrorString("Pointer to be returned is not 4 bytes wide");
237
0
      return error;
238
0
    }
239
0
    lldb::offset_t offset = 0;
240
0
    const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
241
0
    uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
242
0
    register_write_successful =
243
0
        reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
244
0
  } else if ((type_flags & eTypeIsScalar) ||
245
0
             (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
246
0
  {
247
0
    lldb::offset_t offset = 0;
248
0
    const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
249
250
0
    if (type_flags & eTypeIsInteger) // 'Integral' except enum
251
0
    {
252
0
      switch (num_bytes) {
253
0
      default:
254
0
        break;
255
0
      case 16:
256
        // For clang::BuiltinType::UInt128 & Int128 ToDo: Need to decide how to
257
        // handle it
258
0
        break;
259
0
      case 8: {
260
0
        uint32_t raw_value_low = data.GetMaxU32(&offset, 4);
261
0
        const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0);
262
0
        uint32_t raw_value_high = data.GetMaxU32(&offset, num_bytes - offset);
263
0
        register_write_successful =
264
0
            (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value_low) &&
265
0
             reg_ctx->WriteRegisterFromUnsigned(edx_info, raw_value_high));
266
0
        break;
267
0
      }
268
0
      case 4:
269
0
      case 2:
270
0
      case 1: {
271
0
        uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
272
0
        register_write_successful =
273
0
            reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
274
0
        break;
275
0
      }
276
0
      }
277
0
    } else if (type_flags & eTypeIsEnumeration) // handles enum
278
0
    {
279
0
      uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
280
0
      register_write_successful =
281
0
          reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
282
0
    } else if (type_flags & eTypeIsFloat) // 'Floating Point'
283
0
    {
284
0
      RegisterValue st0_value, fstat_value, ftag_value;
285
0
      const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
286
0
      const RegisterInfo *fstat_info =
287
0
          reg_ctx->GetRegisterInfoByName("fstat", 0);
288
0
      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
0
      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
0
      uint32_t value_ftag_u32 = 0x00000080;
310
311
0
      if (num_bytes <= 12) // handles float, double, long double, __float80
312
0
      {
313
0
        long double value_long_dbl = 0.0;
314
0
        if (num_bytes == 4)
315
0
          value_long_dbl = data.GetFloat(&offset);
316
0
        else if (num_bytes == 8)
317
0
          value_long_dbl = data.GetDouble(&offset);
318
0
        else if (num_bytes == 12)
319
0
          value_long_dbl = data.GetLongDouble(&offset);
320
0
        else {
321
0
          error.SetErrorString("Invalid number of bytes for this return type");
322
0
          return error;
323
0
        }
324
0
        st0_value.SetLongDouble(value_long_dbl);
325
0
        fstat_value.SetUInt32(value_fstat_u32);
326
0
        ftag_value.SetUInt32(value_ftag_u32);
327
0
        register_write_successful =
328
0
            reg_ctx->WriteRegister(st0_info, st0_value) &&
329
0
            reg_ctx->WriteRegister(fstat_info, fstat_value) &&
330
0
            reg_ctx->WriteRegister(ftag_info, ftag_value);
331
0
      } else if (num_bytes == 16) // handles __float128
332
0
      {
333
0
        error.SetErrorString("Implementation is missing for this clang type.");
334
0
      }
335
0
    } 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
0
      error.SetErrorString("Invalid clang type");
339
0
    }
340
0
  } else {
341
    /* 'Complex Floating Point', 'Packed', 'Decimal Floating Point' and
342
    'Aggregate' data types
343
    are yet to be implemented */
344
0
    error.SetErrorString("Currently only Integral and Floating Point clang "
345
0
                         "types are supported.");
346
0
  }
347
0
  if (!register_write_successful)
348
0
    error.SetErrorString("Register writing failed");
349
0
  return error;
350
0
}
351
352
ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
353
0
    Thread &thread, CompilerType &return_compiler_type) const {
354
0
  ValueObjectSP return_valobj_sp;
355
0
  Value value;
356
357
0
  if (!return_compiler_type)
358
0
    return return_valobj_sp;
359
360
0
  value.SetCompilerType(return_compiler_type);
361
362
0
  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
363
0
  if (!reg_ctx)
364
0
    return return_valobj_sp;
365
366
0
  const uint32_t type_flags = return_compiler_type.GetTypeInfo();
367
368
0
  unsigned eax_id =
369
0
      reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
370
0
  unsigned edx_id =
371
0
      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
0
  if (type_flags & eTypeIsPointer) // 'Pointer'
378
0
  {
379
0
    uint32_t ptr =
380
0
        thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
381
0
        0xffffffff;
382
0
    value.SetValueType(Value::ValueType::Scalar);
383
0
    value.GetScalar() = ptr;
384
0
    return_valobj_sp = ValueObjectConstResult::Create(
385
0
        thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
386
0
  } else if ((type_flags & eTypeIsScalar) ||
387
0
             (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
388
0
  {
389
0
    value.SetValueType(Value::ValueType::Scalar);
390
0
    std::optional<uint64_t> byte_size =
391
0
        return_compiler_type.GetByteSize(&thread);
392
0
    if (!byte_size)
393
0
      return return_valobj_sp;
394
0
    bool success = false;
395
396
0
    if (type_flags & eTypeIsInteger) // 'Integral' except enum
397
0
    {
398
0
      const bool is_signed = ((type_flags & eTypeIsSigned) != 0);
399
0
      uint64_t raw_value =
400
0
          thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
401
0
          0xffffffff;
402
0
      raw_value |=
403
0
          (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) &
404
0
           0xffffffff)
405
0
          << 32;
406
407
0
      switch (*byte_size) {
408
0
      default:
409
0
        break;
410
411
0
      case 16:
412
        // For clang::BuiltinType::UInt128 & Int128 ToDo: Need to decide how to
413
        // handle it
414
0
        break;
415
416
0
      case 8:
417
0
        if (is_signed)
418
0
          value.GetScalar() = (int64_t)(raw_value);
419
0
        else
420
0
          value.GetScalar() = (uint64_t)(raw_value);
421
0
        success = true;
422
0
        break;
423
424
0
      case 4:
425
0
        if (is_signed)
426
0
          value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
427
0
        else
428
0
          value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
429
0
        success = true;
430
0
        break;
431
432
0
      case 2:
433
0
        if (is_signed)
434
0
          value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
435
0
        else
436
0
          value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
437
0
        success = true;
438
0
        break;
439
440
0
      case 1:
441
0
        if (is_signed)
442
0
          value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
443
0
        else
444
0
          value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
445
0
        success = true;
446
0
        break;
447
0
      }
448
449
0
      if (success)
450
0
        return_valobj_sp = ValueObjectConstResult::Create(
451
0
            thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
452
0
    } else if (type_flags & eTypeIsEnumeration) // handles enum
453
0
    {
454
0
      uint32_t enm =
455
0
          thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
456
0
          0xffffffff;
457
0
      value.SetValueType(Value::ValueType::Scalar);
458
0
      value.GetScalar() = enm;
459
0
      return_valobj_sp = ValueObjectConstResult::Create(
460
0
          thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
461
0
    } else if (type_flags & eTypeIsFloat) // 'Floating Point'
462
0
    {
463
0
      if (*byte_size <= 12) // handles float, double, long double, __float80
464
0
      {
465
0
        const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
466
0
        RegisterValue st0_value;
467
468
0
        if (reg_ctx->ReadRegister(st0_info, st0_value)) {
469
0
          DataExtractor data;
470
0
          if (st0_value.GetData(data)) {
471
0
            lldb::offset_t offset = 0;
472
0
            long double value_long_double = data.GetLongDouble(&offset);
473
474
            // float is 4 bytes.
475
0
            if (*byte_size == 4) {
476
0
              float value_float = (float)value_long_double;
477
0
              value.GetScalar() = value_float;
478
0
              success = true;
479
0
            } 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
0
              double value_double = (double)value_long_double;
484
0
              value.GetScalar() = value_double;
485
0
              success = true;
486
0
            } else if (*byte_size == 12) {
487
              // long double and __float80 are 12 bytes on i386.
488
0
              value.GetScalar() = value_long_double;
489
0
              success = true;
490
0
            }
491
0
          }
492
0
        }
493
494
0
        if (success)
495
0
          return_valobj_sp = ValueObjectConstResult::Create(
496
0
              thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
497
0
      } else if (*byte_size == 16) // handles __float128
498
0
      {
499
0
        lldb::addr_t storage_addr = (uint32_t)(
500
0
            thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
501
0
            0xffffffff);
502
0
        return_valobj_sp = ValueObjectMemory::Create(
503
0
            &thread, "", Address(storage_addr, nullptr), return_compiler_type);
504
0
      }
505
0
    } else // Neither 'Integral' nor 'Floating Point'
506
0
    {
507
      // If flow reaches here then check type_flags This type_flags is
508
      // unhandled
509
0
    }
510
0
  } else if (type_flags & eTypeIsComplex) // 'Complex Floating Point'
511
0
  {
512
    // ToDo: Yet to be implemented
513
0
  } else if (type_flags & eTypeIsVector) // 'Packed'
514
0
  {
515
0
    std::optional<uint64_t> byte_size =
516
0
        return_compiler_type.GetByteSize(&thread);
517
0
    if (byte_size && *byte_size > 0) {
518
0
      const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
519
0
      if (vec_reg == nullptr)
520
0
        vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
521
522
0
      if (vec_reg) {
523
0
        if (*byte_size <= vec_reg->byte_size) {
524
0
          ProcessSP process_sp(thread.GetProcess());
525
0
          if (process_sp) {
526
0
            std::unique_ptr<DataBufferHeap> heap_data_up(
527
0
                new DataBufferHeap(*byte_size, 0));
528
0
            const ByteOrder byte_order = process_sp->GetByteOrder();
529
0
            RegisterValue reg_value;
530
0
            if (reg_ctx->ReadRegister(vec_reg, reg_value)) {
531
0
              Status error;
532
0
              if (reg_value.GetAsMemoryData(*vec_reg, heap_data_up->GetBytes(),
533
0
                                            heap_data_up->GetByteSize(),
534
0
                                            byte_order, error)) {
535
0
                DataExtractor data(DataBufferSP(heap_data_up.release()),
536
0
                                   byte_order,
537
0
                                   process_sp->GetTarget()
538
0
                                       .GetArchitecture()
539
0
                                       .GetAddressByteSize());
540
0
                return_valobj_sp = ValueObjectConstResult::Create(
541
0
                    &thread, return_compiler_type, ConstString(""), data);
542
0
              }
543
0
            }
544
0
          }
545
0
        } else if (*byte_size <= vec_reg->byte_size * 2) {
546
0
          const RegisterInfo *vec_reg2 =
547
0
              reg_ctx->GetRegisterInfoByName("xmm1", 0);
548
0
          if (vec_reg2) {
549
0
            ProcessSP process_sp(thread.GetProcess());
550
0
            if (process_sp) {
551
0
              std::unique_ptr<DataBufferHeap> heap_data_up(
552
0
                  new DataBufferHeap(*byte_size, 0));
553
0
              const ByteOrder byte_order = process_sp->GetByteOrder();
554
0
              RegisterValue reg_value;
555
0
              RegisterValue reg_value2;
556
0
              if (reg_ctx->ReadRegister(vec_reg, reg_value) &&
557
0
                  reg_ctx->ReadRegister(vec_reg2, reg_value2)) {
558
559
0
                Status error;
560
0
                if (reg_value.GetAsMemoryData(
561
0
                        *vec_reg, heap_data_up->GetBytes(), vec_reg->byte_size,
562
0
                        byte_order, error) &&
563
0
                    reg_value2.GetAsMemoryData(
564
0
                        *vec_reg2,
565
0
                        heap_data_up->GetBytes() + vec_reg->byte_size,
566
0
                        heap_data_up->GetByteSize() - vec_reg->byte_size,
567
0
                        byte_order, error)) {
568
0
                  DataExtractor data(DataBufferSP(heap_data_up.release()),
569
0
                                     byte_order,
570
0
                                     process_sp->GetTarget()
571
0
                                         .GetArchitecture()
572
0
                                         .GetAddressByteSize());
573
0
                  return_valobj_sp = ValueObjectConstResult::Create(
574
0
                      &thread, return_compiler_type, ConstString(""), data);
575
0
                }
576
0
              }
577
0
            }
578
0
          }
579
0
        }
580
0
      }
581
0
    }
582
0
  } else // 'Decimal Floating Point'
583
0
  {
584
    // ToDo: Yet to be implemented
585
0
  }
586
0
  return return_valobj_sp;
587
0
}
588
589
ValueObjectSP ABISysV_i386::GetReturnValueObjectImpl(
590
0
    Thread &thread, CompilerType &return_compiler_type) const {
591
0
  ValueObjectSP return_valobj_sp;
592
593
0
  if (!return_compiler_type)
594
0
    return return_valobj_sp;
595
596
0
  ExecutionContext exe_ctx(thread.shared_from_this());
597
0
  return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
598
0
  if (return_valobj_sp)
599
0
    return return_valobj_sp;
600
601
0
  RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
602
0
  if (!reg_ctx_sp)
603
0
    return return_valobj_sp;
604
605
0
  if (return_compiler_type.IsAggregateType()) {
606
0
    unsigned eax_id =
607
0
        reg_ctx_sp->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
608
0
    lldb::addr_t storage_addr = (uint32_t)(
609
0
        thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
610
0
        0xffffffff);
611
0
    return_valobj_sp = ValueObjectMemory::Create(
612
0
        &thread, "", Address(storage_addr, nullptr), return_compiler_type);
613
0
  }
614
615
0
  return return_valobj_sp;
616
0
}
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
622
34
bool ABISysV_i386::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
623
34
  unwind_plan.Clear();
624
34
  unwind_plan.SetRegisterKind(eRegisterKindDWARF);
625
626
34
  uint32_t sp_reg_num = dwarf_esp;
627
34
  uint32_t pc_reg_num = dwarf_eip;
628
629
34
  UnwindPlan::RowSP row(new UnwindPlan::Row);
630
34
  row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4);
631
34
  row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
632
34
  row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
633
34
  unwind_plan.AppendRow(row);
634
34
  unwind_plan.SetSourceName("i386 at-func-entry default");
635
34
  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
636
34
  return true;
637
34
}
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
644
111
bool ABISysV_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
645
111
  unwind_plan.Clear();
646
111
  unwind_plan.SetRegisterKind(eRegisterKindDWARF);
647
648
111
  uint32_t fp_reg_num = dwarf_ebp;
649
111
  uint32_t sp_reg_num = dwarf_esp;
650
111
  uint32_t pc_reg_num = dwarf_eip;
651
652
111
  UnwindPlan::RowSP row(new UnwindPlan::Row);
653
111
  const int32_t ptr_size = 4;
654
655
111
  row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
656
111
  row->SetOffset(0);
657
111
  row->SetUnspecifiedRegistersAreUndefined(true);
658
659
111
  row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
660
111
  row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
661
111
  row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
662
663
111
  unwind_plan.AppendRow(row);
664
111
  unwind_plan.SetSourceName("i386 default unwind plan");
665
111
  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
666
111
  unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
667
111
  unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
668
111
  return true;
669
111
}
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
674
9
bool ABISysV_i386::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
675
9
  if (!reg_info)
676
0
    return false;
677
678
  // Saved registers are ebx, ebp, esi, edi, esp, eip
679
9
  const char *name = reg_info->name;
680
9
  if (name[0] == 'e') {
681
9
    switch (name[1]) {
682
9
    case 'b':
683
9
      if (name[2] == 'x' || name[2] == 'p')
684
9
        return name[3] == '\0';
685
0
      break;
686
0
    case 'd':
687
0
      if (name[2] == 'i')
688
0
        return name[3] == '\0';
689
0
      break;
690
0
    case 'i':
691
0
      if (name[2] == 'p')
692
0
        return name[3] == '\0';
693
0
      break;
694
0
    case 's':
695
0
      if (name[2] == 'i' || name[2] == 'p')
696
0
        return name[3] == '\0';
697
0
      break;
698
9
    }
699
9
  }
700
701
0
  if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
702
0
    return true;
703
0
  if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
704
0
    return true;
705
0
  if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
706
0
    return true;
707
708
0
  return false;
709
0
}
710
711
3.92k
void ABISysV_i386::Initialize() {
712
3.92k
  PluginManager::RegisterPlugin(
713
3.92k
      GetPluginNameStatic(), "System V ABI for i386 targets", CreateInstance);
714
3.92k
}
715
716
3.92k
void ABISysV_i386::Terminate() {
717
3.92k
  PluginManager::UnregisterPlugin(CreateInstance);
718
3.92k
}