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