bluewhalesystems / sold

The sold linker
MIT License
475 stars 33 forks source link

SOLD fails to link on macOS Intel when linking swift's ArgumentParser #23

Open tapthaker opened 1 year ago

tapthaker commented 1 year ago

Swift's argument parser has the following load command:

Load command 8
     cmd LC_LINKER_OPTION
 cmdsize 40
   count 1
  string #1 -lswift_StringProcessing

And the libswift_StringProcessing.tbd has the install_name:

  --- !tapi-tbd
tbd-version:     4
targets:         [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst, 
                   arm64e-macos, arm64e-maccatalyst ]
uuids:
  - target:          x86_64-macos
    value:           E19EB443-F0EC-3A7A-A852-37DC55A065DE
  - target:          x86_64-maccatalyst
    value:           E19EB443-F0EC-3A7A-A852-37DC55A065DE
  - target:          arm64-macos
    value:           00000000-0000-0000-0000-000000000000
  - target:          arm64-maccatalyst
    value:           00000000-0000-0000-0000-000000000000
  - target:          arm64e-macos
    value:           65A6E253-6FB1-330F-BBFC-C9572C216770
  - target:          arm64e-maccatalyst
    value:           65A6E253-6FB1-330F-BBFC-C9572C216770
install-name:    '/usr/lib/swift/libswift_StringProcessing.dylib'
current-version: 0
swift-abi-version: 7

So, SOLD is right in setting the load command:

Load command 20
          cmd LC_LOAD_DYLIB
      cmdsize 72
         name /usr/lib/swift/libswift_StringProcessing.dylib (offset 24)

However, the file /usr/lib/swift/libswift_StringProcessing.dylib doesn't exist and this results in the error:

  Reason: tried: '/usr/lib/swift/libswift_StringProcessing.dylib' (no such file), '/usr/local/lib/libswift_StringProcessing.dylib' (no such file), '/usr/lib/libswift_StringProcessing.dylib' (no such file)
zsh: abort      ./a.o

Interestingly, LD64 or LLD doesn't run into this or add libswift_StringProcessing.dylib to the load command.

Here is a reproducer: sold-repro-libswift-StringProcessing-x86_64.tar.gz

rui314 commented 1 year ago

With 1136fda7277fb0d199ebf41e09fbd46fb7bfe725, the test program now links fine. However, the generated test program runs into an infinite loop which mysteriously finishes only when running under lldb, which is very hard to debug. Could you try again and try to reduce the testcase for me?

tapthaker commented 1 year ago

Hmm, in my case I am running into the following symbols not found:

dyld[58930]: Symbol not found: (_$s10Foundation14LocalizedErrorMp)
  Referenced from: '/Users/mobileci/sold-repro-libswift-StringProcessing/a.out'
  Expected in: '/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation'
rui314 commented 1 year ago

Actually it works just fine on my Intel Mac, and it falls into an infinite loop on an ARM Mac.

On my Intel Mac, symbol _$s10Foundation14LocalizedErrorMp seems to be resolved just fine from /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation.

tapthaker commented 1 year ago

What macOS version are you on your intel mac. Here is mine:

sold-repro-libswift-StringProcessing % sw_vers
ProductName:    macOS
ProductVersion: 12.6.1
BuildVersion:   21G217
rui314 commented 1 year ago

Both my M2 and Intel Macs are at this version:

$ sw_vers
ProductName:        macOS
ProductVersion:     13.2.1
BuildVersion:       22D68
keith commented 1 year ago

Ive seen what i think is the same error in the case that folks used a minimum macOS version to link a binary that is larger than the OS they're running. In this case using macOS 13 to link and then running on macOS 12. Specifically because foundation changed their overlays wrt swift

tapthaker commented 1 year ago

Sorry I have been busy last couple of days. I'll get to this near the end of next week.

rui314 commented 1 year ago

I was trying to downgrade my Intel Mac to Monterey and accidentally bricked it. I'm now trying to fix it...

rui314 commented 1 year ago

So I downgraded my Intel Mac to Monterey and tried to reproduce the problem. However, the test just passed on my machine. Is this still a problem for you? This is my environment:

$ sw_vers
ProductName:    macOS
ProductVersion: 12.3
BuildVersion:   21E230
tapthaker commented 1 year ago

So I tried executing on latest version, this is still a problem for me:

sold-repro-libswift-StringProcessing % ./ld64.mold -v
mold (sold) 1.11.0 (daf2cf3c28eeb8bf081895c94360a14c48c8e4d0; compatible with GNU ld)
sold-repro-libswift-StringProcessing %
sold-repro-libswift-StringProcessing % ./ld64.mold -v
mold (sold) 1.11.0 (daf2cf3c28eeb8bf081895c94360a14c48c8e4d0; compatible with GNU ld)
sold-repro-libswift-StringProcessing % sw_vers
ProductName:    macOS
ProductVersion: 12.6.1
BuildVersion:   21G217
sold-repro-libswift-StringProcessing % bash test.sh
dyld[23235]: Symbol not found: (_$s10Foundation14LocalizedErrorMp)
  Referenced from: '/Users/mobileci/sold-repro-libswift-StringProcessing/a.out'
  Expected in: '/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation'
test.sh: line 10: 23235 Abort trap: 6           ./a.out

@keith's suggestion is spot on !! Things executed successfully after I downgraded to Xcode 13.4 and executed it on macOS 12.6.1. However, I think my setup is correct and sold, or the compiler should handle this since I am setting minimum SDK to 10.15

      cmd LC_BUILD_VERSION
  cmdsize 24
 platform 1
    minos 10.15
      sdk 13.0
tapthaker commented 1 year ago

If I understand the folliowing symbol correctly:

$ld$previous$/usr/lib/swift/libswiftFoundation.dylib$1.0.0$1$10.15$13.0$_$s10Foundation14LocalizedErrorMp

I think we should be replacing the install_name: /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation with /usr/lib/swift/libswiftFoundation.dylib

sold-repro-libswift-StringProcessing % otool -L a.out.ld64
a.out.ld64:
        /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1300.32.0)
        /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.0.0)
        /usr/lib/swift/libswiftCore.dylib (compatibility version 1.0.0, current version 5.7.1)
        /usr/lib/swift/libswiftCoreFoundation.dylib (compatibility version 1.0.0, current version 120.100.0, weak)
        /usr/lib/swift/libswiftDarwin.dylib (compatibility version 1.0.0, current version 0.0.0)
        /usr/lib/swift/libswiftDispatch.dylib (compatibility version 1.0.0, current version 17.0.0, weak)
        /usr/lib/swift/libswiftIOKit.dylib (compatibility version 1.0.0, current version 1.0.0, weak)
        /usr/lib/swift/libswiftObjectiveC.dylib (compatibility version 1.0.0, current version 6.0.0, weak)
        /usr/lib/swift/libswiftXPC.dylib (compatibility version 1.0.0, current version 6.0.0, weak)
        /usr/lib/swift/libswiftFoundation.dylib (compatibility version 1.0.0, current version 1.0.0)

sold-repro-libswift-StringProcessing % otool -L a.out.sold
a.out.sold:
        /usr/lib/libc++.1.dylib (compatibility version 0.0.0, current version 0.0.0)
        /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/libobjc.A.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/libSystem.B.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/swift/libswiftCore.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/swift/libswiftDarwin.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/swift/libswiftObjectiveC.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/swift/libswiftCoreFoundation.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/swift/libswiftDispatch.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/swift/libswiftXPC.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/swift/libswiftIOKit.dylib (compatibility version 0.0.0, current version 0.0.0)
        /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 0.0.0, current version 0.0.0)
rui314 commented 1 year ago

@tapthaker Thank you for pointing that out. It looks like sold indeed handled $ld$previous symbols incorrectly. I'll fix it.