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