EDIT: The below applies only to non-jailbroken devices. Jailbreaks usually disable signature checking completely to allow unsigned homebrew software to run.
Apparently only libraries which are listed as dependencies of the executable in the header (
LC_LOAD_DYLIB and similar commands) are checked, and those loaded with
dlopen are not.
This is mentioned indirectly in the Code Signing Guide:
As with other Gatekeeper functions, this check is performed the first
time the app is run. It does not apply to libraries that the app loads
itself using the
dlopen function, although those libraries are still
potentially subject to library validation, as described in Using
Following the link, we see this passage:
Starting in iOS 8 and macOS 10.10, the system offers library
validation as a policy for the dynamic libraries that a process links
The policy is simple: A program may link against any library
with the same team identifier in its code signature as the main
executable, or with any Apple system library. Requests to link against
other libraries are denied.
In iOS, an Apple system library is a
library that Apple mastered into the OS image. In macOS, an Apple
system library is a library shipped in /System/Library. The team
identifier is the 10-character alphanumeric string, such as
YH9SZ5LKR4, associated with your developer account, and recorded in
your Apple-issued signing certificate.
In iOS, library validation is
always enabled for all apps. There is nothing you need to do to opt
So it would seem that
dlopen should not be able to load unsigned libraries in iOS 8 and higher, though I have not checked this.