1 //===-- ABIMacOSX_i386.cpp ------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "ABIMacOSX_i386.h" 10 11 #include <vector> 12 13 #include "llvm/ADT/STLExtras.h" 14 #include "llvm/ADT/Triple.h" 15 16 #include "lldb/Core/Module.h" 17 #include "lldb/Core/PluginManager.h" 18 #include "lldb/Core/ValueObjectConstResult.h" 19 #include "lldb/Symbol/UnwindPlan.h" 20 #include "lldb/Target/Process.h" 21 #include "lldb/Target/RegisterContext.h" 22 #include "lldb/Target/Target.h" 23 #include "lldb/Target/Thread.h" 24 #include "lldb/Utility/ConstString.h" 25 #include "lldb/Utility/RegisterValue.h" 26 #include "lldb/Utility/Scalar.h" 27 #include "lldb/Utility/Status.h" 28 29 using namespace lldb; 30 using namespace lldb_private; 31 32 LLDB_PLUGIN_DEFINE(ABIMacOSX_i386) 33 34 enum { 35 dwarf_eax = 0, 36 dwarf_ecx, 37 dwarf_edx, 38 dwarf_ebx, 39 dwarf_esp, 40 dwarf_ebp, 41 dwarf_esi, 42 dwarf_edi, 43 dwarf_eip, 44 }; 45 46 size_t ABIMacOSX_i386::GetRedZoneSize() const { return 0; } 47 48 // Static Functions 49 50 ABISP 51 ABIMacOSX_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { 52 if ((arch.GetTriple().getArch() == llvm::Triple::x86) && 53 (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS() || 54 arch.GetTriple().isWatchOS())) { 55 return ABISP( 56 new ABIMacOSX_i386(std::move(process_sp), MakeMCRegisterInfo(arch))); 57 } 58 return ABISP(); 59 } 60 61 bool ABIMacOSX_i386::PrepareTrivialCall(Thread &thread, addr_t sp, 62 addr_t func_addr, addr_t return_addr, 63 llvm::ArrayRef<addr_t> args) const { 64 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 65 if (!reg_ctx) 66 return false; 67 uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber( 68 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 69 uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber( 70 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 71 72 // When writing a register value down to memory, the register info used to 73 // write memory just needs to have the correct size of a 32 bit register, the 74 // actual register it pertains to is not important, just the size needs to be 75 // correct. Here we use "eax"... 76 const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax"); 77 if (!reg_info_32) 78 return false; // TODO this should actually never happen 79 80 // Make room for the argument(s) on the stack 81 82 Status error; 83 RegisterValue reg_value; 84 85 // Write any arguments onto the stack 86 sp -= 4 * args.size(); 87 88 // Align the SP 89 sp &= ~(16ull - 1ull); // 16-byte alignment 90 91 addr_t arg_pos = sp; 92 93 for (addr_t arg : args) { 94 reg_value.SetUInt32(arg); 95 error = reg_ctx->WriteRegisterValueToMemory( 96 reg_info_32, arg_pos, reg_info_32->byte_size, reg_value); 97 if (error.Fail()) 98 return false; 99 arg_pos += 4; 100 } 101 102 // The return address is pushed onto the stack (yes after we just set the 103 // alignment above!). 104 sp -= 4; 105 reg_value.SetUInt32(return_addr); 106 error = reg_ctx->WriteRegisterValueToMemory( 107 reg_info_32, sp, reg_info_32->byte_size, reg_value); 108 if (error.Fail()) 109 return false; 110 111 // %esp is set to the actual stack value. 112 113 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp)) 114 return false; 115 116 // %eip is set to the address of the called function. 117 118 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr)) 119 return false; 120 121 return true; 122 } 123 124 static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width, 125 bool is_signed, Process *process, 126 addr_t ¤t_stack_argument) { 127 128 uint32_t byte_size = (bit_width + (8 - 1)) / 8; 129 Status error; 130 if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, 131 is_signed, scalar, error)) { 132 current_stack_argument += byte_size; 133 return true; 134 } 135 return false; 136 } 137 138 bool ABIMacOSX_i386::GetArgumentValues(Thread &thread, 139 ValueList &values) const { 140 unsigned int num_values = values.GetSize(); 141 unsigned int value_index; 142 143 // Get the pointer to the first stack argument so we have a place to start 144 // when reading data 145 146 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 147 148 if (!reg_ctx) 149 return false; 150 151 addr_t sp = reg_ctx->GetSP(0); 152 153 if (!sp) 154 return false; 155 156 addr_t current_stack_argument = sp + 4; // jump over return address 157 158 for (value_index = 0; value_index < num_values; ++value_index) { 159 Value *value = values.GetValueAtIndex(value_index); 160 161 if (!value) 162 return false; 163 164 // We currently only support extracting values with Clang QualTypes. Do we 165 // care about others? 166 CompilerType compiler_type(value->GetCompilerType()); 167 llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); 168 if (bit_size) { 169 bool is_signed; 170 if (compiler_type.IsIntegerOrEnumerationType(is_signed)) 171 ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed, 172 thread.GetProcess().get(), current_stack_argument); 173 else if (compiler_type.IsPointerType()) 174 ReadIntegerArgument(value->GetScalar(), *bit_size, false, 175 thread.GetProcess().get(), current_stack_argument); 176 } 177 } 178 179 return true; 180 } 181 182 Status ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, 183 lldb::ValueObjectSP &new_value_sp) { 184 Status error; 185 if (!new_value_sp) { 186 error.SetErrorString("Empty value object for return value."); 187 return error; 188 } 189 190 CompilerType compiler_type = new_value_sp->GetCompilerType(); 191 if (!compiler_type) { 192 error.SetErrorString("Null clang type for return value."); 193 return error; 194 } 195 196 Thread *thread = frame_sp->GetThread().get(); 197 198 bool is_signed; 199 uint32_t count; 200 bool is_complex; 201 202 RegisterContext *reg_ctx = thread->GetRegisterContext().get(); 203 204 bool set_it_simple = false; 205 if (compiler_type.IsIntegerOrEnumerationType(is_signed) || 206 compiler_type.IsPointerType()) { 207 DataExtractor data; 208 Status data_error; 209 size_t num_bytes = new_value_sp->GetData(data, data_error); 210 if (data_error.Fail()) { 211 error.SetErrorStringWithFormat( 212 "Couldn't convert return value to raw data: %s", 213 data_error.AsCString()); 214 return error; 215 } 216 lldb::offset_t offset = 0; 217 if (num_bytes <= 8) { 218 const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0); 219 if (num_bytes <= 4) { 220 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); 221 222 if (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value)) 223 set_it_simple = true; 224 } else { 225 uint32_t raw_value = data.GetMaxU32(&offset, 4); 226 227 if (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value)) { 228 const RegisterInfo *edx_info = 229 reg_ctx->GetRegisterInfoByName("edx", 0); 230 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset); 231 232 if (reg_ctx->WriteRegisterFromUnsigned(edx_info, raw_value)) 233 set_it_simple = true; 234 } 235 } 236 } else { 237 error.SetErrorString("We don't support returning longer than 64 bit " 238 "integer values at present."); 239 } 240 } else if (compiler_type.IsFloatingPointType(count, is_complex)) { 241 if (is_complex) 242 error.SetErrorString( 243 "We don't support returning complex values at present"); 244 else 245 error.SetErrorString( 246 "We don't support returning float values at present"); 247 } 248 249 if (!set_it_simple) 250 error.SetErrorString( 251 "We only support setting simple integer return types at present."); 252 253 return error; 254 } 255 256 ValueObjectSP 257 ABIMacOSX_i386::GetReturnValueObjectImpl(Thread &thread, 258 CompilerType &compiler_type) const { 259 Value value; 260 ValueObjectSP return_valobj_sp; 261 262 if (!compiler_type) 263 return return_valobj_sp; 264 265 // value.SetContext (Value::eContextTypeClangType, 266 // compiler_type.GetOpaqueQualType()); 267 value.SetCompilerType(compiler_type); 268 269 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 270 if (!reg_ctx) 271 return return_valobj_sp; 272 273 bool is_signed; 274 275 if (compiler_type.IsIntegerOrEnumerationType(is_signed)) { 276 llvm::Optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread); 277 if (!bit_width) 278 return return_valobj_sp; 279 unsigned eax_id = 280 reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; 281 unsigned edx_id = 282 reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB]; 283 284 switch (*bit_width) { 285 default: 286 case 128: 287 // Scalar can't hold 128-bit literals, so we don't handle this 288 return return_valobj_sp; 289 case 64: 290 uint64_t raw_value; 291 raw_value = 292 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 293 0xffffffff; 294 raw_value |= 295 (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 296 0xffffffff) 297 << 32; 298 if (is_signed) 299 value.GetScalar() = (int64_t)raw_value; 300 else 301 value.GetScalar() = (uint64_t)raw_value; 302 break; 303 case 32: 304 if (is_signed) 305 value.GetScalar() = (int32_t)( 306 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 307 0xffffffff); 308 else 309 value.GetScalar() = (uint32_t)( 310 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 311 0xffffffff); 312 break; 313 case 16: 314 if (is_signed) 315 value.GetScalar() = (int16_t)( 316 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 317 0xffff); 318 else 319 value.GetScalar() = (uint16_t)( 320 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 321 0xffff); 322 break; 323 case 8: 324 if (is_signed) 325 value.GetScalar() = (int8_t)( 326 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 327 0xff); 328 else 329 value.GetScalar() = (uint8_t)( 330 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 331 0xff); 332 break; 333 } 334 } else if (compiler_type.IsPointerType()) { 335 unsigned eax_id = 336 reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; 337 uint32_t ptr = 338 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 339 0xffffffff; 340 value.GetScalar() = ptr; 341 } else { 342 // not handled yet 343 return return_valobj_sp; 344 } 345 346 // If we get here, we have a valid Value, so make our ValueObject out of it: 347 348 return_valobj_sp = ValueObjectConstResult::Create( 349 thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); 350 return return_valobj_sp; 351 } 352 353 // This defines the CFA as esp+4 354 // the saved pc is at CFA-4 (i.e. esp+0) 355 // The saved esp is CFA+0 356 357 bool ABIMacOSX_i386::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { 358 unwind_plan.Clear(); 359 unwind_plan.SetRegisterKind(eRegisterKindDWARF); 360 361 uint32_t sp_reg_num = dwarf_esp; 362 uint32_t pc_reg_num = dwarf_eip; 363 364 UnwindPlan::RowSP row(new UnwindPlan::Row); 365 row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4); 366 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false); 367 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); 368 unwind_plan.AppendRow(row); 369 unwind_plan.SetSourceName("i386 at-func-entry default"); 370 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 371 return true; 372 } 373 374 // This defines the CFA as ebp+8 375 // The saved pc is at CFA-4 (i.e. ebp+4) 376 // The saved ebp is at CFA-8 (i.e. ebp+0) 377 // The saved esp is CFA+0 378 379 bool ABIMacOSX_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { 380 unwind_plan.Clear(); 381 unwind_plan.SetRegisterKind(eRegisterKindDWARF); 382 383 uint32_t fp_reg_num = dwarf_ebp; 384 uint32_t sp_reg_num = dwarf_esp; 385 uint32_t pc_reg_num = dwarf_eip; 386 387 UnwindPlan::RowSP row(new UnwindPlan::Row); 388 const int32_t ptr_size = 4; 389 390 row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); 391 row->SetOffset(0); 392 row->SetUnspecifiedRegistersAreUndefined(true); 393 394 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); 395 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); 396 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); 397 398 unwind_plan.AppendRow(row); 399 unwind_plan.SetSourceName("i386 default unwind plan"); 400 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 401 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 402 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); 403 return true; 404 } 405 406 bool ABIMacOSX_i386::RegisterIsVolatile(const RegisterInfo *reg_info) { 407 return !RegisterIsCalleeSaved(reg_info); 408 } 409 410 // v. 411 // http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130 412 // -IA- 413 // 32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4 414 // 415 // This document ("OS X ABI Function Call Guide", chapter "IA-32 Function 416 // Calling Conventions") says that the following registers on i386 are 417 // preserved aka non-volatile aka callee-saved: 418 // 419 // ebx, ebp, esi, edi, esp 420 421 bool ABIMacOSX_i386::RegisterIsCalleeSaved(const RegisterInfo *reg_info) { 422 if (reg_info) { 423 // Saved registers are ebx, ebp, esi, edi, esp, eip 424 const char *name = reg_info->name; 425 if (name[0] == 'e') { 426 switch (name[1]) { 427 case 'b': 428 if (name[2] == 'x' || name[2] == 'p') 429 return name[3] == '\0'; 430 break; 431 case 'd': 432 if (name[2] == 'i') 433 return name[3] == '\0'; 434 break; 435 case 'i': 436 if (name[2] == 'p') 437 return name[3] == '\0'; 438 break; 439 case 's': 440 if (name[2] == 'i' || name[2] == 'p') 441 return name[3] == '\0'; 442 break; 443 } 444 } 445 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp 446 return true; 447 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp 448 return true; 449 if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc 450 return true; 451 } 452 return false; 453 } 454 455 void ABIMacOSX_i386::Initialize() { 456 PluginManager::RegisterPlugin( 457 GetPluginNameStatic(), "Mac OS X ABI for i386 targets", CreateInstance); 458 } 459 460 void ABIMacOSX_i386::Terminate() { 461 PluginManager::UnregisterPlugin(CreateInstance); 462 } 463