ABIMacOSX_i386.cpp revision 263363
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 addr_t *arg1_ptr, 264 addr_t *arg2_ptr, 265 addr_t *arg3_ptr, 266 addr_t *arg4_ptr, 267 addr_t *arg5_ptr, 268 addr_t *arg6_ptr) const 269{ 270 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 271 if (!reg_ctx) 272 return false; 273 uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 274 uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 275 276 // When writing a register value down to memory, the register info used 277 // to write memory just needs to have the correct size of a 32 bit register, 278 // the actual register it pertains to is not important, just the size needs 279 // to be correct. Here we use "eax"... 280 const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax"); 281 if (!reg_info_32) 282 return false; // TODO this should actually never happen 283 284 // Make room for the argument(s) on the stack 285 286 Error error; 287 RegisterValue reg_value; 288 289 // Write any arguments onto the stack 290 if (arg1_ptr) 291 { 292 sp -= 4; 293 if (arg2_ptr) 294 { 295 sp -= 4; 296 if (arg3_ptr) 297 { 298 sp -= 4; 299 if (arg4_ptr) 300 { 301 sp -= 4; 302 if (arg5_ptr) 303 { 304 sp -= 4; 305 if (arg6_ptr) 306 { 307 sp -= 4; 308 } 309 } 310 } 311 } 312 } 313 } 314 315 // Align the SP 316 sp &= ~(16ull-1ull); // 16-byte alignment 317 318 if (arg1_ptr) 319 { 320 reg_value.SetUInt32(*arg1_ptr); 321 error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 322 sp, 323 reg_info_32->byte_size, 324 reg_value); 325 if (error.Fail()) 326 return false; 327 328 if (arg2_ptr) 329 { 330 reg_value.SetUInt32(*arg2_ptr); 331 // The register info used to write memory just needs to have the correct 332 // size of a 32 bit register, the actual register it pertains to is not 333 // important, just the size needs to be correct. Here we use "eax"... 334 error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 335 sp + 4, 336 reg_info_32->byte_size, 337 reg_value); 338 if (error.Fail()) 339 return false; 340 341 if (arg3_ptr) 342 { 343 reg_value.SetUInt32(*arg3_ptr); 344 // The register info used to write memory just needs to have the correct 345 // size of a 32 bit register, the actual register it pertains to is not 346 // important, just the size needs to be correct. Here we use "eax"... 347 error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 348 sp + 8, 349 reg_info_32->byte_size, 350 reg_value); 351 if (error.Fail()) 352 return false; 353 354 if (arg4_ptr) 355 { 356 reg_value.SetUInt32(*arg4_ptr); 357 // The register info used to write memory just needs to have the correct 358 // size of a 32 bit register, the actual register it pertains to is not 359 // important, just the size needs to be correct. Here we use "eax"... 360 error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 361 sp + 12, 362 reg_info_32->byte_size, 363 reg_value); 364 if (error.Fail()) 365 return false; 366 if (arg5_ptr) 367 { 368 reg_value.SetUInt32(*arg5_ptr); 369 // The register info used to write memory just needs to have the correct 370 // size of a 32 bit register, the actual register it pertains to is not 371 // important, just the size needs to be correct. Here we use "eax"... 372 error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 373 sp + 16, 374 reg_info_32->byte_size, 375 reg_value); 376 if (error.Fail()) 377 return false; 378 if (arg6_ptr) 379 { 380 reg_value.SetUInt32(*arg6_ptr); 381 // The register info used to write memory just needs to have the correct 382 // size of a 32 bit register, the actual register it pertains to is not 383 // important, just the size needs to be correct. Here we use "eax"... 384 error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 385 sp + 20, 386 reg_info_32->byte_size, 387 reg_value); 388 if (error.Fail()) 389 return false; 390 } 391 } 392 } 393 } 394 } 395 } 396 397 398 // The return address is pushed onto the stack (yes after we just set the 399 // alignment above!). 400 sp -= 4; 401 reg_value.SetUInt32(return_addr); 402 error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 403 sp, 404 reg_info_32->byte_size, 405 reg_value); 406 if (error.Fail()) 407 return false; 408 409 // %esp is set to the actual stack value. 410 411 if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_num, sp)) 412 return false; 413 414 // %eip is set to the address of the called function. 415 416 if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_num, func_addr)) 417 return false; 418 419 return true; 420} 421 422bool 423ABIMacOSX_i386::PrepareNormalCall (Thread &thread, 424 addr_t sp, 425 addr_t func_addr, 426 addr_t return_addr, 427 ValueList &args) const 428{ 429 ExecutionContext exe_ctx (thread.shared_from_this()); 430 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 431 if (!reg_ctx) 432 return false; 433 434 Process *process = exe_ctx.GetProcessPtr(); 435 Error error; 436 uint32_t fp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); 437 uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 438 uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 439 440 // Do the argument layout 441 442 std::vector <uint32_t> argLayout; // 4-byte chunks, as discussed in the ABI Function Call Guide 443 444 size_t numArgs = args.GetSize(); 445 size_t index; 446 447 for (index = 0; index < numArgs; ++index) 448 { 449 Value *val = args.GetValueAtIndex(index); 450 451 if (!val) 452 return false; 453 454 switch (val->GetValueType()) 455 { 456 case Value::eValueTypeScalar: 457 { 458 Scalar &scalar = val->GetScalar(); 459 switch (scalar.GetType()) 460 { 461 case Scalar::e_void: 462 return false; 463 case Scalar::e_sint: 464 case Scalar::e_uint: 465 case Scalar::e_slong: 466 case Scalar::e_ulong: 467 case Scalar::e_slonglong: 468 case Scalar::e_ulonglong: 469 { 470 uint64_t data = scalar.ULongLong(); 471 472 switch (scalar.GetByteSize()) 473 { 474 default: 475 return false; 476 case 1: 477 argLayout.push_back((uint32_t)(data & 0xffull)); 478 break; 479 case 2: 480 argLayout.push_back((uint32_t)(data & 0xffffull)); 481 break; 482 case 4: 483 argLayout.push_back((uint32_t)(data & 0xffffffffull)); 484 break; 485 case 8: 486 argLayout.push_back((uint32_t)(data & 0xffffffffull)); 487 argLayout.push_back((uint32_t)(data >> 32)); 488 break; 489 } 490 } 491 break; 492 case Scalar::e_float: 493 { 494 float data = scalar.Float(); 495 uint32_t dataRaw = *((uint32_t*)(&data)); 496 argLayout.push_back(dataRaw); 497 } 498 break; 499 case Scalar::e_double: 500 { 501 double data = scalar.Double(); 502 uint32_t *dataRaw = ((uint32_t*)(&data)); 503 argLayout.push_back(dataRaw[0]); 504 argLayout.push_back(dataRaw[1]); 505 } 506 break; 507 case Scalar::e_long_double: 508 { 509 long double data = scalar.Double(); 510 uint32_t *dataRaw = ((uint32_t*)(&data)); 511 while ((argLayout.size() * 4) & 0xf) 512 argLayout.push_back(0); 513 argLayout.push_back(dataRaw[0]); 514 argLayout.push_back(dataRaw[1]); 515 argLayout.push_back(dataRaw[2]); 516 argLayout.push_back(dataRaw[3]); 517 } 518 break; 519 } 520 } 521 break; 522 case Value::eValueTypeHostAddress: 523 { 524 ClangASTType clang_type (val->GetClangType()); 525 if (clang_type) 526 { 527 uint32_t cstr_length = 0; 528 if (clang_type.IsCStringType (cstr_length)) 529 { 530 const char *cstr = (const char*)val->GetScalar().ULongLong(); 531 cstr_length = strlen(cstr); 532 533 // Push the string onto the stack immediately. 534 535 sp -= (cstr_length + 1); 536 537 if (process->WriteMemory(sp, cstr, cstr_length + 1, error) != (cstr_length + 1)) 538 return false; 539 540 // Put the address of the string into the argument array. 541 542 argLayout.push_back((uint32_t)(sp & 0xffffffff)); 543 } 544 else 545 { 546 return false; 547 } 548 } 549 break; 550 } 551 break; 552 case Value::eValueTypeFileAddress: 553 case Value::eValueTypeLoadAddress: 554 default: 555 return false; 556 } 557 } 558 559 // Make room for the arguments on the stack 560 561 sp -= 4 * argLayout.size(); 562 563 // Align the SP 564 565 sp &= ~(16ull-1ull); // 16-byte alignment 566 567 // Write the arguments on the stack 568 569 size_t numChunks = argLayout.size(); 570 571 for (index = 0; index < numChunks; ++index) 572 if (process->WriteMemory(sp + (index * 4), &argLayout[index], sizeof(uint32_t), error) != sizeof(uint32_t)) 573 return false; 574 575 // The return address is pushed onto the stack. 576 577 sp -= 4; 578 uint32_t returnAddressU32 = return_addr; 579 if (process->WriteMemory (sp, &returnAddressU32, sizeof(returnAddressU32), error) != sizeof(returnAddressU32)) 580 return false; 581 582 // %esp is set to the actual stack value. 583 584 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp)) 585 return false; 586 587 // %ebp is set to a fake value, in our case 0x0x00000000 588 589 if (!reg_ctx->WriteRegisterFromUnsigned(fp_reg_num, 0x00000000)) 590 return false; 591 592 // %eip is set to the address of the called function. 593 594 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr)) 595 return false; 596 597 return true; 598} 599 600static bool 601ReadIntegerArgument (Scalar &scalar, 602 unsigned int bit_width, 603 bool is_signed, 604 Process *process, 605 addr_t ¤t_stack_argument) 606{ 607 608 uint32_t byte_size = (bit_width + (8-1))/8; 609 Error error; 610 if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error)) 611 { 612 current_stack_argument += byte_size; 613 return true; 614 } 615 return false; 616} 617 618bool 619ABIMacOSX_i386::GetArgumentValues (Thread &thread, 620 ValueList &values) const 621{ 622 unsigned int num_values = values.GetSize(); 623 unsigned int value_index; 624 625 // Get the pointer to the first stack argument so we have a place to start 626 // when reading data 627 628 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 629 630 if (!reg_ctx) 631 return false; 632 633 addr_t sp = reg_ctx->GetSP(0); 634 635 if (!sp) 636 return false; 637 638 addr_t current_stack_argument = sp + 4; // jump over return address 639 640 for (value_index = 0; 641 value_index < num_values; 642 ++value_index) 643 { 644 Value *value = values.GetValueAtIndex(value_index); 645 646 if (!value) 647 return false; 648 649 // We currently only support extracting values with Clang QualTypes. 650 // Do we care about others? 651 ClangASTType clang_type (value->GetClangType()); 652 if (clang_type) 653 { 654 bool is_signed; 655 656 if (clang_type.IsIntegerType (is_signed)) 657 { 658 ReadIntegerArgument(value->GetScalar(), 659 clang_type.GetBitSize(), 660 is_signed, 661 thread.GetProcess().get(), 662 current_stack_argument); 663 } 664 else if (clang_type.IsPointerType()) 665 { 666 ReadIntegerArgument(value->GetScalar(), 667 clang_type.GetBitSize(), 668 false, 669 thread.GetProcess().get(), 670 current_stack_argument); 671 } 672 } 673 } 674 675 return true; 676} 677 678Error 679ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp) 680{ 681 Error error; 682 if (!new_value_sp) 683 { 684 error.SetErrorString("Empty value object for return value."); 685 return error; 686 } 687 688 ClangASTType clang_type = new_value_sp->GetClangType(); 689 if (!clang_type) 690 { 691 error.SetErrorString ("Null clang type for return value."); 692 return error; 693 } 694 695 Thread *thread = frame_sp->GetThread().get(); 696 697 bool is_signed; 698 uint32_t count; 699 bool is_complex; 700 701 RegisterContext *reg_ctx = thread->GetRegisterContext().get(); 702 703 bool set_it_simple = false; 704 if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) 705 { 706 DataExtractor data; 707 size_t num_bytes = new_value_sp->GetData(data); 708 lldb::offset_t offset = 0; 709 if (num_bytes <= 8) 710 { 711 const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0); 712 if (num_bytes <= 4) 713 { 714 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); 715 716 if (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value)) 717 set_it_simple = true; 718 } 719 else 720 { 721 uint32_t raw_value = data.GetMaxU32(&offset, 4); 722 723 if (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value)) 724 { 725 const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0); 726 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset); 727 728 if (reg_ctx->WriteRegisterFromUnsigned (edx_info, raw_value)) 729 set_it_simple = true; 730 } 731 } 732 } 733 else 734 { 735 error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); 736 } 737 } 738 else if (clang_type.IsFloatingPointType (count, is_complex)) 739 { 740 if (is_complex) 741 error.SetErrorString ("We don't support returning complex values at present"); 742 else 743 error.SetErrorString ("We don't support returning float values at present"); 744 } 745 746 if (!set_it_simple) 747 error.SetErrorString ("We only support setting simple integer return types at present."); 748 749 return error; 750} 751 752ValueObjectSP 753ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread, 754 ClangASTType &clang_type) const 755{ 756 Value value; 757 ValueObjectSP return_valobj_sp; 758 759 if (!clang_type) 760 return return_valobj_sp; 761 762 //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType()); 763 value.SetClangType (clang_type); 764 765 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 766 if (!reg_ctx) 767 return return_valobj_sp; 768 769 bool is_signed; 770 771 if (clang_type.IsIntegerType (is_signed)) 772 { 773 size_t bit_width = clang_type.GetBitSize(); 774 775 unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; 776 unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB]; 777 778 switch (bit_width) 779 { 780 default: 781 case 128: 782 // Scalar can't hold 128-bit literals, so we don't handle this 783 return return_valobj_sp; 784 case 64: 785 uint64_t raw_value; 786 raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff; 787 raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32; 788 if (is_signed) 789 value.GetScalar() = (int64_t)raw_value; 790 else 791 value.GetScalar() = (uint64_t)raw_value; 792 break; 793 case 32: 794 if (is_signed) 795 value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff); 796 else 797 value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff); 798 break; 799 case 16: 800 if (is_signed) 801 value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff); 802 else 803 value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff); 804 break; 805 case 8: 806 if (is_signed) 807 value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff); 808 else 809 value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff); 810 break; 811 } 812 } 813 else if (clang_type.IsPointerType ()) 814 { 815 unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; 816 uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff; 817 value.GetScalar() = ptr; 818 } 819 else 820 { 821 // not handled yet 822 return return_valobj_sp; 823 } 824 825 // If we get here, we have a valid Value, so make our ValueObject out of it: 826 827 return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), 828 value, 829 ConstString("")); 830 return return_valobj_sp; 831} 832 833bool 834ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) 835{ 836 unwind_plan.Clear(); 837 unwind_plan.SetRegisterKind (eRegisterKindDWARF); 838 839 uint32_t sp_reg_num = dwarf_esp; 840 uint32_t pc_reg_num = dwarf_eip; 841 842 UnwindPlan::RowSP row(new UnwindPlan::Row); 843 row->SetCFARegister (sp_reg_num); 844 row->SetCFAOffset (4); 845 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false); 846 unwind_plan.AppendRow (row); 847 unwind_plan.SetSourceName ("i386 at-func-entry default"); 848 unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); 849 return true; 850} 851 852bool 853ABIMacOSX_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) 854{ 855 unwind_plan.Clear (); 856 unwind_plan.SetRegisterKind (eRegisterKindDWARF); 857 858 uint32_t fp_reg_num = dwarf_ebp; 859 uint32_t sp_reg_num = dwarf_esp; 860 uint32_t pc_reg_num = dwarf_eip; 861 862 UnwindPlan::RowSP row(new UnwindPlan::Row); 863 const int32_t ptr_size = 4; 864 865 row->SetCFARegister (fp_reg_num); 866 row->SetCFAOffset (2 * ptr_size); 867 row->SetOffset (0); 868 869 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); 870 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); 871 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); 872 873 unwind_plan.AppendRow (row); 874 unwind_plan.SetSourceName ("i386 default unwind plan"); 875 unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); 876 unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); 877 return true; 878} 879 880bool 881ABIMacOSX_i386::RegisterIsVolatile (const RegisterInfo *reg_info) 882{ 883 return !RegisterIsCalleeSaved (reg_info); 884} 885 886// 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 887 888bool 889ABIMacOSX_i386::RegisterIsCalleeSaved (const RegisterInfo *reg_info) 890{ 891 if (reg_info) 892 { 893 // Saved registers are ebx, ebp, esi, edi, esp, eip 894 const char *name = reg_info->name; 895 if (name[0] == 'e') 896 { 897 switch (name[1]) 898 { 899 case 'b': 900 if (name[2] == 'x' || name[2] == 'p') 901 return name[3] == '\0'; 902 break; 903 case 'd': 904 if (name[2] == 'i') 905 return name[3] == '\0'; 906 break; 907 case 'i': 908 if (name[2] == 'p') 909 return name[3] == '\0'; 910 break; 911 case 's': 912 if (name[2] == 'i' || name[2] == 'p') 913 return name[3] == '\0'; 914 break; 915 } 916 } 917 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp 918 return true; 919 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp 920 return true; 921 if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc 922 return true; 923 } 924 return false; 925} 926 927void 928ABIMacOSX_i386::Initialize() 929{ 930 PluginManager::RegisterPlugin (GetPluginNameStatic(), 931 "Mac OS X ABI for i386 targets", 932 CreateInstance); 933} 934 935void 936ABIMacOSX_i386::Terminate() 937{ 938 PluginManager::UnregisterPlugin (CreateInstance); 939} 940 941lldb_private::ConstString 942ABIMacOSX_i386::GetPluginNameStatic () 943{ 944 static ConstString g_short_name("abi.macosx-i386"); 945 return g_short_name; 946 947} 948 949//------------------------------------------------------------------ 950// PluginInterface protocol 951//------------------------------------------------------------------ 952lldb_private::ConstString 953ABIMacOSX_i386::GetPluginName() 954{ 955 return GetPluginNameStatic(); 956} 957 958uint32_t 959ABIMacOSX_i386::GetPluginVersion() 960{ 961 return 1; 962} 963 964