(Fixed typo that exposed formatting.) |
m (→Workaround) |
||
Line 219: | Line 219: | ||
rpetrich has built a workaround called RocketBootstrap. Install this from Cydia or add a depends to your deb of com.rpetrich.rocketbootstrap. | 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 | Download bootstrap.h and rocketbootstrap.h from https://github.com/rpetrich/RocketBootstrap/tree/master | ||
Edit rocketbootstrap.h and after the includes write #define ROCKETBOOTSTRAP_LOAD_DYNAMIC 1 | Edit rocketbootstrap.h and after the includes write `#define ROCKETBOOTSTRAP_LOAD_DYNAMIC 1` | ||
You may also need to change the following lines in rocketbootstrap.h: | |||
... | |||
//impl = dlsym(handle, "rocketbootstrap_look_up"); | |||
impl = (kern_return_t (*)(mach_port_t, const char *, mach_port_t *))dlsym(handle, "rocketbootstrap_look_up"); | |||
... | |||
//impl = dlsym(handle, "rocketbootstrap_unlock"); | |||
impl = (kern_return_t (*)(const char *))dlsym(handle, "rocketbootstrap_unlock"); | |||
... | |||
//impl = dlsym(handle, "rocketbootstrap_register"); | |||
impl = (kern_return_t (*)(mach_port_t, char *, mach_port_t))dlsym(handle, "rocketbootstrap_register"); | |||
... | |||
//impl = dlsym(handle, "rocketbootstrap_distributedmessagingcenter_apply"); | |||
impl = (void (*)(CPDistributedMessagingCenter *))dlsym(handle, "rocketbootstrap_distributedmessagingcenter_apply"); | |||
You may also need to copy `librocketbootstrap.dylib` from `/usr/lib` on your iDevice to `$THEOS/lib` and link against it in your Makefile: | |||
myTweak_LDFLAGS = -lrocketbootstrap | |||
Example Usage (server): | |||
#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" | #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 | |||
* Printing a stack trace doesn't show symbols. | * 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. | * Wee apps' (Notification Center widgets) principal class must now be a view controller subclass instead of implementing a protocol. |
Revision as of 05:03, 3 January 2014
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.
Apple hasn't yet released the source code of the Xcode 5 toolchain, so it is not yet possible to support ARM64 if you don't use OS X and Xcode's toolchain.
How to compile for ARMv6 and ARM64
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.5000_iphoneos-arm.deb
ar p mobilesubstrate_0.9.5000_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
mv ldid bin/ldid
chmod +x bin/ldid
wget http://cdn.hbang.ws/dl/libsubstrate_arm64.dylib
mv libsubstrate_arm64.dylib 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
IPHONE_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.)
Example Projects: Take a look at the Makefiles of these projects:
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
- CPDistributedMessagingCenter doesn'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 Edit rocketbootstrap.h and after the includes write `#define ROCKETBOOTSTRAP_LOAD_DYNAMIC 1`
You may also need to change the following lines in rocketbootstrap.h:
... //impl = dlsym(handle, "rocketbootstrap_look_up"); impl = (kern_return_t (*)(mach_port_t, const char *, mach_port_t *))dlsym(handle, "rocketbootstrap_look_up"); ... //impl = dlsym(handle, "rocketbootstrap_unlock"); impl = (kern_return_t (*)(const char *))dlsym(handle, "rocketbootstrap_unlock"); ... //impl = dlsym(handle, "rocketbootstrap_register"); impl = (kern_return_t (*)(mach_port_t, char *, mach_port_t))dlsym(handle, "rocketbootstrap_register"); ... //impl = dlsym(handle, "rocketbootstrap_distributedmessagingcenter_apply"); impl = (void (*)(CPDistributedMessagingCenter *))dlsym(handle, "rocketbootstrap_distributedmessagingcenter_apply");
You may also need to copy `librocketbootstrap.dylib` from `/usr/lib` on your iDevice to `$THEOS/lib` and link against it in your Makefile:
myTweak_LDFLAGS = -lrocketbootstrap
Example Usage (server):
#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
- 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.