1 //===----------------------- ABISysV_i386.cpp -------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
7 // See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "ABISysV_i386.h"
14 // Other libraries and framework includes
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/Triple.h"
19 #include "lldb/Core/ConstString.h"
20 #include "lldb/Core/DataExtractor.h"
21 #include "lldb/Core/Error.h"
22 #include "lldb/Core/Log.h"
23 #include "lldb/Core/Module.h"
24 #include "lldb/Core/PluginManager.h"
25 #include "lldb/Core/RegisterValue.h"
26 #include "lldb/Core/Value.h"
27 #include "lldb/Core/ValueObjectConstResult.h"
28 #include "lldb/Core/ValueObjectMemory.h"
29 #include "lldb/Core/ValueObjectRegister.h"
30 #include "lldb/Symbol/UnwindPlan.h"
31 #include "lldb/Target/Process.h"
32 #include "lldb/Target/RegisterContext.h"
33 #include "lldb/Target/StackFrame.h"
34 #include "lldb/Target/Target.h"
35 #include "lldb/Target/Thread.h"
38 using namespace lldb_private;
40 // This source file uses the following document as a reference:
41 //====================================================================
42 // System V Application Binary Interface
43 // Intel386 Architecture Processor Supplement, Version 1.0
45 // H.J. Lu, David L Kreitzer, Milind Girkar, Zia Ansari
48 // System V Application Binary Interface,
49 // AMD64 Architecture Processor Supplement,
51 // H.J. Lu, Michael Matz, Milind Girkar, Jan Hubicka,
52 // Andreas Jaeger, Mark Mitchell)
55 //====================================================================
57 // DWARF Register Number Mapping
58 // See Table 2.14 of the reference document (specified on top of this file)
59 // Comment: Table 2.14 is followed till 'mm' entries.
60 // 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,
115 static RegisterInfo g_register_infos[] = {
117 //NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE INVAL DYN EXPR SZ
118 //========== ======= == === ============= ==================== =================== =================== ========================= =================== =================== ======= ======= ======== ==
119 {"eax", nullptr, 4, 0, eEncodingUint, eFormatHex, {dwarf_eax, dwarf_eax, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
120 {"ebx", nullptr, 4, 0, eEncodingUint, eFormatHex, {dwarf_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
121 {"ecx", nullptr, 4, 0, eEncodingUint, eFormatHex, {dwarf_ecx, dwarf_ecx, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
122 {"edx", nullptr, 4, 0, eEncodingUint, eFormatHex, {dwarf_edx, dwarf_edx, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
123 {"esi", nullptr, 4, 0, eEncodingUint, eFormatHex, {dwarf_esi, dwarf_esi, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
124 {"edi", nullptr, 4, 0, eEncodingUint, eFormatHex, {dwarf_edi, dwarf_edi, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
125 {"ebp", "fp", 4, 0, eEncodingUint, eFormatHex, {dwarf_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
126 {"esp", "sp", 4, 0, eEncodingUint, eFormatHex, {dwarf_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
127 {"eip", "pc", 4, 0, eEncodingUint, eFormatHex, {dwarf_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
128 {"eflags", nullptr, 4, 0, eEncodingUint, eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
129 {"cs", nullptr, 4, 0, eEncodingUint, eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
130 {"ss", nullptr, 4, 0, eEncodingUint, eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
131 {"ds", nullptr, 4, 0, eEncodingUint, eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
132 {"es", nullptr, 4, 0, eEncodingUint, eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
133 {"fs", nullptr, 4, 0, eEncodingUint, eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
134 {"gs", nullptr, 4, 0, eEncodingUint, eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
135 {"st0", nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
136 {"st1", nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
137 {"st2", nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
138 {"st3", nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
139 {"st4", nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
140 {"st5", nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
141 {"st6", nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
142 {"st7", nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
143 {"fctrl", nullptr, 4, 0, eEncodingUint, eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
144 {"fstat", nullptr, 4, 0, eEncodingUint, eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
145 {"ftag", nullptr, 4, 0, eEncodingUint, eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
146 {"fiseg", nullptr, 4, 0, eEncodingUint, eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
147 {"fioff", nullptr, 4, 0, eEncodingUint, eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
148 {"foseg", nullptr, 4, 0, eEncodingUint, eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
149 {"fooff", nullptr, 4, 0, eEncodingUint, eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
150 {"fop", nullptr, 4, 0, eEncodingUint, eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
151 {"xmm0", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
152 {"xmm1", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
153 {"xmm2", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
154 {"xmm3", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
155 {"xmm4", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
156 {"xmm5", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
157 {"xmm6", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
158 {"xmm7", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
159 {"mxcsr", nullptr, 4, 0, eEncodingUint, eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
160 {"ymm0", nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
161 {"ymm1", nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
162 {"ymm2", nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
163 {"ymm3", nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
164 {"ymm4", nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
165 {"ymm5", nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
166 {"ymm6", nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
167 {"ymm7", nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
168 {"bnd0", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt64,{dwarf_bnd0, dwarf_bnd0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
169 {"bnd1", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt64,{dwarf_bnd1, dwarf_bnd1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
170 {"bnd2", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt64,{dwarf_bnd2, dwarf_bnd2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
171 {"bnd3", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt64,{dwarf_bnd3, dwarf_bnd3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
172 {"bndcfgu", nullptr, 8, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
173 {"bndstatus",nullptr, 8, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0}
177 static const uint32_t k_num_register_infos =
178 llvm::array_lengthof(g_register_infos);
179 static bool g_register_info_names_constified = false;
181 const lldb_private::RegisterInfo *
182 ABISysV_i386::GetRegisterInfoArray(uint32_t &count) {
183 // Make the C-string names and alt_names for the register infos into const
184 // C-string values by having the ConstString unique the names in the global
185 // constant C-string pool.
186 if (!g_register_info_names_constified) {
187 g_register_info_names_constified = true;
188 for (uint32_t i = 0; i < k_num_register_infos; ++i) {
189 if (g_register_infos[i].name)
190 g_register_infos[i].name =
191 ConstString(g_register_infos[i].name).GetCString();
192 if (g_register_infos[i].alt_name)
193 g_register_infos[i].alt_name =
194 ConstString(g_register_infos[i].alt_name).GetCString();
197 count = k_num_register_infos;
198 return g_register_infos;
201 //------------------------------------------------------------------
203 //------------------------------------------------------------------
206 ABISysV_i386::CreateInstance(const ArchSpec &arch) {
207 static ABISP g_abi_sp;
208 if ((arch.GetTriple().getArch() == llvm::Triple::x86) &&
209 arch.GetTriple().isOSLinux()) {
211 g_abi_sp.reset(new ABISysV_i386);
217 bool ABISysV_i386::PrepareTrivialCall(Thread &thread, addr_t sp,
218 addr_t func_addr, addr_t return_addr,
219 llvm::ArrayRef<addr_t> args) const {
220 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
225 uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
226 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
227 uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
228 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
230 // While using register info to write a register value to memory, the register
232 // just needs to have the correct size of a 32 bit register, the actual
234 // pertains to is not important, just the size needs to be correct.
235 // "eax" is used here for this purpose.
236 const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
238 return false; // TODO this should actually never happen
241 RegisterValue reg_value;
243 // Make room for the argument(s) on the stack
244 sp -= 4 * args.size();
247 sp &= ~(16ull - 1ull); // 16-byte alignment
249 // Write arguments onto the stack
251 for (addr_t arg : args) {
252 reg_value.SetUInt32(arg);
253 error = reg_ctx->WriteRegisterValueToMemory(
254 reg_info_32, arg_pos, reg_info_32->byte_size, reg_value);
260 // The return address is pushed onto the stack
262 reg_value.SetUInt32(return_addr);
263 error = reg_ctx->WriteRegisterValueToMemory(
264 reg_info_32, sp, reg_info_32->byte_size, reg_value);
268 // Setting %esp to the actual stack value.
269 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp))
272 // Setting %eip to the address of the called function.
273 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr))
279 static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width,
280 bool is_signed, Process *process,
281 addr_t ¤t_stack_argument) {
282 uint32_t byte_size = (bit_width + (8 - 1)) / 8;
288 if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size,
289 is_signed, scalar, error)) {
290 current_stack_argument += byte_size;
296 bool ABISysV_i386::GetArgumentValues(Thread &thread, ValueList &values) const {
297 unsigned int num_values = values.GetSize();
298 unsigned int value_index;
300 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
305 // Get pointer to the first stack argument
306 addr_t sp = reg_ctx->GetSP(0);
310 addr_t current_stack_argument = sp + 4; // jump over return address
312 for (value_index = 0; value_index < num_values; ++value_index) {
313 Value *value = values.GetValueAtIndex(value_index);
318 // Currently: Support for extracting values with Clang QualTypes only.
319 CompilerType compiler_type(value->GetCompilerType());
322 if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
323 ReadIntegerArgument(value->GetScalar(),
324 compiler_type.GetBitSize(&thread), is_signed,
325 thread.GetProcess().get(), current_stack_argument);
326 } else if (compiler_type.IsPointerType()) {
327 ReadIntegerArgument(value->GetScalar(),
328 compiler_type.GetBitSize(&thread), false,
329 thread.GetProcess().get(), current_stack_argument);
336 Error ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
337 lldb::ValueObjectSP &new_value_sp) {
340 error.SetErrorString("Empty value object for return value.");
344 CompilerType compiler_type = new_value_sp->GetCompilerType();
345 if (!compiler_type) {
346 error.SetErrorString("Null clang type for return value.");
350 const uint32_t type_flags = compiler_type.GetTypeInfo();
351 Thread *thread = frame_sp->GetThread().get();
352 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
355 size_t num_bytes = new_value_sp->GetData(data, data_error);
356 bool register_write_successful = true;
358 if (data_error.Fail()) {
359 error.SetErrorStringWithFormat(
360 "Couldn't convert return value to raw data: %s",
361 data_error.AsCString());
365 // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
366 // The terminology 'Fundamental Data Types' used here is adopted from
367 // Table 2.1 of the reference document (specified on top of this file)
369 if (type_flags & eTypeIsPointer) // 'Pointer'
371 if (num_bytes != sizeof(uint32_t)) {
372 error.SetErrorString("Pointer to be returned is not 4 bytes wide");
375 lldb::offset_t offset = 0;
376 const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
377 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
378 register_write_successful =
379 reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
380 } else if ((type_flags & eTypeIsScalar) ||
381 (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
383 lldb::offset_t offset = 0;
384 const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
386 if (type_flags & eTypeIsInteger) // 'Integral' except enum
392 // For clang::BuiltinType::UInt128 & Int128
393 // ToDo: Need to decide how to handle it
396 uint32_t raw_value_low = data.GetMaxU32(&offset, 4);
397 const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0);
398 uint32_t raw_value_high = data.GetMaxU32(&offset, num_bytes - offset);
399 register_write_successful =
400 (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value_low) &&
401 reg_ctx->WriteRegisterFromUnsigned(edx_info, raw_value_high));
407 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
408 register_write_successful =
409 reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
413 } else if (type_flags & eTypeIsEnumeration) // handles enum
415 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
416 register_write_successful =
417 reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
418 } else if (type_flags & eTypeIsFloat) // 'Floating Point'
420 RegisterValue st0_value, fstat_value, ftag_value;
421 const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
422 const RegisterInfo *fstat_info =
423 reg_ctx->GetRegisterInfoByName("fstat", 0);
424 const RegisterInfo *ftag_info = reg_ctx->GetRegisterInfoByName("ftag", 0);
426 /* According to Page 3-12 of document
427 System V Application Binary Interface, Intel386 Architecture Processor
428 Supplement, Fourth Edition
429 To return Floating Point values, all st% registers except st0 should be
430 empty after exiting from
431 a function. This requires setting fstat and ftag registers to specific
433 fstat: The TOP field of fstat should be set to a value [0,7]. ABI doesn't
435 value of TOP in case of function return. Hence, we set the TOP field to 7
437 uint32_t value_fstat_u32 = 0x00003800;
439 /* ftag: Implication of setting TOP to 7 and indicating all st% registers
440 empty except st0 is to set
441 7th bit of 4th byte of FXSAVE area to 1 and all other bits of this byte to
442 0. This is in accordance
443 with the document Intel 64 and IA-32 Architectures Software Developer's
444 Manual, January 2015 */
445 uint32_t value_ftag_u32 = 0x00000080;
447 if (num_bytes <= 12) // handles float, double, long double, __float80
449 long double value_long_dbl = 0.0;
451 value_long_dbl = data.GetFloat(&offset);
452 else if (num_bytes == 8)
453 value_long_dbl = data.GetDouble(&offset);
454 else if (num_bytes == 12)
455 value_long_dbl = data.GetLongDouble(&offset);
457 error.SetErrorString("Invalid number of bytes for this return type");
460 st0_value.SetLongDouble(value_long_dbl);
461 fstat_value.SetUInt32(value_fstat_u32);
462 ftag_value.SetUInt32(value_ftag_u32);
463 register_write_successful =
464 reg_ctx->WriteRegister(st0_info, st0_value) &&
465 reg_ctx->WriteRegister(fstat_info, fstat_value) &&
466 reg_ctx->WriteRegister(ftag_info, ftag_value);
467 } else if (num_bytes == 16) // handles __float128
469 error.SetErrorString("Implementation is missing for this clang type.");
472 // Neither 'Integral' nor 'Floating Point'. If flow reaches here
473 // then check type_flags. This type_flags is not a valid type.
474 error.SetErrorString("Invalid clang type");
477 /* 'Complex Floating Point', 'Packed', 'Decimal Floating Point' and
478 'Aggregate' data types
479 are yet to be implemented */
480 error.SetErrorString("Currently only Integral and Floating Point clang "
481 "types are supported.");
483 if (!register_write_successful)
484 error.SetErrorString("Register writing failed");
488 ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
489 Thread &thread, CompilerType &return_compiler_type) const {
490 ValueObjectSP return_valobj_sp;
493 if (!return_compiler_type)
494 return return_valobj_sp;
496 value.SetCompilerType(return_compiler_type);
498 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
500 return return_valobj_sp;
502 const uint32_t type_flags = return_compiler_type.GetTypeInfo();
505 reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
507 reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
509 // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
510 // The terminology 'Fundamental Data Types' used here is adopted from
511 // Table 2.1 of the reference document (specified on top of this file)
513 if (type_flags & eTypeIsPointer) // 'Pointer'
516 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
518 value.SetValueType(Value::eValueTypeScalar);
519 value.GetScalar() = ptr;
520 return_valobj_sp = ValueObjectConstResult::Create(
521 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
522 } else if ((type_flags & eTypeIsScalar) ||
523 (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
525 value.SetValueType(Value::eValueTypeScalar);
526 const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
527 bool success = false;
529 if (type_flags & eTypeIsInteger) // 'Integral' except enum
531 const bool is_signed = ((type_flags & eTypeIsSigned) != 0);
533 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
536 (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) &
545 // For clang::BuiltinType::UInt128 & Int128
546 // ToDo: Need to decide how to handle it
551 value.GetScalar() = (int64_t)(raw_value);
553 value.GetScalar() = (uint64_t)(raw_value);
559 value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
561 value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
567 value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
569 value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
575 value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
577 value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
583 return_valobj_sp = ValueObjectConstResult::Create(
584 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
585 } else if (type_flags & eTypeIsEnumeration) // handles enum
588 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
590 value.SetValueType(Value::eValueTypeScalar);
591 value.GetScalar() = enm;
592 return_valobj_sp = ValueObjectConstResult::Create(
593 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
594 } else if (type_flags & eTypeIsFloat) // 'Floating Point'
596 if (byte_size <= 12) // handles float, double, long double, __float80
598 const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
599 RegisterValue st0_value;
601 if (reg_ctx->ReadRegister(st0_info, st0_value)) {
603 if (st0_value.GetData(data)) {
604 lldb::offset_t offset = 0;
605 long double value_long_double = data.GetLongDouble(&offset);
607 if (byte_size == 4) // float is 4 bytes
609 float value_float = (float)value_long_double;
610 value.GetScalar() = value_float;
612 } else if (byte_size == 8) // double is 8 bytes
614 // On Android Platform: long double is also 8 bytes
615 // It will be handled here only.
616 double value_double = (double)value_long_double;
617 value.GetScalar() = value_double;
619 } else if (byte_size ==
620 12) // long double and __float80 are 12 bytes on i386
622 value.GetScalar() = value_long_double;
629 return_valobj_sp = ValueObjectConstResult::Create(
630 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
631 } else if (byte_size == 16) // handles __float128
633 lldb::addr_t storage_addr = (uint32_t)(
634 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
636 return_valobj_sp = ValueObjectMemory::Create(
637 &thread, "", Address(storage_addr, nullptr), return_compiler_type);
639 } else // Neither 'Integral' nor 'Floating Point'
641 // If flow reaches here then check type_flags
642 // This type_flags is unhandled
644 } else if (type_flags & eTypeIsComplex) // 'Complex Floating Point'
646 // ToDo: Yet to be implemented
647 } else if (type_flags & eTypeIsVector) // 'Packed'
649 const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
651 const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
652 if (vec_reg == nullptr)
653 vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
656 if (byte_size <= vec_reg->byte_size) {
657 ProcessSP process_sp(thread.GetProcess());
659 std::unique_ptr<DataBufferHeap> heap_data_ap(
660 new DataBufferHeap(byte_size, 0));
661 const ByteOrder byte_order = process_sp->GetByteOrder();
662 RegisterValue reg_value;
663 if (reg_ctx->ReadRegister(vec_reg, reg_value)) {
665 if (reg_value.GetAsMemoryData(vec_reg, heap_data_ap->GetBytes(),
666 heap_data_ap->GetByteSize(),
667 byte_order, error)) {
668 DataExtractor data(DataBufferSP(heap_data_ap.release()),
669 byte_order, process_sp->GetTarget()
671 .GetAddressByteSize());
672 return_valobj_sp = ValueObjectConstResult::Create(
673 &thread, return_compiler_type, ConstString(""), data);
677 } else if (byte_size <= vec_reg->byte_size * 2) {
678 const RegisterInfo *vec_reg2 =
679 reg_ctx->GetRegisterInfoByName("xmm1", 0);
681 ProcessSP process_sp(thread.GetProcess());
683 std::unique_ptr<DataBufferHeap> heap_data_ap(
684 new DataBufferHeap(byte_size, 0));
685 const ByteOrder byte_order = process_sp->GetByteOrder();
686 RegisterValue reg_value;
687 RegisterValue reg_value2;
688 if (reg_ctx->ReadRegister(vec_reg, reg_value) &&
689 reg_ctx->ReadRegister(vec_reg2, reg_value2)) {
692 if (reg_value.GetAsMemoryData(vec_reg, heap_data_ap->GetBytes(),
693 vec_reg->byte_size, byte_order,
695 reg_value2.GetAsMemoryData(
696 vec_reg2, heap_data_ap->GetBytes() + vec_reg->byte_size,
697 heap_data_ap->GetByteSize() - vec_reg->byte_size,
698 byte_order, error)) {
699 DataExtractor data(DataBufferSP(heap_data_ap.release()),
700 byte_order, process_sp->GetTarget()
702 .GetAddressByteSize());
703 return_valobj_sp = ValueObjectConstResult::Create(
704 &thread, return_compiler_type, ConstString(""), data);
712 } else // 'Decimal Floating Point'
714 // ToDo: Yet to be implemented
716 return return_valobj_sp;
719 ValueObjectSP ABISysV_i386::GetReturnValueObjectImpl(
720 Thread &thread, CompilerType &return_compiler_type) const {
721 ValueObjectSP return_valobj_sp;
723 if (!return_compiler_type)
724 return return_valobj_sp;
726 ExecutionContext exe_ctx(thread.shared_from_this());
727 return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
728 if (return_valobj_sp)
729 return return_valobj_sp;
731 RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
733 return return_valobj_sp;
735 if (return_compiler_type.IsAggregateType()) {
737 reg_ctx_sp->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
738 lldb::addr_t storage_addr = (uint32_t)(
739 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
741 return_valobj_sp = ValueObjectMemory::Create(
742 &thread, "", Address(storage_addr, nullptr), return_compiler_type);
745 return return_valobj_sp;
748 // This defines CFA as esp+4
749 // The saved pc is at CFA-4 (i.e. esp+0)
750 // The saved esp is CFA+0
752 bool ABISysV_i386::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
754 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
756 uint32_t sp_reg_num = dwarf_esp;
757 uint32_t pc_reg_num = dwarf_eip;
759 UnwindPlan::RowSP row(new UnwindPlan::Row);
760 row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4);
761 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
762 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
763 unwind_plan.AppendRow(row);
764 unwind_plan.SetSourceName("i386 at-func-entry default");
765 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
769 // This defines CFA as ebp+8
770 // The saved pc is at CFA-4 (i.e. ebp+4)
771 // The saved ebp is at CFA-8 (i.e. ebp+0)
772 // The saved esp is CFA+0
774 bool ABISysV_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
776 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
778 uint32_t fp_reg_num = dwarf_ebp;
779 uint32_t sp_reg_num = dwarf_esp;
780 uint32_t pc_reg_num = dwarf_eip;
782 UnwindPlan::RowSP row(new UnwindPlan::Row);
783 const int32_t ptr_size = 4;
785 row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
788 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
789 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
790 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
792 unwind_plan.AppendRow(row);
793 unwind_plan.SetSourceName("i386 default unwind plan");
794 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
795 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
799 // According to "Register Usage" in reference document (specified on top
800 // of this source file) ebx, ebp, esi, edi and esp registers are preserved
801 // i.e. non-volatile i.e. callee-saved on i386
802 bool ABISysV_i386::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
806 // Saved registers are ebx, ebp, esi, edi, esp, eip
807 const char *name = reg_info->name;
808 if (name[0] == 'e') {
811 if (name[2] == 'x' || name[2] == 'p')
812 return name[3] == '\0';
816 return name[3] == '\0';
820 return name[3] == '\0';
823 if (name[2] == 'i' || name[2] == 'p')
824 return name[3] == '\0';
829 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
831 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
833 if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
839 void ABISysV_i386::Initialize() {
840 PluginManager::RegisterPlugin(
841 GetPluginNameStatic(), "System V ABI for i386 targets", CreateInstance);
844 void ABISysV_i386::Terminate() {
845 PluginManager::UnregisterPlugin(CreateInstance);
848 //------------------------------------------------------------------
849 // PluginInterface protocol
850 //------------------------------------------------------------------
852 lldb_private::ConstString ABISysV_i386::GetPluginNameStatic() {
853 static ConstString g_name("sysv-i386");
857 lldb_private::ConstString ABISysV_i386::GetPluginName() {
858 return GetPluginNameStatic();