Debugserver: Difference between revisions

From iPhone Development Wiki
(formatting and copyediting)
Line 1: Line 1:
{{DISPLAYTITLE:debugserver}}
{{DISPLAYTITLE:debugserver}}
<tt>[[debugserver]]</tt> is a console app that as server for remote gdb debugging. It is installed when a device is marked for development. It can be found in <tt>/Developer/usr/bin/debugserver</tt>. This is also the process invoked by Xcode to debug applications on the device.
<tt>[[debugserver]]</tt> is a console app that as server for remote gdb debugging. It is installed when a device is marked for development. It can be found in <tt>/Developer/usr/bin/debugserver</tt>. This is also the process invoked by Xcode to debug applications on the device.


Line 42: Line 41:


== Patching for process attaching ==
== Patching for process attaching ==
The vanilla <tt>debugserver</tt> cannot attach to any processes due to lack of entitlement to allow <tt>task_for_pid()</tt>. An entitlement must be inserted to the binary to allow this.
The vanilla <tt>debugserver</tt> cannot attach to any processes due to lack of entitlement to allow <tt>task_for_pid()</tt>. An entitlement must be inserted into the binary to allow this.
 
'''0.''' <code>cd ~</code>
 
'''1.''' Thin the binary because <tt>[[ldid]]</tt> does not support fat binaries:
<source lang="bash">
lipo -thin armv6 /Developer/usr/bin/debugserver -output ~/debugserver
</source>


* '''0.''' <code>cd ~</code>
'''2.''' Save the following as <tt>ent.xml</tt>:
* '''1.''' Thin the binary because <tt>[[ldid]]</tt> does not support fat binaries:<br />
lipo -thin armv6 /Developer/usr/bin/debugserver -output ~/debugserver
* '''2.''' Save for following as <tt>ent.xml</tt>:
<source lang="xml">
<source lang="xml">
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
Line 63: Line 66:
</plist>
</plist>
</source>
</source>
* '''3.''' Apply the entitlement with <tt>ldid</tt>:
 
'''3.''' Apply the entitlement with <tt>ldid</tt>:
  ldid -Sent.xml debugserver
  ldid -Sent.xml debugserver


=== Alternative Instructions (64-bit compatible) ===


 
Alternatively if you are on a Mac with Xcode, installed you can follow Peter Steinberger's instructions to add entitlements to the debugserver that comes with Xcode. This will allow you to keep it as a fat binary, which will work on all devices including 64-bit iPhone 5s [https://speakerd.s3.amazonaws.com/presentations/43ca7dd05d120131795d129291fe58eb/Taking_Advantage_of_the_Runtime.pdf Here are Peter's full slides in PDF format] or [https://speakerdeck.com/steipete/taking-advantage-of-the-runtime on a website (with more tips)] - start at slide 45 for instructions for getting the debugserver to work.
=== Alternative Instructions (64bit compatible) ===
 
Alternatively if you are on a mac with xcode installed you can follow Peter Steinberger's instructions to add entitlement's to the debugserver that comes with xcode. This will allow you to keep it as a fat binary, which will work on all devices including 64bit iPhone 5S.
 
You can find Peter's full slides here: https://speakerd.s3.amazonaws.com/presentations/43ca7dd05d120131795d129291fe58eb/Taking_Advantage_of_the_Runtime.pdf and https://speakerdeck.com/steipete/taking-advantage-of-the-runtime which contain more useful tips. Instructions for getting the debugserver to work start on slide 45.


I am not sure if you need an Apple developer membership and certificate to add the entitlements. If this fails for you, try the first method above.
I am not sure if you need an Apple developer membership and certificate to add the entitlements. If this fails for you, try the first method above.


* '''1.''' Mount xcode's developer disk image on your Mac and copy the debugserver binary to your working directory:
'''1.''' Mount Xcode's developer disk image on your Mac and copy the debugserver binary to your working directory:
  hdiutil attach /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/ DeviceSupport/7.0.3\ \(11B508\)/DeveloperDiskImage.dmg
  hdiutil attach /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/ DeviceSupport/7.0.3\ \(11B508\)/DeveloperDiskImage.dmg
  cp /Volumes/DeveloperDiskImage/usr/bin/debugserver .
  cp /Volumes/DeveloperDiskImage/usr/bin/debugserver .


* '''2.''' Save for following as <tt>entitlements.plist</tt>:
'''2.''' Save the following as <tt>entitlements.plist</tt>:
<source lang="xml">
<source lang="xml">
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/ PropertyList-1.0.dtd">
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/ PropertyList-1.0.dtd">
Line 93: Line 93:
</source>
</source>


* '''3.''' Apply the entitlement with <tt>codesign</tt>:
'''3.''' Apply the entitlement with <tt>codesign</tt>:
  codesign -s - --entitlements entitlements.plist -f debugserver
  codesign -s - --entitlements entitlements.plist -f debugserver


== Attaching to a process ==
== Attaching to a process ==
* '''1.''' On the device, type:
'''1.''' On the device, type:
  ./debugserver *:1234 -a "YouTube"
  ./debugserver *:1234 -a "YouTube"


Line 109: Line 108:
  Listening to port 1234 for a connection from *...
  Listening to port 1234 for a connection from *...


 
'''2.''' On your Mac, launch lldb and type the following commands (but replace the IP with your device's IP):
* '''2.''' On your mac launch lldb and type the following commands:
  platform select remote-ios
  platform select remote-ios
  process connect connect://192.168.2.104:1234
  process connect connect://192.168.2.104:1234
<blockquote>Obviously, replace the IP with your device's IP</blockquote>


'''Example:'''
'''Example:'''
Line 140: Line 137:


=== Debugging through USB instead of WiFi ===
=== Debugging through USB instead of WiFi ===
If you find debugging through WiFi is a little slow or you need to debug an app while WiFi is off, you can use usbmuxd to connect through USB. Mac users can also use iphone tunnel: https://code.google.com/p/iphonetunnel-mac/
If you find that debugging through WiFi is a little slow, or if you need to debug an app while WiFi is off, you can use usbmuxd to connect through USB. Mac users can also use [https://code.google.com/p/iphonetunnel-mac/ iPhoneTunnel].


  wget http://cgit.sukimashita.com/usbmuxd.git/snapshot/usbmuxd-1.0.8.tar.bz2
  wget http://cgit.sukimashita.com/usbmuxd.git/snapshot/usbmuxd-1.0.8.tar.bz2
Line 146: Line 143:
  cd usbmuxd-1.0.8/python-client/
  cd usbmuxd-1.0.8/python-client/
  python tcprelay.py -t 1234:1234
  python tcprelay.py -t 1234:1234
<blockquote>Now all connections to localhost:1234 will be forwarded to your iPhone through USB to port 1234</blockquote>
 
Now all connections to localhost:1234 will be forwarded to your iPhone through USB to port 1234.


Connecting lldb:
Connecting lldb:
Line 165: Line 163:
== Example session ==
== Example session ==


<blockquote>These instructions probably only work on very old firmware's like iOS 3. For iOS 7 follow the example above.</blockquote>
'''Note: these instructions probably only work on very old firmwares such as iOS 3. For iOS 7, follow the example above.'''
 


* '''1.''' Copy MobileNotes to your Mac, e.g. to <tt>/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.sdk/Applications/MobileNotes.app/MobileNotes</tt>.
'''1.''' Copy MobileNotes to your Mac, e.g. to <tt>/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.sdk/Applications/MobileNotes.app/MobileNotes</tt>.
* '''2.''' On the device, type:
'''2.''' On the device, type:
  ~/debugserver -x spring host:6789 /Applications/MobileNotes.app/MobileNotes
  ~/debugserver -x spring host:6789 /Applications/MobileNotes.app/MobileNotes
<blockquote>This will launch MobileNotes and wait for the remote debugger.</blockquote>
This will launch MobileNotes and wait for the remote debugger.


* '''3.''' Launch the debugger and attach it to the remote process:
'''3.''' Launch the debugger and attach it to the remote process:
If using '''GDB''':
If using '''GDB''':
* On your Mac, launch <tt>/Developer/Platforms/iPhoneOS.platform/Developer/usr/libexec/gdb/gdb-arm-apple-darwin</tt>.
* On your Mac, launch <tt>/Developer/Platforms/iPhoneOS.platform/Developer/usr/libexec/gdb/gdb-arm-apple-darwin</tt>.
Line 180: Line 177:
  file /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.sdk/Applications/MobileNotes.app/MobileNotes
  file /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.sdk/Applications/MobileNotes.app/MobileNotes
  target remote-macosx 192.168.1.101:6789
  target remote-macosx 192.168.1.101:6789
<blockquote>where 192.168.1.101 should be replaced by the actual IP address of your device. The remote debug connection is now complete.</blockquote>
Where 192.168.1.101 should be replaced by the actual IP address of your device. The remote debug connection is now complete.


If using '''LLDB''':
If using '''LLDB''':
Line 188: Line 185:
  process connect connect://192.168.1.101:6789
  process connect connect://192.168.1.101:6789


* '''4.''' Enter <tt>c</tt> to continue and do whatever you want.
'''4.''' Enter <tt>c</tt> to continue and do whatever you want.


== References ==
== References ==
* iphone-debugserver project — http://code.google.com/p/iphone-debugserver/
* [http://code.google.com/p/iphone-debugserver/ iphone-debugserver project]

Revision as of 23:16, 17 January 2014

debugserver is a console app that as server for remote gdb debugging. It is installed when a device is marked for development. It can be found in /Developer/usr/bin/debugserver. This is also the process invoked by Xcode to debug applications on the device.

Command line options

debugserver can be invoked with

debugserver [<options>] host:<port> [<prog-name> <arg1> <arg2> ...]

Where options can be:

Option Effect
-a process Attach debugserver to process. The process can be a pid or executable name.
-d integer Assign the waitfor-duration.
-f ? ?
-g Turn on debugging.
-i integer Assign the waitfor-interval.
-l filename Log to file. Set filename to stdout to log to standard output.
-t Use task ID instead of process ID.
-v Verbose.
-w ? ?
-x method
--launch=method
How to launch the program. Can be one of:
  • auto: Auto-detect the best launch method to use.
  • fork: Launch program using fork(2) and exec(3).
  • posix: Launch program using posix_spawn(2).
  • spring: Launch program via SpringBoard.
--lockdown Obtain parameters from lockdown (?)

Patching for process attaching

The vanilla debugserver cannot attach to any processes due to lack of entitlement to allow task_for_pid(). An entitlement must be inserted into the binary to allow this.

0. cd ~

1. Thin the binary because ldid does not support fat binaries:

lipo -thin armv6 /Developer/usr/bin/debugserver -output ~/debugserver

2. Save the following as ent.xml:

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.springboard.debugapplications</key>
	<true/>
	<key>get-task-allow</key>
	<true/>
	<key>task_for_pid-allow</key>
	<true/>
	<key>run-unsigned-code</key>
	<true/>
</dict>
</plist>

3. Apply the entitlement with ldid:

ldid -Sent.xml debugserver

Alternative Instructions (64-bit compatible)

Alternatively if you are on a Mac with Xcode, installed you can follow Peter Steinberger's instructions to add entitlements to the debugserver that comes with Xcode. This will allow you to keep it as a fat binary, which will work on all devices including 64-bit iPhone 5s Here are Peter's full slides in PDF format or on a website (with more tips) - start at slide 45 for instructions for getting the debugserver to work.

I am not sure if you need an Apple developer membership and certificate to add the entitlements. If this fails for you, try the first method above.

1. Mount Xcode's developer disk image on your Mac and copy the debugserver binary to your working directory:

hdiutil attach /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/ DeviceSupport/7.0.3\ \(11B508\)/DeveloperDiskImage.dmg
cp /Volumes/DeveloperDiskImage/usr/bin/debugserver .

2. Save the following as entitlements.plist:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/ PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.springboard.debugapplications</key> <true/>
	<key>run-unsigned-code</key>
	<true/>
	<key>get-task-allow</key> <true/> <key>task_for_pid-allow</key> <true/>
</dict> 
</plist>

3. Apply the entitlement with codesign:

codesign -s - --entitlements entitlements.plist -f debugserver

Attaching to a process

1. On the device, type:

./debugserver *:1234 -a "YouTube"

Example:

My-iPhone-5S:~ root# ./debugserver *:1234 -a "YouTube"
debugserver-300.2 for arm64.
Attaching to process YouTube...
Spawning general listening thread.
Spawning kqueue listening thread.
Listening to port 1234 for a connection from *...

2. On your Mac, launch lldb and type the following commands (but replace the IP with your device's IP):

platform select remote-ios
process connect connect://192.168.2.104:1234

Example:

mbkim:Debug_Server Kim$ lldb
(lldb) platform select remote-ios
  Platform: remote-ios
 Connected: no
  SDK Path: "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/7.0"
 SDK Roots: [ 0] "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.2"
[...]
 SDK Roots: [21] "/Users/Kim/Library/Developer/Xcode/iOS DeviceSupport/7.0.4 (11B554a)"
(lldb) process connect connect://192.168.2.104:1234
Process 2612 stopped
* thread #1: tid = 0x30d1e, 0x3ba51a84 libsystem_kernel.dylib`mach_msg_trap + 20, queue = 'com.apple.main-thread, stop reason = signal SIGSTOP
    frame #0: 0x3ba51a84 libsystem_kernel.dylib`mach_msg_trap + 20
libsystem_kernel.dylib`mach_msg_trap + 20:
-> 0x3ba51a84:  pop    {r4, r5, r6, r8}
   0x3ba51a88:  bx     lr

libsystem_kernel.dylib`mach_msg_overwrite_trap:
   0x3ba51a8c:  mov    r12, sp
   0x3ba51a90:  push   {r4, r5, r6, r8}
(lldb) po [[UIApplication sharedApplication] delegate]
<YTAppDelegate: 0x15e635a0>
(lldb) 

Debugging through USB instead of WiFi

If you find that debugging through WiFi is a little slow, or if you need to debug an app while WiFi is off, you can use usbmuxd to connect through USB. Mac users can also use iPhoneTunnel.

wget http://cgit.sukimashita.com/usbmuxd.git/snapshot/usbmuxd-1.0.8.tar.bz2
tar xjfv usbmuxd-1.0.8.tar.bz2
cd usbmuxd-1.0.8/python-client/
python tcprelay.py -t 1234:1234

Now all connections to localhost:1234 will be forwarded to your iPhone through USB to port 1234.

Connecting lldb:

(lldb) process connect connect://localhost:1234
Process 2612 stopped
* thread #1: tid = 0x30d1e, 0x3ba51a84 libsystem_kernel.dylib`mach_msg_trap + 20, queue = 'com.apple.main-thread, stop reason = signal SIGSTOP
    frame #0: 0x3ba51a84 libsystem_kernel.dylib`mach_msg_trap + 20
libsystem_kernel.dylib`mach_msg_trap + 20:
-> 0x3ba51a84:  pop    {r4, r5, r6, r8}
   0x3ba51a88:  bx     lr

libsystem_kernel.dylib`mach_msg_overwrite_trap:
   0x3ba51a8c:  mov    r12, sp
   0x3ba51a90:  push   {r4, r5, r6, r8}
(lldb) po [[UIApplication sharedApplication] delegate]
<YTAppDelegate: 0x15e635a0>

Example session

Note: these instructions probably only work on very old firmwares such as iOS 3. For iOS 7, follow the example above.

1. Copy MobileNotes to your Mac, e.g. to /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.sdk/Applications/MobileNotes.app/MobileNotes. 2. On the device, type:

~/debugserver -x spring host:6789 /Applications/MobileNotes.app/MobileNotes

This will launch MobileNotes and wait for the remote debugger.

3. Launch the debugger and attach it to the remote process: If using GDB:

  • On your Mac, launch /Developer/Platforms/iPhoneOS.platform/Developer/usr/libexec/gdb/gdb-arm-apple-darwin.
  • Type the following in gdb:
set shlib-path-substitutions / /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.sdk/
file /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.sdk/Applications/MobileNotes.app/MobileNotes
target remote-macosx 192.168.1.101:6789

Where 192.168.1.101 should be replaced by the actual IP address of your device. The remote debug connection is now complete.

If using LLDB:

  • On your Mac, launch lldb.
  • Type the following in lldb:
platform select remote-ios
process connect connect://192.168.1.101:6789

4. Enter c to continue and do whatever you want.

References