| ... | @@ -7,6 +7,10 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { | ... | @@ -7,6 +7,10 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { |
| 7 | const default_target = b.resolveTargetQuery(.{ | 7 | const default_target = b.resolveTargetQuery(.{ |
| 8 | .os_tag = .macos, | 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 | macho_step.dependOn(testDeadStrip(b, .{ .target = default_target })); | 15 | macho_step.dependOn(testDeadStrip(b, .{ .target = default_target })); |
| 12 | macho_step.dependOn(testEntryPointDylib(b, .{ .target = default_target })); | 16 | macho_step.dependOn(testEntryPointDylib(b, .{ .target = default_target })); |
| ... | @@ -17,6 +21,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { | ... | @@ -17,6 +21,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { |
| 17 | macho_step.dependOn(testMhExecuteHeader(b, .{ .target = default_target })); | 21 | macho_step.dependOn(testMhExecuteHeader(b, .{ .target = default_target })); |
| 18 | macho_step.dependOn(testSectionBoundarySymbols(b, .{ .target = default_target })); | 22 | macho_step.dependOn(testSectionBoundarySymbols(b, .{ .target = default_target })); |
| 19 | macho_step.dependOn(testSegmentBoundarySymbols(b, .{ .target = default_target })); | 23 | macho_step.dependOn(testSegmentBoundarySymbols(b, .{ .target = default_target })); |
| | 24 | macho_step.dependOn(testWeakBind(b, .{ .target = x86_64_target })); |
| 20 | | 25 | |
| 21 | // Tests requiring symlinks when tested on Windows | 26 | // Tests requiring symlinks when tested on Windows |
| 22 | if (build_opts.has_symlinks_windows) { | 27 | if (build_opts.has_symlinks_windows) { |
| ... | @@ -629,6 +634,138 @@ fn testSegmentBoundarySymbols(b: *Build, opts: Options) *Step { | ... | @@ -629,6 +634,138 @@ fn testSegmentBoundarySymbols(b: *Build, opts: Options) *Step { |
| 629 | return test_step; | 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 | fn addTestStep(b: *Build, comptime prefix: []const u8, opts: Options) *Step { | 769 | fn addTestStep(b: *Build, comptime prefix: []const u8, opts: Options) *Step { |
| 633 | return link.addTestStep(b, "macho-" ++ prefix, opts); | 770 | return link.addTestStep(b, "macho-" ++ prefix, opts); |
| 634 | } | 771 | } |