feat(tweaks): configurable injection path and optional tweak loader - #223
feat(tweaks): configurable injection path and optional tweak loader#223Mr-Tomahawk wants to merge 1 commit into
Conversation
Add --tweak-loader to choose between bundling ElleKit/CydiaSubstrate and bundling nothing, plus --tweak-inject-path/--tweak-inject-folder to control where user tweak dylibs and frameworks are copied and what load path is written into the app executable. Supporting Mach-O work: LC_RPATH listing and insertion (rpaths()/add_rpath()) exposed through the machO subcommand as --list-rpaths/--add-rpath, and LC_* string parsing generalised to any load command offset field.
|
Something I need to know is that what's actually the point of the injection path options for tweaks? To me, yes they're in different directories but achieve the same functionality. Is it for tweak detection or what? |
|
tweak detection is one aspect yes. but sometimes due to app structures a tweak will successfully inject in one path but not the other. to be honest its not too critical, but I figure'd might as well include the option. the idea was to bring it to parity with the "Esign" side loading app, which I have used extensively. The paths are more of an edge case, but one thats nice to have at least for me, though I understand why it may not be the case for others |
is there an example of this? |
not off the top of my head but I've had cases where a tweak will fail to inject unless it was in frameworks folder, or root folder. in those rare cases being able to choose is beneficial, though it may have been a tweak issue or a side load tool issue (see claration/Feather#256 as an example, it may have been something like that). However it's also nice for apps with poor tweak detection, who check for tweaks solely by scanning one dir but might overlook another, this works nicely. However I can see why it might not be merge worthy, my main concern is the ability to choose to not inject ellekit or anything at all into a tweak since not all tweaks depend on it |
Adds control over two things that were previously hardcoded when applying tweaks: which loader gets bundled, and where user tweak dylibs/frameworks land and are loaded from.
Tweak loader
New
--tweak-loader <ellekit|none>onplumesign sign(defaultellekit, i.e. current behavior).ellekit— unchanged: the bundled ElleKit/CydiaSubstrate compatibility deb is installed andCydiaSubstratereferences in tweaks are patched to point at it.none— nothing is bundled. User tweak dylibs/frameworks are still copied in and injected, but no loader deb is installed and no CydiaSubstrate patching happens. This is what you want for tweaks that link nothing (or ship their own hooking), and for tweaks meant to run against a substitute/substrate already present on the target.SignerOptions::tweak_loadercarries this, so it's usable from the library too.Injection path
Two new flags, both opt-in — if neither is passed, behavior is byte-for-byte the old one (copy into
Frameworks/, inject@rpath/<leaf>):--tweak-inject-path <@rpath|@executable_path>(default@rpath)--tweak-inject-folder </|Frameworks/>(default/)Passing either switches to explicit mode, where the destination directory and the
LC_LOAD_DYLIBstring are derived from the pair — e.g.@executable_path+/copies the dylib next to the executable and injects@executable_path/MyTweak.dylib;@rpath+Frameworks/injects@rpath/Frameworks/MyTweak.dylib. Frameworks resolve their executable from the inner Info.plist and get the same treatment.When
@rpathis selected in explicit mode, anLC_RPATHof@executable_pathis added to the app executable first so the load path actually resolves.Mach-O support
Needed for the above:
MachO::rpaths()/MachO::add_rpath(), withLC_RPATHinsertion done in place in the load-command padding (errors out rather than corrupting the binary if there isn't room).plumesign macho --list-rpathsand--add-rpath <RPATH>to drive those from the CLI.lc_strparser is generalised to take the offset-field position instead of assuming 8, sinceLC_RPATHandLC_LOAD_DYLIBboth need it.add_dylibalready flushes, so the redundantwrite_changes()call after it is gone.Compatibility
Defaults are unchanged everywhere.
Tweak::new()keeps its signature and maps to ellekit + legacy injection;new_with_loader()/new_with_options()are the new entry points.