ABIMacOSX_i386.cpp revision 360784
1//===-- ABIMacOSX_i386.cpp --------------------------------------*- C++ -*-===// 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 29using namespace lldb; 30using namespace lldb_private; 31 32enum { 33 ehframe_eax = 0, 34 ehframe_ecx, 35 ehframe_edx, 36 ehframe_ebx, 37 ehframe_ebp, // Different from DWARF the regnums - eh_frame esp/ebp had their 38 // regnums switched on i386 darwin 39 ehframe_esp, // Different from DWARF the regnums - eh_frame esp/ebp had their 40 // regnums switched on i386 darwin 41 ehframe_esi, 42 ehframe_edi, 43 ehframe_eip, 44 ehframe_eflags 45}; 46 47enum { 48 dwarf_eax = 0, 49 dwarf_ecx, 50 dwarf_edx, 51 dwarf_ebx, 52 dwarf_esp, 53 dwarf_ebp, 54 dwarf_esi, 55 dwarf_edi, 56 dwarf_eip, 57 dwarf_eflags, 58 dwarf_stmm0 = 11, 59 dwarf_stmm1, 60 dwarf_stmm2, 61 dwarf_stmm3, 62 dwarf_stmm4, 63 dwarf_stmm5, 64 dwarf_stmm6, 65 dwarf_stmm7, 66 dwarf_xmm0 = 21, 67 dwarf_xmm1, 68 dwarf_xmm2, 69 dwarf_xmm3, 70 dwarf_xmm4, 71 dwarf_xmm5, 72 dwarf_xmm6, 73 dwarf_xmm7, 74 dwarf_ymm0 = dwarf_xmm0, 75 dwarf_ymm1 = dwarf_xmm1, 76 dwarf_ymm2 = dwarf_xmm2, 77 dwarf_ymm3 = dwarf_xmm3, 78 dwarf_ymm4 = dwarf_xmm4, 79 dwarf_ymm5 = dwarf_xmm5, 80 dwarf_ymm6 = dwarf_xmm6, 81 dwarf_ymm7 = dwarf_xmm7 82}; 83 84static RegisterInfo g_register_infos[] = { 85 // NAME ALT SZ OFF ENCODING FORMAT 86 // EH_FRAME DWARF GENERIC 87 // PROCESS PLUGIN LLDB NATIVE 88 // ====== ======= == === ============= ============ 89 // ===================== ===================== ============================ 90 // ==================== ====================== 91 {"eax", 92 nullptr, 93 4, 94 0, 95 eEncodingUint, 96 eFormatHex, 97 {ehframe_eax, dwarf_eax, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 98 LLDB_INVALID_REGNUM}, 99 nullptr, 100 nullptr, 101 nullptr, 102 0}, 103 {"ebx", 104 nullptr, 105 4, 106 0, 107 eEncodingUint, 108 eFormatHex, 109 {ehframe_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 110 LLDB_INVALID_REGNUM}, 111 nullptr, 112 nullptr, 113 nullptr, 114 0}, 115 {"ecx", 116 nullptr, 117 4, 118 0, 119 eEncodingUint, 120 eFormatHex, 121 {ehframe_ecx, dwarf_ecx, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, 122 LLDB_INVALID_REGNUM}, 123 nullptr, 124 nullptr, 125 nullptr, 126 0}, 127 {"edx", 128 nullptr, 129 4, 130 0, 131 eEncodingUint, 132 eFormatHex, 133 {ehframe_edx, dwarf_edx, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, 134 LLDB_INVALID_REGNUM}, 135 nullptr, 136 nullptr, 137 nullptr, 138 0}, 139 {"esi", 140 nullptr, 141 4, 142 0, 143 eEncodingUint, 144 eFormatHex, 145 {ehframe_esi, dwarf_esi, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, 146 LLDB_INVALID_REGNUM}, 147 nullptr, 148 nullptr, 149 nullptr, 150 0}, 151 {"edi", 152 nullptr, 153 4, 154 0, 155 eEncodingUint, 156 eFormatHex, 157 {ehframe_edi, dwarf_edi, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, 158 LLDB_INVALID_REGNUM}, 159 nullptr, 160 nullptr, 161 nullptr, 162 0}, 163 {"ebp", 164 "fp", 165 4, 166 0, 167 eEncodingUint, 168 eFormatHex, 169 {ehframe_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, 170 LLDB_INVALID_REGNUM}, 171 nullptr, 172 nullptr, 173 nullptr, 174 0}, 175 {"esp", 176 "sp", 177 4, 178 0, 179 eEncodingUint, 180 eFormatHex, 181 {ehframe_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, 182 LLDB_INVALID_REGNUM}, 183 nullptr, 184 nullptr, 185 nullptr, 186 0}, 187 {"eip", 188 "pc", 189 4, 190 0, 191 eEncodingUint, 192 eFormatHex, 193 {ehframe_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, 194 LLDB_INVALID_REGNUM}, 195 nullptr, 196 nullptr, 197 nullptr, 198 0}, 199 {"eflags", 200 nullptr, 201 4, 202 0, 203 eEncodingUint, 204 eFormatHex, 205 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, 206 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 207 nullptr, 208 nullptr, 209 nullptr, 210 0}, 211 {"cs", 212 nullptr, 213 4, 214 0, 215 eEncodingUint, 216 eFormatHex, 217 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 218 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 219 nullptr, 220 nullptr, 221 nullptr, 222 0}, 223 {"ss", 224 nullptr, 225 4, 226 0, 227 eEncodingUint, 228 eFormatHex, 229 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 230 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 231 nullptr, 232 nullptr, 233 nullptr, 234 0}, 235 {"ds", 236 nullptr, 237 4, 238 0, 239 eEncodingUint, 240 eFormatHex, 241 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 242 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 243 nullptr, 244 nullptr, 245 nullptr, 246 0}, 247 {"es", 248 nullptr, 249 4, 250 0, 251 eEncodingUint, 252 eFormatHex, 253 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 254 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 255 nullptr, 256 nullptr, 257 nullptr, 258 0}, 259 {"fs", 260 nullptr, 261 4, 262 0, 263 eEncodingUint, 264 eFormatHex, 265 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 266 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 267 nullptr, 268 nullptr, 269 nullptr, 270 0}, 271 {"gs", 272 nullptr, 273 4, 274 0, 275 eEncodingUint, 276 eFormatHex, 277 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 278 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 279 nullptr, 280 nullptr, 281 nullptr, 282 0}, 283 {"stmm0", 284 nullptr, 285 10, 286 0, 287 eEncodingVector, 288 eFormatVectorOfUInt8, 289 {LLDB_INVALID_REGNUM, dwarf_stmm0, LLDB_INVALID_REGNUM, 290 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 291 nullptr, 292 nullptr, 293 nullptr, 294 0}, 295 {"stmm1", 296 nullptr, 297 10, 298 0, 299 eEncodingVector, 300 eFormatVectorOfUInt8, 301 {LLDB_INVALID_REGNUM, dwarf_stmm1, LLDB_INVALID_REGNUM, 302 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 303 nullptr, 304 nullptr, 305 nullptr, 306 0}, 307 {"stmm2", 308 nullptr, 309 10, 310 0, 311 eEncodingVector, 312 eFormatVectorOfUInt8, 313 {LLDB_INVALID_REGNUM, dwarf_stmm2, LLDB_INVALID_REGNUM, 314 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 315 nullptr, 316 nullptr, 317 nullptr, 318 0}, 319 {"stmm3", 320 nullptr, 321 10, 322 0, 323 eEncodingVector, 324 eFormatVectorOfUInt8, 325 {LLDB_INVALID_REGNUM, dwarf_stmm3, LLDB_INVALID_REGNUM, 326 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 327 nullptr, 328 nullptr, 329 nullptr, 330 0}, 331 {"stmm4", 332 nullptr, 333 10, 334 0, 335 eEncodingVector, 336 eFormatVectorOfUInt8, 337 {LLDB_INVALID_REGNUM, dwarf_stmm4, LLDB_INVALID_REGNUM, 338 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 339 nullptr, 340 nullptr, 341 nullptr, 342 0}, 343 {"stmm5", 344 nullptr, 345 10, 346 0, 347 eEncodingVector, 348 eFormatVectorOfUInt8, 349 {LLDB_INVALID_REGNUM, dwarf_stmm5, LLDB_INVALID_REGNUM, 350 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 351 nullptr, 352 nullptr, 353 nullptr, 354 0}, 355 {"stmm6", 356 nullptr, 357 10, 358 0, 359 eEncodingVector, 360 eFormatVectorOfUInt8, 361 {LLDB_INVALID_REGNUM, dwarf_stmm6, LLDB_INVALID_REGNUM, 362 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 363 nullptr, 364 nullptr, 365 nullptr, 366 0}, 367 {"stmm7", 368 nullptr, 369 10, 370 0, 371 eEncodingVector, 372 eFormatVectorOfUInt8, 373 {LLDB_INVALID_REGNUM, dwarf_stmm7, LLDB_INVALID_REGNUM, 374 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 375 nullptr, 376 nullptr, 377 nullptr, 378 0}, 379 {"fctrl", 380 nullptr, 381 4, 382 0, 383 eEncodingUint, 384 eFormatHex, 385 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 386 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 387 nullptr, 388 nullptr, 389 nullptr, 390 0}, 391 {"fstat", 392 nullptr, 393 4, 394 0, 395 eEncodingUint, 396 eFormatHex, 397 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 398 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 399 nullptr, 400 nullptr, 401 nullptr, 402 0}, 403 {"ftag", 404 nullptr, 405 4, 406 0, 407 eEncodingUint, 408 eFormatHex, 409 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 410 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 411 nullptr, 412 nullptr, 413 nullptr, 414 0}, 415 {"fiseg", 416 nullptr, 417 4, 418 0, 419 eEncodingUint, 420 eFormatHex, 421 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 422 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 423 nullptr, 424 nullptr, 425 nullptr, 426 0}, 427 {"fioff", 428 nullptr, 429 4, 430 0, 431 eEncodingUint, 432 eFormatHex, 433 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 434 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 435 nullptr, 436 nullptr, 437 nullptr, 438 0}, 439 {"foseg", 440 nullptr, 441 4, 442 0, 443 eEncodingUint, 444 eFormatHex, 445 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 446 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 447 nullptr, 448 nullptr, 449 nullptr, 450 0}, 451 {"fooff", 452 nullptr, 453 4, 454 0, 455 eEncodingUint, 456 eFormatHex, 457 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 458 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 459 nullptr, 460 nullptr, 461 nullptr, 462 0}, 463 {"fop", 464 nullptr, 465 4, 466 0, 467 eEncodingUint, 468 eFormatHex, 469 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 470 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 471 nullptr, 472 nullptr, 473 nullptr, 474 0}, 475 {"xmm0", 476 nullptr, 477 16, 478 0, 479 eEncodingVector, 480 eFormatVectorOfUInt8, 481 {LLDB_INVALID_REGNUM, dwarf_xmm0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 482 LLDB_INVALID_REGNUM}, 483 nullptr, 484 nullptr, 485 nullptr, 486 0}, 487 {"xmm1", 488 nullptr, 489 16, 490 0, 491 eEncodingVector, 492 eFormatVectorOfUInt8, 493 {LLDB_INVALID_REGNUM, dwarf_xmm1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 494 LLDB_INVALID_REGNUM}, 495 nullptr, 496 nullptr, 497 nullptr, 498 0}, 499 {"xmm2", 500 nullptr, 501 16, 502 0, 503 eEncodingVector, 504 eFormatVectorOfUInt8, 505 {LLDB_INVALID_REGNUM, dwarf_xmm2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 506 LLDB_INVALID_REGNUM}, 507 nullptr, 508 nullptr, 509 nullptr, 510 0}, 511 {"xmm3", 512 nullptr, 513 16, 514 0, 515 eEncodingVector, 516 eFormatVectorOfUInt8, 517 {LLDB_INVALID_REGNUM, dwarf_xmm3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 518 LLDB_INVALID_REGNUM}, 519 nullptr, 520 nullptr, 521 nullptr, 522 0}, 523 {"xmm4", 524 nullptr, 525 16, 526 0, 527 eEncodingVector, 528 eFormatVectorOfUInt8, 529 {LLDB_INVALID_REGNUM, dwarf_xmm4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 530 LLDB_INVALID_REGNUM}, 531 nullptr, 532 nullptr, 533 nullptr, 534 0}, 535 {"xmm5", 536 nullptr, 537 16, 538 0, 539 eEncodingVector, 540 eFormatVectorOfUInt8, 541 {LLDB_INVALID_REGNUM, dwarf_xmm5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 542 LLDB_INVALID_REGNUM}, 543 nullptr, 544 nullptr, 545 nullptr, 546 0}, 547 {"xmm6", 548 nullptr, 549 16, 550 0, 551 eEncodingVector, 552 eFormatVectorOfUInt8, 553 {LLDB_INVALID_REGNUM, dwarf_xmm6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 554 LLDB_INVALID_REGNUM}, 555 nullptr, 556 nullptr, 557 nullptr, 558 0}, 559 {"xmm7", 560 nullptr, 561 16, 562 0, 563 eEncodingVector, 564 eFormatVectorOfUInt8, 565 {LLDB_INVALID_REGNUM, dwarf_xmm7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 566 LLDB_INVALID_REGNUM}, 567 nullptr, 568 nullptr, 569 nullptr, 570 0}, 571 {"mxcsr", 572 nullptr, 573 4, 574 0, 575 eEncodingUint, 576 eFormatHex, 577 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 578 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, 579 nullptr, 580 nullptr, 581 nullptr, 582 0}, 583 {"ymm0", 584 nullptr, 585 32, 586 0, 587 eEncodingVector, 588 eFormatVectorOfUInt8, 589 {LLDB_INVALID_REGNUM, dwarf_ymm0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 590 LLDB_INVALID_REGNUM}, 591 nullptr, 592 nullptr, 593 nullptr, 594 0}, 595 {"ymm1", 596 nullptr, 597 32, 598 0, 599 eEncodingVector, 600 eFormatVectorOfUInt8, 601 {LLDB_INVALID_REGNUM, dwarf_ymm1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 602 LLDB_INVALID_REGNUM}, 603 nullptr, 604 nullptr, 605 nullptr, 606 0}, 607 {"ymm2", 608 nullptr, 609 32, 610 0, 611 eEncodingVector, 612 eFormatVectorOfUInt8, 613 {LLDB_INVALID_REGNUM, dwarf_ymm2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 614 LLDB_INVALID_REGNUM}, 615 nullptr, 616 nullptr, 617 nullptr, 618 0}, 619 {"ymm3", 620 nullptr, 621 32, 622 0, 623 eEncodingVector, 624 eFormatVectorOfUInt8, 625 {LLDB_INVALID_REGNUM, dwarf_ymm3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 626 LLDB_INVALID_REGNUM}, 627 nullptr, 628 nullptr, 629 nullptr, 630 0}, 631 {"ymm4", 632 nullptr, 633 32, 634 0, 635 eEncodingVector, 636 eFormatVectorOfUInt8, 637 {LLDB_INVALID_REGNUM, dwarf_ymm4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 638 LLDB_INVALID_REGNUM}, 639 nullptr, 640 nullptr, 641 nullptr, 642 0}, 643 {"ymm5", 644 nullptr, 645 32, 646 0, 647 eEncodingVector, 648 eFormatVectorOfUInt8, 649 {LLDB_INVALID_REGNUM, dwarf_ymm5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 650 LLDB_INVALID_REGNUM}, 651 nullptr, 652 nullptr, 653 nullptr, 654 0}, 655 {"ymm6", 656 nullptr, 657 32, 658 0, 659 eEncodingVector, 660 eFormatVectorOfUInt8, 661 {LLDB_INVALID_REGNUM, dwarf_ymm6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 662 LLDB_INVALID_REGNUM}, 663 nullptr, 664 nullptr, 665 nullptr, 666 0}, 667 {"ymm7", 668 nullptr, 669 32, 670 0, 671 eEncodingVector, 672 eFormatVectorOfUInt8, 673 {LLDB_INVALID_REGNUM, dwarf_ymm7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 674 LLDB_INVALID_REGNUM}, 675 nullptr, 676 nullptr, 677 nullptr, 678 0}}; 679 680static const uint32_t k_num_register_infos = 681 llvm::array_lengthof(g_register_infos); 682static bool g_register_info_names_constified = false; 683 684const lldb_private::RegisterInfo * 685ABIMacOSX_i386::GetRegisterInfoArray(uint32_t &count) { 686 // Make the C-string names and alt_names for the register infos into const 687 // C-string values by having the ConstString unique the names in the global 688 // constant C-string pool. 689 if (!g_register_info_names_constified) { 690 g_register_info_names_constified = true; 691 for (uint32_t i = 0; i < k_num_register_infos; ++i) { 692 if (g_register_infos[i].name) 693 g_register_infos[i].name = 694 ConstString(g_register_infos[i].name).GetCString(); 695 if (g_register_infos[i].alt_name) 696 g_register_infos[i].alt_name = 697 ConstString(g_register_infos[i].alt_name).GetCString(); 698 } 699 } 700 count = k_num_register_infos; 701 return g_register_infos; 702} 703 704size_t ABIMacOSX_i386::GetRedZoneSize() const { return 0; } 705 706// Static Functions 707 708ABISP 709ABIMacOSX_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { 710 if ((arch.GetTriple().getArch() == llvm::Triple::x86) && 711 (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS() || 712 arch.GetTriple().isWatchOS())) { 713 return ABISP( 714 new ABIMacOSX_i386(std::move(process_sp), MakeMCRegisterInfo(arch))); 715 } 716 return ABISP(); 717} 718 719bool ABIMacOSX_i386::PrepareTrivialCall(Thread &thread, addr_t sp, 720 addr_t func_addr, addr_t return_addr, 721 llvm::ArrayRef<addr_t> args) const { 722 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 723 if (!reg_ctx) 724 return false; 725 uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber( 726 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 727 uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber( 728 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 729 730 // When writing a register value down to memory, the register info used to 731 // write memory just needs to have the correct size of a 32 bit register, the 732 // actual register it pertains to is not important, just the size needs to be 733 // correct. Here we use "eax"... 734 const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax"); 735 if (!reg_info_32) 736 return false; // TODO this should actually never happen 737 738 // Make room for the argument(s) on the stack 739 740 Status error; 741 RegisterValue reg_value; 742 743 // Write any arguments onto the stack 744 sp -= 4 * args.size(); 745 746 // Align the SP 747 sp &= ~(16ull - 1ull); // 16-byte alignment 748 749 addr_t arg_pos = sp; 750 751 for (addr_t arg : args) { 752 reg_value.SetUInt32(arg); 753 error = reg_ctx->WriteRegisterValueToMemory( 754 reg_info_32, arg_pos, reg_info_32->byte_size, reg_value); 755 if (error.Fail()) 756 return false; 757 arg_pos += 4; 758 } 759 760 // The return address is pushed onto the stack (yes after we just set the 761 // alignment above!). 762 sp -= 4; 763 reg_value.SetUInt32(return_addr); 764 error = reg_ctx->WriteRegisterValueToMemory( 765 reg_info_32, sp, reg_info_32->byte_size, reg_value); 766 if (error.Fail()) 767 return false; 768 769 // %esp is set to the actual stack value. 770 771 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp)) 772 return false; 773 774 // %eip is set to the address of the called function. 775 776 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr)) 777 return false; 778 779 return true; 780} 781 782static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width, 783 bool is_signed, Process *process, 784 addr_t ¤t_stack_argument) { 785 786 uint32_t byte_size = (bit_width + (8 - 1)) / 8; 787 Status error; 788 if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, 789 is_signed, scalar, error)) { 790 current_stack_argument += byte_size; 791 return true; 792 } 793 return false; 794} 795 796bool ABIMacOSX_i386::GetArgumentValues(Thread &thread, 797 ValueList &values) const { 798 unsigned int num_values = values.GetSize(); 799 unsigned int value_index; 800 801 // Get the pointer to the first stack argument so we have a place to start 802 // when reading data 803 804 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 805 806 if (!reg_ctx) 807 return false; 808 809 addr_t sp = reg_ctx->GetSP(0); 810 811 if (!sp) 812 return false; 813 814 addr_t current_stack_argument = sp + 4; // jump over return address 815 816 for (value_index = 0; value_index < num_values; ++value_index) { 817 Value *value = values.GetValueAtIndex(value_index); 818 819 if (!value) 820 return false; 821 822 // We currently only support extracting values with Clang QualTypes. Do we 823 // care about others? 824 CompilerType compiler_type(value->GetCompilerType()); 825 llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread); 826 if (bit_size) { 827 bool is_signed; 828 if (compiler_type.IsIntegerOrEnumerationType(is_signed)) 829 ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed, 830 thread.GetProcess().get(), current_stack_argument); 831 else if (compiler_type.IsPointerType()) 832 ReadIntegerArgument(value->GetScalar(), *bit_size, false, 833 thread.GetProcess().get(), current_stack_argument); 834 } 835 } 836 837 return true; 838} 839 840Status ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, 841 lldb::ValueObjectSP &new_value_sp) { 842 Status error; 843 if (!new_value_sp) { 844 error.SetErrorString("Empty value object for return value."); 845 return error; 846 } 847 848 CompilerType compiler_type = new_value_sp->GetCompilerType(); 849 if (!compiler_type) { 850 error.SetErrorString("Null clang type for return value."); 851 return error; 852 } 853 854 Thread *thread = frame_sp->GetThread().get(); 855 856 bool is_signed; 857 uint32_t count; 858 bool is_complex; 859 860 RegisterContext *reg_ctx = thread->GetRegisterContext().get(); 861 862 bool set_it_simple = false; 863 if (compiler_type.IsIntegerOrEnumerationType(is_signed) || 864 compiler_type.IsPointerType()) { 865 DataExtractor data; 866 Status data_error; 867 size_t num_bytes = new_value_sp->GetData(data, data_error); 868 if (data_error.Fail()) { 869 error.SetErrorStringWithFormat( 870 "Couldn't convert return value to raw data: %s", 871 data_error.AsCString()); 872 return error; 873 } 874 lldb::offset_t offset = 0; 875 if (num_bytes <= 8) { 876 const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0); 877 if (num_bytes <= 4) { 878 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); 879 880 if (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value)) 881 set_it_simple = true; 882 } else { 883 uint32_t raw_value = data.GetMaxU32(&offset, 4); 884 885 if (reg_ctx->WriteRegisterFromUnsigned(eax_info, raw_value)) { 886 const RegisterInfo *edx_info = 887 reg_ctx->GetRegisterInfoByName("edx", 0); 888 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset); 889 890 if (reg_ctx->WriteRegisterFromUnsigned(edx_info, raw_value)) 891 set_it_simple = true; 892 } 893 } 894 } else { 895 error.SetErrorString("We don't support returning longer than 64 bit " 896 "integer values at present."); 897 } 898 } else if (compiler_type.IsFloatingPointType(count, is_complex)) { 899 if (is_complex) 900 error.SetErrorString( 901 "We don't support returning complex values at present"); 902 else 903 error.SetErrorString( 904 "We don't support returning float values at present"); 905 } 906 907 if (!set_it_simple) 908 error.SetErrorString( 909 "We only support setting simple integer return types at present."); 910 911 return error; 912} 913 914ValueObjectSP 915ABIMacOSX_i386::GetReturnValueObjectImpl(Thread &thread, 916 CompilerType &compiler_type) const { 917 Value value; 918 ValueObjectSP return_valobj_sp; 919 920 if (!compiler_type) 921 return return_valobj_sp; 922 923 // value.SetContext (Value::eContextTypeClangType, 924 // compiler_type.GetOpaqueQualType()); 925 value.SetCompilerType(compiler_type); 926 927 RegisterContext *reg_ctx = thread.GetRegisterContext().get(); 928 if (!reg_ctx) 929 return return_valobj_sp; 930 931 bool is_signed; 932 933 if (compiler_type.IsIntegerOrEnumerationType(is_signed)) { 934 llvm::Optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread); 935 if (!bit_width) 936 return return_valobj_sp; 937 unsigned eax_id = 938 reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; 939 unsigned edx_id = 940 reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB]; 941 942 switch (*bit_width) { 943 default: 944 case 128: 945 // Scalar can't hold 128-bit literals, so we don't handle this 946 return return_valobj_sp; 947 case 64: 948 uint64_t raw_value; 949 raw_value = 950 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 951 0xffffffff; 952 raw_value |= 953 (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 954 0xffffffff) 955 << 32; 956 if (is_signed) 957 value.GetScalar() = (int64_t)raw_value; 958 else 959 value.GetScalar() = (uint64_t)raw_value; 960 break; 961 case 32: 962 if (is_signed) 963 value.GetScalar() = (int32_t)( 964 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 965 0xffffffff); 966 else 967 value.GetScalar() = (uint32_t)( 968 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 969 0xffffffff); 970 break; 971 case 16: 972 if (is_signed) 973 value.GetScalar() = (int16_t)( 974 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 975 0xffff); 976 else 977 value.GetScalar() = (uint16_t)( 978 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 979 0xffff); 980 break; 981 case 8: 982 if (is_signed) 983 value.GetScalar() = (int8_t)( 984 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 985 0xff); 986 else 987 value.GetScalar() = (uint8_t)( 988 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 989 0xff); 990 break; 991 } 992 } else if (compiler_type.IsPointerType()) { 993 unsigned eax_id = 994 reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; 995 uint32_t ptr = 996 thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 997 0xffffffff; 998 value.GetScalar() = ptr; 999 } else { 1000 // not handled yet 1001 return return_valobj_sp; 1002 } 1003 1004 // If we get here, we have a valid Value, so make our ValueObject out of it: 1005 1006 return_valobj_sp = ValueObjectConstResult::Create( 1007 thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); 1008 return return_valobj_sp; 1009} 1010 1011// This defines the CFA as esp+4 1012// the saved pc is at CFA-4 (i.e. esp+0) 1013// The saved esp is CFA+0 1014 1015bool ABIMacOSX_i386::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { 1016 unwind_plan.Clear(); 1017 unwind_plan.SetRegisterKind(eRegisterKindDWARF); 1018 1019 uint32_t sp_reg_num = dwarf_esp; 1020 uint32_t pc_reg_num = dwarf_eip; 1021 1022 UnwindPlan::RowSP row(new UnwindPlan::Row); 1023 row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4); 1024 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false); 1025 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); 1026 unwind_plan.AppendRow(row); 1027 unwind_plan.SetSourceName("i386 at-func-entry default"); 1028 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 1029 return true; 1030} 1031 1032// This defines the CFA as ebp+8 1033// The saved pc is at CFA-4 (i.e. ebp+4) 1034// The saved ebp is at CFA-8 (i.e. ebp+0) 1035// The saved esp is CFA+0 1036 1037bool ABIMacOSX_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { 1038 unwind_plan.Clear(); 1039 unwind_plan.SetRegisterKind(eRegisterKindDWARF); 1040 1041 uint32_t fp_reg_num = dwarf_ebp; 1042 uint32_t sp_reg_num = dwarf_esp; 1043 uint32_t pc_reg_num = dwarf_eip; 1044 1045 UnwindPlan::RowSP row(new UnwindPlan::Row); 1046 const int32_t ptr_size = 4; 1047 1048 row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); 1049 row->SetOffset(0); 1050 1051 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); 1052 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); 1053 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); 1054 1055 unwind_plan.AppendRow(row); 1056 unwind_plan.SetSourceName("i386 default unwind plan"); 1057 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 1058 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 1059 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); 1060 return true; 1061} 1062 1063bool ABIMacOSX_i386::RegisterIsVolatile(const RegisterInfo *reg_info) { 1064 return !RegisterIsCalleeSaved(reg_info); 1065} 1066 1067// v. 1068// http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130 1069// -IA- 1070// 32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4 1071// 1072// This document ("OS X ABI Function Call Guide", chapter "IA-32 Function 1073// Calling Conventions") says that the following registers on i386 are 1074// preserved aka non-volatile aka callee-saved: 1075// 1076// ebx, ebp, esi, edi, esp 1077 1078bool ABIMacOSX_i386::RegisterIsCalleeSaved(const RegisterInfo *reg_info) { 1079 if (reg_info) { 1080 // Saved registers are ebx, ebp, esi, edi, esp, eip 1081 const char *name = reg_info->name; 1082 if (name[0] == 'e') { 1083 switch (name[1]) { 1084 case 'b': 1085 if (name[2] == 'x' || name[2] == 'p') 1086 return name[3] == '\0'; 1087 break; 1088 case 'd': 1089 if (name[2] == 'i') 1090 return name[3] == '\0'; 1091 break; 1092 case 'i': 1093 if (name[2] == 'p') 1094 return name[3] == '\0'; 1095 break; 1096 case 's': 1097 if (name[2] == 'i' || name[2] == 'p') 1098 return name[3] == '\0'; 1099 break; 1100 } 1101 } 1102 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp 1103 return true; 1104 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp 1105 return true; 1106 if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc 1107 return true; 1108 } 1109 return false; 1110} 1111 1112void ABIMacOSX_i386::Initialize() { 1113 PluginManager::RegisterPlugin( 1114 GetPluginNameStatic(), "Mac OS X ABI for i386 targets", CreateInstance); 1115} 1116 1117void ABIMacOSX_i386::Terminate() { 1118 PluginManager::UnregisterPlugin(CreateInstance); 1119} 1120 1121lldb_private::ConstString ABIMacOSX_i386::GetPluginNameStatic() { 1122 static ConstString g_short_name("abi.macosx-i386"); 1123 return g_short_name; 1124} 1125 1126// PluginInterface protocol 1127 1128lldb_private::ConstString ABIMacOSX_i386::GetPluginName() { 1129 return GetPluginNameStatic(); 1130} 1131 1132uint32_t ABIMacOSX_i386::GetPluginVersion() { return 1; } 1133