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