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