| ... | ... | @@ -7,6 +7,10 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { |
| 7 | 7 | const default_target = b.resolveTargetQuery(.{ |
| 8 | 8 | .os_tag = .macos, |
| 9 | 9 | }); |
| 10 | const x86_64_target = b.resolveTargetQuery(.{ |
| 11 | .cpu_arch = .x86_64, |
| 12 | .os_tag = .macos, |
| 13 | }); |
| 10 | 14 | |
| 11 | 15 | macho_step.dependOn(testDeadStrip(b, .{ .target = default_target })); |
| 12 | 16 | macho_step.dependOn(testEntryPointDylib(b, .{ .target = default_target })); |
| ... | ... | @@ -17,6 +21,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { |
| 17 | 21 | macho_step.dependOn(testMhExecuteHeader(b, .{ .target = default_target })); |
| 18 | 22 | macho_step.dependOn(testSectionBoundarySymbols(b, .{ .target = default_target })); |
| 19 | 23 | macho_step.dependOn(testSegmentBoundarySymbols(b, .{ .target = default_target })); |
| 24 | macho_step.dependOn(testWeakBind(b, .{ .target = x86_64_target })); |
| 20 | 25 | |
| 21 | 26 | // Tests requiring symlinks when tested on Windows |
| 22 | 27 | if (build_opts.has_symlinks_windows) { |
| ... | ... | @@ -629,6 +634,138 @@ fn testSegmentBoundarySymbols(b: *Build, opts: Options) *Step { |
| 629 | 634 | return test_step; |
| 630 | 635 | } |
| 631 | 636 | |
| 637 | // Adapted from https://github.com/llvm/llvm-project/blob/main/lld/test/MachO/weak-binding.s |
| 638 | fn testWeakBind(b: *Build, opts: Options) *Step { |
| 639 | const test_step = addTestStep(b, "macho-weak-bind", opts); |
| 640 | |
| 641 | const lib = addSharedLibrary(b, opts, .{ .name = "foo", .asm_source_bytes = |
| 642 | \\.globl _weak_dysym |
| 643 | \\.weak_definition _weak_dysym |
| 644 | \\_weak_dysym: |
| 645 | \\ .quad 0x1234 |
| 646 | \\ |
| 647 | \\.globl _weak_dysym_for_gotpcrel |
| 648 | \\.weak_definition _weak_dysym_for_gotpcrel |
| 649 | \\_weak_dysym_for_gotpcrel: |
| 650 | \\ .quad 0x1234 |
| 651 | \\ |
| 652 | \\.globl _weak_dysym_fn |
| 653 | \\.weak_definition _weak_dysym_fn |
| 654 | \\_weak_dysym_fn: |
| 655 | \\ ret |
| 656 | \\ |
| 657 | \\.section __DATA,__thread_vars,thread_local_variables |
| 658 | \\ |
| 659 | \\.globl _weak_dysym_tlv |
| 660 | \\.weak_definition _weak_dysym_tlv |
| 661 | \\_weak_dysym_tlv: |
| 662 | \\ .quad 0x1234 |
| 663 | }); |
| 664 | |
| 665 | { |
| 666 | const check = lib.checkObject(); |
| 667 | check.checkInExports(); |
| 668 | check.checkExtract("[WEAK] {vmaddr1} _weak_dysym"); |
| 669 | check.checkExtract("[WEAK] {vmaddr2} _weak_dysym_for_gotpcrel"); |
| 670 | check.checkExtract("[WEAK] {vmaddr3} _weak_dysym_fn"); |
| 671 | check.checkExtract("[THREAD_LOCAL, WEAK] {vmaddr4} _weak_dysym_tlv"); |
| 672 | test_step.dependOn(&check.step); |
| 673 | } |
| 674 | |
| 675 | const exe = addExecutable(b, opts, .{ .name = "main", .asm_source_bytes = |
| 676 | \\.globl _main, _weak_external, _weak_external_for_gotpcrel, _weak_external_fn |
| 677 | \\.weak_definition _weak_external, _weak_external_for_gotpcrel, _weak_external_fn, _weak_internal, _weak_internal_for_gotpcrel, _weak_internal_fn |
| 678 | \\ |
| 679 | \\_main: |
| 680 | \\ mov _weak_dysym_for_gotpcrel@GOTPCREL(%rip), %rax |
| 681 | \\ mov _weak_external_for_gotpcrel@GOTPCREL(%rip), %rax |
| 682 | \\ mov _weak_internal_for_gotpcrel@GOTPCREL(%rip), %rax |
| 683 | \\ mov _weak_tlv@TLVP(%rip), %rax |
| 684 | \\ mov _weak_dysym_tlv@TLVP(%rip), %rax |
| 685 | \\ mov _weak_internal_tlv@TLVP(%rip), %rax |
| 686 | \\ callq _weak_dysym_fn |
| 687 | \\ callq _weak_external_fn |
| 688 | \\ callq _weak_internal_fn |
| 689 | \\ mov $0, %rax |
| 690 | \\ ret |
| 691 | \\ |
| 692 | \\_weak_external: |
| 693 | \\ .quad 0x1234 |
| 694 | \\ |
| 695 | \\_weak_external_for_gotpcrel: |
| 696 | \\ .quad 0x1234 |
| 697 | \\ |
| 698 | \\_weak_external_fn: |
| 699 | \\ ret |
| 700 | \\ |
| 701 | \\_weak_internal: |
| 702 | \\ .quad 0x1234 |
| 703 | \\ |
| 704 | \\_weak_internal_for_gotpcrel: |
| 705 | \\ .quad 0x1234 |
| 706 | \\ |
| 707 | \\_weak_internal_fn: |
| 708 | \\ ret |
| 709 | \\ |
| 710 | \\.data |
| 711 | \\ .quad _weak_dysym |
| 712 | \\ .quad _weak_external + 2 |
| 713 | \\ .quad _weak_internal |
| 714 | \\ |
| 715 | \\.tbss _weak_tlv$tlv$init, 4, 2 |
| 716 | \\.tbss _weak_internal_tlv$tlv$init, 4, 2 |
| 717 | \\ |
| 718 | \\.section __DATA,__thread_vars,thread_local_variables |
| 719 | \\.globl _weak_tlv |
| 720 | \\.weak_definition _weak_tlv, _weak_internal_tlv |
| 721 | \\ |
| 722 | \\_weak_tlv: |
| 723 | \\ .quad __tlv_bootstrap |
| 724 | \\ .quad 0 |
| 725 | \\ .quad _weak_tlv$tlv$init |
| 726 | \\ |
| 727 | \\_weak_internal_tlv: |
| 728 | \\ .quad __tlv_bootstrap |
| 729 | \\ .quad 0 |
| 730 | \\ .quad _weak_internal_tlv$tlv$init |
| 731 | }); |
| 732 | exe.linkLibrary(lib); |
| 733 | |
| 734 | { |
| 735 | const check = exe.checkObject(); |
| 736 | |
| 737 | check.checkInExports(); |
| 738 | check.checkExtract("[WEAK] {vmaddr1} _weak_external"); |
| 739 | check.checkExtract("[WEAK] {vmaddr2} _weak_external_for_gotpcrel"); |
| 740 | check.checkExtract("[WEAK] {vmaddr3} _weak_external_fn"); |
| 741 | check.checkExtract("[THREAD_LOCAL, WEAK] {vmaddr4} _weak_tlv"); |
| 742 | |
| 743 | check.checkInDyldBind(); |
| 744 | check.checkContains("(libfoo.dylib) _weak_dysym_for_gotpcrel"); |
| 745 | check.checkContains("(libfoo.dylib) _weak_dysym_fn"); |
| 746 | check.checkContains("(libfoo.dylib) _weak_dysym"); |
| 747 | check.checkContains("(libfoo.dylib) _weak_dysym_tlv"); |
| 748 | |
| 749 | check.checkInDyldWeakBind(); |
| 750 | check.checkContains("_weak_external_for_gotpcrel"); |
| 751 | check.checkContains("_weak_dysym_for_gotpcrel"); |
| 752 | check.checkContains("_weak_external_fn"); |
| 753 | check.checkContains("_weak_dysym_fn"); |
| 754 | check.checkContains("_weak_dysym"); |
| 755 | check.checkContains("_weak_external"); |
| 756 | check.checkContains("_weak_tlv"); |
| 757 | check.checkContains("_weak_dysym_tlv"); |
| 758 | |
| 759 | test_step.dependOn(&check.step); |
| 760 | } |
| 761 | |
| 762 | const run = addRunArtifact(exe); |
| 763 | run.expectExitCode(0); |
| 764 | test_step.dependOn(&run.step); |
| 765 | |
| 766 | return test_step; |
| 767 | } |
| 768 | |
| 632 | 769 | fn addTestStep(b: *Build, comptime prefix: []const u8, opts: Options) *Step { |
| 633 | 770 | return link.addTestStep(b, "macho-" ++ prefix, opts); |
| 634 | 771 | } |