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