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/ADT/Triple.h" 16 17 #include "lldb/Core/Module.h" 18 #include "lldb/Core/PluginManager.h" 19 #include "lldb/Core/ValueObjectConstResult.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 #include "lldb/Utility/ConstString.h" 26 #include "lldb/Utility/RegisterValue.h" 27 #include "lldb/Utility/Scalar.h" 28 #include "lldb/Utility/Status.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.SetErrorString("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.SetErrorString("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.SetErrorStringWithFormat( 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.SetErrorString("We don't support returning longer than 64 bit " 239 "integer values at present."); 240 } 241 } else if (compiler_type.IsFloatingPointType(count, is_complex)) { 242 if (is_complex) 243 error.SetErrorString( 244 "We don't support returning complex values at present"); 245 else 246 error.SetErrorString( 247 "We don't support returning float values at present"); 248 } 249 250 if (!set_it_simple) 251 error.SetErrorString( 252 "We only support setting simple integer return types at present."); 253 254 return error; 255 } 256 257 ValueObjectSP 258 ABIMacOSX_i386::GetReturnValueObjectImpl(Thread &thread, 259 CompilerType &compiler_type) const { 260 Value value; 261 ValueObjectSP return_valobj_sp; 262 263 if (!compiler_type) 264 return return_valobj_sp; 265 266 // value.SetContext (Value::eContextTypeClangType, 267 // compiler_type.GetOpaqueQualType()); 268 value.SetCompilerType(compiler_type); 269 270 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 271 if (!reg_ctx) 272 return return_valobj_sp; 273 274 bool is_signed; 275 276 if (compiler_type.IsIntegerOrEnumerationType(is_signed)) { 277 std::optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread); 278 if (!bit_width) 279 return return_valobj_sp; 280 unsigned eax_id = 281 reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; 282 unsigned edx_id = 283 reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB]; 284 285 switch (*bit_width) { 286 default: 287 case 128: 288 // Scalar can't hold 128-bit literals, so we don't handle this 289 return return_valobj_sp; 290 case 64: 291 uint64_t raw_value; 292 raw_value = 293 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 294 0xffffffff; 295 raw_value |= 296 (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 297 0xffffffff) 298 << 32; 299 if (is_signed) 300 value.GetScalar() = (int64_t)raw_value; 301 else 302 value.GetScalar() = (uint64_t)raw_value; 303 break; 304 case 32: 305 if (is_signed) 306 value.GetScalar() = (int32_t)( 307 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 308 0xffffffff); 309 else 310 value.GetScalar() = (uint32_t)( 311 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 312 0xffffffff); 313 break; 314 case 16: 315 if (is_signed) 316 value.GetScalar() = (int16_t)( 317 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 318 0xffff); 319 else 320 value.GetScalar() = (uint16_t)( 321 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 322 0xffff); 323 break; 324 case 8: 325 if (is_signed) 326 value.GetScalar() = (int8_t)( 327 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 328 0xff); 329 else 330 value.GetScalar() = (uint8_t)( 331 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 332 0xff); 333 break; 334 } 335 } else if (compiler_type.IsPointerType()) { 336 unsigned eax_id = 337 reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; 338 uint32_t ptr = 339 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 340 0xffffffff; 341 value.GetScalar() = ptr; 342 } else { 343 // not handled yet 344 return return_valobj_sp; 345 } 346 347 // If we get here, we have a valid Value, so make our ValueObject out of it: 348 349 return_valobj_sp = ValueObjectConstResult::Create( 350 thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); 351 return return_valobj_sp; 352 } 353 354 // This defines the CFA as esp+4 355 // the saved pc is at CFA-4 (i.e. esp+0) 356 // The saved esp is CFA+0 357 358 bool ABIMacOSX_i386::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { 359 unwind_plan.Clear(); 360 unwind_plan.SetRegisterKind(eRegisterKindDWARF); 361 362 uint32_t sp_reg_num = dwarf_esp; 363 uint32_t pc_reg_num = dwarf_eip; 364 365 UnwindPlan::RowSP row(new UnwindPlan::Row); 366 row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4); 367 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false); 368 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); 369 unwind_plan.AppendRow(row); 370 unwind_plan.SetSourceName("i386 at-func-entry default"); 371 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 372 return true; 373 } 374 375 // This defines the CFA as ebp+8 376 // The saved pc is at CFA-4 (i.e. ebp+4) 377 // The saved ebp is at CFA-8 (i.e. ebp+0) 378 // The saved esp is CFA+0 379 380 bool ABIMacOSX_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { 381 unwind_plan.Clear(); 382 unwind_plan.SetRegisterKind(eRegisterKindDWARF); 383 384 uint32_t fp_reg_num = dwarf_ebp; 385 uint32_t sp_reg_num = dwarf_esp; 386 uint32_t pc_reg_num = dwarf_eip; 387 388 UnwindPlan::RowSP row(new UnwindPlan::Row); 389 const int32_t ptr_size = 4; 390 391 row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); 392 row->SetOffset(0); 393 row->SetUnspecifiedRegistersAreUndefined(true); 394 395 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); 396 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); 397 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); 398 399 unwind_plan.AppendRow(row); 400 unwind_plan.SetSourceName("i386 default unwind plan"); 401 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 402 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 403 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); 404 return true; 405 } 406 407 bool ABIMacOSX_i386::RegisterIsVolatile(const RegisterInfo *reg_info) { 408 return !RegisterIsCalleeSaved(reg_info); 409 } 410 411 // v. 412 // http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130 413 // -IA- 414 // 32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4 415 // 416 // This document ("OS X ABI Function Call Guide", chapter "IA-32 Function 417 // Calling Conventions") says that the following registers on i386 are 418 // preserved aka non-volatile aka callee-saved: 419 // 420 // ebx, ebp, esi, edi, esp 421 422 bool ABIMacOSX_i386::RegisterIsCalleeSaved(const RegisterInfo *reg_info) { 423 if (reg_info) { 424 // Saved registers are ebx, ebp, esi, edi, esp, eip 425 const char *name = reg_info->name; 426 if (name[0] == 'e') { 427 switch (name[1]) { 428 case 'b': 429 if (name[2] == 'x' || name[2] == 'p') 430 return name[3] == '\0'; 431 break; 432 case 'd': 433 if (name[2] == 'i') 434 return name[3] == '\0'; 435 break; 436 case 'i': 437 if (name[2] == 'p') 438 return name[3] == '\0'; 439 break; 440 case 's': 441 if (name[2] == 'i' || name[2] == 'p') 442 return name[3] == '\0'; 443 break; 444 } 445 } 446 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp 447 return true; 448 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp 449 return true; 450 if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc 451 return true; 452 } 453 return false; 454 } 455 456 void ABIMacOSX_i386::Initialize() { 457 PluginManager::RegisterPlugin( 458 GetPluginNameStatic(), "Mac OS X ABI for i386 targets", CreateInstance); 459 } 460 461 void ABIMacOSX_i386::Terminate() { 462 PluginManager::UnregisterPlugin(CreateInstance); 463 } 464