Search code examples
xcodelinkerclangdylibios-frameworks

Change dylib name after linkage


After linkage, a dylib's name seems to be embedded into it's binary code (similar to the SONAME tag under Linux). Is it possible to change this field retrospectively?

Detailed Desciption

I have a dylib which I want to package as an iOS framework. Building a project which uses the framework under XCode works fine. However, if I try to install it to a device, I get the following error (from the device log)

codeSigningInfoByValidatingResources:performingOnlineAuthorization:ignoringCachedSigningInfo:checkingTrustCacheIfApplicable:error:]: 817: Code signing identifier DYLIB_NAME does not match bundle identifier BUNDLE_IDENTIFIER

I have found that the error disappears if I change the dylib name to match the bundle identifier at link time, i.e. calling

clang++ -shared -Wl,-dylib {OBJECT_FILES} -o BUNDLE_IDENTIFIER

Simply renaming the dylib does not solve the problem. Indeed, if I open the dylib in a hex editor, I can see that BUNDLE_IDENTIFIER is embedded into the binary. However, I was not able to find a corresponding tag if I use e.g. otool (I am no expert though, so maybe I was just using the wrong parameters). Do to build system restrictions, I would like to create the dylib with a different name and change it to the bundle identifier later.

Specific Questions

  1. Can I change the name retrospectively?
  2. What is the connection between dylib name and code signing identifier?
  3. How does Apple parse the name from the dylib?

Solution

  • Your issue is likely about this identifier, which is stored in the code signature blob (using CFNetwork.framework for demo):

    $ codesign -dvv CFNetwork 2>&1 | egrep ^Identifier
    Identifier=com.apple.CFNetwork
    

    You can change that with the codesign -i flag. From the man page:

     -i, --identifier identifier
             During signing, explicitly specify the unique identifier string that is embedded in
             code signatures. If this option is omitted, the identifier is derived from either
             the Info.plist (if present), or the filename of the executable being signed, possi-
             bly modified by the --prefix option.  It is a very bad idea to sign different pro-
             grams with the same identifier.
    

    Note that this is separate from the "library identification name", which is stored in a load command (i.e. the Mach-O header):

    $ otool -l CFNetwork | fgrep -B1 -A5 LC_ID_DYLIB
    Load command 5
              cmd LC_ID_DYLIB
          cmdsize 88
             name /System/Library/Frameworks/CFNetwork.framework/CFNetwork (offset 24)
       time stamp 1 Thu Jan  1 01:00:01 1970
          current version 0.0.0
    compatibility version 1.0.0
    

    That one you can change with install_name_tool -id (though you'll have to do that before signing, or it will invalidate the signature). Again from the man page:

       -id name
              Changes the shared library identification name of a  dynamic  shared  library  to
              name.  If the Mach-O binary is not a dynamic shared library and the -id option is
              specified it is ignored.