Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp
39653 views
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
ABISysV_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
84
bool 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
144
static 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
161
bool 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
200
Status 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
352
ValueObjectSP 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
589
ValueObjectSP 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
622
bool 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
644
bool 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
674
bool 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
711
void ABISysV_i386::Initialize() {
712
PluginManager::RegisterPlugin(
713
GetPluginNameStatic(), "System V ABI for i386 targets", CreateInstance);
714
}
715
716
void ABISysV_i386::Terminate() {
717
PluginManager::UnregisterPlugin(CreateInstance);
718
}
719
720