13

The Xamarin debugging documentation indicates:

Use Xamarin Studio's native debugging support for debugging C# and other managed languages code and use LLDB when you need to debug C, C++ or Objective C codethat you might be linking with your Xamarin.iOS project.

However I cannot find any documentation on how to use LLDB to debug a Xamarin app. If I run my app in the iPhone Simulator and try to attach to it using LLDB I get the following error:

(lldb) attach --pid 37993
Process 37993 exited with status = -1 (0xffffffff) lost connection

error: attach failed: lost connection

Attaching using Xcode doesn't work either. I tried different variations of attach but none of them worked.

Can someone point me in the correct direction on how to debug Xamarin apps with LLDB? Moreover is this something I could do on the device and not just in the simulator? I didn't find any information on how to use LLDB to attach to a process on a device.

Update

It looks like the debugserver process is crashing whenever I use lldb to connect to my binary. Here is a link to the crash report for debugserver: https://www.dropbox.com/s/9lizhl2quj9n0cc/debugserver_2015-07-07-131423_gauss.crash?dl=0

Update 2

When I run dtruss on the app it prints the system calls till it encounters

dtrace: error on enabled probe ID 2475 (ID 194: syscall::ptrace:return): invalid user access in action #5 at DIF offset 0

which happens when something calls ptrace(PT_DENY_ATTACH, 0, 0, 0); Why is PT_DENY_ATTACH called?

Update 3

I traced the ptrace system call to this function: mono_assembly_init_with_opt which happens very early in the life of the program. All that function does is call ptrace, so if I just return early from that function, I can debug with lldb.

Basically, I can do:

(lldb) process attach --name AppName --waitfor
# when the process starts
(lldb) b mono_assembly_init_with_opt    
(lldb) c
# when the thread breaks
(lldb) thread return 0
(lldb) c

and now I can happily debug with lldb.

But, I shouldn't have to do this. Is there something wrong with my project config (I can debug simpler apps with lldb) or is Xamarin being evil?

Kostub Deshmukh
  • 2,852
  • 2
  • 25
  • 35
  • Attaching lldb to the pid should work, I do it all the time. Are you sure you're using the right pid? Where did you get it from? – Rolf Bjarne Kvinge Jul 03 '15 at 05:47
  • From Xcode. Debug -> Attach to process -> Likely Targets lists my app and its pid. ps auxwww | grep App gives me the same pid. Does the app need to be in a particular state? – Kostub Deshmukh Jul 03 '15 at 13:03
  • I'm almost 100% sure you're trying to debug the wrong pid. Can you show the full `ps auxwww | grep App` output whose pid you're trying to attach to? – Rolf Bjarne Kvinge Jul 13 '15 at 14:20
  • Eh? You should look at some of the other answers/comments and updates to the question before commenting. I'm 100% sure that I am debugging the right pid. – Kostub Deshmukh Jul 14 '15 at 09:24
  • `ps aux|grep App` will usually show multiple processes (if launched from the IDE), and in none of the other comments did you give any indication of this fact, nor how you chose between them. Could you add "-v -v -v -v" to the additional mtouch arguments in the project's iOS Build options and gist the build log? If there is private information in the build output, you can file a private bug (http://bugzilla.xamarin.com) and we can continue there. – Rolf Bjarne Kvinge Jul 14 '15 at 10:34
  • See the accepted answer. This is a limitation Xamarin imposes on the trial version. Note sure why, maybe you can tell me since you work there. – Kostub Deshmukh Jul 17 '15 at 11:22

3 Answers3

2

Codesigned apps on Mac OS X can only be debugged if they have a particular attribute set in their app plist. You want something that looks like:

<key>SecTaskAccess</key>
<array>
    <string>allowed</string>
    <string>debug</string>
</array>

You can look at the man page for taskgated for a somewhat terse description of this process.

Usually for Xcode projects, this attribute gets consed up and inserted into your debug builds by Xcode, so you don't need to do anything to get this to happen.

I don't know how Xamarin works, but it is possible that it is not setting this attribute. On older OS X systems, root can debug anything, so you could try sudo -s and then debugging from there. But starting with Yosemite, the request not to be debugged is being more broadly honored...

Jim Ingham
  • 25,260
  • 2
  • 55
  • 63
  • Thanks. That's interesting, however it didn't work. I get the same lost connection error after modifying the Info.plist file. Debugging as root has the same error as well. – Kostub Deshmukh Jul 07 '15 at 05:43
  • 1
    Very odd. lldb uses a debug agent (called debugserver) that actually manages the program being debugged. Try running a failing debug session, then look in the system log in Console.app and search for debugserver. You should see some log output from debugserver, and oftentimes if there are any security issues from the other daemons (usually taskgated) which are responsible for enforcing these policies, there will be some log from them around the same time. There might be something there that gives a clue to what is going wrong. – Jim Ingham Jul 07 '15 at 18:18
  • debugserver crashes whenever I connect to the process. Link to crash report: https://www.dropbox.com/s/9lizhl2quj9n0cc/debugserver_2015-07-07-131423_gauss.crash?dl=0 – Kostub Deshmukh Jul 07 '15 at 20:21
  • 1
    That crash is because the application you are trying to debug has requested that it not be debugged by calling the ptrace function with the "PT_DENY_ATTACH" control. When debugserver (or any debug agent) tries to attach to a process that has marked itself that way, the attach call (the __ptrace in your crash log) will crash exactly as in your sample - harsh way of enforcing this, but it has the virtue of being hard to work around. Someone - presumably the Xamarin folks - is trying pretty hard to keep you from debugging the app... Have you tried asking them how you are supposed to do this? – Jim Ingham Jul 08 '15 at 22:48
  • Wow. Ok, what's interesting is that the Xamarin documentation says I should be using lldb. Secondly, I tried creating another simple project in Xamarin and I can attach to it using lldb. So there is something wrong with this one. Is there a way for me to undo the ptrace call? Maybe call something in my code? – Kostub Deshmukh Jul 09 '15 at 00:43
  • Try setting a breakpoint on ptrace (which shouldn't be called very much in the app, and then run the app under lldb. The first argument (in lldb you can see this using "reg read $arg1") will be the "request" and PT_DENY_ATTACH is 31, so you can check that my analysis is correct when you stop. Then looking up the stack at the callers may give you some clue as to who is doing this... – Jim Ingham Jul 09 '15 at 17:57
  • The app doesn't seem to break at ptrace. I get this using lldb. The app exits with status 45 shortly after. (lldb) b ptrace Breakpoint 1: where = libsystem_kernel.dylib`__ptrace, address = 0x08c456e4 (lldb) c Process 11155 resuming Process 11155 exited with status = 45 (0x0000002d) – Kostub Deshmukh Jul 10 '15 at 10:16
  • I can see that ptrace was called, when I run dtruss, it prints system calls till it encounters: dtrace: error on enabled probe ID 2475 (ID 194: syscall::ptrace:return): invalid user access in action #5 at DIF offset 0 – Kostub Deshmukh Jul 10 '15 at 10:26
  • What's a good way to find out what is calling ptrace on my app? – Kostub Deshmukh Jul 13 '15 at 05:20
  • 1
    It looks like dtruss has a "-s" option that will print a backtrace when a probe fires. That might tell you something. – Jim Ingham Jul 13 '15 at 20:00
  • Thanks. I didn't get the ptrace backtrace, but was able to put a breakpoint on the backtrace of the previous system call and keep stepping forward till I found the ptrace. The system call was made using "int 0x80", which is why breaking on ptrace in lldb didn't work. And I verified that the argument passed in is 31. Your help has been invaluable. – Kostub Deshmukh Jul 14 '15 at 09:29
1

Have you tried using the pid from the Activity Monitor? Just type your app name into the search box in Activity Monitor when running it in Debug.

If it still doesnt work can you try just creating a new project and attaching to that just to rule out any project config.

Iain Smith
  • 9,230
  • 4
  • 50
  • 61
  • The pid in Activity Monitor is the same as the one I get using ps. However, I did try creating a new empty project and I can attach to that app using lldb. So what could be wrong with my project config? – Kostub Deshmukh Jul 06 '15 at 09:02
1

This happens to be a limitation imposed by Xamarin in the trial version. After upgrading to a paid license, this is no longer an issue. Even though Xamarin's website says:

When you begin a Xamarin Trial, you get access to the full Xamarin Business feature set for 30 days.

It's clearly not the full feature set since they explicitly disable attaching lldb to the app if you are using a native library. I'm not sure the reason for doing so, maybe someone from Xamarin can comment on it.

Explanation

Thanks to Jim Ingham for pointing me in the right direction. The way Xamarin events debuggers from attaching to the app is by calling ptrace with PT_DENY_ATTACH. This system call enables the process to deny requests for debugging. (Detailed Explanation).

Moreover rather than calling the ptrace function directly, Xamarin tries to hide the call by using the syscall method (link).

Workaround

If you really need to debug your app and are still using the trial version, here is a workaround. The ptrace system call is made in the function mono_assembly_init_with_opt which happens very early in the life of the program. That function doesn't do anything else and can be skipped. Since the function is called right in the beginning of the process, we need to attach lldb before the function is called.

The steps are as follows:

  1. Start lldb and wait for the app to start.
  2. When the app starts, add a break point for mono_assembly_init_with_opt
  3. Resume the app and when it stops at that function, return early without executing that function.
  4. After this you can use lldb or attach Xcode to the app and debug your native code as usual.

Steps in lldb:

(lldb) process attach --name AppName --waitfor
(lldb) b mono_assembly_init_with_opt    
(lldb) c
# when the thread breaks
(lldb) thread return 0
(lldb) c
Kostub Deshmukh
  • 2,852
  • 2
  • 25
  • 35