Just wait until akemin_dayo is coming up with a solution.
Makes no sense when getting it to work half baked yourself and risking to do chages to the system, so that the solution from akemin_dayo won’t work when it’s released.
Just use xtraFinder in the meantime. It’s free (no need to register) and works well as a temp solution.
Coloured labels are now fully working in my development build on macOS 13!
(※ Tested up to macOS 13.2 beta 1 22D5027d on both Apple Silicon [arm64e/AArch64] and Intel/AMD [x86_64].)
I ended up just completely stepping around Apple’s changes by using a different approach and completely rewriting how TotalFinder performs label colour lookups.
In other words: I dealt with the headache that Apple created by simply not dealing with it.
The only major thing left to do now is to fix up the somewhat broken cut-and-paste behaviour described above.
This has taken longer than expected due to me running into what I can best describe as a very strange code injection-related issue while trying to fix cut-and-paste.
※ UPDATE (2023/01/07): Cut-and-paste is now fixed!
When will 1.14.4 1.15.0 be releasing?
TotalFinder 1.15.0 will be released in 7 days or less from this writing. (※ Plus whatever time Antonin may need to actually codesign and notarise the binaries and push it to the BinaryAge servers, as he’s pretty busy these days, too.)
If I can’t fully fix cut-and-paste by then, it’ll just have to be pushed to a future version — I’ve kept you guys waiting for long enough.
Thank you all for remaining patient and for continuing to use TotalFinder!
@eBara Yeah, the iOS jailbreaking community is actually where people usually tend to recognise me from, as I work on and maintain… several popular projects ranging from iOS 16 all the way down to iOS 5 (which, in the interest of trying not to self-advertise here, you’ll have to find through my website).
My experience with reverse engineering and code-injecting/hooking into iOS/macOS processes (as well as just having a wide range of knowledge on how Apple operating systems work in general) also helps a lot when working on TotalFinder ;P
Sounds nice, but I could still wait to really get it working with cut/paste & Intel macOS13.
It’s to important to miss cut/paste ability until the next release.
Just to see what (if any) results would occur if I did that, I re-enabled SIP, rebooted,went into Recover mode and did: csrutil --without fs --without debug and restarted. In terminal, I cleared the boot args using the command line you used. Restarted and re-enabled the boot args and get the following: sudo nvram boot-args=-arm64e_preview_abi
Error setting variable - ‘boot-args’: (iokit/common) not permitted.
So, I think I’ll completely disable SIP and try again.
@Welaxxx XtraFinder is paid software, and even if it wasn’t, I don’t feel comfortable referencing from other people’s work without their explicit consent/permission, anyway.
I have very good news for everyone — cut-and-paste is now fully working in my development build on macOS 13!
(※ Tested up to macOS 13.2 beta 1 22D5027d on both Apple Silicon [arm64e/AArch64] and Intel/AMD [x86_64].)
This means all TotalFinder features are now fully working on macOS 13!!
I’ll take some time to add some dialogs to improve the initial onboarding user experience for macOS 13, as well as write up some new documentation for the TotalFinder website.
Release should arrive on schedule as stated above!
As always, thank you all for your patience.
※ The issue with TotalFinder not being able to inject into Finder on some old machines patched with OCLP is not something I can really fix on TotalFinder’s side. The root cause lies with OCLP, as their patches on those machines are actually breaking other parts of macOS functionality too, including things like SSH and authentication modules.
Only a select few machines are affected by the issue — not all OCLP-patched machines are affected, especially the more modern ones, as I’ve actually actively been using one for TotalFinder development testing purposes.
Also, this is completely unrelated to OpenCore (the UEFI bootloader).
This is wonderful news, thanks so much Karen. Can’t wait to try it out and finally update to MacOS 13.x.
Quick question though:
I currently run TotalFinder 1.14.3. If I update to MacOS 13.x (from 12.6), can you tell me if I can just run the new version of TotalFinder 1.14.4 that you’ll be releasing and be fine, or will I need to redo that whole process of disabling SIP, due to the OS update possibly putting it back ‘on’?
Thanks!
Updating macOS versions will not modify your SIP configuration — this has been the case since SIP’s introduction all the way back in OS X 10.11 (〜2015).
※ If you are using an Intel/AMD (x86_64) machine, the rest of this post does not apply to you, and you are free to ignore it.
Anyway, if you are using an Apple Silicon (arm64e/AArch64) machine and have been using the “partially weakened” SIP configuration mentioned in the documentation, you will have to go back to 1TR (One True recoveryOS) and disable NVRAM protections in addition to the other two (debug and fs).
If you have been using the “fully disabled” SIP configuration (csrutil disable), then you will not have to make any other changes.
The reason for this is because you will need to add a new boot-arg to your NVRAM configuration (-arm64e_preview_abi) to use TotalFinder on macOS 13.
Not to worry though — I’m currently working on the onboarding experience for this to make it as easy as possible for you all.
Basically, TotalFinder will detect and appropriately help walk you through the process of:
Disabling SIP NVRAM protections if you still have them on
Adding the -arm64e_preview_abi boot-arg either automatically using one button press, or instructing you on how to do it manually for those that prefer that, and then prompting for a reboot
In the interest of trying to not go on yet another multi-paragraph lecture, here’s a really over-simplified explanation.
(Hi, Future Karen here! I uh… definitely failed at that goal.)
Traditionally, when loading a dynamically-linked library (or a “dylib”) on Apple OSes, something called dyld handles the entire process of loading the dylib into a random empty space in memory and then “translating” all of the relevant memory addresses so that they’d correctly point to the wherever the dylib is actually located in memory.
(※ I’m sorry to all the developers that are currently yelling at their screens while reading this.)
Apple — in their ever-eternal pursuit of making their OSes as fast and efficient as possible — started using a technique almost a decade ago that they call “page-in linking” for dynamic libraries that are shipped as part of the system — specifically, those that are loaded from something called the dyld_shared_cache (DSC).
By letting the kernel (XNU/Darwin) handle this operation instead of dyld, the “time and memory cost” of loading a dylib is greatly lessened, leading to much faster application launch times, higher system responsiveness, lower memory usage, better security, and of course, greater power efficiency.
Basically, you can say that the full name of “page-in linking” is actually “kernel page-in linking”.
(Again, if you want to know more, I highly recommend watching the video linked above. This explanation is extremely simplified and completely disregards a lot of important aspects. See also: XNU/Darwin source code for map_with_linking_np().)
Okay, but like, you said that was almost a decade ago. What changed now?
The major change that Apple made in macOS 13 / iOS 16 is that now “page-in linking” is used for all dynamic libraries, not just ones shipped with the system (in the DSC).
… Or, well, it tries to. Not every dylib can be loaded this way, as only dylibs that are built with chained fixups enabled (LC_DYLD_CHAINED_FIXUPS) are eligible.
Basically, that means anything targetting macOS 12 / iOS 15 as a minimum version.
“But Karen,” I hear you ask. “TotalFinder currently targets macOS 10.15 as a minimum version! Doesn’t this mean it’s exempt?”
Not quite. The important part thing that is affecting TotalFinder (and other macOS tweaks like it) is the “it tries to” part.
Instead of the traditional behaviour seen in macOS 12 / iOS 15 and below where loading dylibs is pretty much almost solely handled by dyld, macOS 13 / iOS 16 appears to now always get the kernel involved to some extent in this process, regardless of whether or not the dylib works with page-in linking.
Apple’s arm64e ABI
Apple’s platform-binaries shipped as part of their OSes are all compiled using the arm64e architecture (arm64 + pointer authentication). Naturally, this includes Finder.
In order to inject code into another process, the architecture of the code you want to inject must match the architecture of the original process. (※ There are slight exceptions to this regarding minor compatible subtypes such as armv7s vs. armv7, or x86_64h vs. x86_64.)
As a result, the TotalFinder dynamic library is compiled for arm64e (and x86_64), so it can be injected into Finder, an arm64e process.
The problem here is that Apple considers their arm64e ABI to be not yet ready for production use by anyone that isn’t themselves.
In other words, they consider the ABI “unstable” — in that the specifications of the ABI are subject to breaking changes in future OS versions at Apple’s leisure, without any notice or support given.
For this reason, Apple actually prevents you from running arm64e executables by default.
Instead, you have to manually add a boot argument in NVRAM called -arm64e_preview_abi, which you have to disable SIP NVRAM protections in order to do so.
This has been true since macOS 11, the first version of macOS to support Apple Silicon.
… But I don’t need that boot-arg on my Apple Silicon machine running macOS 12 or 11! What changed in macOS 13?
Ah.
So here’s a fun little implementation detail.
The XNU/Darwin kernel is where the “Is this arm64e binary a platform-binary?” check is performed. (※ See below for the actual code excerpt.)
dyld on the other hand, will happily load anything you give it.
Including an non-platform-binary arm64e dynamic library. Such as TotalFinder.
But because macOS 13 now passes all dylib load requests through the kernel, TotalFinder is now suddenly affected by the arm64e restrictions, and thus now requires the -arm64e_preview_abi boot-arg in order to successfully inject.
Aren’t there any workarounds?
Yes, actually!
I read through the source code for the XNU/Darwin kernel to see if I could find out how the arm64e validation is being performed.
After doing that, I managed to find… one potential workaround.
It involves manually modifying the Mach-O header to bypass the arm64e check in the kernel.
If you don’t know what that means, let’s just say it’s a really horrible no good very bad super ultra you should never do this idea.
So… yeah. I’m not doing that.
For the curious: Basically, if you modify your Mach-O header’s cpusubtype in such a way that CPU_SUBTYPE_ARM64_PTR_AUTH_VERSION (which uses CPU_SUBTYPE_ARM64_PTR_AUTH_MASK) would result in some value that isn’t 0, the XNU/Darwin kernel will just… happily allow your binaries to run.
This is because it quite literally only checks to see if the value is exactly 0, and nothing else.
(Please, please never ship software that does this.)
Final notes
Unlike typical macOS / iOS tweaks, TotalFinder is technically not really a “dynamic library” or a “dylib” in the Apple Mach-O MH_DYLIB sense. Rather, it is actually a “loadable bundle”, or an MH_BUNDLE.
That being said, it is still, for all intents and purposes, a dynamic library (the generic terminology), and is therefore loaded and treated like one.
For more information, you can run otool -hvvvvvv ${PATH_TO_WHATEVER_YOU_WANT_TO_ANALYSE}.
My best guesses for how this is triggered is perhaps a flag in the SMBIOS? Or maybe detection based on regional hardware model IDs like what triggers camera shutter sounds in Japanese and South Korean iPhones? Honestly, it’s anyone’s guess, and Apple sure doesn’t have this behaviour documented anywhere (or even in the XNU/Darwin source code).
I absolutely failed at my original goal of trying not to write a massive essay. I’m sorry. ;P Hopefully this was interesting, at least!