1 //===----------------------- ABISysV_i386.cpp -------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source License.
6 // See LICENSE.TXT for details.
7 //===----------------------------------------------------------------------===//
9 #include "ABISysV_i386.h"
11 #include "lldb/Core/ConstString.h"
12 #include "lldb/Core/DataExtractor.h"
13 #include "lldb/Core/Error.h"
14 #include "lldb/Core/Log.h"
15 #include "lldb/Core/Module.h"
16 #include "lldb/Core/PluginManager.h"
17 #include "lldb/Core/RegisterValue.h"
18 #include "lldb/Core/Value.h"
19 #include "lldb/Core/ValueObjectConstResult.h"
20 #include "lldb/Core/ValueObjectRegister.h"
21 #include "lldb/Core/ValueObjectMemory.h"
22 #include "lldb/Symbol/UnwindPlan.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Target/Process.h"
25 #include "lldb/Target/RegisterContext.h"
26 #include "lldb/Target/StackFrame.h"
27 #include "lldb/Target/Thread.h"
29 #include "llvm/ADT/STLExtras.h"
30 #include "llvm/ADT/Triple.h"
33 using namespace lldb_private;
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
42 // H.J. Lu, David L Kreitzer, Milind Girkar, Zia Ansari
45 // System V Application Binary Interface,
46 // AMD64 Architecture Processor Supplement,
48 // H.J. Lu, Michael Matz, Milind Girkar, Jan Hubicka,
49 // Andreas Jaeger, Mark Mitchell)
52 //====================================================================
56 // DWARF Register Number Mapping
57 // See Table 2.14 of the reference document (specified on top of this file)
58 // Comment: Table 2.14 is followed till 'mm' entries.
59 // After that, all entries are ignored here.
91 dwarf_ymm0 = dwarf_xmm0,
92 dwarf_ymm1 = dwarf_xmm1,
93 dwarf_ymm2 = dwarf_xmm2,
94 dwarf_ymm3 = dwarf_xmm3,
95 dwarf_ymm4 = dwarf_xmm4,
96 dwarf_ymm5 = dwarf_xmm5,
97 dwarf_ymm6 = dwarf_xmm6,
98 dwarf_ymm7 = dwarf_xmm7,
111 static RegisterInfo g_register_infos[] =
113 // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
114 // ====== ======= == === ============= ============ ===================== ===================== ============================ ==================== ====================== ========== ===============
115 { "eax", nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_eax , dwarf_eax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
116 { "ebx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
117 { "ecx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_ecx , dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
118 { "edx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_edx , dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
119 { "esi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_esi , dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
120 { "edi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_edi , dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
121 { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { dwarf_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
122 { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { dwarf_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
123 { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { dwarf_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
124 { "eflags", nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
125 { "cs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
126 { "ss" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
127 { "ds" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
128 { "es" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
129 { "fs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
130 { "gs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
131 { "st0" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
132 { "st1" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
133 { "st2" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
134 { "st3" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
135 { "st4" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
136 { "st5" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
137 { "st6" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
138 { "st7" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
139 { "fctrl" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
140 { "fstat" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
141 { "ftag" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
142 { "fiseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
143 { "fioff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
144 { "foseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
145 { "fooff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
146 { "fop" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
147 { "xmm0" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
148 { "xmm1" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
149 { "xmm2" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
150 { "xmm3" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
151 { "xmm4" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
152 { "xmm5" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
153 { "xmm6" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
154 { "xmm7" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
155 { "mxcsr" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
156 { "ymm0" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
157 { "ymm1" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
158 { "ymm2" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
159 { "ymm3" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
160 { "ymm4" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
161 { "ymm5" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
162 { "ymm6" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
163 { "ymm7" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}
166 static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
167 static bool g_register_info_names_constified = false;
169 const lldb_private::RegisterInfo *
170 ABISysV_i386::GetRegisterInfoArray (uint32_t &count)
172 // Make the C-string names and alt_names for the register infos into const
173 // C-string values by having the ConstString unique the names in the global
174 // constant C-string pool.
175 if (!g_register_info_names_constified)
177 g_register_info_names_constified = true;
178 for (uint32_t i=0; i<k_num_register_infos; ++i)
180 if (g_register_infos[i].name)
181 g_register_infos[i].name = ConstString(g_register_infos[i].name).GetCString();
182 if (g_register_infos[i].alt_name)
183 g_register_infos[i].alt_name = ConstString(g_register_infos[i].alt_name).GetCString();
186 count = k_num_register_infos;
187 return g_register_infos;
191 //------------------------------------------------------------------
193 //------------------------------------------------------------------
195 ABISysV_i386::CreateInstance (const ArchSpec &arch)
197 static ABISP g_abi_sp;
198 if ((arch.GetTriple().getArch() == llvm::Triple::x86) &&
199 arch.GetTriple().isOSLinux())
202 g_abi_sp.reset (new ABISysV_i386);
209 ABISysV_i386::PrepareTrivialCall (Thread &thread,
213 llvm::ArrayRef<addr_t> args) const
215 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
220 uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
221 uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
223 // While using register info to write a register value to memory, the register info
224 // just needs to have the correct size of a 32 bit register, the actual register it
225 // pertains to is not important, just the size needs to be correct.
226 // "eax" is used here for this purpose.
227 const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
229 return false; // TODO this should actually never happen
232 RegisterValue reg_value;
234 // Make room for the argument(s) on the stack
235 sp -= 4 * args.size();
238 sp &= ~(16ull-1ull); // 16-byte alignment
240 // Write arguments onto the stack
242 for (addr_t arg : args)
244 reg_value.SetUInt32(arg);
245 error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
247 reg_info_32->byte_size,
254 // The return address is pushed onto the stack
256 reg_value.SetUInt32(return_addr);
257 error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
259 reg_info_32->byte_size,
264 // Setting %esp to the actual stack value.
265 if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_num, sp))
268 // Setting %eip to the address of the called function.
269 if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_num, func_addr))
277 ReadIntegerArgument (Scalar &scalar,
278 unsigned int bit_width,
281 addr_t ¤t_stack_argument)
283 uint32_t byte_size = (bit_width + (8-1))/8;
289 if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error))
291 current_stack_argument += byte_size;
299 ABISysV_i386::GetArgumentValues (Thread &thread,
300 ValueList &values) const
302 unsigned int num_values = values.GetSize();
303 unsigned int value_index;
305 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
310 // Get pointer to the first stack argument
311 addr_t sp = reg_ctx->GetSP(0);
315 addr_t current_stack_argument = sp + 4; // jump over return address
317 for (value_index = 0;
318 value_index < num_values;
321 Value *value = values.GetValueAtIndex(value_index);
326 // Currently: Support for extracting values with Clang QualTypes only.
327 CompilerType compiler_type (value->GetCompilerType());
331 if (compiler_type.IsIntegerType (is_signed))
333 ReadIntegerArgument(value->GetScalar(),
334 compiler_type.GetBitSize(&thread),
336 thread.GetProcess().get(),
337 current_stack_argument);
339 else if (compiler_type.IsPointerType())
341 ReadIntegerArgument(value->GetScalar(),
342 compiler_type.GetBitSize(&thread),
344 thread.GetProcess().get(),
345 current_stack_argument);
355 ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
360 error.SetErrorString("Empty value object for return value.");
364 CompilerType compiler_type = new_value_sp->GetCompilerType();
367 error.SetErrorString ("Null clang type for return value.");
371 const uint32_t type_flags = compiler_type.GetTypeInfo ();
372 Thread *thread = frame_sp->GetThread().get();
373 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
376 size_t num_bytes = new_value_sp->GetData(data, data_error);
377 bool register_write_successful = true;
379 if (data_error.Fail())
381 error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
385 // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
386 // The terminology 'Fundamental Data Types' used here is adopted from
387 // Table 2.1 of the reference document (specified on top of this file)
389 if (type_flags & eTypeIsPointer) // 'Pointer'
391 if(num_bytes != sizeof(uint32_t))
393 error.SetErrorString("Pointer to be returned is not 4 bytes wide");
396 lldb::offset_t offset = 0;
397 const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
398 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
399 register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value);
401 else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
403 lldb::offset_t offset = 0;
404 const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
406 if (type_flags & eTypeIsInteger) // 'Integral' except enum
413 // For clang::BuiltinType::UInt128 & Int128
414 // ToDo: Need to decide how to handle it
418 uint32_t raw_value_low = data.GetMaxU32(&offset, 4);
419 const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0);
420 uint32_t raw_value_high = data.GetMaxU32(&offset, num_bytes - offset);
421 register_write_successful = (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value_low) &&
422 reg_ctx->WriteRegisterFromUnsigned (edx_info, raw_value_high));
429 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
430 register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value);
435 else if (type_flags & eTypeIsEnumeration) // handles enum
437 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
438 register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value);
440 else if (type_flags & eTypeIsFloat) // 'Floating Point'
442 RegisterValue st0_value, fstat_value, ftag_value;
443 const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
444 const RegisterInfo *fstat_info = reg_ctx->GetRegisterInfoByName("fstat", 0);
445 const RegisterInfo *ftag_info = reg_ctx->GetRegisterInfoByName("ftag", 0);
447 /* According to Page 3-12 of document
448 System V Application Binary Interface, Intel386 Architecture Processor Supplement, Fourth Edition
449 To return Floating Point values, all st% registers except st0 should be empty after exiting from
450 a function. This requires setting fstat and ftag registers to specific values.
451 fstat: The TOP field of fstat should be set to a value [0,7]. ABI doesn't specify the specific
452 value of TOP in case of function return. Hence, we set the TOP field to 7 by our choice. */
453 uint32_t value_fstat_u32 = 0x00003800;
455 /* ftag: Implication of setting TOP to 7 and indicating all st% registers empty except st0 is to set
456 7th bit of 4th byte of FXSAVE area to 1 and all other bits of this byte to 0. This is in accordance
457 with the document Intel 64 and IA-32 Architectures Software Developer's Manual, January 2015 */
458 uint32_t value_ftag_u32 = 0x00000080;
460 if (num_bytes <= 12) // handles float, double, long double, __float80
462 long double value_long_dbl = 0.0;
464 value_long_dbl = data.GetFloat(&offset);
465 else if (num_bytes == 8)
466 value_long_dbl = data.GetDouble(&offset);
467 else if (num_bytes == 12)
468 value_long_dbl = data.GetLongDouble(&offset);
471 error.SetErrorString ("Invalid number of bytes for this return type");
474 st0_value.SetLongDouble(value_long_dbl);
475 fstat_value.SetUInt32(value_fstat_u32);
476 ftag_value.SetUInt32(value_ftag_u32);
477 register_write_successful = reg_ctx->WriteRegister(st0_info, st0_value) &&
478 reg_ctx->WriteRegister(fstat_info, fstat_value) &&
479 reg_ctx->WriteRegister(ftag_info, ftag_value);
481 else if(num_bytes == 16) // handles __float128
483 error.SetErrorString ("Implementation is missing for this clang type.");
488 // Neither 'Integral' nor 'Floating Point'. If flow reaches here
489 // then check type_flags. This type_flags is not a valid type.
490 error.SetErrorString ("Invalid clang type");
495 /* 'Complex Floating Point', 'Packed', 'Decimal Floating Point' and 'Aggregate' data types
496 are yet to be implemented */
497 error.SetErrorString ("Currently only Integral and Floating Point clang types are supported.");
499 if(!register_write_successful)
500 error.SetErrorString ("Register writing failed");
506 ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,
507 CompilerType &return_compiler_type) const
509 ValueObjectSP return_valobj_sp;
512 if (!return_compiler_type)
513 return return_valobj_sp;
515 value.SetCompilerType (return_compiler_type);
517 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
519 return return_valobj_sp;
521 const uint32_t type_flags = return_compiler_type.GetTypeInfo ();
523 unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
524 unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
527 // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
528 // The terminology 'Fundamental Data Types' used here is adopted from
529 // Table 2.1 of the reference document (specified on top of this file)
531 if (type_flags & eTypeIsPointer) // 'Pointer'
533 uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff ;
534 value.SetValueType(Value::eValueTypeScalar);
535 value.GetScalar() = ptr;
536 return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
541 else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
543 value.SetValueType(Value::eValueTypeScalar);
544 const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
545 bool success = false;
547 if (type_flags & eTypeIsInteger) // 'Integral' except enum
549 const bool is_signed = ((type_flags & eTypeIsSigned) != 0);
550 uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff ;
551 raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32;
559 // For clang::BuiltinType::UInt128 & Int128
560 // ToDo: Need to decide how to handle it
565 value.GetScalar() = (int64_t)(raw_value);
567 value.GetScalar() = (uint64_t)(raw_value);
573 value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
575 value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
581 value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
583 value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
589 value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
591 value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
597 return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
602 else if (type_flags & eTypeIsEnumeration) // handles enum
604 uint32_t enm = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff ;
605 value.SetValueType(Value::eValueTypeScalar);
606 value.GetScalar() = enm;
607 return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
612 else if (type_flags & eTypeIsFloat) // 'Floating Point'
614 if (byte_size <= 12) // handles float, double, long double, __float80
616 const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
617 RegisterValue st0_value;
619 if (reg_ctx->ReadRegister (st0_info, st0_value))
622 if (st0_value.GetData(data))
624 lldb::offset_t offset = 0;
625 long double value_long_double = data.GetLongDouble(&offset);
627 if (byte_size == 4) // float is 4 bytes
629 float value_float = (float)value_long_double;
630 value.GetScalar() = value_float;
633 else if (byte_size == 8) // double is 8 bytes
635 // On Android Platform: long double is also 8 bytes
636 // It will be handled here only.
637 double value_double = (double)value_long_double;
638 value.GetScalar() = value_double;
641 else if (byte_size == 12) // long double and __float80 are 12 bytes on i386
643 value.GetScalar() = value_long_double;
650 return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
654 else if(byte_size == 16) // handles __float128
656 lldb::addr_t storage_addr = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
657 return_valobj_sp = ValueObjectMemory::Create (&thread,
659 Address (storage_addr, nullptr),
660 return_compiler_type);
664 else // Neither 'Integral' nor 'Floating Point'
666 // If flow reaches here then check type_flags
667 // This type_flags is unhandled
671 else if (type_flags & eTypeIsComplex) // 'Complex Floating Point'
673 // ToDo: Yet to be implemented
676 else if (type_flags & eTypeIsVector) // 'Packed'
678 const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
681 const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
682 if (vec_reg == nullptr)
683 vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
687 if (byte_size <= vec_reg->byte_size)
689 ProcessSP process_sp (thread.GetProcess());
692 std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
693 const ByteOrder byte_order = process_sp->GetByteOrder();
694 RegisterValue reg_value;
695 if (reg_ctx->ReadRegister(vec_reg, reg_value))
698 if (reg_value.GetAsMemoryData (vec_reg,
699 heap_data_ap->GetBytes(),
700 heap_data_ap->GetByteSize(),
704 DataExtractor data (DataBufferSP (heap_data_ap.release()),
706 process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
707 return_valobj_sp = ValueObjectConstResult::Create (&thread,
708 return_compiler_type,
715 else if (byte_size <= vec_reg->byte_size*2)
717 const RegisterInfo *vec_reg2 = reg_ctx->GetRegisterInfoByName("xmm1", 0);
720 ProcessSP process_sp (thread.GetProcess());
723 std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
724 const ByteOrder byte_order = process_sp->GetByteOrder();
725 RegisterValue reg_value;
726 RegisterValue reg_value2;
727 if (reg_ctx->ReadRegister(vec_reg, reg_value) && reg_ctx->ReadRegister(vec_reg2, reg_value2))
731 if (reg_value.GetAsMemoryData (vec_reg,
732 heap_data_ap->GetBytes(),
736 reg_value2.GetAsMemoryData (vec_reg2,
737 heap_data_ap->GetBytes() + vec_reg->byte_size,
738 heap_data_ap->GetByteSize() - vec_reg->byte_size,
742 DataExtractor data (DataBufferSP (heap_data_ap.release()),
744 process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
745 return_valobj_sp = ValueObjectConstResult::Create (&thread,
746 return_compiler_type,
758 else // 'Decimal Floating Point'
760 //ToDo: Yet to be implemented
762 return return_valobj_sp;
767 ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
769 ValueObjectSP return_valobj_sp;
771 if (!return_compiler_type)
772 return return_valobj_sp;
774 ExecutionContext exe_ctx (thread.shared_from_this());
775 return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
776 if (return_valobj_sp)
777 return return_valobj_sp;
779 RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
781 return return_valobj_sp;
783 if (return_compiler_type.IsAggregateType())
785 unsigned eax_id = reg_ctx_sp->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
786 lldb::addr_t storage_addr = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
787 return_valobj_sp = ValueObjectMemory::Create (&thread,
789 Address (storage_addr, nullptr),
790 return_compiler_type);
793 return return_valobj_sp;
796 // This defines CFA as esp+4
797 // The saved pc is at CFA-4 (i.e. esp+0)
798 // The saved esp is CFA+0
801 ABISysV_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
804 unwind_plan.SetRegisterKind (eRegisterKindDWARF);
806 uint32_t sp_reg_num = dwarf_esp;
807 uint32_t pc_reg_num = dwarf_eip;
809 UnwindPlan::RowSP row(new UnwindPlan::Row);
810 row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4);
811 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
812 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
813 unwind_plan.AppendRow (row);
814 unwind_plan.SetSourceName ("i386 at-func-entry default");
815 unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
819 // This defines CFA as ebp+8
820 // The saved pc is at CFA-4 (i.e. ebp+4)
821 // The saved ebp is at CFA-8 (i.e. ebp+0)
822 // The saved esp is CFA+0
825 ABISysV_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
828 unwind_plan.SetRegisterKind (eRegisterKindDWARF);
830 uint32_t fp_reg_num = dwarf_ebp;
831 uint32_t sp_reg_num = dwarf_esp;
832 uint32_t pc_reg_num = dwarf_eip;
834 UnwindPlan::RowSP row(new UnwindPlan::Row);
835 const int32_t ptr_size = 4;
837 row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
840 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
841 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
842 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
844 unwind_plan.AppendRow (row);
845 unwind_plan.SetSourceName ("i386 default unwind plan");
846 unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
847 unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
852 // According to "Register Usage" in reference document (specified on top
853 // of this source file) ebx, ebp, esi, edi and esp registers are preserved
854 // i.e. non-volatile i.e. callee-saved on i386
856 ABISysV_i386::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
861 // Saved registers are ebx, ebp, esi, edi, esp, eip
862 const char *name = reg_info->name;
868 if (name[2] == 'x' || name[2] == 'p')
869 return name[3] == '\0';
873 return name[3] == '\0';
877 return name[3] == '\0';
880 if (name[2] == 'i' || name[2] == 'p')
881 return name[3] == '\0';
886 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
888 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
890 if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
898 ABISysV_i386::Initialize()
900 PluginManager::RegisterPlugin (GetPluginNameStatic(),
901 "System V ABI for i386 targets",
907 ABISysV_i386::Terminate()
909 PluginManager::UnregisterPlugin (CreateInstance);
913 //------------------------------------------------------------------
914 // PluginInterface protocol
915 //------------------------------------------------------------------
916 lldb_private::ConstString
917 ABISysV_i386::GetPluginNameStatic()
919 static ConstString g_name("sysv-i386");
924 lldb_private::ConstString
925 ABISysV_i386::GetPluginName()
927 return GetPluginNameStatic();