ABIMacOSX_i386.cpp revision 263367
1//===-- ABIMacOSX_i386.cpp --------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "ABIMacOSX_i386.h" 11 12#include "lldb/Core/ConstString.h" 13#include "lldb/Core/Error.h" 14#include "lldb/Core/Module.h" 15#include "lldb/Core/PluginManager.h" 16#include "lldb/Core/RegisterValue.h" 17#include "lldb/Core/Scalar.h" 18#include "lldb/Core/ValueObjectConstResult.h" 19#include "lldb/Symbol/ClangASTContext.h" 20#include "lldb/Symbol/UnwindPlan.h" 21#include "lldb/Target/Process.h" 22#include "lldb/Target/RegisterContext.h" 23#include "lldb/Target/Target.h" 24#include "lldb/Target/Thread.h" 25 26#include "llvm/ADT/Triple.h" 27 28#include <vector> 29 30using namespace lldb; 31using namespace lldb_private; 32 33enum 34{ 35 gcc_eax = 0, 36 gcc_ecx, 37 gcc_edx, 38 gcc_ebx, 39 gcc_ebp, 40 gcc_esp, 41 gcc_esi, 42 gcc_edi, 43 gcc_eip, 44 gcc_eflags 45}; 46 47enum 48{ 49 dwarf_eax = 0, 50 dwarf_ecx, 51 dwarf_edx, 52 dwarf_ebx, 53 dwarf_esp, 54 dwarf_ebp, 55 dwarf_esi, 56 dwarf_edi, 57 dwarf_eip, 58 dwarf_eflags, 59 dwarf_stmm0 = 11, 60 dwarf_stmm1, 61 dwarf_stmm2, 62 dwarf_stmm3, 63 dwarf_stmm4, 64 dwarf_stmm5, 65 dwarf_stmm6, 66 dwarf_stmm7, 67 dwarf_xmm0 = 21, 68 dwarf_xmm1, 69 dwarf_xmm2, 70 dwarf_xmm3, 71 dwarf_xmm4, 72 dwarf_xmm5, 73 dwarf_xmm6, 74 dwarf_xmm7, 75 dwarf_ymm0 = dwarf_xmm0, 76 dwarf_ymm1 = dwarf_xmm1, 77 dwarf_ymm2 = dwarf_xmm2, 78 dwarf_ymm3 = dwarf_xmm3, 79 dwarf_ymm4 = dwarf_xmm4, 80 dwarf_ymm5 = dwarf_xmm5, 81 dwarf_ymm6 = dwarf_xmm6, 82 dwarf_ymm7 = dwarf_xmm7 83}; 84 85enum 86{ 87 gdb_eax = 0, 88 gdb_ecx = 1, 89 gdb_edx = 2, 90 gdb_ebx = 3, 91 gdb_esp = 4, 92 gdb_ebp = 5, 93 gdb_esi = 6, 94 gdb_edi = 7, 95 gdb_eip = 8, 96 gdb_eflags = 9, 97 gdb_cs = 10, 98 gdb_ss = 11, 99 gdb_ds = 12, 100 gdb_es = 13, 101 gdb_fs = 14, 102 gdb_gs = 15, 103 gdb_stmm0 = 16, 104 gdb_stmm1 = 17, 105 gdb_stmm2 = 18, 106 gdb_stmm3 = 19, 107 gdb_stmm4 = 20, 108 gdb_stmm5 = 21, 109 gdb_stmm6 = 22, 110 gdb_stmm7 = 23, 111 gdb_fctrl = 24, gdb_fcw = gdb_fctrl, 112 gdb_fstat = 25, gdb_fsw = gdb_fstat, 113 gdb_ftag = 26, gdb_ftw = gdb_ftag, 114 gdb_fiseg = 27, gdb_fpu_cs = gdb_fiseg, 115 gdb_fioff = 28, gdb_ip = gdb_fioff, 116 gdb_foseg = 29, gdb_fpu_ds = gdb_foseg, 117 gdb_fooff = 30, gdb_dp = gdb_fooff, 118 gdb_fop = 31, 119 gdb_xmm0 = 32, 120 gdb_xmm1 = 33, 121 gdb_xmm2 = 34, 122 gdb_xmm3 = 35, 123 gdb_xmm4 = 36, 124 gdb_xmm5 = 37, 125 gdb_xmm6 = 38, 126 gdb_xmm7 = 39, 127 gdb_mxcsr = 40, 128 gdb_mm0 = 41, 129 gdb_mm1 = 42, 130 gdb_mm2 = 43, 131 gdb_mm3 = 44, 132 gdb_mm4 = 45, 133 gdb_mm5 = 46, 134 gdb_mm6 = 47, 135 gdb_mm7 = 48, 136 gdb_ymm0 = gdb_xmm0, 137 gdb_ymm1 = gdb_xmm1, 138 gdb_ymm2 = gdb_xmm2, 139 gdb_ymm3 = gdb_xmm3, 140 gdb_ymm4 = gdb_xmm4, 141 gdb_ymm5 = gdb_xmm5, 142 gdb_ymm6 = gdb_xmm6, 143 gdb_ymm7 = gdb_xmm7 144}; 145 146 147static RegisterInfo g_register_infos[] = 148{ 149 // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS 150 // ====== ======= == === ============= ============ ===================== ===================== ============================ ==================== ====================== ========== =============== 151 { "eax", NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_eax , dwarf_eax , LLDB_INVALID_REGNUM , gdb_eax , LLDB_INVALID_REGNUM }, NULL, NULL}, 152 { "ebx" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , gdb_ebx , LLDB_INVALID_REGNUM }, NULL, NULL}, 153 { "ecx" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_ecx , dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , gdb_ecx , LLDB_INVALID_REGNUM }, NULL, NULL}, 154 { "edx" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_edx , dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , gdb_edx , LLDB_INVALID_REGNUM }, NULL, NULL}, 155 { "esi" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_esi , dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , gdb_esi , LLDB_INVALID_REGNUM }, NULL, NULL}, 156 { "edi" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_edi , dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , gdb_edi , LLDB_INVALID_REGNUM }, NULL, NULL}, 157 { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { gcc_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , gdb_ebp , LLDB_INVALID_REGNUM }, NULL, NULL}, 158 { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { gcc_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , gdb_esp , LLDB_INVALID_REGNUM }, NULL, NULL}, 159 { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { gcc_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , gdb_eip , LLDB_INVALID_REGNUM }, NULL, NULL}, 160 { "eflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags , LLDB_INVALID_REGNUM }, NULL, NULL}, 161 { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs , LLDB_INVALID_REGNUM }, NULL, NULL}, 162 { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ss , LLDB_INVALID_REGNUM }, NULL, NULL}, 163 { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds , LLDB_INVALID_REGNUM }, NULL, NULL}, 164 { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_es , LLDB_INVALID_REGNUM }, NULL, NULL}, 165 { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fs , LLDB_INVALID_REGNUM }, NULL, NULL}, 166 { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gs , LLDB_INVALID_REGNUM }, NULL, NULL}, 167 { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm0 , LLDB_INVALID_REGNUM , gdb_stmm0 , LLDB_INVALID_REGNUM }, NULL, NULL}, 168 { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm1 , LLDB_INVALID_REGNUM , gdb_stmm1 , LLDB_INVALID_REGNUM }, NULL, NULL}, 169 { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm2 , LLDB_INVALID_REGNUM , gdb_stmm2 , LLDB_INVALID_REGNUM }, NULL, NULL}, 170 { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm3 , LLDB_INVALID_REGNUM , gdb_stmm3 , LLDB_INVALID_REGNUM }, NULL, NULL}, 171 { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm4 , LLDB_INVALID_REGNUM , gdb_stmm4 , LLDB_INVALID_REGNUM }, NULL, NULL}, 172 { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm5 , LLDB_INVALID_REGNUM , gdb_stmm5 , LLDB_INVALID_REGNUM }, NULL, NULL}, 173 { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm6 , LLDB_INVALID_REGNUM , gdb_stmm6 , LLDB_INVALID_REGNUM }, NULL, NULL}, 174 { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm7 , LLDB_INVALID_REGNUM , gdb_stmm7 , LLDB_INVALID_REGNUM }, NULL, NULL}, 175 { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fctrl , LLDB_INVALID_REGNUM }, NULL, NULL}, 176 { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fstat , LLDB_INVALID_REGNUM }, NULL, NULL}, 177 { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ftag , LLDB_INVALID_REGNUM }, NULL, NULL}, 178 { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fiseg , LLDB_INVALID_REGNUM }, NULL, NULL}, 179 { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fioff , LLDB_INVALID_REGNUM }, NULL, NULL}, 180 { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_foseg , LLDB_INVALID_REGNUM }, NULL, NULL}, 181 { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fooff , LLDB_INVALID_REGNUM }, NULL, NULL}, 182 { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fop , LLDB_INVALID_REGNUM }, NULL, NULL}, 183 { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0 , LLDB_INVALID_REGNUM , gdb_xmm0 , LLDB_INVALID_REGNUM }, NULL, NULL}, 184 { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1 , LLDB_INVALID_REGNUM , gdb_xmm1 , LLDB_INVALID_REGNUM }, NULL, NULL}, 185 { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2 , LLDB_INVALID_REGNUM , gdb_xmm2 , LLDB_INVALID_REGNUM }, NULL, NULL}, 186 { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3 , LLDB_INVALID_REGNUM , gdb_xmm3 , LLDB_INVALID_REGNUM }, NULL, NULL}, 187 { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4 , LLDB_INVALID_REGNUM , gdb_xmm4 , LLDB_INVALID_REGNUM }, NULL, NULL}, 188 { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5 , LLDB_INVALID_REGNUM , gdb_xmm5 , LLDB_INVALID_REGNUM }, NULL, NULL}, 189 { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6 , LLDB_INVALID_REGNUM , gdb_xmm6 , LLDB_INVALID_REGNUM }, NULL, NULL}, 190 { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7 , LLDB_INVALID_REGNUM , gdb_xmm7 , LLDB_INVALID_REGNUM }, NULL, NULL}, 191 { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_mxcsr , LLDB_INVALID_REGNUM }, NULL, NULL}, 192 { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0 , LLDB_INVALID_REGNUM , gdb_ymm0 , LLDB_INVALID_REGNUM }, NULL, NULL}, 193 { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1 , LLDB_INVALID_REGNUM , gdb_ymm1 , LLDB_INVALID_REGNUM }, NULL, NULL}, 194 { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2 , LLDB_INVALID_REGNUM , gdb_ymm2 , LLDB_INVALID_REGNUM }, NULL, NULL}, 195 { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3 , LLDB_INVALID_REGNUM , gdb_ymm3 , LLDB_INVALID_REGNUM }, NULL, NULL}, 196 { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4 , LLDB_INVALID_REGNUM , gdb_ymm4 , LLDB_INVALID_REGNUM }, NULL, NULL}, 197 { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5 , LLDB_INVALID_REGNUM , gdb_ymm5 , LLDB_INVALID_REGNUM }, NULL, NULL}, 198 { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6 , LLDB_INVALID_REGNUM , gdb_ymm6 , LLDB_INVALID_REGNUM }, NULL, NULL}, 199 { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7 , LLDB_INVALID_REGNUM , gdb_ymm7 , LLDB_INVALID_REGNUM }, NULL, NULL} 200}; 201 202static const uint32_t k_num_register_infos = sizeof(g_register_infos)/sizeof(RegisterInfo); 203static bool g_register_info_names_constified = false; 204 205const lldb_private::RegisterInfo * 206ABIMacOSX_i386::GetRegisterInfoArray (uint32_t &count) 207{ 208 // Make the C-string names and alt_names for the register infos into const 209 // C-string values by having the ConstString unique the names in the global 210 // constant C-string pool. 211 if (!g_register_info_names_constified) 212 { 213 g_register_info_names_constified = true; 214 for (uint32_t i=0; i<k_num_register_infos; ++i) 215 { 216 if (g_register_infos[i].name) 217 g_register_infos[i].name = ConstString(g_register_infos[i].name).GetCString(); 218 if (g_register_infos[i].alt_name) 219 g_register_infos[i].alt_name = ConstString(g_register_infos[i].alt_name).GetCString(); 220 } 221 } 222 count = k_num_register_infos; 223 return g_register_infos; 224} 225 226size_t 227ABIMacOSX_i386::GetRedZoneSize () const 228{ 229 return 0; 230} 231 232//------------------------------------------------------------------ 233// Static Functions 234//------------------------------------------------------------------ 235ABISP 236ABIMacOSX_i386::CreateInstance (const ArchSpec &arch) 237{ 238 static ABISP g_abi_mac_sp; 239 static ABISP g_abi_other_sp; 240 if (arch.GetTriple().getArch() == llvm::Triple::x86) 241 { 242 if (arch.GetTriple().isOSDarwin()) 243 { 244 if (!g_abi_mac_sp) 245 g_abi_mac_sp.reset (new ABIMacOSX_i386(true)); 246 return g_abi_mac_sp; 247 } 248 else 249 { 250 if (!g_abi_other_sp) 251 g_abi_other_sp.reset (new ABIMacOSX_i386(false)); 252 return g_abi_other_sp; 253 } 254 } 255 return ABISP(); 256} 257 258bool 259ABIMacOSX_i386::PrepareTrivialCall (Thread &thread, 260 addr_t sp, 261 addr_t func_addr, 262 addr_t return_addr, 263 llvm::ArrayRef<addr_t> args) const 264{ 265 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 266 if (!reg_ctx) 267 return false; 268 uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 269 uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 270 271 // When writing a register value down to memory, the register info used 272 // to write memory just needs to have the correct size of a 32 bit register, 273 // the actual register it pertains to is not important, just the size needs 274 // to be correct. Here we use "eax"... 275 const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax"); 276 if (!reg_info_32) 277 return false; // TODO this should actually never happen 278 279 // Make room for the argument(s) on the stack 280 281 Error error; 282 RegisterValue reg_value; 283 284 // Write any arguments onto the stack 285 sp -= 4 * args.size(); 286 287 // Align the SP 288 sp &= ~(16ull-1ull); // 16-byte alignment 289 290 addr_t arg_pos = sp; 291 292 for (addr_t arg : args) 293 { 294 reg_value.SetUInt32(arg); 295 error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 296 arg_pos, 297 reg_info_32->byte_size, 298 reg_value); 299 if (error.Fail()) 300 return false; 301 arg_pos += 4; 302 } 303 304 // The return address is pushed onto the stack (yes after we just set the 305 // alignment above!). 306 sp -= 4; 307 reg_value.SetUInt32(return_addr); 308 error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 309 sp, 310 reg_info_32->byte_size, 311 reg_value); 312 if (error.Fail()) 313 return false; 314 315 // %esp is set to the actual stack value. 316 317 if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_num, sp)) 318 return false; 319 320 // %eip is set to the address of the called function. 321 322 if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_num, func_addr)) 323 return false; 324 325 return true; 326} 327 328bool 329ABIMacOSX_i386::PrepareNormalCall (Thread &thread, 330 addr_t sp, 331 addr_t func_addr, 332 addr_t return_addr, 333 ValueList &args) const 334{ 335 ExecutionContext exe_ctx (thread.shared_from_this()); 336 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 337 if (!reg_ctx) 338 return false; 339 340 Process *process = exe_ctx.GetProcessPtr(); 341 Error error; 342 uint32_t fp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); 343 uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 344 uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 345 346 // Do the argument layout 347 348 std::vector <uint32_t> argLayout; // 4-byte chunks, as discussed in the ABI Function Call Guide 349 350 size_t numArgs = args.GetSize(); 351 size_t index; 352 353 for (index = 0; index < numArgs; ++index) 354 { 355 Value *val = args.GetValueAtIndex(index); 356 357 if (!val) 358 return false; 359 360 switch (val->GetValueType()) 361 { 362 case Value::eValueTypeScalar: 363 { 364 Scalar &scalar = val->GetScalar(); 365 switch (scalar.GetType()) 366 { 367 case Scalar::e_void: 368 return false; 369 case Scalar::e_sint: 370 case Scalar::e_uint: 371 case Scalar::e_slong: 372 case Scalar::e_ulong: 373 case Scalar::e_slonglong: 374 case Scalar::e_ulonglong: 375 { 376 uint64_t data = scalar.ULongLong(); 377 378 switch (scalar.GetByteSize()) 379 { 380 default: 381 return false; 382 case 1: 383 argLayout.push_back((uint32_t)(data & 0xffull)); 384 break; 385 case 2: 386 argLayout.push_back((uint32_t)(data & 0xffffull)); 387 break; 388 case 4: 389 argLayout.push_back((uint32_t)(data & 0xffffffffull)); 390 break; 391 case 8: 392 argLayout.push_back((uint32_t)(data & 0xffffffffull)); 393 argLayout.push_back((uint32_t)(data >> 32)); 394 break; 395 } 396 } 397 break; 398 case Scalar::e_float: 399 { 400 float data = scalar.Float(); 401 uint32_t dataRaw = *((uint32_t*)(&data)); 402 argLayout.push_back(dataRaw); 403 } 404 break; 405 case Scalar::e_double: 406 { 407 double data = scalar.Double(); 408 uint32_t *dataRaw = ((uint32_t*)(&data)); 409 argLayout.push_back(dataRaw[0]); 410 argLayout.push_back(dataRaw[1]); 411 } 412 break; 413 case Scalar::e_long_double: 414 { 415 long double data = scalar.Double(); 416 uint32_t *dataRaw = ((uint32_t*)(&data)); 417 while ((argLayout.size() * 4) & 0xf) 418 argLayout.push_back(0); 419 argLayout.push_back(dataRaw[0]); 420 argLayout.push_back(dataRaw[1]); 421 argLayout.push_back(dataRaw[2]); 422 argLayout.push_back(dataRaw[3]); 423 } 424 break; 425 } 426 } 427 break; 428 case Value::eValueTypeHostAddress: 429 { 430 ClangASTType clang_type (val->GetClangType()); 431 if (clang_type) 432 { 433 uint32_t cstr_length = 0; 434 if (clang_type.IsCStringType (cstr_length)) 435 { 436 const char *cstr = (const char*)val->GetScalar().ULongLong(); 437 cstr_length = strlen(cstr); 438 439 // Push the string onto the stack immediately. 440 441 sp -= (cstr_length + 1); 442 443 if (process->WriteMemory(sp, cstr, cstr_length + 1, error) != (cstr_length + 1)) 444 return false; 445 446 // Put the address of the string into the argument array. 447 448 argLayout.push_back((uint32_t)(sp & 0xffffffff)); 449 } 450 else 451 { 452 return false; 453 } 454 } 455 break; 456 } 457 break; 458 case Value::eValueTypeFileAddress: 459 case Value::eValueTypeLoadAddress: 460 default: 461 return false; 462 } 463 } 464 465 // Make room for the arguments on the stack 466 467 sp -= 4 * argLayout.size(); 468 469 // Align the SP 470 471 sp &= ~(16ull-1ull); // 16-byte alignment 472 473 // Write the arguments on the stack 474 475 size_t numChunks = argLayout.size(); 476 477 for (index = 0; index < numChunks; ++index) 478 if (process->WriteMemory(sp + (index * 4), &argLayout[index], sizeof(uint32_t), error) != sizeof(uint32_t)) 479 return false; 480 481 // The return address is pushed onto the stack. 482 483 sp -= 4; 484 uint32_t returnAddressU32 = return_addr; 485 if (process->WriteMemory (sp, &returnAddressU32, sizeof(returnAddressU32), error) != sizeof(returnAddressU32)) 486 return false; 487 488 // %esp is set to the actual stack value. 489 490 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp)) 491 return false; 492 493 // %ebp is set to a fake value, in our case 0x0x00000000 494 495 if (!reg_ctx->WriteRegisterFromUnsigned(fp_reg_num, 0x00000000)) 496 return false; 497 498 // %eip is set to the address of the called function. 499 500 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr)) 501 return false; 502 503 return true; 504} 505 506static bool 507ReadIntegerArgument (Scalar &scalar, 508 unsigned int bit_width, 509 bool is_signed, 510 Process *process, 511 addr_t ¤t_stack_argument) 512{ 513 514 uint32_t byte_size = (bit_width + (8-1))/8; 515 Error error; 516 if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error)) 517 { 518 current_stack_argument += byte_size; 519 return true; 520 } 521 return false; 522} 523 524bool 525ABIMacOSX_i386::GetArgumentValues (Thread &thread, 526 ValueList &values) const 527{ 528 unsigned int num_values = values.GetSize(); 529 unsigned int value_index; 530 531 // Get the pointer to the first stack argument so we have a place to start 532 // when reading data 533 534 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 535 536 if (!reg_ctx) 537 return false; 538 539 addr_t sp = reg_ctx->GetSP(0); 540 541 if (!sp) 542 return false; 543 544 addr_t current_stack_argument = sp + 4; // jump over return address 545 546 for (value_index = 0; 547 value_index < num_values; 548 ++value_index) 549 { 550 Value *value = values.GetValueAtIndex(value_index); 551 552 if (!value) 553 return false; 554 555 // We currently only support extracting values with Clang QualTypes. 556 // Do we care about others? 557 ClangASTType clang_type (value->GetClangType()); 558 if (clang_type) 559 { 560 bool is_signed; 561 562 if (clang_type.IsIntegerType (is_signed)) 563 { 564 ReadIntegerArgument(value->GetScalar(), 565 clang_type.GetBitSize(), 566 is_signed, 567 thread.GetProcess().get(), 568 current_stack_argument); 569 } 570 else if (clang_type.IsPointerType()) 571 { 572 ReadIntegerArgument(value->GetScalar(), 573 clang_type.GetBitSize(), 574 false, 575 thread.GetProcess().get(), 576 current_stack_argument); 577 } 578 } 579 } 580 581 return true; 582} 583 584Error 585ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp) 586{ 587 Error error; 588 if (!new_value_sp) 589 { 590 error.SetErrorString("Empty value object for return value."); 591 return error; 592 } 593 594 ClangASTType clang_type = new_value_sp->GetClangType(); 595 if (!clang_type) 596 { 597 error.SetErrorString ("Null clang type for return value."); 598 return error; 599 } 600 601 Thread *thread = frame_sp->GetThread().get(); 602 603 bool is_signed; 604 uint32_t count; 605 bool is_complex; 606 607 RegisterContext *reg_ctx = thread->GetRegisterContext().get(); 608 609 bool set_it_simple = false; 610 if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) 611 { 612 DataExtractor data; 613 size_t num_bytes = new_value_sp->GetData(data); 614 lldb::offset_t offset = 0; 615 if (num_bytes <= 8) 616 { 617 const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0); 618 if (num_bytes <= 4) 619 { 620 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); 621 622 if (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value)) 623 set_it_simple = true; 624 } 625 else 626 { 627 uint32_t raw_value = data.GetMaxU32(&offset, 4); 628 629 if (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value)) 630 { 631 const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0); 632 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset); 633 634 if (reg_ctx->WriteRegisterFromUnsigned (edx_info, raw_value)) 635 set_it_simple = true; 636 } 637 } 638 } 639 else 640 { 641 error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); 642 } 643 } 644 else if (clang_type.IsFloatingPointType (count, is_complex)) 645 { 646 if (is_complex) 647 error.SetErrorString ("We don't support returning complex values at present"); 648 else 649 error.SetErrorString ("We don't support returning float values at present"); 650 } 651 652 if (!set_it_simple) 653 error.SetErrorString ("We only support setting simple integer return types at present."); 654 655 return error; 656} 657 658ValueObjectSP 659ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread, 660 ClangASTType &clang_type) const 661{ 662 Value value; 663 ValueObjectSP return_valobj_sp; 664 665 if (!clang_type) 666 return return_valobj_sp; 667 668 //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType()); 669 value.SetClangType (clang_type); 670 671 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 672 if (!reg_ctx) 673 return return_valobj_sp; 674 675 bool is_signed; 676 677 if (clang_type.IsIntegerType (is_signed)) 678 { 679 size_t bit_width = clang_type.GetBitSize(); 680 681 unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; 682 unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB]; 683 684 switch (bit_width) 685 { 686 default: 687 case 128: 688 // Scalar can't hold 128-bit literals, so we don't handle this 689 return return_valobj_sp; 690 case 64: 691 uint64_t raw_value; 692 raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff; 693 raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32; 694 if (is_signed) 695 value.GetScalar() = (int64_t)raw_value; 696 else 697 value.GetScalar() = (uint64_t)raw_value; 698 break; 699 case 32: 700 if (is_signed) 701 value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff); 702 else 703 value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff); 704 break; 705 case 16: 706 if (is_signed) 707 value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff); 708 else 709 value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff); 710 break; 711 case 8: 712 if (is_signed) 713 value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff); 714 else 715 value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff); 716 break; 717 } 718 } 719 else if (clang_type.IsPointerType ()) 720 { 721 unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; 722 uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff; 723 value.GetScalar() = ptr; 724 } 725 else 726 { 727 // not handled yet 728 return return_valobj_sp; 729 } 730 731 // If we get here, we have a valid Value, so make our ValueObject out of it: 732 733 return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), 734 value, 735 ConstString("")); 736 return return_valobj_sp; 737} 738 739bool 740ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) 741{ 742 unwind_plan.Clear(); 743 unwind_plan.SetRegisterKind (eRegisterKindDWARF); 744 745 uint32_t sp_reg_num = dwarf_esp; 746 uint32_t pc_reg_num = dwarf_eip; 747 748 UnwindPlan::RowSP row(new UnwindPlan::Row); 749 row->SetCFARegister (sp_reg_num); 750 row->SetCFAOffset (4); 751 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false); 752 unwind_plan.AppendRow (row); 753 unwind_plan.SetSourceName ("i386 at-func-entry default"); 754 unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); 755 return true; 756} 757 758bool 759ABIMacOSX_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) 760{ 761 unwind_plan.Clear (); 762 unwind_plan.SetRegisterKind (eRegisterKindDWARF); 763 764 uint32_t fp_reg_num = dwarf_ebp; 765 uint32_t sp_reg_num = dwarf_esp; 766 uint32_t pc_reg_num = dwarf_eip; 767 768 UnwindPlan::RowSP row(new UnwindPlan::Row); 769 const int32_t ptr_size = 4; 770 771 row->SetCFARegister (fp_reg_num); 772 row->SetCFAOffset (2 * ptr_size); 773 row->SetOffset (0); 774 775 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); 776 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); 777 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); 778 779 unwind_plan.AppendRow (row); 780 unwind_plan.SetSourceName ("i386 default unwind plan"); 781 unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); 782 unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); 783 return true; 784} 785 786bool 787ABIMacOSX_i386::RegisterIsVolatile (const RegisterInfo *reg_info) 788{ 789 return !RegisterIsCalleeSaved (reg_info); 790} 791 792// v. http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130-IA-32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4 793 794bool 795ABIMacOSX_i386::RegisterIsCalleeSaved (const RegisterInfo *reg_info) 796{ 797 if (reg_info) 798 { 799 // Saved registers are ebx, ebp, esi, edi, esp, eip 800 const char *name = reg_info->name; 801 if (name[0] == 'e') 802 { 803 switch (name[1]) 804 { 805 case 'b': 806 if (name[2] == 'x' || name[2] == 'p') 807 return name[3] == '\0'; 808 break; 809 case 'd': 810 if (name[2] == 'i') 811 return name[3] == '\0'; 812 break; 813 case 'i': 814 if (name[2] == 'p') 815 return name[3] == '\0'; 816 break; 817 case 's': 818 if (name[2] == 'i' || name[2] == 'p') 819 return name[3] == '\0'; 820 break; 821 } 822 } 823 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp 824 return true; 825 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp 826 return true; 827 if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc 828 return true; 829 } 830 return false; 831} 832 833void 834ABIMacOSX_i386::Initialize() 835{ 836 PluginManager::RegisterPlugin (GetPluginNameStatic(), 837 "Mac OS X ABI for i386 targets", 838 CreateInstance); 839} 840 841void 842ABIMacOSX_i386::Terminate() 843{ 844 PluginManager::UnregisterPlugin (CreateInstance); 845} 846 847lldb_private::ConstString 848ABIMacOSX_i386::GetPluginNameStatic () 849{ 850 static ConstString g_short_name("abi.macosx-i386"); 851 return g_short_name; 852 853} 854 855//------------------------------------------------------------------ 856// PluginInterface protocol 857//------------------------------------------------------------------ 858lldb_private::ConstString 859ABIMacOSX_i386::GetPluginName() 860{ 861 return GetPluginNameStatic(); 862} 863 864uint32_t 865ABIMacOSX_i386::GetPluginVersion() 866{ 867 return 1; 868} 869 870