Hello,
I am currently researching for ways to get the versions of all of the Mach-O executables and dylibs installed on my MacOS machine.
Based on my initial research, I am able to get the information of installed applications from commands like "lsappinfo" and "system_profiler SPApplicationsDataType".
However, the above commands only give me information about applications installed in my machine, not all the Mach-O binaries and dylibs.
I also saw otool -L output is not very reliable as some dylibs don't show the current version.
Are there any alternate commands I can try to get this information? Can this be achievable through any frameworks on MacOS? Any pointers will help me a lot.
From the perspective of a security product:
- You can’t trust
lsappinfoor any API layered on top of Launch Services. It’s possible for apps to be on the system that are not known to LS. - Given an app bundle, you can’t find all the Mach-O images within that bundle other than by walking the file system hierarchy.
That second point warrants further explanation. While Apple has clear guidelines about where to put code within a bundle — see Placing content in a bundle — many (many many) third-party apps bend those guidelines. For example, it’s very common to see entire Java runtimes placed within Contents/Resources. APIs like NSBundle assume that the bundle is structured correctly, and thus won’t be useful in a security product that can’t trust the bundle’s structure.
Finally, there’s your question about dynamic library versions. There are no good APIs for that, but the Mach-O on-disk image structure is reasonably well defined [1] and thus you can open the file and read the info you need:
- Identify a relevant file by looking for the Mach-O and universal binary magic numbers. If it’s a universal binary, process each Mach-O image within that separately.
- Look at the
filetypefield of the Mach-O header to tell whether it’s a dynamic library or not. - If it’s a dynamic library, parse the load commands look for a
LC_ID_DYLIBcommand. That includescurrent_versionandcompatibility_versionfields. - You should also look for the
LC_BUILD_VERSIONcommand (and the olderLC_VERSION_MIN_xyzcommands) to confirm whether this code is actually built for macOS or not. Keep in mind that:
- DriverKit is a separate platform than macOS.
- macOS supports the iOS Apps on Mac feature.
- On a Mac used by a developer, you will likely encounter Mach-O images built for the simulator platform.
I have a bunch of links to Mach-O docs and resources in An Apple Library Primer.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] That “reasonably” is important. The general structure of a Mach-O file is quite stable. Once you start digging into the details, that story starts to change. For example, a Mach-O file will likely container a code signature, and we only support folks creating that with Apple tools.