tag:blogger.com,1999:blog-35400734477802955512024-03-19T11:35:56.971+08:00networkpx Project BlogA blog about internals of iPhoneOS, and the networkpx project collection.KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.comBlogger88125tag:blogger.com,1999:blog-3540073447780295551.post-59167255682594033732010-01-18T03:51:00.004+08:002010-01-18T04:10:40.310+08:00CrashReporter 0.2f available for testing; iKeyEx 0.3 sneak peak<a href="http://code.google.com/p/networkpx/downloads/detail?name=hk.kennytm.CrashReporter-0.2f.deb ">CrashReporter 0.2f</a> has been available for testing. This version should fully eliminate the crash caused by fat binaries. Also, it has a hidden preference enabling "Email crash report to developer" within CR. But to avoid swarm of emails by stupid users blaming the tertiary suspects without any grounds you're required to read the source code of CR to know how to enable it ;).<br /><br />Also, I have put up <a href="http://code.google.com/p/networkpx/downloads/detail?name=hk.kennytm.iKeyEx3-0.3%7Ebeta1.deb">iKeyEx 0.3~beta1</a> for anyone who needs the new feature to test. 0.3 is an intermediate version between 0.2 and 0.5 to address some keyboard developers' requests, in particular:<br /><ul><li>When the key is a combining character, NFC is automatically applied.</li><br /><li>variantType = "immediate-accents" (e.g. Thai and Arabic) is available via "text with traits".</li><br /><li>more-after and shift-after (e.g. Zhuyin keyboard and the apostrophe) can be explicitly turned on and off via the "after" traits.</li></ul><br /><br />(0.5 shall support the "image" traits again, and thus keyboard theming; and the "star" operator in .cin IME.)<br /><br />And, I'd like to point out that, if you want to change the text of Return and Space in your keyboard, you can already do so by <a href="http://code.google.com/p/networkpx/wiki/Creating_Keyboard_Bundles#strings.plist">strings.plist</a>. This is supported from the start, not a new feature.KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com2tag:blogger.com,1999:blog-3540073447780295551.post-34990255363531943472010-01-06T05:51:00.002+08:002010-01-06T06:10:16.249+08:00Two IDA Pro 5.x Scripts for iPhoneOS binariesIf you use IDA Pro to disasseble iPhoneOS binaries (Mach-O/ARM), you may find these scripts useful:<br /><ul><li><a href="http://networkpx.googlecode.com/svn/etc/idc/dyldinfo.idc">dyldinfo</a>: This script lets IDA Pro understands the DYLD_INFO[_ONLY] command introduced in firmware 3.1. Running this recovers some missing symbols.</li><br /><li><a href="http://networkpx.googlecode.com/svn/etc/idc/fixobjc2.idc">fixobjc2</a>: For binaries built with Objective-C ABI 2, this script can find and label all Objective-C functions and ivar offsets.</li></ul><br /><br />The result will look like this:<br /><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioa_a3XrU0NpGh1Gw_7YdECyeFbotfzfkt9-iXKgHTIPuEvjOANxiaHD7Re4LZmslvDP_80jxPoKr-IGO6EZuSUE1-VhsWt77Y9G2OTrx9w9yxIJ92Z0_8B0P4VRy6JSE6InVt3rTHxx8/" /><br /><br />Because IDA doesn't allow "-" and spaces in names, the Objective-C function names are renamed like this:<br /><ul><li>-[Foo bar:baz:] → Foo.bar:baz:</li><li>+[Foo bar:baz:] → @Foo.bar:baz:</li><li>-[Foo(Cat) bar:baz:] → Foo(Cat).bar:baz:</li></ul><br /><br /> (Note: Try not to run fixobjc2 before dyldinfo, some information cannot be found.)KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com9tag:blogger.com,1999:blog-3540073447780295551.post-90161169966040869022009-12-29T01:52:00.005+08:002009-12-29T21:03:18.583+08:00iKeyEx 0.2b, CrashReporter 0.2e, class-dump-z 0.2a releasedChange log for <a href="http://code.google.com/p/networkpx/downloads/detail?name=hk.kennytm.iKeyEx3-0.2b.deb ">iKeyEx 0.2b</a>:<br /><ul><br /><li>iKeyEx now uses <a href="http://www.seanius.net/blog/2009/09/dpkg-triggers-howto/">postinst triggers</a> to register layouts and input managers (<a href="http://code.google.com/p/networkpx/source/detail?r=594">r594</a>). Keyboard makers may leave out the [pre|post][inst|rm] scripts now because the list will be updated as your keyboard is installed or removed. (You still need a postinst script if you want to support automatic purging.) As a side effect, all input modes explicitly deleted by the user (via Mix and Match) will be added back in and activated. If you really don't want that layout, uninstall it from Cydia.</li><br /><li>Fixed issue 470: iKeyEx left/right arrows don't work in multi-line text input controls (<a href="http://code.google.com/p/networkpx/source/detail?r=593">r593</a>).</li><br /><li>No longer crashes for a layout with different landscape and portrait layout classes (<a href="http://code.google.com/p/networkpx/source/detail?r=588">r588</a>). Thanks erik_joya for reporting!</li><br /></ul><br /><br />Change log for <a href="http://code.google.com/p/networkpx/downloads/detail?name=hk.kennytm.CrashReporter-0.2e.deb ">CrashReporter 0.2e</a>:<br /><ul><br /><li>Fixed issue 481: CrashReport doesn't recognize FAT binaries. (<a href="http://code.google.com/p/networkpx/source/detail?r=592">r592</a>)</li><br /></ul><br /><br />Change log for <a href="http://code.google.com/p/networkpx/downloads/detail?name=class-dump-z_0.2a.tar.gz ">class-dump-z 0.2a</a> <del>(except Windows, I need to reinstall VS2008 first)</del>:<br /><ul><br /><li>Support for "hints file" (<a href="http://code.google.com/p/networkpx/source/detail?r=589">r589</a>). See <a href="http://code.google.com/p/networkpx/wiki/class_dump_z#Hints_file">this wiki page</a> for detail. Thanks rpetrich for suggestion!</li><br /></ul>KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com0tag:blogger.com,1999:blog-3540073447780295551.post-60684867523878132022009-12-15T01:44:00.002+08:002009-12-15T02:02:38.836+08:00iKeyEx and 5-Row QWERTY 0.2a will be on Cydia soon.The minor updates for iKeyEx (r579) and 5-Row QWERTY (r580) are released and will be on the Big Boss repo within 2 days. They can be downloaded from <a href="http://code.google.com/p/networkpx/downloads/list">here</a> as usual.<br /><br />These updates are to address some defects reported after 0.2 is put on the repo, for iKeyEx:<br /><ul><li>Keyboards for Hebrew, Arabic and other right-to-left languages will default to use right-to-left input direction. (<a href="http://code.google.com/p/networkpx/source/detail?r=578">r578</a>. Thanks DB42/OpenHebrew for reporting!)</li><br /><li>Eliminated the built-in keyboard selection list in Settings, which became useless when iKeyEx is installed (it cannot be respected because the keyboard list is not safemode-safe otherwise). (<a href="http://code.google.com/p/networkpx/source/detail?r=579">r579</a>)</li></ul> <br /><br />For 5-Row QWERTY:<br /><ul><li>The , and . keys are swapped back to their expected position. (Thanks Optimo for noticing!)</li><br /><li>Reset the special characters won't duplicate the double quote (") anymore. (<a href="http://code.google.com/p/networkpx/source/detail?r=580">r580</a>)</li><br /><li>Changing the layout flushes the cache correctly now. (<a href="http://code.google.com/p/networkpx/issues/detail?id=471">issue 471</a>)</li></ul>KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com0tag:blogger.com,1999:blog-3540073447780295551.post-60326782450038235212009-12-04T18:07:00.003+08:002009-12-04T18:39:52.366+08:00iKeyEx 0.2~rc1, Cangjie 0.2-3, CrashReporter 0.2d releasedO hai, long time no post! <br /><br />This is because I have posted many material which were to be put here to the <a href="http://www.iphonedevwiki.net/index.php?title=Main_Page">"iPhone Development Wiki"</a> created by <a href="http://www.howett.net/">Dustin Howett</a>. (And also because of "schoolworks and tests" :p) This blog will remain for release notes only.<br /><br />Back to the main topic, there are 3 major releases today: <strong><a href="http://code.google.com/p/networkpx/downloads/detail?name=hk.kennytm.iKeyEx3-0.2%7Erc1.deb">iKeyEx 0.2~rc1</a></strong>:<br /><ul><li>Different layouts in portrait and landscape orientation is supported again (r509, thanks DB42 for noticing)</li><li>CrashReporter support (r548)</li><li>Hooks only UIKit (r548).</li><li>Config file is now placed in ~/Library/Preferences/hk.kennytm.iKeyEx3.plist (r559).</li><li>Keyboard settings won't be lost due to Safe mode anymore.</li><li>.cin IME: Stop radical composition on failure by default.</li><li>.cin IME: Corrected sorting.</li><li>Other minor stuff.</li></ul><br /><br /><strong><a href="http://code.google.com/p/networkpx/downloads/detail?name=hk.kennytm.Cangjie-0.2-3.deb">Cangjie 0.2-3:</a></strong><br /><ul><li>The shift key will be disabled in the 倉頡QWERTY鍵盤. If you want to enter English letters in this keyboard layout, long press on a key (e.g. 水 -> [水][E]).</li></ul><br /><br /><strong><a href="http://code.google.com/p/networkpx/downloads/detail?name=hk.kennytm.CrashReporter-0.2d.deb">CrashReporter 0.2d:</a></strong><br /><ul><li>Made UIProgressHUD truly model to avoid crash due to accidental file deletion during symbolication.</li><li>Smarter suspect identification.</li><li>Symbolication in command line with the "-s" flag.</li><li>Complains if you did not install syslogd :)</li></ul>KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com0tag:blogger.com,1999:blog-3540073447780295551.post-45706696410553793762009-09-28T00:50:00.002+08:002009-09-28T00:54:45.462+08:00Sorry Ollie Kett but...can I sell this scriptlet for $0.99?<br /><br /><blockquote><code>javascript:var s=document.documentElement.outerHTML.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\n/g,"<br/>");document.open();document.write(s);document.close();</code></blockquote><br /><br /><em>Disclaimer: This is <strong>not</strong> how Source Explore works. I did not even buy, try, pirate, or do anything with this app.</em>KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com4tag:blogger.com,1999:blog-3540073447780295551.post-41477813578022952202009-09-26T02:05:00.005+08:002009-12-10T23:07:47.965+08:00Compiling iPhoneOS (3.1) apps with Xcode 3.2 without Provisioning ProfileNote: I don't know if <a href="http://iphonesdkdev.blogspot.com/2009/06/use-xcode-312-to-build-sdk-30-app-to-30.html">this method</a> still works, and I don't care. (And <strong>do not</strong> use the <tt>dd</tt> method mentioned in the article. It is extremely fragile to patch a binary file.)<br /><br />Note 2: Please also check <a href="http://iphonedevwiki.howett.net/index.php?title=Xcode#Developing_without_Provisioning_Profile">http://iphonedevwiki.howett.net/index.php?title=Xcode#Developing_without_Provisioning_Profile</a>.<br /><br /><h3>I want to compile.</h3><br />This is easiest to solve. To compile you still need a certificate that can code-sign, but think this as a lip-service. <a href="http://developer.apple.com/mac/library/documentation/Security/Conceptual/CodeSigningGuide/Procedures/Procedures.html">Here is the procedure to create a self-signed code-signing certificate using Keychain Access</a>. Make sure you create the certificate in the "login" (default) keychain, not the "System" keychain. After the certificate is created, perform these steps:<br /><ol><li>Open <tt>/Developer/Platforms/iPhoneOS.platform/Info.plist</tt>. (Backup if you want to be safe.)</li><li>Go to line 46. Replace the <tt>XCiPhoneOSCodeSignContext</tt> with <tt>XCCodeSignContext</tt></li><li>Go to line 79. Replace the <tt>XCiPhoneOSCodeSignContext</tt> with <tt>XCCodeSignContext</tt></li><li>Save the file.</li><li>Restart Xcode.</li><li>Compile!</li></ol><br />After doing this, you can't use entitlements with Xcode anymore. But you have <tt>ldid -Sxyz.xml</tt> that does the same job.<br /><br /><a name='more'></a><br /><br />The theory behind this is simple. When Xcode wants to code-sign, it has to consult DevToolsCore.framework on the procedures to code sign. The procedures are coded in the XCCodeSignContext class. The iPhoneOS placed more restrictions on the code-signing requirements, e.g. you must have a provision file. These extra procedures are provided in the class XCiPhoneOSCodeSignContext, as a plug-in at <tt>/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Plug-ins/iPhoneOS Build System Support.xcplugin</tt>. Xcode isn't omniscience, so something must tell it that XCiPhoneOSCodeSignContext should be used, instead of the default XCCodeSignContext. This thing is the <tt>/Developer/Platforms/iPhoneOS.platform/Info.plist</tt>. In the past (iPhoneOS 2.x day), you add the PROVISIONING_PROFILE_[ALLOWED|REQUIRED] keys to give extra instructions to the plug-in, <em>which it can promptly ignore</em>. That's why eventually you need to take the dangerous way of binary-patching the plug-in. But why not just hide XCiPhoneOSCodeSignContext entirely? This is my hack's principle - tell Xcode to meet the new boss, same as the old boss. <br /><br /><h3>I want to install and debug too.</h3><br /><br />(Note: I'm not fond of patching MobileInstallation.framework. In fact, on 3.1 there's no framework you can statically patch with.)<br /><br />Unfortunately, installing is more complex than compiling because there are much more checking in the device side. Therefore the procedures will be so complex that ordinary developers should not follow ;).<br /><ol><li>Make sure you have ldid on Mac. (e.g. <a href="http://code.google.com/p/networkpx/downloads/detail?name=ldid">this</a>). Place it in <tt>/usr/local/bin</tt>.</li><li>Create the file <tt>/usr/local/bin/ldid2</tt>. Make it executable. Fill it with:<blockquote><pre>#!/bin/sh<br /><br />hasGTA=`expr "$*" : '.* -gta .*'`;<br />objpath=${!#}/`expr ${!#} : '.*/\([^/]\{1,\}\)\.app$'`;<br /><br />if [[ $hasGTA == 0 ]]; then<br /> /usr/local/bin/ldid -S $objpath;<br />else<br /> TF=`mktemp -t x`;<br /> echo "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"><plist version=\"1.0\"><dict><key>get-task-allow</key><true/></dict></plist>" > $TF;<br /> /usr/local/bin/ldid -S$TF $objpath;<br /> rm $TF;<br />fi;</pre></blockquote></li><li>Open <tt>/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Plug-ins/iPhoneOS Build System Support.xcplugin/Contents/Resources/iPhoneCodeSign.xcspec</tt></li><li>Replace the line saying <tt>CommandLine = "/usr/bin/codesign"</tt> with <tt>CommandLine = "/usr/local/bin/ldid2"</tt></li><li>Now, copy <tt>/usr/libexec/installd</tt> from your device to your Mac.</li><li>Run this:<blockquote><pre>install_name_tool -change /usr/lib/libmis.dylib /usr/lib/libmiss.dylib installd<br />ldid -S installd</pre></blockquote></li><li>Now, create a file named <tt>libmiss.c</tt>, and enter these into the file:<blockquote><pre>extern int MISValidateSignature() { return 0; }</pre></blockquote></li><li>Compile libmiss.c to libmiss.dylib with gcc targeting iPhone. Make sure t you have all these flags:<blockquote><pre>-dynamiclib<br />-install_name /usr/lib/libmiss.dylib<br />-current_version 1<br />-compatibility_version 1<br />-Wl,-reexport-lmis<br />-flat_namespace</pre></blockquote></li><li>ldid -S libmiss.dylib, of course.</li><li>Copy the new installd to the device's <tt>/usr/libexec</tt>, and the libmiss.dylib to the device's <tt>/usr/lib</tt>.</li><li>Restart Xcode.</li><li>Install!</li></ol><br />If you want to debug, add the <tt>-gta</tt> flag in "Other Code Signing Flags" in your Xcode Project.<br /><br />OK, so WTF is going on? The first 4 steps allows you to debug the app on the device. The essence of this is replace codesign with ldid. Why this is necessary? Because of the change in Part 1, entitlements are no longer respected. But to debug you must have the get-task-allow entitlement. To fix it, we have to entirely replace codesign with our executable that adds the entitlement ourselves. ldid2 is created with this purpose.<br /><br />The rest of the steps allows mobile installation to succeed without validation. When the app is installed from Xcode, "mobile_installation_proxy" is invoked, which spawned "installd". The validation part of installd is this:<br /><blockquote><pre> +00cd4 0000af2c 0010A0E3 loc_000cd4: mov r1,#0x0<br /> +00cd8 0000af30 D19701EB bl MISValidateSignature (stub)<br /> +00cdc 0000af34 005050E2 subs r5,r0,#0x0<br /> +00ce0 0000af38 0600000A beq loc_000d00<br /> +00ce4 0000af3c 54049FE5 ldr r0,[pc,#0x454] ; -> 0xb398 "verify_executable"<br /> +00ce8 0000af40 5C149FE5 ldr r1,[pc,#0x45c] ; -> 0xb3a4 "Could not validate signature: %x"<br /> +00cec 0000af44 0520A0E1 mov r2,r5 ; "_CodeSignature/CodeResources"<br /> +00cf0 0000af48 C9E3FFEB bl proc_00003E74<br /> +00cf4 0000af4c 0400A0E1 mov r0,r4<br /> +00cf8 0000af50 B49701EB bl CFRelease (stub)<br /> +00cfc 0000af54 060000EA b loc_000d1c</pre></blockquote>If we can force MISValidateSignature() to always return 0, any binaries will pass the test. This function is part of libmis.dylib, which is now part of the shared cache, so you can't binary patch this file. Replacing the implementation of a function is a perfect job with MobileSubstrate, unfortunately, no matter how I tried MS can't be injected. Therefore I use a trick: create a "proxy dynamic library" that changes only the MISValidateSignature function, and let the rest pass through. This is the purpose of libmiss.dylib. First, install_name_tool is used to repoint the libmis.dylib in installd to libmiss.dylib. Then, in libmiss.dylib we define a single function, MISValidateSignature, which returns 0 as we wanted. It linked with libmis.dylib, and reexport all the symbols so that the original symbols can still be found. But we have to use flat namespace to make sure our new MISValidateSignature can shadow the old one. Finally, there is a quirk in installd that required the dylib to be at version 1.0.0, so the -compatibility_version and -current_version flags are added.<br /><br /><h3>Ouch these are all so difficult. Any easier methods?</h3><br />Yes. Pay $99 to Apple. :pKennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com43tag:blogger.com,1999:blog-3540073447780295551.post-68173403757218416392009-09-25T12:21:00.005+08:002009-09-25T13:32:22.179+08:00GreenTea devices — You can still use Maps.I have forcefully enabled GreenTea on my device (with MobileSubstrate) but <strong>almost everything behaves normally</strong> (iTunes is still accessible, YouTube is not hidden, Maps shows everywhere, etc.). The only difference I've noticed is:<br /><ul><li>There is no Hybrid mode in Maps when GreenTea is on.</li></ul><br />Oh well.<br /><br /><a name='more'></a><br /><br /><hr /><br />Anyway, the string "GreenTea" can be found in at least these 5 binaries: SpringBoard, MapKit, GMM, GraphicsServices, PhotoLibrary.<br /><br />In SpringBoard, GreenTea can be found in these scenarios:<br /><ul><li>CFSTR("SBShowITunesStoreOnGreenTea") // in -[SpringBoard userDefaultsDidChange:]</li><li>kGSGreenTeaDeviceCapability near @selector(allowYouTube)</li></ul><br />In MapKit, <br /><ul><li>-[UIDevice(MKAdditions) _mapkit_isChinaDevice] which returns GSSystemHasCapability(kGSGreenTeaDeviceCapability)</li><li>Some non-harmful changes in MKSearch***</li><li>In MKMaxZoomLevelForCoordinate(), if _mapkit_isChinaDevice returns true, jumps over the test against MKCoordinateIsInSouthKorea() // wtf is going on?!</li></ul><br />In GMM,<br /><ul><li>Changes the server to http://www.google.cn/glm/...</li></ul><br />In PhotoLibrary,<br /><ul><li>Something related to MMS.</li></ul>KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com0tag:blogger.com,1999:blog-3540073447780295551.post-29827000905989570382009-09-24T04:00:00.003+08:002009-09-24T05:07:31.537+08:00China, no Google Maps for you (maybe)Today I was making the <a href="http://github.com/kennytm/iphone-private-frameworks/tree/master/GraphicsServices/">API for GraphicsServices</a>, and found something... interesting.<br /><br />Since 3.0 it was "well known" that there is a mysterious capability called as "Green Tea". Nothing was known except for this funny name. Things start to get clear in the 3.1 firmware. The GraphicsServices of 3.1 has a <a href="http://github.com/kennytm/iphone-private-frameworks/blob/master/GraphicsServices/GSMaps.h">new set of API</a> for querying some properties of Maps and MapKit. Strangely, in the disassembly of these functions, the mysterious "Green Tea" capability was refered, e.g.<br /><blockquote><pre>Boolean GSMapKitUserShifting() {<br /> static CFStringRef gtDefault = CFSTR("MapKitUserShiftingGreenTea");<br /> static CFStringRef ngtDefault = CFSTR("MapKitUserShiftingNonGreenTea");<br /> if (GSSystemHasCapability(CFSTR("green-tea")))<br /> return GetMapsDefault(gtDefault);<br /> else<br /> return GetMapsDefault(ngtDefault);<br />}</pre></blockquote><br />It means the "Green Tea" capability is related to Maps, and takes different default values. No big deal right?<br /><br /><a name='more'></a><br /><br />Moving downwards shows a more horrific picture, e.g. the GSMapKitAvailable() function is<br /><blockquote><pre>Boolean GSMapKitAvailable() {<br /> if (!GSSystemHasCapability(CFSTR("green-tea")))<br /> return true;<br /> else {<br /> static CFStringRef defaultName = CFSTR("MapKitAvailableGreenTea");<br /> return GetMapsDefault(defaultName);<br /> }<br />}</pre></blockquote><br />Ah, when a device is "Not Green Tea", it directly says MapKit is available, but when the device is "Green Tea" it needs to check a default value? Sounds more like a restriction than a capability!<br /><br />Further down, in GSMapsVisible(),<blockquote><pre>static Boolean _mapsLastVisible;<br />Boolean GSMapsVisible() {<br /> static Boolean _registeredListener = false;<br /> _mapsLastVisible = _GSMapsVisible();<br /> if (!_registeredListener) {<br /> CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, CarrierBundleChangedHandler, CFSTR("NewCarrierNotification"), NULL, 0);<br /> _registeredListener = true;<br /> }<br /> return _mapsLastVisible;<br />}</pre></blockquote><br />_GSMapsVisible() has a same "Green Tea" check as GSMapKitAvailable(). Strangely, it subscribes to the "New Carrier" Darwin notification, which probably means the Carrier can decide if Maps is visible or not (if com.apple.GMM.plist can be edited)!<br /><br />So what does this "Green Tea" capability refers to? If we turn to GMM.framework, we can find the following code:<br /><blockquote><pre> +00244 0000ba5c ldr r0,[pc,r0] ; -> kGSGreenTeaDeviceCapability _mh_dylib_header<br /> +00248 0000ba60 ldr r0,[r0] ; -> _mh_dylib_header<br /> +0024c 0000ba64 bl GSSystemHasCapability (stub)<br /> +00250 0000ba68 ldr r3,[pc,#0x1bc] ; -> 0xbc2c<br /> +00254 0000ba6c add r3,pc,r3 ; GMM::Factory::isChinaDevice_<br /> +00258 0000ba70 subs r0,r0,#0x0<br /> +0025c 0000ba74 movne r0,#0x1<br /> +00260 0000ba78 strb r0,[r3] ; -> GMM::Factory::isChinaDevice_</pre></blockquote><br />So having "Green Tea" is equivalent to China device! Let's recap:<br /><ol><li>Green Tea ⇒ Maps can be disabled.</li><li>Visibility of Maps is affected by Carrier</li><li>Green Tea = China Device</li></ol><br />so a logical conclusion could be <strong>Carriers in China can affect the visibility of iPhone's Maps</strong>. Could it be a political decision? No matter what, China's iPhone already has no WiFi, but turns out it could be more crippled than expected.KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com5tag:blogger.com,1999:blog-3540073447780295551.post-73789261448519787772009-09-20T19:54:00.003+08:002009-09-20T20:09:22.541+08:00class-dump-z 0.2-0 released.(The version jump is mainly because every other project is moving to 0.2 era.)<br /><br />Download: <a href="http://code.google.com/p/networkpx/downloads/detail?name=class-dump-z_0.2-0.tar.gz">http://code.google.com/p/networkpx/downloads/detail?name=class-dump-z_0.2-0.tar.gz</a>.<br /><br /><strong>Note:</strong> Mac OS X 10.6 is required in this version. <br /><br />What's changed:<br /><ul><li>Universal binary is supported. You can choose different architectures with the -u switch. (Not -arch or --arch because I didn't use getopt_long.)</li><li>Completely recognizes the new __LINKEDIT format. XXUnknownSuperclass shall no longer appears for 3.1 binaries.</li><li>__attribute__((visibility("hidden"))) will be included as well when the class is not exported (e.g. UIKeyboardLayoutStar).</li><li>Options to hide categories and protocols.</li><li>Sort class alphabetically, but keep class methods and -init methods on top (suggested by ashikase)</li><li>Option to choose between <tt>+(void)foo;</tt> and <tt>+ (void)foo;</tt>. (suggested by ashikase)</li><li>Fixes a minor bug where timeOut:(int)out was written instead of timeOut:(int)anOut.</li></ul>KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com1tag:blogger.com,1999:blog-3540073447780295551.post-83774063396104537262009-09-20T03:14:00.004+08:002009-09-20T19:54:13.071+08:00About the LC_DYLD_INFO[_ONLY] command.With the introduction of the new __LINKEDIT format in iPhoneOS 3.1, many tools in the open toolchain are broken. This is all due to the unknown new commands LC_DYLD_INFO[_ONLY]. Although it's known to exist by many now, I found no useful documentation about this new format. Therefore, I'll outline what it is. Alternatively, you can study the source code of <a href="http://www.opensource.apple.com/source/ld64/ld64-96.5/src/other/dyldinfo.cpp">dyldinfo</a> which contains every information here.<br /><br /><a name='more'></a><br /><br /><h3>The LC_DYLD_INFO[_ONLY] commands</h3><br />These load commands are numerically 0x22 and 0x80000022. The only difference between them are LC_DYLD_INFO_ONLY will abort loading when dyld doesn't understand the new format.<br /><br />The structure of this load command has been <a href="http://pastie.org/572025">described</a> before. It refers to 5 chunks of data in the __LINKEDIT segment, which are called <strong>rebase</strong>, <strong>bind/weak_bind/lazy_bind</strong>, and <strong>export</strong>.<br /><br /><h3>bind/weak_bind/lazy_bind</h3><br />These 3 chunks are encoded with the same format. Please think of the data in these chunks as a tiny assembly language, which the only purpose is to "bind" (map) VM addresses to a symbol.<br /><br />The encoding of each data is of the form:<br /><table border="1"><tbody><tr><td>Bit 7</td><td>6</td><td>5</td><td>4</td><td>3</td><td>2</td><td>1</td><td>0</td><td></td></tr><tr><td colspan="4">opcode</td><td colspan="4">imm operand</td><td>(extra data)</td></tr></tbody></table><br />So there are at most 16 different opcodes can be used, and the immediate operand can hold a value 0 to 15. But most of the times a value >15, or even non-numeric data is needed. In these cases, extra data will be appended after this byte.<br /><br />A large number is encoded in the <a href="http://en.wikipedia.org/wiki/LEB128">"LEB128" format</a>. In this format, each byte is separated into a "continue bit" (bit 7) and the "digits" (bit 0-6).<br /><br />Suppose we want to encode the number 123456 in LEB128. Firstly, we write 123456 in binary, and separated into groups of 7 digits: <strong>0000111,1000100,1000000</strong>. Then we insert the "continue bit" as 1, except the most significant one, which is 0 to signal the end of the number: <strong><u>0</u>0000111,<u>1</u>1000100,<u>1</u>1000000</strong>. Finally, it should be in little endian, so we flip it around and write out the result: <strong>0xC0 0xC4 0x07</strong>.<br /><br />Apple so far defined 13 opcodes:<br /><table border="1"><tbody><tr><th>opcode</th><th>Symbol</th><th>Meaning</th></tr><tr><td>0</td><td>DONE</td><td>Finished defining a symbol.</td></tr><tr><td>1</td><td>SET_DYLIB_ORDINAL_IMM</td><td>Set the <em>library ordinal</em> of the current symbol to the <em>imm operand</em>.</td></tr><tr><td>2</td><td>SET_DYLIB_ORDINAL_ULEB</td><td>Same as above, but the library ordinary is read from the unsigned LEB128-encoded extra data.</td></tr><tr><td>3</td><td>SET_DYLIB_SPECIAL_IMM</td><td>Same as above, but the ordinary as set as <em>negative</em> of imm. Typical values are:<ul><li>0 = SELF</li><li>-1 = MAIN_EXECUTABLE</li><li>-2 = FLAT_LOOKUP</li></ul></td></tr><tr><td>4</td><td>SET_SYMBOL_TRAILING_FLAGS_IMM</td><td>Set flags of the symbol in imm, and the symbol name as a C string in the extra data. The flags are:<ul><li>1 = WEAK_IMPORT</li><li>8 = NON_WEAK_DEFINITION</li></ul></td></tr><tr><td>5</td><td>SET_TYPE_IMM</td><td>Set the type of symbol as imm. Known values are:<ul><li>1 = POINTER</li><li>2 = TEXT_ABSOLUTE32</li><li>3 = TEXT_PCREL32</li></ul></td></tr><tr><td>6</td><td>SET_ADDEND_SLEB</td><td>Set the addend of the symbol as the signed LEB128-encoded extra data. Usage unknown.</td></tr><tr><td>7</td><td>SET_SEGMENT_AND_OFFSET_ULEB</td><td>Set that the symbol can be found in the imm-th segment, at an offset found in the extra data.</td></tr><tr><td>8</td><td>ADD_ADDR_ULEB</td><td>Increase the offset (as above) by the LEB128-encoded extra data.</td></tr><tr><td>9</td><td>DO_BIND</td><td>Define a symbol from the gathered information. Increase the offset by 4 (or 8 on 64-bit targets) after this operation.</td></tr><tr><td>A</td><td>DO_BIND_ADD_ADDR_ULEB</td><td>Same as above, but besides the 4 byte increment, the extra data is also added.</td></tr><tr><td>B</td><td>DO_BIND_ADD_ADDR_IMM_SCALED</td><td>Same as DO_BIND, but an extra imm*4 bytes is also added.</td></tr><tr><td>C</td><td>DO_BIND_ULEB_TIMES_SKIPPING_ULEB</td><td>This is a very complex operation. <em>Two</em> unsigned LEB128-encoded numbers are read off from the extra data. The first is the count of symbols to be added, and the second is the bytes to skip after a symbol is added. In pseudocode, all it does is:<blockquote><pre>for i = 1 to count<br /> define symbol<br /> offset += 4 + skip<br />end for</pre></blockquote></td></tr></tbody></table><br /><br />For example, we want to bind the address 0x2020 (of the __DATA section, starting at 0x2000) to the symbol _XXHello, which is defined in the 9th loaded dylib, Hello.dylib. We would perform the following operations:<pre>SET_DYLIB_ORDINAL_IMM(9)<br />SET_SYMBOL_TRAILING_FLAGS_IMM(0, "_XXHello")<br />SET_SEGMENT_AND_OFFSET_ULEB(2, 0x20) ; usually __DATA is the 2nd segment.<br />DO_BIND()</pre><br />So in binary it will be<br /><pre>0x19 0x40 "_XXHello\0" 0x72 0x20 0x90</pre><br /><br /><h3>rebase</h3><br />I don't think rebase is useful, and rebase uses a similar approach to code rebase info as bind, so I'm ignoring it here.<br /><br /><h3>export</h3><br />Unlike bind, export is an entirely different beast. The content of the export chunk defines a <em>trie</em>, or a prefix tree. A node in this trie is encoded as:<br /><blockquote>Node = «uint8_t terminal_size» [Terminal] «uint8_t child_count» [Child] [Child] [Child] ...<br />Child = «char* suffix» «uleb128 offset»<br />Terminal = «uleb128 flags» «uleb128 address»</blockquote><br /><br />Known flags are:<br /><ul><li>1 = THREAD_LOCAL</li><li>4 = WEAK_DEFINITION</li><li>8 = INDIRECT_DEFINITION</li><li>0x10 = HAS_SPECIALIZATIONS</li></ul><br /><br />For example, if a dylib exported _XXHello at 0x1022 and _XXWorld at 0x1064, and _XXHelloWorld2 at 0x1558. A trie that represent these symbols would be:<br /><br /><pre>_XX - [Hello] - [World2]<br /> \<br /> [World]</pre><br /><br />So we encode our root node as<br /><pre>00 01 "_XX\0" (offset to _XX)</pre><br />and _XX as<br /><pre>00 02 "Hello\0" (offset to Hello) "World\0" (offset to World)</pre><br />if we place the _XX node right after the root node the offset would be 7, so the root node is<br /><pre>00 01 "_XX\0" 07</pre><br />The offset of the rest can be obtained like this. Now for the Hello node, since it defined a symbol, we have to fill in the Terminal info:<br /><pre>05 00 A2 20 /*=0x1022*/ 01 "World2\0" (offset to World2)</pre><br />etc.KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com0tag:blogger.com,1999:blog-3540073447780295551.post-77545879544699995002009-09-18T22:16:00.003+08:002009-09-19T01:31:43.067+08:00QuickScroll 2.2a should be available on Cydia soon.QuickScroll <del>2.2</del> <ins>2.2a</ins> is released, and this marks the completion (so far) of the QuickScroll project. Thanks to the gdb for 3.1 I've finally squashed the "HiCalc" bug. I have already submitted it to BigBoss and should be available in a day. If you can't wait, you can still download from <a href="http://code.google.com/p/networkpx/downloads/detail?name=hk.kennytm.quickscroll2-0.2-2a.deb">here</a>. <br /><br />Change log from 2.1a:<br /><ul><li>The scrolling indicator is no longer visible when scrollbar is used.</li><li>You should be able to use the scroller in HiCalc and other apps that canCancelContentTouches.</li></ul><br />Change log from 2.2:<br /><ul><li>Fixed an obscure bug that causes crashing when the scroll view disappears. Thanks Optimo for discovering.</li></ul>KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com4tag:blogger.com,1999:blog-3540073447780295551.post-12494979685983258382009-09-18T19:39:00.007+08:002009-09-19T15:51:47.769+08:00Porting the SDK's gdb for 3.1The gdb on Cydia currently doesn't work on 3.1 because of the new Mach-O format. We could compile gdb from source (which I've failed to do so), wait for someone else to compile from source (<del>which I'm still waiting</del>), or just use the gdb in the SDK.<br /><br /><blockquote><strong>Update:</strong> saurik has updated the gdb package that works in 3.1, which will be available tomorrow. You can download it now from <a href="http://apt.saurik.com/debs/gdb_1128-8_iphoneos-arm.deb">http://apt.saurik.com/debs/gdb_1128-8_iphoneos-arm.deb</a>.</blockquote><br /><br />The SDK's gdb is in <tt>/Developer/Platforms/iPhoneOS.platform/Developer/usr/libexec/gdb/gdb-arm-apple-darwin</tt>. While you can run it directly on your Mac, it is in fact a fat binary with 3 architectures:<br /><br /><blockquote><strong>file gdb-arm-apple-darwin </strong><br /><br />gdb-arm-apple-darwin: Mach-O universal binary with 3 architectures<br />gdb-arm-apple-darwin (for architecture ppc): Mach-O executable ppc<br />gdb-arm-apple-darwin (for architecture i386): Mach-O executable i386<br />gdb-arm-apple-darwin (for architecture armv5): Mach-O executable arm</blockquote><br /><br />The ARMv5 portion is what we want. But this gdb is useless to run on the iPhoneOS because it lacks all the essential entitlements. While entitlements can be inserted using ldid, there is a limitation needs to be worked-around: ldid doesn't support the <tt>armv5</tt> architecture. We have to modify the source code of ldid to allow it:<br /><blockquote><pre>@@ -557,6 +557,7 @@<br /> case 12: switch (framework->cpusubtype) {<br /> case 0: arch = "arm"; break;<br /> case 6: arch = "armv6"; break;<br />+ case 7: arch = "armv5"; break;<br /> default: arch = NULL; break;<br /> } break;</pre></blockquote><br />(I have also <tt>lipo -thin</tt>-ed the gdb before ldid-ing to make everything smooth.) After applying this patch, the ldid should recognize armv5 correctly. Now, save this portion of text as an XML file (e.g. gdb.xml):<br /><blockquote><pre><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><br /><plist version="1.0"><br /><dict><br /> <key>com.apple.springboard.debugapplications</key><br /> <true/><br /> <key>get-task-allow</key><br /> <true/><br /> <key>task_for_pid-allow</key><br /> <true/><br /> <key>run-unsigned-code</key><br /> <true/><br /></dict><br /></plist></pre></blockquote><br />and then run:<br /><blockquote><strong>ldid -Sgdb.xml gdb</strong></blockquote><br />, and the gdb should now be completely usable on the iPhoneOS.KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com0tag:blogger.com,1999:blog-3540073447780295551.post-12832610169367178492009-09-17T02:13:00.002+08:002009-09-17T02:18:25.820+08:00iKeyEx 0.1-99j released, now works in 3.1Download: <a href="http://code.google.com/p/networkpx/downloads/detail?name=hk.kennytm.iKeyEx3-0.1-99j.deb"> http://code.google.com/p/networkpx/downloads/detail?name=hk.kennytm.iKeyEx3-0.1-99j.deb</a><br /><br />This version is an emergency release to make it work in 3.1 (r497, r498). Along with it there are also these changes:<br /><ol><li>Fixed a crash when uninstalling the Chinese Phrase Tables package (r491)</li><li>Fixed a crash when phrases longer than 2 characters are processed (r499)</li><li>Fixed a bug in characters sorting, that the sorted array is incorrect (r499).</li></ol>KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com19tag:blogger.com,1999:blog-3540073447780295551.post-43894566189018250852009-09-16T03:19:00.004+08:002009-09-16T03:24:25.238+08:00QuickScroll 2.1a.Download: <a href="http://code.google.com/p/networkpx/downloads/detail?name=hk.kennytm.quickscroll2-0.2-1a.deb"> http://code.google.com/p/networkpx/downloads/detail?name=hk.kennytm.quickscroll2-0.2-1a.deb</a>.<br /><br />New features:<br /><ul><li>QuickScroll can be disabled for each particular app, including SpringBoard.</li><li>Activate by scrolling. (This is off by default since you can't have smooth scrolling with QuickScroll. Oh you have 3GS? Forget I what say then...)</li><li>New icon design by Sagitt.</li><li>Localizations.</li></ul><br /><br />After this release all features will be frozen. That is, no new features will be accepted, no matter how ingenious it is. (Ya know, this thing gotta be pushed out some day). Only bug fix and new localizations will be allowed for 2.2 (the public version).KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com14tag:blogger.com,1999:blog-3540073447780295551.post-75631697220647658582009-09-15T02:26:00.002+08:002009-09-15T02:31:35.691+08:00QuickScroll 2.1.Download: <a href="http://code.google.com/p/networkpx/downloads/detail?name=hk.kennytm.quickscroll2-0.2-1.deb"> http://code.google.com/p/networkpx/downloads/detail?name=hk.kennytm.quickscroll2-0.2-1.deb</a><br /><br />Changes:<br /><ul><li>The scrollers should now be easier to grab and move around.</li><li>Duration now really defaults to 2 seconds on first install. Thanks fusen for noticing.</li><li>Scrollbars can be chosen to jump on spot instead of next page. Thanks Sagitt for suggestion.</li></ul><br /><br />(If there're no other bugs I'll submit this version to BigBoss.)KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com3tag:blogger.com,1999:blog-3540073447780295551.post-4405582164155426572009-09-14T01:37:00.002+08:002009-09-14T02:44:32.986+08:00QuickScroll 2 releasedWith a 333% size increase*, <a href="http://code.google.com/p/networkpx/downloads/detail?name=hk.kennytm.quickscroll2-0.2.deb ">QuickScroll 2</a> is released to improve the scrolling experience.<br /><br /><ul><br /><li>QuickScroll 2 now introduces scrollbars, which is the default. <br /><img src="http://x28.xanga.com/ad2f737a06632254588213/w202389898.png" /></li><br /><li>Besides PDF files, scroll views that explicitly allowed for paging can also be targeted.<br /><img src="http://xcd.xanga.com/3b9f564343133254591514/w202392728.png" /></li><br /><li>The old scroller is still accessible, but you can now move it around (and occupies much less space).<br /><img src="http://x94.xanga.com/c0cf777a26635254588214/w202389899.png" /></li><br /><li>(To jump to a page, tap the 123 icon at the lower right corner in scroll bar mode, or tap the ← arrow button in scroller dialog mode.)</li><br /><li>These configuration can be set in Settings.<br /><img src="http://xdd.xanga.com/4d6f434039033254588215/w202389900.png" /></li><br /><li>As you can see, there are 2 more gestures you can choose. The two-finger tap should allow you activate QuickScroll in a table view easier.</li><br /><li>I've eliminated the close button. The scrollers will disappear in 2 seconds of inactivity.</li><br /><li>QuickScroll's scrollers are now actually a subview of the scrolling view, while in the 1st version it is an alert box. This change allows QuickScroll to be used in very high-level windows like those in SBSettings and GriP.</li><br /><li>I don't know how to localize PreferenceLoader entries yet. So no localizations in this version, sorry.</li><br /></ul><br /><br /><br />*: 24 KiB → 104 KiB on disk.KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com7tag:blogger.com,1999:blog-3540073447780295551.post-15680930634220133682009-09-11T22:22:00.002+08:002009-09-11T22:30:06.744+08:00Get UIView hierarchy, take 3.The <a href="http://networkpx.blogspot.com/2009/08/easier-way-to-get-uiview-hierarchy.html">previous post</a> about dumping UIView hierarchy is actually over-complicated. Actually all you need is one command (in gdb):<br /><br /><blockquote><pre>po [[[UIApplication sharedApplication] keyWindow] scriptingInfoWithChildren]</pre></blockquote><br /><br />The result will be very verbose, make sure your terminal has enough scrollback.KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com0tag:blogger.com,1999:blog-3540073447780295551.post-90793063374104274472009-09-10T03:11:00.003+08:002009-09-10T03:28:42.606+08:00iKeyEx 0.1-99i released.Download = <a href="http://code.google.com/p/networkpx/downloads/detail?name=hk.kennytm.iKeyEx3-0.1-99i.deb">here</a>.<br /><br />Changes:<br /><ul><li>Fixed issue <a href="http://code.google.com/p/networkpx/issues/detail?id=313">313</a>. In an alt (numbers) plane, pressing the space key will go back to the main (alphabets) plane.</li><li>Typing the apostrophe (') in the main plane no longer auto-switch to the alt plane.</li><li>Fixed issue <a href="http://code.google.com/p/networkpx/issues/detail?id=312">312</a>, and many other auto-shift related quirks.</li><li>.cin IME:<ul><li>Number of candidates is limited to avoid near-infinite loop. 64.0 candidates should be enough for everyone.</li><li>Multi-radical continuation works again.</li><li>Fixed cases where blank candidates appear.</li><li>Candidate searching now operates in serial for reliability. You may experience some degrade in performance.</li><li>A progress indicator is added when the Patricia tree dump for the IME was first generated. This is essential for some huge IME like 輕鬆輸入法, which takes nearly 2 minutes for the first launch.</li></ul></li></ul><br /><br />(Chinese Users: 倉頡輸入法及額外字頻表及詞庫亦更新至 0.2-1 版,這與 0.2-0 版內容上其實沒分別,只是製作 deb 時改用了 gnutar,從而避免因含非 ASCII 檔名而導致安裝失敗。若果你正在使用這些軟件,則不用更新。)<br /><br />By the way, if you find any bugs, please report at <a href="http://code.google.com/p/networkpx/issues/list">Issues</a> in the project page. If you leave a comment here or the wiki I can't guarantee I can dig and fix that.<br /><br /><em>Preemptive Warning</em>: Comments not related to this content will be ignored.KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com10tag:blogger.com,1999:blog-3540073447780295551.post-68344176201151946512009-09-07T02:17:00.006+08:002009-09-11T16:44:22.109+08:00Introducing Subjective-C, an objc_msgSend[_[st|fp]ret]? logger.Time ago I <a href="http://code.google.com/p/networkpx/source/browse/etc/objc_msgSend_hook.mm?r=472">logged calls</a> to objc_msgSend to understand how to construct UIKBKeyboards. But that logger is known to cause problems due to asserting the arguments use less than 1024 bytes. I needed to log calls again for <a href="http://code.google.com/p/networkpx/issues/detail?id=312">issue 312</a>, but the old buggy behavior leads me to rewriting it more reliably.<br /><br />The result is the dynamic library called <a href="http://code.google.com/p/networkpx/downloads/detail?name=libsubjc.dylib ">Subjective-C</a>. It has the following new features:<br /><ul><li>Stack-safe. No arguments will be lost due to this logger.</li><li>Call tree construction.</li><li>Filtering.</li></ul><br />along with the old features:<br /><ul><li>Print and format all arguments, and the return value.</li></ul><br /><br />Note:<ul><li>Due to licensing, only the ARM version is released, although the x86 version works perfectly.</li><li>If your product depends on Subjective-C (why?), please note that it is GPLv3.</li><li>(No, it won't help even if I BSD everything.)</li></ul><br /><br /><h3>Sample output</h3><br /><br /><pre><br /> +[UIScroller _registerForNotifications]<br /> +[NSString alloc] {<br /> +[NSString allocWithZone:] (0x0)<br /> }<br /> +[NSBundle mainBundle] {<br /> -[NSRecursiveLock lock] <0x1007540><br /> -[NSRecursiveLock unlock] <0x1007540><br /> } = <NSBundle 0x100db50><br /> -[NSBundle bundleIdentifier] <0x100db50> {<br /> -[NSBundle infoDictionary] <0x100db50> {<br /> -[NSBundle _cfBundle] <0x100db50> = 0x1009d60<br /> } = <NSCFDictionary 0x100af10><br /> -[NSCFDictionary objectForKey:] <0x100af10> (@"CFBundleIdentifier") = @"com.yourcompany.Untitled4"<br /> } = @"com.yourcompany.Untitled4"<br /> -[NSPlaceholderString initWithFormat:] <0x100cf70> (@"%@.UIKit.migserver") {<br /> -[NSPlaceholderString initWithFormat:locale:arguments:] <0x100cf70> (@"%@.UIKit.migserver", nil, "∞≠") {<br /> -[NSCFString respondsToSelector:] <0x100adb0> (@selector(descriptionWithLocale:)) {<br /> -[NSCFString class] <0x100adb0> = NSCFString<br /> +[NSCFString resolveInstanceMethod:] (@selector(descriptionWithLocale:)) = NO<br /> } = NO<br /> -[NSCFString description] <0x100adb0> = /*self*/ @"com.yourcompany.Untitled4"<br /> } = @"com.yourcompany.Untitled4.UIKit.migserver"<br /> } = @"com.yourcompany.Untitled4.UIKit.migserver"<br /></pre><br /><br /><a name='more'></a><br /><br /><h3>API</h3><br /><br />You can find the header file in <a href="http://code.google.com/p/networkpx/source/browse/etc/subjc.h">subjc.h</a>. <br /><br />Most of the case you just need to call two functions:<br /><ul><li>void <strong>SubjC_start</strong>(FILE* f, size_t maximum_depth, bool print_arguments, bool print_return_value)<br /><ul><li>Starts logging all objective-C calls. The result will be written to the file <em>f</em>, up to a maximum call-tree depth <em>maximum_depth</em>. You may use the boolean parameters <em>print_arguments</em> and <em>print_return_value</em> to control whether to format the arguments and return values. Not doing so may save some time.</li></ul></li><li>void <strong>SubjC_end</strong>();<br /><ul><li>Stops logging. This function must be called at the same level as <tt>SubjC_start</tt>.</li></ul></li></ul><br /><br />The SubjC_initialize() function does the initialization things. It will be called automatically in SubjC_start if not done, so you don't need to explicitly call it.<br /><br />The rest are to control whether a (sub)message can be logged. If a message is <em>filtered</em>, all calls <em>spawned by <br />this message</em> will not be logged. For example, if the selector <tt>copy</tt> is filtered, then in the log you will only see<br /><blockquote><pre>-[XXSomeClass copy] <0xfedcba98> = <XXSomeClass 0x12345678></pre></blockquote>instead of <blockquote><pre>-[XXSomeClass copy] = {<br /> -[XXSomeClass copyWithZone:] <0xfedcba98> (0x0) = <XXSomeClass 0x12345678><br />} = <XXSomeClass 0x12345678></pre></blockquote><br /><br /><h3>Known issues</h3><br /><br /><ul><li>Subjective-C is not thread-safe. <del>I repeat: Subjective-C is not thread-safe. If there are ≥1 threads that uses Objective-C during logging you're almost surely doomed to crash.</del> OK it won't crash now by changing the global lr stack to thread-local, but it's still not completely thread-safe.</li><li>Variadic arguments can never be logged.</li><li>+initialize messages cannot be logged. This is because Subjective-C cannot work if the class is not initialized, so it implicitly initialize the class before logging.</li></ul><br /><br /><h3>How it works</h3><br /><br />All Objective-C calls (except the manually cached ones) will go through objc_msgSend, objc_msgSend_stret, and in x86, objc_msgSend_fpret. Therefore, if we replace these functions with our custom one the every message can be logged. <br /><br />The tricky part is to call the original function after logging is finished. GCC has __builtin_apply_args and friends to construct the calls, but it assumes you know the maximum bytes of the arguments, because the approach taken by these is to <em>copy</em> the content of stack. This leads to the buggy behavior in the old logger.<br /><br />To avoid this, the new logger was written in assembly. The approach (and the name) was inspired by saurik's <a href="http://svn.saurik.com/repos/menes/trunk/aspectivec/">Aspective-C</a> (thanks for informing this work). In the new logger, every action before calling the original function was done without modifying the stack pointer and the content above it, nor the registers.<br /><br />That means, in ARM, the registers r0-r3 cannot be modified, push/pop cannot be used, and the only free register is r12. Fortunately, heap memory can still be accessed, and well-defined functions will not affect anything except r0-r3, r12 and lr, so the only necessary step to perform is<br /><ul><li>Load the address of an array of 32-bit integers</li><li>Store r0-r3 in there</li><li>Call any functions we like</li><li>Load the address of that array again</li><li>Restore r0-r3 from there.</li><li>Call original objc_msgSend</li><li>Print the returned value and return.</li></ul><br />But to return, the link register (lr) need to persist. And it needs to persist throughout the whole replaced function, which in the middle a self-call may happen. This means the lr must be stored on a stack:<ul><li>Load the address of an array of 32-bit integers</li><li>Store r0-r3 in there</li><li style="color:red;">Push lr onto a custom stack</li><li>Call any functions we like</li><li>Load the address of that array again</li><li>Restore r0-r3 from there.</li><li>Call original objc_msgSend</li><li style="color:red;">Pop lr from the custom stack</li><li>Print the returned value and return.</li></ul><br /><br />The situation is easier on x86. Every argument, and the return address must be on the stack. Therefore the "Store r0-r3" steps can be ignored. Nevertheless, we need to replace the return address to ensure the original objc_msgSend return to our place, so the custom stack is still needed.<br /><br /><h3>Compiling Subjective-C</h3><br /><br />To compile Subjective-C you need the following:<br /><ul><li>g++</li><li><a href="http://www.boost.org/">Boost C++ library</a> (for unordered_set)</li><li>Source code for the whole <a href="http://code.google.com/p/networkpx/source/browse/#svn/trunk/hk.kennytm.Peace">hk.kennytm.Peace</a> subproject (for argument formatting).</li><li><a href="http://unsanity.com/haxies/ape/sdk">APELite</a>, if you compile for x86.</li><li>MobileSubstrate, if you compile for ARM.</li></ul><br /><br /><a href="http://code.google.com/p/networkpx/source/browse/etc/subjc.mf">subjc.mf</a> contains the Makefile for ARM, and <a href="http://code.google.com/p/networkpx/source/browse/etc/subjc.x86">subjc.x86</a> for x86.KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com2tag:blogger.com,1999:blog-3540073447780295551.post-44259061576878980932009-09-02T03:31:00.004+08:002009-09-02T03:46:54.610+08:00stmXX<pre><br />static int rx_reserve[8];<br /><br />...<br /><br /> __asm__(" mov r1, #1\n"<br /> " mov r2, #2\n"<br /> " mov r3, #3\n"<br /> " ldr r0, (reserve)\n"<br /> " mov r4, r0\n"<br /> " ????? r0!, {r1-r3}\n"<br /> " str r0, [r4, #16]\n"<br /> " b after_data\n"<br /> "reserve:\n"<br /> " .long _rx_reserve+12\n"<br /> "after_data:\n");<br /> <br /> printf("%d %d %d [%d] %d %d %d;\ndelta = %d\n",<br /> rx_reserve[0], rx_reserve[1], rx_reserve[2], rx_reserve[3], rx_reserve[4], rx_reserve[5], rx_reserve[6],<br /> rx_reserve[7]-(int)(rx_reserve+3) );<br /></pre><br /><br /><table border="1"><tr><th>?????</th><th>Result</th></tr><tr><td>stmia</td><td>0 0 0 [1] 2 3 <u>0</u>;<br />delta = 12</td></tr><tr><td>stmib</td><td>0 0 0 [0] 1 2 <u>3</u>;<br />delta = 12</td></tr><tr><td>stmda</td><td><u>0</u> 1 2 [3] 0 0 0;<br />delta = -12</td></tr><tr><td>stmdb</td><td><u>1</u> 2 3 [0] 0 0 0;<br />delta = -12</td></tr></table>KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com1tag:blogger.com,1999:blog-3540073447780295551.post-37088863258370821152009-09-01T06:57:00.002+08:002009-09-01T07:37:19.947+08:00iKeyEx & 5-Row QWERTY 0.1-99h are releasedDownloads can be found in <a href="http://code.google.com/p/networkpx/downloads/list">here</a> as usual. <br /><br />Changes from "g" are:<br /><br /><ul><li>You can now long-press control keys (left, right, etc) to repeat actions.</li><li>ANSI and X11 apps for control keys are now correctly detected.</li><li>The config file is moved to ~/Library/Keyboard/iKeyEx::config.plist. This allows the config to be preserved even after firmware upgrade. (Permission problems will also be fixed during installation.)</li><li>PSBundle for layouts and IMEs. Normal users can find them in Settings → iKeyEx → Customize.</li><li>In the delete cache page, the total file size of the cache entry will be reported.</li><li>Candidate calculation in .cin IMEs now actually runs in background.</li><li>Associated phrases (aka Completion) can be disabled.</li><li>iKeyEx-KBMan now registers input modes correctly without causing crashes. Also it now purges layout cache correctly.</li></ul><br /><br />The "h" version of iKeyEx is considered a release candidate. I'll try to get it to BigBoss's beta repo if no major bug is found.<br /><br />Many of the changes in "g" and "h" are to prepare for the 5 Row QWERTY layout. Of course, the major change for 5 Row QWERTY is it works on 3.0, but even compared with 0.1-9b, there are a few points to need to notice:<ol><li>You'll find that the Tab, Esc, Page Up keys etc become words instead of symbols. This is because, with the system fonts all the previous symbols cannot be rendered. For consistency I just change them all into words.</li><li>The "Autocorrection" part of the old pref bundle is now handled by Mix & Match.</li><li>Sometimes your customization won't take effect. Try to Delete cache if that happens.</li></ol><br />There are no modifications other than these.KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com22tag:blogger.com,1999:blog-3540073447780295551.post-60512105543698996002009-08-30T21:36:00.002+08:002009-08-30T21:42:48.930+08:00iKeyEx 0.1-99g is released<a href="http://networkpx.googlecode.com/files/hk.kennytm.iKeyEx3-0.1-99g.deb">Download.</a><br /><br />Changelog:<br /><ul><li>“Text with traits” is now supported, that means your can add color, change font and text size for each key. However, you still cannot use key with image.</li><li>Native control keys support. (Left, right, home, page down, etc.)</li></ul>KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com9tag:blogger.com,1999:blog-3540073447780295551.post-64132129741757295432009-08-26T05:14:00.004+08:002009-08-28T03:52:05.080+08:00Easier way to get UIView hierarchy.Before I documented <a href="http://networkpx.blogspot.com/2009/06/displaying-uiview-hierarchy-in-runtime.html">how you can obtain the UIView hierarchy in syslog</a>. It uses custom function, but there is are 2 built-in way to get this.<br /><br />The first, standard way is to send a GSEvent type #500 to the application, then the dump will be written to /tmp/UIDump in plist format. You can achieve the same by calling in gdb:<br /><pre><br />call (void)[[UIApplication sharedApplication] _dumpUIHierarchy:0]<br /></pre><br />When the dump is completed, a Darwin notification "com.apple.UIHierarchyDump.finished" will be posted.<br /><br />(You can also take a screenshot with _dumpScreenContents:0 / GSEvent type #501, but the file is in JPEG and pressing Lock+Home isn't that hard...)<br /><br />(Note: May fail for AppStore apps due to sandboxing.)KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com0tag:blogger.com,1999:blog-3540073447780295551.post-35009776629552265092009-08-26T02:37:00.003+08:002009-08-26T03:38:54.029+08:00GSEvent Recording and Playback in 3.0iPhoneOS has built-in API for application macro since 2.x. (Of course it was never documented.) (And the API was really changed in 3.0 to adopt for multiple recorders.)<br /><br />For example, to record everything you've done during the for yourUIApplication:<br /><pre><br /> recorder = [Recorder new];<br /> <font color="red">[yourUIApplication _addRecorder:recorder];</font><br /> [recorder release];<br /></pre ><br />The command _addRecorder: adds the object to the application's event recorder array. You can remove your recorder at anytime with <br /><pre><br /> <font color="red">[yourUIApplication _removeRecorder:recorder];</font><br /></pre><br /><br />An event recorder must conform to the informal protocol<br /><pre><br />@protocol UIEventRecorder<br />-(void)recordApplicationEvent:(NSDictionary*)event;<br />@end<br /></pre><br />Here, "event" is a GSEvent converted to a plist using GSEventCreatePlistRepresentation(). You can add the event to an array and save that array for later reference, e.g.<br /><pre><br />@interface Recorder : NSObject { NSMutableArray* eventList; } @end<br />@implementation Recorder<br />-(id)init { if ((self = [super init])) eventList = [NSMutableArray new]; return self; }<br />-(void)save { [eventList writeToFile:@"events.plist" atomically:YES]; }<br />-(void)recordApplicationEvent:(NSDictionary*)event { [eventList addObject:event]; }<br />@end<br /></pre><br /><br /><br />Now say you want to play back the events you've previously collected. Just use this code:<br /><pre><br />NSArray* eventList = [NSArray arrayWithContentsOfFile:@"events.plist"];<br />float playbackRate = 1;<br />[app _playbackEvents:eventList atPlaybackRate:playbackRate messageWhenDone:target withSelector:@selector(done:)];<br /></pre><br />The higher the playback rate, the faster the system will run the events. <br /><br />When the playback is finished, the "done:" selector will be called for "target". This selector must have a signature of<br /><pre><br />-(void)done:(NSDictionary*)detail;<br /></pre><br />the "detail" argument contains exactly 1 key, "UIApplicationEventRecordingDeliveryTimeUserInfoKey", which points to an array of the time the corresponding event happened.KennyTM~http://www.blogger.com/profile/13952454490450371593noreply@blogger.com1