Updating extensions for iOS 7: Difference between revisions

From iPhone Development Wiki
m (add a category for these pages)
 
(39 intermediate revisions by 16 users not shown)
Line 1: Line 1:
This is an informal collection of advice; feel free to add to it and rearrange. A lot of this is from #theos on irc.saurik.com - if you're working on updating your tweaks and you use Theos, join in and share what you've learned (see [[IRC]]).
This is an informal collection of advice; feel free to add to it and rearrange. A lot of this is from #theos on irc.saurik.com - if you're working on updating your tweaks and you use Theos, join in and share what you've learned (see [[IRC]]).


== How to compile for ARMv6 and ARM64 using the iOS 7 SDK ==
== How to compile for ARM64 ==
 
Tweak binaries must contain an ARM64 slice in order for it to be loaded into 64-bit processes. If you don't need to support iOS 4.2.1 or older, ensure Xcode 5 is installed and set <code>ARCHS</code> in your Makefile:
 
<source lang="bash">
ARCHS = armv7 arm64
</source>
 
You will also need updated versions of any libraries that you link against which contain an arm64 slice. To get the updated Substrate dylib, see saurik's instructions below, starting from the <code>wget</code> of the Substrate deb.
 
== How to compile for ARMv6 and ARM64 ==
{{Warning|Compiling for ARMv6 and ARM64 is useful in only a subset of normal situations. If you've made it this far and you do not have a particular reason to retain ARMv6 support, please see the above section.}}
 
{{Warning|This technique does not appear to work anymore with Xcode 6 - I suspect the compiler is at fault.  The Alternative Method described below using rpetrich's theos fork and separate SDKs still works. -joedj}}


These instructions only use first-party components from Apple, DHowett, and saurik (and were written by saurik).
These instructions only use first-party components from Apple, DHowett, and saurik (and were written by saurik).


The idea is that we are going to use parts of Xcode 4 (which you don't have to install: you might just have it sitting in /Volumes) to "fix" parts of Xcode 5 so that it can target armv6 (need Xcode 4.4 or lower).
The idea is that we are going to use parts of Xcode 4 (which you don't have to install: you might just have it sitting in /Volumes) to "fix" parts of Xcode 5 so that it can target armv6 (need Xcode 4.4.1).


cd $Xcode5/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/5.0/lib/darwin/
<source lang="bash">
mv libclang_rt.ios.a libclang_rt.ios-7.0.a
cd $Xcode5/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/5.0/lib/darwin/
lipo -thin armv6 -output libclang_rt.ios-5.1.a $Xcode4/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/4.0/lib/darwin/libclang_rt.ios.a
mv libclang_rt.ios.a libclang_rt.ios-7.0.a
lipo -create -output libclang_rt.ios.a libclang_rt.ios-5.1.a libclang_rt.ios-7.0.a
lipo -thin armv6 -output libclang_rt.ios-5.1.a $Xcode4/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/4.0/lib/darwin/libclang_rt.ios.a
cd $Xcode5/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/usr/lib/
lipo -create -output libclang_rt.ios.a libclang_rt.ios-5.1.a libclang_rt.ios-7.0.a
mv dylib1.o dylib1-7.0.o
cd $Xcode5/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/usr/lib/
lipo -thin armv6 -output dylib1-5.1.o $Xcode4/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/usr/lib/dylib1.o
mv dylib1.o dylib1-7.0.o
lipo -create -output dylib1.o dylib1-5.1.o dylib1-7.0.o
lipo -thin armv6 -output dylib1-5.1.o $Xcode4/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/usr/lib/dylib1.o
lipo -create -output dylib1.o dylib1-5.1.o dylib1-7.0.o
</source>


Then, we download Theos directly from DHowett's code repository, and add in the parts it needs from the various packages provided by saurik.
Then, we download Theos directly from DHowett's code repository, and add in the parts it needs from the various packages provided by saurik.


sudo mkdir /opt/theos
<source lang="bash">
sudo chown "$(id -u):$(id -g)" /opt/theos
sudo mkdir -p /opt/theos
cd /opt/theos
sudo chown "$(id -u):$(id -g)" /opt/theos
git clone https://github.com/DHowett/theos.git .
cd /opt/theos
wget http://apt.saurik.com/debs/ldid_1:1.1.2_iphoneos-arm.deb
git clone https://github.com/DHowett/theos.git .
ar p ldid_1:1.1.2_iphoneos-arm.deb data.tar.gz | tar -zxvf- --strip-components 2 ./usr/bin/ldid
wget http://apt.saurik.com/debs/ldid_1:1.1.2_iphoneos-arm.deb
wget http://apt.saurik.com/debs/mobilesubstrate_0.9.5000_iphoneos-arm.deb
ar p ldid_1:1.1.2_iphoneos-arm.deb data.tar.gz | tar -zxvf- --strip-components 2 ./usr/bin/ldid
ar p mobilesubstrate_0.9.5000_iphoneos-arm.deb data.tar.lzma >substrate.tar.lzma
wget http://apt.saurik.com/debs/mobilesubstrate_0.9.5001_iphoneos-arm.deb
... extract the lama file; OS X doesn't come with an lzma utility :( ...
ar p mobilesubstrate_0.9.5001_iphoneos-arm.deb data.tar.lzma >substrate.tar.lzma
tar -xvf substrate.tar --strip-components 3 ./Library/Frameworks/CydiaSubstrate.framework/
# ... extract the lama file; OS X doesn't come with an lzma utility :( ...
ln -s ../CydiaSubstrate.framework/Headers/CydiaSubstrate.h include/substrate.h
tar -xvf substrate.tar --strip-components 3 ./Library/Frameworks/CydiaSubstrate.framework/
ln -s ../CydiaSubstrate.framework/CydiaSubstrate lib/libsubstrate.dylib
ln -s ../CydiaSubstrate.framework/Headers/CydiaSubstrate.h include/substrate.h
ln -s ../CydiaSubstrate.framework/CydiaSubstrate lib/libsubstrate.dylib
</source>


Finally, in our Theos Makefile, we specify that we want to target iOS 2.0 using the 7.0 SDK, and that we want both ARMv6 and ARM64 slices.
Finally, in our Theos Makefile, we specify that we want to target iOS 2.0 using the 7.0 SDK, and that we want both ARMv6 and ARM64 slices.


TARGET := iphone:7.0:2.0
<source lang="bash">
ARCHS := armv6 arm64
TARGET := iphone:7.0:2.0
 
ARCHS := armv6 arm64
== Tweaks that do NOT need iOS 4.2.1 and below compatibility ==
</source>
Very easy, simply follow Kirb's advice on his blog: http://sharedinstance.net/2013/12/how-to-support-arm64/


== Tweaks that do need iOS 4.2.1 and below compatibility ==
=== Alternative method ===
This is slightly more complicated. You need to compile an armv6 slice using the 5.1 SDK and another arm64 slice using the 7.0 SDK. You then stitch both together with lipo. Kirk's blog post describes how to do that manually, but rpetrich has created a theos fork, which does that automatically for you.
This is slightly more complicated. You need to compile an armv6 slice using the 5.1 SDK and another arm64 slice using the 7.0 SDK. You then stitch both together with lipo. [http://sharedinstance.net/2013/12/how-to-support-arm64/ This blog post] describes how to do that manually, but rpetrich has created a theos fork, which does that automatically for you.


Setup rpetrich’s theos:
Setup rpetrich’s theos:


$ export THEOS=/opt/theos-rpetrich
<source lang="bash">
$ sudo git clone https://github.com/rpetrich/theos $THEOS
export THEOS=/opt/theos-rpetrich
$ wget http://joedj.net/ldid
sudo mkdir -p $THEOS
$ sudo mv ldid $THEOS/bin/ldid
sudo chown "$(id -u):$(id -g)" $THEOS
$ sudo chmod +x $THEOS/bin/ldid
cd $THEOS
$ wget http://cdn.hbang.ws/dl/libsubstrate_arm64.dylib
git clone https://github.com/rpetrich/theos .
$ sudo mv libsubstrate_arm64.dylib $THEOS/lib/libsubstrate.dylib
wget http://joedj.net/ldid -O bin/ldid
chmod +x bin/ldid
wget https://cdn.hbang.ws/dl/libsubstrate_arm64.dylib -O lib/libsubstrate.dylib
</source>


(note from rpetrich: theos should be as a submodule for my fork, not installed in a system path. system paths are dangerous)
(note from rpetrich: theos should be as a submodule for my fork, not installed in a system path. system paths are dangerous)
Line 56: Line 75:
Install headers:
Install headers:


$ cd $THEOS/; sudo ./git-submodule-recur.sh init; sudo git submodule update --recursive
<source lang="bash">
 
cd $THEOS
./git-submodule-recur.sh init
git submodule update --recursive
</source>


Setup the Makefile
Setup the Makefile


TARGET := iphone:clang
<source lang="bash">
THEOS_PLATFORM_SDK_ROOT_armv6 = /Applications/Xcode_4.4.1.app/Contents/Developer
TARGET := iphone:clang
SDKVERSION_armv6 = 5.1
THEOS_PLATFORM_SDK_ROOT_armv6 = /Applications/Xcode_4.4.1.app/Contents/Developer
TARGET_IPHONEOS_DEPLOYMENT_VERSION = 3.0
SDKVERSION_armv6 = 5.1
TARGET_IPHONEOS_DEPLOYMENT_VERSION_arm64 = 7.0
TARGET_IPHONEOS_DEPLOYMENT_VERSION = 3.0
IPHONE_ARCHS = armv6 arm64
TARGET_IPHONEOS_DEPLOYMENT_VERSION_arm64 = 7.0
ARCHS = armv6 arm64
TWEAK_NAME = iLogIt
iLogIt_FILES = Tweak.xm
include theos/makefiles/common.mk
include $(THEOS_MAKE_PATH)/tweak.mk


TWEAK_NAME = iLogIt
iLogIt_FILES = Tweak.xm
include theos/makefiles/common.mk
include $(THEOS_MAKE_PATH)/tweak.mk
</source>


rpetrich's theos is using objc's hooking method instead of MobileSubstrate therefore it doesn't link with MS by default. This is OK if you are only hooking objc messages, but if you need to use MSHookFunction, you have to tell theos to link to lib substrate:
rpetrich's theos is using objc's hooking method instead of MobileSubstrate therefore it doesn't link with MS by default. This is OK if you are only hooking objc messages, but if you need to use MSHookFunction, you have to tell theos to link to lib substrate:


<source lang="bash">
iLogIt_LIBRARIES = substrate
iLogIt_LIBRARIES = substrate
</source>


(note from saurik: I highly disrecommend not using Substrate's MSHookMessage implementation; I never understood why rpetrich doesn't use it, but on multiple occasions the way we hook messages has had to change, and centralizing it in Substrate means that I can fix it once for everyone's compiled extensions... this happened last as recently as iOS 5, and all of rpetrich's extensions had to be recompiled and redeployed, which is reasonably fine for him as he's insanely productive and around constantly, but for most people you should please just use the centralized implementation.)
(note from saurik: I highly disrecommend not using Substrate's MSHookMessage implementation; I never understood why rpetrich doesn't use it, but on multiple occasions the way we hook messages has had to change, and centralizing it in Substrate means that I can fix it once for everyone's compiled extensions... this happened last as recently as iOS 5, and all of rpetrich's extensions had to be recompiled and redeployed, which is reasonably fine for him as he's insanely productive and around constantly, but for most people you should please just use the centralized implementation.)
To use Substrate for hooking, either add this add the top of your Logos source file (e.g., Tweak.xm)
<source lang="c">
%config(generator=MobileSubstrate);
</source>
Or add it to your target's Logos flags:
<source lang="bash">
iLogIt_LOGOSFLAGS = -c generator=MobileSubstrate
</source>


Example Projects:
Example Projects:
Take a look at the Makefiles of these projects:
Take a look at the Makefiles of these projects:


https://dl.dropboxusercontent.com/u/15373/Other/iPhone/ilogit-tweak-ios7-example.tar
* https://dl.dropboxusercontent.com/u/15373/Other/iPhone/ilogit-tweak-ios7-example.tar
* https://github.com/joedj/ExchangePolicyCleaner/blob/master/Makefile#L3
* https://github.com/a3tweaks/Flipswitch


https://github.com/joedj/ExchangePolicyCleaner/blob/master/Makefile#L3
=== ARM64 on Linux ===


https://github.com/a3tweaks/Flipswitch
Using [https://github.com/LubosD/darling Darling], Apple's official toolchain is able to be used on Linux. Once Darling is installed, [https://github.com/eswick/theos-darling eswick's theos fork] can be used to build for ARM64.


== Activator Listener for 64Bit ==
XcodeDefault.xctoolchain (obtain from a Mac, or download Xcode from Apple's website) needs to be placed in $THEOS/toolchain, and $THEOS/sdk needs to point to the iOS 7 SDK, like so:
Activator binaries with support for arm64, armv6, armv7 and armv7s are available at http://rpetri.ch/repo/


== Updating code for iOS 7 ==
<source lang="bash">
git clone https://github.com/eswick/theos-darling.git /opt/theos
mv ~/XcodeDefault.xctoolchain /opt/theos/toolchain/
ln -s /var/sdks/iPhoneOS7.0.sdk /opt/theos/sdk
</source>
 
See the full blog post [http://www.eswick.com/2014/03/building-ios-arm64-binaries-on-linux/ here] for step-by-step instructions.
 
== Updating code for ARM64 ==
Read Apple's documentation on ARM64: [https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaTouch64BitGuide/ConvertingYourAppto64-Bit/ConvertingYourAppto64-Bit.html "Converting Your App to a 64-Bit Binary"]
 
If you need to specifically test for 64-bit:
 
<source lang="objc">
#ifdef __LP64__
NSLog(@"64-bit");
#else
NSLog(@"32-bit");
#endif
</source>
 
== Detecting iOS 7 ==


Detecting whether code is being compiled for iOS 7.0 or higher:
Detecting whether code is being compiled for iOS 7.0 or higher:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
    [[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleLightContent animated: YES];
#endif


== Updating Depictions ==
<source lang="objc">
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_0
[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleLightContent animated: YES];
#endif
</source>


It's best to make the background transparent to make it match Cydia's background. Just add the following to your depictions header:
Note that this is a compile time check. To check for iOS 7 at runtime, compare against the CoreFoundation version:
 
<source lang="objc">
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_0) {
// do >= iOS 7 stuff
} else {
// do <= iOS 6 stuff
}
</source>
 
Apple often forgets to add new version number constants to their headers, so you may need to define the version numbers yourself:
 
<source lang="objc">
#ifndef kCFCoreFoundationVersionNumber_iOS_7_0
#define kCFCoreFoundationVersionNumber_iOS_7_0 847.20
#endif
</source>
 
See [[CoreFoundation.framework]] for a full list.
 
== Updating Cydia Depictions ==
 
It's best to make the background transparent to make it match Cydia's background. Just add the following to your depiction's header:


<source lang="html4strict">
<source lang="html4strict">
Line 120: Line 201:
</source>
</source>


== Dealing with 64bit ==
Cydia's table cell styling hasn't currently been changed to reflect the iOS 7 UI, so no other CSS needs updating.
 
https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaTouch64BitGuide/ConvertingYourAppto64-Bit/ConvertingYourAppto64-Bit.html
 
20:44:45 <@sbingner> saurik said all tweaks will need to be recompiled to have a 64bit slice
 
20:45:10 <@sbingner> which is what I've been working on... as soon as substrate is updated I should be able to just type "make" :D
 
20:49:27 <@sbingner> crash-x, installing rpetrich's fork of theos and making sure it can compile for armv6 with latest xcode on it... and that arm64 will compile except for the mobilesubstrate lib being missing


20:45:32 <@Optimo> dlopen from a variety of avenues, or ...INSERT_LIBRARIES -- all for your own testing of course
== Theos bootstrap.sh patch for ARM64 ==


20:45:54 <@Optimo> (if you have a 64bit device)
  01:03:36 < therpgitbot> [theos] rpetrich pushed 1 new commit to master: http://git.io/ankV8g
 
01:03:36 < therpgitbot> theos/master f6ebd79 Ryan Petrich: Workaround bootstrap problems on Xcode 5.x (temporary fix for now)
If you need to specifically test for 64-bit:
 
#ifdef __LP64__
NSLog(@"64-bit\n");
#else
NSLog(@"32-bit\n");
  #endif
 
== Working with Mobile Substrate ==
 
21:22:35 < Alcatraz> https://ghostbin.com/paste/zhsx9
Tutorial to Make mobilesubstrate more stable while we wait for an official update.
 
 
Install MobileSubstrate
 
Add the repo: rpetri.ch/repo
 
Install the beta Activator
 
Done
 
Some Stuff that was broken before you installed the beta activator such as SBSettings and PreferenceLoader should be working now.
 
If they are not,it is likely another package that still wont work. Or you rebooted your device.
 
Rebooting the device seems to break mobilesubstrate for whatever reason.
 
So each time you reboot you have to reinstall mobilesubstrate or run this command:
<blockquote>
/usr/bin/cynject 1 /Library/Frameworks/CydiaSubstrate.framework/Libraries/SubstrateLauncher.dylib && killall backboardd && sbreload
</blockquote>
 
== Theos advice ==
 
21:25:55 <@DHowett> This time, you're all wrong
 
21:25:59 <@sbingner> oh?
 
21:26:01 <@DHowett> theos passes -arch flags to the compiler, after all.
 
21:26:07 < Maximus> ARCH=armv7 and uh
 
21:26:08 <@sbingner> ^^
 
21:26:12 < Maximus> ARCHS
 
21:26:18 <@DHowett> alexzielenski: by default, theos passes armv7 armv7s to the compiler on 6.0+
 
21:26:39 <@DHowett> alexzielenski: you can override this by setting ARCHS=armv7 arm64 before you include common.mk
 
21:26:48 < alexzielenski> DHowett: thanks
 
21:27:10 <@sbingner> DHowett, what I said was wrong because it wasn't complete? :P
 
21:27:26 < Maximus> i was getting there
 
21:27:41 <@DHowett> sbingner: well, because it doesn't have anything to do with the compiler, really: this is all a compiler driver problem once you have upgraded xcode
 
21:27:43 <@sbingner> have time to point me to the right place to add support for foo_FILES_arch to rpetrich's fork? I'm missing the right spot
 
21:27:52 <@DHowett> instance/rules.mk
 
21:28:29 < coolstar> screw arm64
 
21:28:36 < coolstar> the build tools are still not out yet
 
21:28:36 < coolstar> http://opensource.apple.com/
 
21:28:37 <@sbingner> ok thanks... I guess I was in the right spot but doing something wrong lol... I'll figure it out
 
21:28:44 <@DHowett> the proprietary ones are.
 
21:28:50 <@DHowett> why is everybody focusing on this now?
 
 
 
 
 
01:03:36 < therpgitbot> [theos] rpetrich pushed 1 new commit to master: http://git.io/ankV8g
 
01:03:36 < therpgitbot> theos/master f6ebd79 Ryan Petrich: Workaround bootstrap problems on Xcode 5.x (temporary fix for now)
 
 
 
 
22:58:21 <%joedj> here's a tip: if you aren't using low-level substrate features like MSHookFunction, you may be able to prepare arm64-ready packages using %config(generator=internal). of course, they won't actually work until substrate can load them
 
== Theos and ldid ==
 
12:11:37 < Ge0rges> if anyone here has a tip Still having this problem when installing ldid for theos: https://pastee.org/vasuu
 
12:28:42 <%joedj> Ge0rges: just put the ldid binary i gave you into theos/bin/ and move on to the next step
 
13:14:13 <%joedj> Ge0rges: http://joedj.net/ldid


== Dealing with 32-bit and 64-bit ==
== Dealing with 32-bit and 64-bit ==


12:38:15 <%joedj> sbingner: i did find this question (and the response 2 posts down) interesting, i'm not sure what they're talking about: https://www.mikeash.com/pyblog/friday-qa-2013-09-27-arm64-and-you.html#comment-7436311d02c5a55738d1baefa03b0d34
12:38:15 <%joedj> sbingner: i did find this question (and the response 2 posts down) interesting, i'm not sure what they're talking about: https://www.mikeash.com/pyblog/friday-qa-2013-09-27-arm64-and-you.html#comment-7436311d02c5a55738d1baefa03b0d34
 
09:55:43 <@rpetrich> joedj: it's a bug with the components that communicate with the App Store
[09:25]  <rpetrich> joedj: it's a bug with the components that communicate with the App Store
 
== Mobile Substrate tip ==
 
14:20:58 < ganbold_> so mobilesubstrate is working partially? after reboot/restart doesn't work
 
14:29:03 < ac3xx> ganbold_, either just reinstall it through cydia or run this over SSH - /var/lib/dpkg/info/mobilesubstrate.extrainst_ upgrade && killall SpringBoard


== Theos and ldid errors ==
== Theos and ldid errors ==


19:02:14 < yoshbu> I've been off the jailbreak train for awhile now. Trying to reinstall theos, getting some build failures when trying to install ldid, anybody know if there's a quick fix?
19:02:14 < yoshbu> I've been off the jailbreak train for awhile now. Trying to reinstall theos, getting some build failures when trying to install ldid, anybody know if there's a quick fix?
19:02:52 < yoshbu> like, error: unknown type name '__darwin_intptr_t'
19:02:59 < yoshbu> and, error: unknown type name '__uint32_t'; did you mean 'uint32_t'?
19:05:27 < Alcatraz> are you trying to compile ldid on mac?
19:05:55 < yoshbu> following step 4 of http://iphonedevwiki.net/index.php/Theos/Getting_Started
19:06:10 < Alcatraz> yeah compiling it has been broken for some time
19:06:27 < Alcatraz> has to do with xcode 5
19:06:32 < Alcatraz> pretty sure anyway
19:06:50 < yoshbu> ldid is a dependency of theos though right?
19:07:01 < Alcatraz> yeah. you can ask someone on here for a copy
19:08:05 < ac3xx> yoshbu, wget http://ac3xx.com/ldid -O $THEOS/bin/ldid && chmod +x $THEOS/bin/ldid


== Accessing the device's UDID ==
UDID access is blocked by default on iOS7 and iOS will substitute a generated ID in UIDevice's uniqueIdentifier property. Use <code>MGCopyAnswer(CFSTR("UniqueDeviceID"))</code> and link against libMobileGestalt.dylib (<code>ProjectName_LIBRARIES = MobileGestalt</code>) to get access to the device ID from system processes or apps installed to /Applications. Device ID is completely inaccessible from app store processes and some daemons.


For App Store apps, it appears you can still retrieve the UDID from MobileGestalt with a private entitlement:


19:02:52 < yoshbu> like, error: unknown type name '__darwin_intptr_t'
<source lang="xml">
<key>com.apple.private.MobileGestalt.AllowedProtectedKeys</key>
<array>
<string>UniqueDeviceID</string>
</array>
</source>


19:02:59 < yoshbu> and, error: unknown type name '__uint32_t'; did you mean 'uint32_t'?
== Ongoing issues ==


19:05:27 < Alcatraz> are you trying to compile ldid on mac?
=== Miscellaneous ===


19:05:55 < yoshbu> following step 4 of http://iphonedevwiki.net/index.php/Theos/Getting_Started
* Printing a stack trace doesn't show symbols.
* Wee apps' (Notification Center widgets) principal class must now be a view controller subclass instead of implementing a protocol.


19:06:10 < Alcatraz> yeah compiling it has been broken for some time
=== Missing icons ===
* After copying an app to /Applications and respringing, sometimes the icon doesn't appear. Also if it was there before, sometimes it can disappear.


19:06:27 < Alcatraz> has to do with xcode 5
* Apps installed to /Applications stop launching after a while with this error:
backboardd[12261] <Warning>: Launch Services: Registering unknown app identifier libactivator failed
backboardd[12261] <Warning>: Launch Services: Unable to find app identifier libactivator
backboardd[12261] <Warning>: Can't create application "libactivator" without a bundle path


19:06:32 < Alcatraz> pretty sure anyway
Or their icons disappear after this happens:
lsd[11724] <Warning>: LaunchServices: Updating identifier store
/usr/libexec/lsd[11724] <Error>: Need to synchronize with MobileInstallation
/usr/libexec/lsd[11724] <Notice>: LaunchServices: Adding com.malcolmhall.PhoneNumberTest to unregister list
/usr/libexec/lsd[11724] <Notice>: LaunchServices: Adding com.malcolmhall.AppWhere to unregister list
/usr/libexec/lsd[11724] <Notice>: LaunchServices: Adding libactivator to unregister list
lsd[11724] <Warning>: LaunchServies: No placeholder bundle to remove for com.malcolmhall.AppWhere.


19:06:50 < yoshbu> ldid is a dependency of theos though right?
=== ARM64-specific ===


19:07:01 < Alcatraz> yeah. you can ask someone on here for a copy
* Hooking a method that uses a struct gives wrong layout of fields on arm64. You may need to #pragma pack(push,4) before and then #pragma pack(pop) after the struct however you really need to use the debugger and view the memory to understand for sure what's happening.
* Using MSHookMessage arm64 requires the original function pointer to declare the parameters or it seg faults at runtime.


19:07:23 -!- mindw0rk [~mindw0rk@78.57.233.231] has joined #theos
=== Inter-process communication ===
* CPDistributedMessagingCenter, XPC and other IPC methods built on top of bootstrap registered mach services don't work; you get deny lookup in the Xcode console.
'''Workaround:'''


19:08:05 < ac3xx> yoshbu, wget http://ac3xx.com/ldid -O $THEOS/bin/ldid && chmod +x $THEOS/bin/ldid
rpetrich has built a workaround called [[RocketBootstrap]].


== Supporting iOS 4-7 with one binary & Example project link ==
Install this from Cydia or add a depends to your deb of com.rpetrich.rocketbootstrap.
23:59:59 <%joedj> sbingner: i used 5.1 SDK (xcode 4.4.1) for the armv6 slice, targetting 4.0: https://github.com/joedj/ExchangePolicyCleaner/blob/master/Makefile#L3
Download bootstrap.h and rocketbootstrap.h from https://github.com/rpetrich/RocketBootstrap/tree/master
You will also need to copy `librocketbootstrap.dylib` from `/usr/lib` on your iDevice to `$THEOS/lib` and link against it in your Makefile:
<source lang="bash">
myTweak_LIBRARIES = rocketbootstrap
</source>


(also rpetrich's canonical example: https://github.com/a3tweaks/Flipswitch/blob/master/Makefile#L16 )
Example usage (server inside a SpringBoard tweak):


Day changed to 24 Dec 2013
<source lang="objc">
#import "rocketbootstrap.h"
   
CPDistributedMessagingCenter *c = [CPDistributedMessagingCenter centerNamed:@"com.mycompany.myCenter"];
// apply rocketbootstrap regardless of iOS version (via rpetrich)
rocketbootstrap_distributedmessagingcenter_apply(c);
[c runServerOnCurrentThread];
[c registerForMessageName:@"myMessageName" target:myTarget selector:@selector(handleMessageNamed:withUserInfo:)];
</source>


00:01:43 <+crash-x> joedj: you can make a fat binary with the armv6 slice targetting 4.0 and the arm64 part targetting ios 7 and achieve support for iOS 4-7?
Example usage (client from sandboxed app):
 
<source lang="objc">
00:03:53 <+crash-x> joedj: is that project on github been updated for iOS 7 and rpetrich's theos fork?
#import "rocketbootstrap.h"
   
CPDistributedMessagingCenter *c = [%c(CPDistributedMessagingCenter) centerNamed:@"com.mycompany.myCenter"];
rocketbootstrap_distributedmessagingcenter_apply(c);
[c sendMessageName:@"myMessageName" userInfo:nil]; //send an NSDictionary here to pass data
</source>


00:04:09 <%joedj> crash-x: indeed, i believe so, although i think i've only tested down to ios6
If you want to run a server inside a daemon, then you still need a simple SpringBoard tweak, that just has to call bootstrap_unlock with the service name (take the code from the rocket bootstrap header and include bootstrap.h). Then you can run a server with the same name inside your daemon. rocketbootstrap_distributedmessagingcenter_apply must still be called on both the server and on the clients. It even works for sendMessageAndReceiveReplyName.


00:04:10 <%joedj> crash-x: yes
'''Usage notes:'''


00:04:22 <+crash-x> thats amazing, thank you!
You shouldn't be registering Mach services in sandboxed apps; RocketBootstrap allows exposing services ''to'' sandboxed apps, but can't allow exposing services ''from'' sandboxed apps without exposing a very large security flaw.


00:04:25 -!- charliebashford [~charliebash@86.173.69.10] has quit [Client exited]
Assuming there aren't any security problems, actually calling a service that's running inside of an app from SpringBoard (which is usually what people want to do) is problematic. Backgrounding apps causes them to enter a frozen "SIGSTOP" state, which means any calls to the service running inside of the app will block indefinitely.


00:04:53 <+crash-x> if i wanted to get this working, what would i have to do? install rpetrich's theos fork and then I could just make package it or is there anything else I would have to install or do>
Even if that is suppressed, it could happen that the SpringBoard part attempts to call the service running in the app at the same time as the app is trying to call any of the usual SpringBoard services. When that happens, they deadlock. This might happen infrequently, but it's a really bad failure case in that the system just hangs. Real users will encounter it, if it's present.


00:07:36 <%joedj> crash-x: there are a few other things like setting THEOS_PLATFORM_SDK_ROOT_armv6  (see the Makefile i just linked), and possibly switching to using %config(generator=internal) in your logos files unless you have an arm64 substrate you can link against (i think theos might be able to bootstrap this for you, but haven't tried)
You can call from a background thread (not good, it could stay alive for a long time), or use timeouts (not good, now you have to tune it and you get UI hitches) or use asynchronous code (not bad, but it's more work than you may be willing to go through).


00:08:04 <%joedj> crash-x: %config(generator=internal) might also be the default with rpetrich's fork, but i prefer to be explicit
'''Related projects:'''


== Accessing the device's UDID ==
* [[libobjcipc]] by a1anyip: "An inter-process communication (between app and SpringBoard) solution for jailbroken iOS. Specifically written for iOS 7 (not tested on previous versions). It handles the socket connections between SpringBoard and app processes, the automatic set up of process assertions and the auto disconnection after timeout or the process terminates. You only need to call the static methods in the main class OBJCIPC. Messages and replies can be sent synchronously (blocking) or asynchronously."
UDID access is blocked by default on iOS7 and iOS will substitute a generated ID in UIDevice's uniqueIdentifier property. Use MGCopyAnswer(CFSTR("UniqueDeviceID")) and link to libMobileGestalt.dylib to get access to the device ID from system processes or apps installed to \Applications. Device ID is completely inaccessible from app store processes and some daemons.


== Ongoing issues ==
[[Category:Updating extensions]]
CPDistributedMessagingCenter doesn't work.
<br />
Printing a stack trace doesn't show symbols.

Latest revision as of 01:13, 10 August 2016

This is an informal collection of advice; feel free to add to it and rearrange. A lot of this is from #theos on irc.saurik.com - if you're working on updating your tweaks and you use Theos, join in and share what you've learned (see IRC).

How to compile for ARM64

Tweak binaries must contain an ARM64 slice in order for it to be loaded into 64-bit processes. If you don't need to support iOS 4.2.1 or older, ensure Xcode 5 is installed and set ARCHS in your Makefile:

ARCHS = armv7 arm64

You will also need updated versions of any libraries that you link against which contain an arm64 slice. To get the updated Substrate dylib, see saurik's instructions below, starting from the wget of the Substrate deb.

How to compile for ARMv6 and ARM64

Compiling for ARMv6 and ARM64 is useful in only a subset of normal situations. If you've made it this far and you do not have a particular reason to retain ARMv6 support, please see the above section.
This technique does not appear to work anymore with Xcode 6 - I suspect the compiler is at fault. The Alternative Method described below using rpetrich's theos fork and separate SDKs still works. -joedj

These instructions only use first-party components from Apple, DHowett, and saurik (and were written by saurik).

The idea is that we are going to use parts of Xcode 4 (which you don't have to install: you might just have it sitting in /Volumes) to "fix" parts of Xcode 5 so that it can target armv6 (need Xcode 4.4.1).

cd $Xcode5/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/5.0/lib/darwin/
mv libclang_rt.ios.a libclang_rt.ios-7.0.a
lipo -thin armv6 -output libclang_rt.ios-5.1.a $Xcode4/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/4.0/lib/darwin/libclang_rt.ios.a
lipo -create -output libclang_rt.ios.a libclang_rt.ios-5.1.a libclang_rt.ios-7.0.a
cd $Xcode5/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/usr/lib/
mv dylib1.o dylib1-7.0.o
lipo -thin armv6 -output dylib1-5.1.o $Xcode4/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/usr/lib/dylib1.o
lipo -create -output dylib1.o dylib1-5.1.o dylib1-7.0.o

Then, we download Theos directly from DHowett's code repository, and add in the parts it needs from the various packages provided by saurik.

sudo mkdir -p /opt/theos
sudo chown "$(id -u):$(id -g)" /opt/theos
cd /opt/theos
git clone https://github.com/DHowett/theos.git .
wget http://apt.saurik.com/debs/ldid_1:1.1.2_iphoneos-arm.deb
ar p ldid_1:1.1.2_iphoneos-arm.deb data.tar.gz | tar -zxvf- --strip-components 2 ./usr/bin/ldid
wget http://apt.saurik.com/debs/mobilesubstrate_0.9.5001_iphoneos-arm.deb
ar p mobilesubstrate_0.9.5001_iphoneos-arm.deb data.tar.lzma >substrate.tar.lzma
# ... extract the lama file; OS X doesn't come with an lzma utility :( ...
tar -xvf substrate.tar --strip-components 3 ./Library/Frameworks/CydiaSubstrate.framework/
ln -s ../CydiaSubstrate.framework/Headers/CydiaSubstrate.h include/substrate.h
ln -s ../CydiaSubstrate.framework/CydiaSubstrate lib/libsubstrate.dylib

Finally, in our Theos Makefile, we specify that we want to target iOS 2.0 using the 7.0 SDK, and that we want both ARMv6 and ARM64 slices.

TARGET := iphone:7.0:2.0
ARCHS := armv6 arm64

Alternative method

This is slightly more complicated. You need to compile an armv6 slice using the 5.1 SDK and another arm64 slice using the 7.0 SDK. You then stitch both together with lipo. This blog post describes how to do that manually, but rpetrich has created a theos fork, which does that automatically for you.

Setup rpetrich’s theos:

export THEOS=/opt/theos-rpetrich
sudo mkdir -p $THEOS
sudo chown "$(id -u):$(id -g)" $THEOS
cd $THEOS
git clone https://github.com/rpetrich/theos .
wget http://joedj.net/ldid -O bin/ldid
chmod +x bin/ldid
wget https://cdn.hbang.ws/dl/libsubstrate_arm64.dylib -O lib/libsubstrate.dylib

(note from rpetrich: theos should be as a submodule for my fork, not installed in a system path. system paths are dangerous)

Install headers:

cd $THEOS
./git-submodule-recur.sh init
git submodule update --recursive

Setup the Makefile

TARGET := iphone:clang
THEOS_PLATFORM_SDK_ROOT_armv6 = /Applications/Xcode_4.4.1.app/Contents/Developer
SDKVERSION_armv6 = 5.1
TARGET_IPHONEOS_DEPLOYMENT_VERSION = 3.0
TARGET_IPHONEOS_DEPLOYMENT_VERSION_arm64 = 7.0
ARCHS = armv6 arm64

TWEAK_NAME = iLogIt
iLogIt_FILES = Tweak.xm

include theos/makefiles/common.mk
include $(THEOS_MAKE_PATH)/tweak.mk

rpetrich's theos is using objc's hooking method instead of MobileSubstrate therefore it doesn't link with MS by default. This is OK if you are only hooking objc messages, but if you need to use MSHookFunction, you have to tell theos to link to lib substrate:

iLogIt_LIBRARIES = substrate

(note from saurik: I highly disrecommend not using Substrate's MSHookMessage implementation; I never understood why rpetrich doesn't use it, but on multiple occasions the way we hook messages has had to change, and centralizing it in Substrate means that I can fix it once for everyone's compiled extensions... this happened last as recently as iOS 5, and all of rpetrich's extensions had to be recompiled and redeployed, which is reasonably fine for him as he's insanely productive and around constantly, but for most people you should please just use the centralized implementation.)

To use Substrate for hooking, either add this add the top of your Logos source file (e.g., Tweak.xm)

%config(generator=MobileSubstrate);

Or add it to your target's Logos flags:

iLogIt_LOGOSFLAGS = -c generator=MobileSubstrate

Example Projects: Take a look at the Makefiles of these projects:

ARM64 on Linux

Using Darling, Apple's official toolchain is able to be used on Linux. Once Darling is installed, eswick's theos fork can be used to build for ARM64.

XcodeDefault.xctoolchain (obtain from a Mac, or download Xcode from Apple's website) needs to be placed in $THEOS/toolchain, and $THEOS/sdk needs to point to the iOS 7 SDK, like so:

git clone https://github.com/eswick/theos-darling.git /opt/theos
mv ~/XcodeDefault.xctoolchain /opt/theos/toolchain/
ln -s /var/sdks/iPhoneOS7.0.sdk /opt/theos/sdk

See the full blog post here for step-by-step instructions.

Updating code for ARM64

Read Apple's documentation on ARM64: "Converting Your App to a 64-Bit Binary"

If you need to specifically test for 64-bit:

#ifdef __LP64__
NSLog(@"64-bit");
#else
NSLog(@"32-bit");
#endif

Detecting iOS 7

Detecting whether code is being compiled for iOS 7.0 or higher:

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_0
[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleLightContent animated: YES];
#endif

Note that this is a compile time check. To check for iOS 7 at runtime, compare against the CoreFoundation version:

if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_0) {
	// do >= iOS 7 stuff
} else {
	// do <= iOS 6 stuff
}

Apple often forgets to add new version number constants to their headers, so you may need to define the version numbers yourself:

#ifndef kCFCoreFoundationVersionNumber_iOS_7_0
#define kCFCoreFoundationVersionNumber_iOS_7_0 847.20
#endif

See CoreFoundation.framework for a full list.

Updating Cydia Depictions

It's best to make the background transparent to make it match Cydia's background. Just add the following to your depiction's header:

<script>
if (navigator.userAgent.search(/Cydia/) != -1) {
	document.body.classList.add("cydia");
}
</script>

And in your CSS:

body.cydia {
	background: none !important;
}

Cydia's table cell styling hasn't currently been changed to reflect the iOS 7 UI, so no other CSS needs updating.

Theos bootstrap.sh patch for ARM64

01:03:36 < therpgitbot> [theos] rpetrich pushed 1 new commit to master: http://git.io/ankV8g
01:03:36 < therpgitbot> theos/master f6ebd79 Ryan Petrich: Workaround bootstrap problems on Xcode 5.x (temporary fix for now)

Dealing with 32-bit and 64-bit

12:38:15 <%joedj> sbingner: i did find this question (and the response 2 posts down) interesting, i'm not sure what they're talking about: https://www.mikeash.com/pyblog/friday-qa-2013-09-27-arm64-and-you.html#comment-7436311d02c5a55738d1baefa03b0d34
09:55:43 <@rpetrich> joedj: it's a bug with the components that communicate with the App Store

Theos and ldid errors

19:02:14 < yoshbu> I've been off the jailbreak train for awhile now. Trying to reinstall theos, getting some build failures when trying to install ldid, anybody know if there's a quick fix?
19:02:52 < yoshbu> like, error: unknown type name '__darwin_intptr_t'
19:02:59 < yoshbu> and, error: unknown type name '__uint32_t'; did you mean 'uint32_t'?
19:05:27 < Alcatraz> are you trying to compile ldid on mac?
19:05:55 < yoshbu> following step 4 of http://iphonedevwiki.net/index.php/Theos/Getting_Started
19:06:10 < Alcatraz> yeah compiling it has been broken for some time
19:06:27 < Alcatraz> has to do with xcode 5
19:06:32 < Alcatraz> pretty sure anyway
19:06:50 < yoshbu> ldid is a dependency of theos though right?
19:07:01 < Alcatraz> yeah. you can ask someone on here for a copy
19:08:05 < ac3xx> yoshbu, wget http://ac3xx.com/ldid -O $THEOS/bin/ldid && chmod +x $THEOS/bin/ldid

Accessing the device's UDID

UDID access is blocked by default on iOS7 and iOS will substitute a generated ID in UIDevice's uniqueIdentifier property. Use MGCopyAnswer(CFSTR("UniqueDeviceID")) and link against libMobileGestalt.dylib (ProjectName_LIBRARIES = MobileGestalt) to get access to the device ID from system processes or apps installed to /Applications. Device ID is completely inaccessible from app store processes and some daemons.

For App Store apps, it appears you can still retrieve the UDID from MobileGestalt with a private entitlement:

<key>com.apple.private.MobileGestalt.AllowedProtectedKeys</key>
<array>
	<string>UniqueDeviceID</string>
</array>

Ongoing issues

Miscellaneous

  • Printing a stack trace doesn't show symbols.
  • Wee apps' (Notification Center widgets) principal class must now be a view controller subclass instead of implementing a protocol.

Missing icons

  • After copying an app to /Applications and respringing, sometimes the icon doesn't appear. Also if it was there before, sometimes it can disappear.
  • Apps installed to /Applications stop launching after a while with this error:
backboardd[12261] <Warning>: Launch Services: Registering unknown app identifier libactivator failed
backboardd[12261] <Warning>: Launch Services: Unable to find app identifier libactivator
backboardd[12261] <Warning>: Can't create application "libactivator" without a bundle path

Or their icons disappear after this happens:

lsd[11724] <Warning>: LaunchServices: Updating identifier store
/usr/libexec/lsd[11724] <Error>: Need to synchronize with MobileInstallation
/usr/libexec/lsd[11724] <Notice>: LaunchServices: Adding com.malcolmhall.PhoneNumberTest to unregister list
/usr/libexec/lsd[11724] <Notice>: LaunchServices: Adding com.malcolmhall.AppWhere to unregister list
/usr/libexec/lsd[11724] <Notice>: LaunchServices: Adding libactivator to unregister list
lsd[11724] <Warning>: LaunchServies: No placeholder bundle to remove for com.malcolmhall.AppWhere.

ARM64-specific

  • Hooking a method that uses a struct gives wrong layout of fields on arm64. You may need to #pragma pack(push,4) before and then #pragma pack(pop) after the struct however you really need to use the debugger and view the memory to understand for sure what's happening.
  • Using MSHookMessage arm64 requires the original function pointer to declare the parameters or it seg faults at runtime.

Inter-process communication

  • CPDistributedMessagingCenter, XPC and other IPC methods built on top of bootstrap registered mach services don't work; you get deny lookup in the Xcode console.

Workaround:

rpetrich has built a workaround called RocketBootstrap.

Install this from Cydia or add a depends to your deb of com.rpetrich.rocketbootstrap. Download bootstrap.h and rocketbootstrap.h from https://github.com/rpetrich/RocketBootstrap/tree/master You will also need to copy `librocketbootstrap.dylib` from `/usr/lib` on your iDevice to `$THEOS/lib` and link against it in your Makefile:

myTweak_LIBRARIES = rocketbootstrap

Example usage (server inside a SpringBoard tweak):

#import "rocketbootstrap.h"
    
CPDistributedMessagingCenter *c = [CPDistributedMessagingCenter centerNamed:@"com.mycompany.myCenter"];
// apply rocketbootstrap regardless of iOS version (via rpetrich)
rocketbootstrap_distributedmessagingcenter_apply(c);
[c runServerOnCurrentThread];
[c registerForMessageName:@"myMessageName" target:myTarget selector:@selector(handleMessageNamed:withUserInfo:)];

Example usage (client from sandboxed app):

#import "rocketbootstrap.h"
    
CPDistributedMessagingCenter *c = [%c(CPDistributedMessagingCenter) centerNamed:@"com.mycompany.myCenter"];
rocketbootstrap_distributedmessagingcenter_apply(c);
[c sendMessageName:@"myMessageName" userInfo:nil]; //send an NSDictionary here to pass data

If you want to run a server inside a daemon, then you still need a simple SpringBoard tweak, that just has to call bootstrap_unlock with the service name (take the code from the rocket bootstrap header and include bootstrap.h). Then you can run a server with the same name inside your daemon. rocketbootstrap_distributedmessagingcenter_apply must still be called on both the server and on the clients. It even works for sendMessageAndReceiveReplyName.

Usage notes:

You shouldn't be registering Mach services in sandboxed apps; RocketBootstrap allows exposing services to sandboxed apps, but can't allow exposing services from sandboxed apps without exposing a very large security flaw.

Assuming there aren't any security problems, actually calling a service that's running inside of an app from SpringBoard (which is usually what people want to do) is problematic. Backgrounding apps causes them to enter a frozen "SIGSTOP" state, which means any calls to the service running inside of the app will block indefinitely.

Even if that is suppressed, it could happen that the SpringBoard part attempts to call the service running in the app at the same time as the app is trying to call any of the usual SpringBoard services. When that happens, they deadlock. This might happen infrequently, but it's a really bad failure case in that the system just hangs. Real users will encounter it, if it's present.

You can call from a background thread (not good, it could stay alive for a long time), or use timeouts (not good, now you have to tune it and you get UI hitches) or use asynchronous code (not bad, but it's more work than you may be willing to go through).

Related projects:

  • libobjcipc by a1anyip: "An inter-process communication (between app and SpringBoard) solution for jailbroken iOS. Specifically written for iOS 7 (not tested on previous versions). It handles the socket connections between SpringBoard and app processes, the automatic set up of process assertions and the auto disconnection after timeout or the process terminates. You only need to call the static methods in the main class OBJCIPC. Messages and replies can be sent synchronously (blocking) or asynchronously."