1 //===----------------------- ABISysV_i386.cpp -------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //===----------------------------------------------------------------------===//
9 #include "ABISysV_i386.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/Triple.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Core/Value.h"
17 #include "lldb/Core/ValueObjectConstResult.h"
18 #include "lldb/Core/ValueObjectMemory.h"
19 #include "lldb/Core/ValueObjectRegister.h"
20 #include "lldb/Symbol/UnwindPlan.h"
21 #include "lldb/Target/Process.h"
22 #include "lldb/Target/RegisterContext.h"
23 #include "lldb/Target/StackFrame.h"
24 #include "lldb/Target/Target.h"
25 #include "lldb/Target/Thread.h"
26 #include "lldb/Utility/ConstString.h"
27 #include "lldb/Utility/DataExtractor.h"
28 #include "lldb/Utility/Log.h"
29 #include "lldb/Utility/RegisterValue.h"
30 #include "lldb/Utility/Status.h"
33 using namespace lldb_private;
35 // This source file uses the following document as a reference:
36 //====================================================================
37 // System V Application Binary Interface
38 // Intel386 Architecture Processor Supplement, Version 1.0
40 // H.J. Lu, David L Kreitzer, Milind Girkar, Zia Ansari
43 // System V Application Binary Interface,
44 // AMD64 Architecture Processor Supplement,
46 // H.J. Lu, Michael Matz, Milind Girkar, Jan Hubicka,
47 // Andreas Jaeger, Mark Mitchell)
50 //====================================================================
52 // DWARF Register Number Mapping
53 // See Table 2.14 of the reference document (specified on top of this file)
54 // Comment: Table 2.14 is followed till 'mm' entries. After that, all entries
86 dwarf_ymm0 = dwarf_xmm0,
87 dwarf_ymm1 = dwarf_xmm1,
88 dwarf_ymm2 = dwarf_xmm2,
89 dwarf_ymm3 = dwarf_xmm3,
90 dwarf_ymm4 = dwarf_xmm4,
91 dwarf_ymm5 = dwarf_xmm5,
92 dwarf_ymm6 = dwarf_xmm6,
93 dwarf_ymm7 = dwarf_xmm7,
110 static RegisterInfo g_register_infos[] = {
112 //NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE INVAL DYN EXPR SZ
113 //========== ======= == === ============= ==================== =================== =================== ========================= =================== =================== ======= ======= ======== ==
114 {"eax", nullptr, 4, 0, eEncodingUint, eFormatHex, {dwarf_eax, dwarf_eax, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
115 {"ebx", nullptr, 4, 0, eEncodingUint, eFormatHex, {dwarf_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
116 {"ecx", nullptr, 4, 0, eEncodingUint, eFormatHex, {dwarf_ecx, dwarf_ecx, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
117 {"edx", nullptr, 4, 0, eEncodingUint, eFormatHex, {dwarf_edx, dwarf_edx, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
118 {"esi", nullptr, 4, 0, eEncodingUint, eFormatHex, {dwarf_esi, dwarf_esi, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
119 {"edi", nullptr, 4, 0, eEncodingUint, eFormatHex, {dwarf_edi, dwarf_edi, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
120 {"ebp", "fp", 4, 0, eEncodingUint, eFormatHex, {dwarf_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
121 {"esp", "sp", 4, 0, eEncodingUint, eFormatHex, {dwarf_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
122 {"eip", "pc", 4, 0, eEncodingUint, eFormatHex, {dwarf_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
123 {"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},
124 {"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},
125 {"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},
126 {"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},
127 {"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},
128 {"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},
129 {"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},
130 {"st0", nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
131 {"st1", nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
132 {"st2", nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
133 {"st3", nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
134 {"st4", nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
135 {"st5", nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
136 {"st6", nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
137 {"st7", nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_st7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
138 {"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},
139 {"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},
140 {"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},
141 {"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},
142 {"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},
143 {"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},
144 {"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},
145 {"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},
146 {"xmm0", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
147 {"xmm1", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
148 {"xmm2", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
149 {"xmm3", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
150 {"xmm4", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
151 {"xmm5", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
152 {"xmm6", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
153 {"xmm7", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_xmm7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
154 {"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},
155 {"ymm0", nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
156 {"ymm1", nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
157 {"ymm2", nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
158 {"ymm3", nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
159 {"ymm4", nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
160 {"ymm5", nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
161 {"ymm6", nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
162 {"ymm7", nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, dwarf_ymm7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
163 {"bnd0", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt64,{dwarf_bnd0, dwarf_bnd0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
164 {"bnd1", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt64,{dwarf_bnd1, dwarf_bnd1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
165 {"bnd2", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt64,{dwarf_bnd2, dwarf_bnd2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
166 {"bnd3", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt64,{dwarf_bnd3, dwarf_bnd3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr, nullptr, 0},
167 {"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},
168 {"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}
172 static const uint32_t k_num_register_infos =
173 llvm::array_lengthof(g_register_infos);
174 static bool g_register_info_names_constified = false;
176 const lldb_private::RegisterInfo *
177 ABISysV_i386::GetRegisterInfoArray(uint32_t &count) {
178 // Make the C-string names and alt_names for the register infos into const
179 // C-string values by having the ConstString unique the names in the global
180 // constant C-string pool.
181 if (!g_register_info_names_constified) {
182 g_register_info_names_constified = true;
183 for (uint32_t i = 0; i < k_num_register_infos; ++i) {
184 if (g_register_infos[i].name)
185 g_register_infos[i].name =
186 ConstString(g_register_infos[i].name).GetCString();
187 if (g_register_infos[i].alt_name)
188 g_register_infos[i].alt_name =
189 ConstString(g_register_infos[i].alt_name).GetCString();
192 count = k_num_register_infos;
193 return g_register_infos;
196 //------------------------------------------------------------------
198 //------------------------------------------------------------------
201 ABISysV_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
202 if (arch.GetTriple().getVendor() != llvm::Triple::Apple) {
203 if (arch.GetTriple().getArch() == llvm::Triple::x86) {
204 return ABISP(new ABISysV_i386(process_sp));
210 bool ABISysV_i386::PrepareTrivialCall(Thread &thread, addr_t sp,
211 addr_t func_addr, addr_t return_addr,
212 llvm::ArrayRef<addr_t> args) const {
213 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
218 uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
219 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
220 uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
221 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
223 // While using register info to write a register value to memory, the
224 // register info just needs to have the correct size of a 32 bit register,
225 // the actual register it pertains to is not important, just the size needs
226 // to be correct. "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) {
243 reg_value.SetUInt32(arg);
244 error = reg_ctx->WriteRegisterValueToMemory(
245 reg_info_32, arg_pos, reg_info_32->byte_size, reg_value);
251 // The return address is pushed onto the stack
253 reg_value.SetUInt32(return_addr);
254 error = reg_ctx->WriteRegisterValueToMemory(
255 reg_info_32, sp, reg_info_32->byte_size, reg_value);
259 // Setting %esp to the actual stack value.
260 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp))
263 // Setting %eip to the address of the called function.
264 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr))
270 static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width,
271 bool is_signed, Process *process,
272 addr_t ¤t_stack_argument) {
273 uint32_t byte_size = (bit_width + (8 - 1)) / 8;
279 if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size,
280 is_signed, scalar, error)) {
281 current_stack_argument += byte_size;
287 bool ABISysV_i386::GetArgumentValues(Thread &thread, ValueList &values) const {
288 unsigned int num_values = values.GetSize();
289 unsigned int value_index;
291 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
296 // Get pointer to the first stack argument
297 addr_t sp = reg_ctx->GetSP(0);
301 addr_t current_stack_argument = sp + 4; // jump over return address
303 for (value_index = 0; value_index < num_values; ++value_index) {
304 Value *value = values.GetValueAtIndex(value_index);
309 // Currently: Support for extracting values with Clang QualTypes only.
310 CompilerType compiler_type(value->GetCompilerType());
311 llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
314 if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
315 ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed,
316 thread.GetProcess().get(), current_stack_argument);
317 } else if (compiler_type.IsPointerType()) {
318 ReadIntegerArgument(value->GetScalar(), *bit_size, false,
319 thread.GetProcess().get(), current_stack_argument);
326 Status ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
327 lldb::ValueObjectSP &new_value_sp) {
330 error.SetErrorString("Empty value object for return value.");
334 CompilerType compiler_type = new_value_sp->GetCompilerType();
335 if (!compiler_type) {
336 error.SetErrorString("Null clang type for return value.");
340 const uint32_t type_flags = compiler_type.GetTypeInfo();
341 Thread *thread = frame_sp->GetThread().get();
342 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
345 size_t num_bytes = new_value_sp->GetData(data, data_error);
346 bool register_write_successful = true;
348 if (data_error.Fail()) {
349 error.SetErrorStringWithFormat(
350 "Couldn't convert return value to raw data: %s",
351 data_error.AsCString());
355 // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
356 // The terminology 'Fundamental Data Types' used here is adopted from Table
357 // 2.1 of the reference document (specified on top of this file)
359 if (type_flags & eTypeIsPointer) // 'Pointer'
361 if (num_bytes != sizeof(uint32_t)) {
362 error.SetErrorString("Pointer to be returned is not 4 bytes wide");
365 lldb::offset_t offset = 0;
366 const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
367 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
368 register_write_successful =
369 reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
370 } else if ((type_flags & eTypeIsScalar) ||
371 (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
373 lldb::offset_t offset = 0;
374 const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
376 if (type_flags & eTypeIsInteger) // 'Integral' except enum
382 // For clang::BuiltinType::UInt128 & Int128 ToDo: Need to decide how to
386 uint32_t raw_value_low = data.GetMaxU32(&offset, 4);
387 const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0);
388 uint32_t raw_value_high = data.GetMaxU32(&offset, num_bytes - offset);
389 register_write_successful =
390 (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value_low) &&
391 reg_ctx->WriteRegisterFromUnsigned(edx_info, raw_value_high));
397 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
398 register_write_successful =
399 reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
403 } else if (type_flags & eTypeIsEnumeration) // handles enum
405 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
406 register_write_successful =
407 reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value);
408 } else if (type_flags & eTypeIsFloat) // 'Floating Point'
410 RegisterValue st0_value, fstat_value, ftag_value;
411 const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
412 const RegisterInfo *fstat_info =
413 reg_ctx->GetRegisterInfoByName("fstat", 0);
414 const RegisterInfo *ftag_info = reg_ctx->GetRegisterInfoByName("ftag", 0);
416 /* According to Page 3-12 of document
417 System V Application Binary Interface, Intel386 Architecture Processor
418 Supplement, Fourth Edition
419 To return Floating Point values, all st% registers except st0 should be
420 empty after exiting from
421 a function. This requires setting fstat and ftag registers to specific
423 fstat: The TOP field of fstat should be set to a value [0,7]. ABI doesn't
425 value of TOP in case of function return. Hence, we set the TOP field to 7
427 uint32_t value_fstat_u32 = 0x00003800;
429 /* ftag: Implication of setting TOP to 7 and indicating all st% registers
430 empty except st0 is to set
431 7th bit of 4th byte of FXSAVE area to 1 and all other bits of this byte to
432 0. This is in accordance
433 with the document Intel 64 and IA-32 Architectures Software Developer's
434 Manual, January 2015 */
435 uint32_t value_ftag_u32 = 0x00000080;
437 if (num_bytes <= 12) // handles float, double, long double, __float80
439 long double value_long_dbl = 0.0;
441 value_long_dbl = data.GetFloat(&offset);
442 else if (num_bytes == 8)
443 value_long_dbl = data.GetDouble(&offset);
444 else if (num_bytes == 12)
445 value_long_dbl = data.GetLongDouble(&offset);
447 error.SetErrorString("Invalid number of bytes for this return type");
450 st0_value.SetLongDouble(value_long_dbl);
451 fstat_value.SetUInt32(value_fstat_u32);
452 ftag_value.SetUInt32(value_ftag_u32);
453 register_write_successful =
454 reg_ctx->WriteRegister(st0_info, st0_value) &&
455 reg_ctx->WriteRegister(fstat_info, fstat_value) &&
456 reg_ctx->WriteRegister(ftag_info, ftag_value);
457 } else if (num_bytes == 16) // handles __float128
459 error.SetErrorString("Implementation is missing for this clang type.");
462 // Neither 'Integral' nor 'Floating Point'. If flow reaches here then
463 // check type_flags. This type_flags is not a valid type.
464 error.SetErrorString("Invalid clang type");
467 /* 'Complex Floating Point', 'Packed', 'Decimal Floating Point' and
468 'Aggregate' data types
469 are yet to be implemented */
470 error.SetErrorString("Currently only Integral and Floating Point clang "
471 "types are supported.");
473 if (!register_write_successful)
474 error.SetErrorString("Register writing failed");
478 ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
479 Thread &thread, CompilerType &return_compiler_type) const {
480 ValueObjectSP return_valobj_sp;
483 if (!return_compiler_type)
484 return return_valobj_sp;
486 value.SetCompilerType(return_compiler_type);
488 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
490 return return_valobj_sp;
492 const uint32_t type_flags = return_compiler_type.GetTypeInfo();
495 reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
497 reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
499 // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
500 // The terminology 'Fundamental Data Types' used here is adopted from Table
501 // 2.1 of the reference document (specified on top of this file)
503 if (type_flags & eTypeIsPointer) // 'Pointer'
506 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
508 value.SetValueType(Value::eValueTypeScalar);
509 value.GetScalar() = ptr;
510 return_valobj_sp = ValueObjectConstResult::Create(
511 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
512 } else if ((type_flags & eTypeIsScalar) ||
513 (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
515 value.SetValueType(Value::eValueTypeScalar);
516 llvm::Optional<uint64_t> byte_size =
517 return_compiler_type.GetByteSize(nullptr);
519 return return_valobj_sp;
520 bool success = false;
522 if (type_flags & eTypeIsInteger) // 'Integral' except enum
524 const bool is_signed = ((type_flags & eTypeIsSigned) != 0);
526 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
529 (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) &
533 switch (*byte_size) {
538 // For clang::BuiltinType::UInt128 & Int128 ToDo: Need to decide how to
544 value.GetScalar() = (int64_t)(raw_value);
546 value.GetScalar() = (uint64_t)(raw_value);
552 value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
554 value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
560 value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
562 value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
568 value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
570 value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
576 return_valobj_sp = ValueObjectConstResult::Create(
577 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
578 } else if (type_flags & eTypeIsEnumeration) // handles enum
581 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
583 value.SetValueType(Value::eValueTypeScalar);
584 value.GetScalar() = enm;
585 return_valobj_sp = ValueObjectConstResult::Create(
586 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
587 } else if (type_flags & eTypeIsFloat) // 'Floating Point'
589 if (*byte_size <= 12) // handles float, double, long double, __float80
591 const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
592 RegisterValue st0_value;
594 if (reg_ctx->ReadRegister(st0_info, st0_value)) {
596 if (st0_value.GetData(data)) {
597 lldb::offset_t offset = 0;
598 long double value_long_double = data.GetLongDouble(&offset);
601 if (*byte_size == 4) {
602 float value_float = (float)value_long_double;
603 value.GetScalar() = value_float;
605 } else if (*byte_size == 8) {
607 // On Android Platform: long double is also 8 bytes It will be
608 // handled here only.
609 double value_double = (double)value_long_double;
610 value.GetScalar() = value_double;
612 } else if (*byte_size == 12) {
613 // long double and __float80 are 12 bytes on i386.
614 value.GetScalar() = value_long_double;
621 return_valobj_sp = ValueObjectConstResult::Create(
622 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
623 } else if (*byte_size == 16) // handles __float128
625 lldb::addr_t storage_addr = (uint32_t)(
626 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
628 return_valobj_sp = ValueObjectMemory::Create(
629 &thread, "", Address(storage_addr, nullptr), return_compiler_type);
631 } else // Neither 'Integral' nor 'Floating Point'
633 // If flow reaches here then check type_flags This type_flags is
636 } else if (type_flags & eTypeIsComplex) // 'Complex Floating Point'
638 // ToDo: Yet to be implemented
639 } else if (type_flags & eTypeIsVector) // 'Packed'
641 llvm::Optional<uint64_t> byte_size =
642 return_compiler_type.GetByteSize(nullptr);
643 if (byte_size && *byte_size > 0) {
644 const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
645 if (vec_reg == nullptr)
646 vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
649 if (*byte_size <= vec_reg->byte_size) {
650 ProcessSP process_sp(thread.GetProcess());
652 std::unique_ptr<DataBufferHeap> heap_data_ap(
653 new DataBufferHeap(*byte_size, 0));
654 const ByteOrder byte_order = process_sp->GetByteOrder();
655 RegisterValue reg_value;
656 if (reg_ctx->ReadRegister(vec_reg, reg_value)) {
658 if (reg_value.GetAsMemoryData(vec_reg, heap_data_ap->GetBytes(),
659 heap_data_ap->GetByteSize(),
660 byte_order, error)) {
661 DataExtractor data(DataBufferSP(heap_data_ap.release()),
662 byte_order, process_sp->GetTarget()
664 .GetAddressByteSize());
665 return_valobj_sp = ValueObjectConstResult::Create(
666 &thread, return_compiler_type, ConstString(""), data);
670 } else if (*byte_size <= vec_reg->byte_size * 2) {
671 const RegisterInfo *vec_reg2 =
672 reg_ctx->GetRegisterInfoByName("xmm1", 0);
674 ProcessSP process_sp(thread.GetProcess());
676 std::unique_ptr<DataBufferHeap> heap_data_ap(
677 new DataBufferHeap(*byte_size, 0));
678 const ByteOrder byte_order = process_sp->GetByteOrder();
679 RegisterValue reg_value;
680 RegisterValue reg_value2;
681 if (reg_ctx->ReadRegister(vec_reg, reg_value) &&
682 reg_ctx->ReadRegister(vec_reg2, reg_value2)) {
685 if (reg_value.GetAsMemoryData(vec_reg, heap_data_ap->GetBytes(),
686 vec_reg->byte_size, byte_order,
688 reg_value2.GetAsMemoryData(
689 vec_reg2, heap_data_ap->GetBytes() + vec_reg->byte_size,
690 heap_data_ap->GetByteSize() - vec_reg->byte_size,
691 byte_order, error)) {
692 DataExtractor data(DataBufferSP(heap_data_ap.release()),
693 byte_order, process_sp->GetTarget()
695 .GetAddressByteSize());
696 return_valobj_sp = ValueObjectConstResult::Create(
697 &thread, return_compiler_type, ConstString(""), data);
705 } else // 'Decimal Floating Point'
707 // ToDo: Yet to be implemented
709 return return_valobj_sp;
712 ValueObjectSP ABISysV_i386::GetReturnValueObjectImpl(
713 Thread &thread, CompilerType &return_compiler_type) const {
714 ValueObjectSP return_valobj_sp;
716 if (!return_compiler_type)
717 return return_valobj_sp;
719 ExecutionContext exe_ctx(thread.shared_from_this());
720 return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
721 if (return_valobj_sp)
722 return return_valobj_sp;
724 RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
726 return return_valobj_sp;
728 if (return_compiler_type.IsAggregateType()) {
730 reg_ctx_sp->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
731 lldb::addr_t storage_addr = (uint32_t)(
732 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
734 return_valobj_sp = ValueObjectMemory::Create(
735 &thread, "", Address(storage_addr, nullptr), return_compiler_type);
738 return return_valobj_sp;
741 // This defines CFA as esp+4
742 // The saved pc is at CFA-4 (i.e. esp+0)
743 // The saved esp is CFA+0
745 bool ABISysV_i386::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
747 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
749 uint32_t sp_reg_num = dwarf_esp;
750 uint32_t pc_reg_num = dwarf_eip;
752 UnwindPlan::RowSP row(new UnwindPlan::Row);
753 row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4);
754 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
755 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
756 unwind_plan.AppendRow(row);
757 unwind_plan.SetSourceName("i386 at-func-entry default");
758 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
762 // This defines CFA as ebp+8
763 // The saved pc is at CFA-4 (i.e. ebp+4)
764 // The saved ebp is at CFA-8 (i.e. ebp+0)
765 // The saved esp is CFA+0
767 bool ABISysV_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
769 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
771 uint32_t fp_reg_num = dwarf_ebp;
772 uint32_t sp_reg_num = dwarf_esp;
773 uint32_t pc_reg_num = dwarf_eip;
775 UnwindPlan::RowSP row(new UnwindPlan::Row);
776 const int32_t ptr_size = 4;
778 row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
781 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
782 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
783 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
785 unwind_plan.AppendRow(row);
786 unwind_plan.SetSourceName("i386 default unwind plan");
787 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
788 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
792 // According to "Register Usage" in reference document (specified on top of
793 // this source file) ebx, ebp, esi, edi and esp registers are preserved i.e.
794 // non-volatile i.e. callee-saved on i386
795 bool ABISysV_i386::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
799 // Saved registers are ebx, ebp, esi, edi, esp, eip
800 const char *name = reg_info->name;
801 if (name[0] == 'e') {
804 if (name[2] == 'x' || name[2] == 'p')
805 return name[3] == '\0';
809 return name[3] == '\0';
813 return name[3] == '\0';
816 if (name[2] == 'i' || name[2] == 'p')
817 return name[3] == '\0';
822 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
824 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
826 if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
832 void ABISysV_i386::Initialize() {
833 PluginManager::RegisterPlugin(
834 GetPluginNameStatic(), "System V ABI for i386 targets", CreateInstance);
837 void ABISysV_i386::Terminate() {
838 PluginManager::UnregisterPlugin(CreateInstance);
841 //------------------------------------------------------------------
842 // PluginInterface protocol
843 //------------------------------------------------------------------
845 lldb_private::ConstString ABISysV_i386::GetPluginNameStatic() {
846 static ConstString g_name("sysv-i386");
850 lldb_private::ConstString ABISysV_i386::GetPluginName() {
851 return GetPluginNameStatic();