使用 lldb 通过 Xamarin 调试本机库

Use lldb to debug native libraries with Xamarin

Xamarin debugging documentation表示:

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.

但是我找不到任何关于如何使用 LLDB 调试 Xamarin 应用程序的文档。如果我 运行 我的应用程序在 iPhone 模拟器中并尝试使用 LLDB 附加到它,我会收到以下错误:

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

error: attach failed: lost connection

使用 Xcode 附加也不起作用。我尝试了 attach 的不同变体,但其中 none 有效。

有人可以为我指明如何使用 LLDB 调试 Xamarin 应用程序的正确方向吗?此外,这是我可以在设备上做的事情,而不仅仅是在模拟器中吗?我没有找到有关如何使用 LLDB 附加到设备上的进程的任何信息。

更新

似乎每当我使用 lldb 连接到我的二进制文件时,debugserver 进程就会崩溃。这是 debugserver 的崩溃报告 link: https://www.dropbox.com/s/9lizhl2quj9n0cc/debugserver_2015-07-07-131423_gauss.crash?dl=0

更新 2

当我在应用程序上 运行 dtruss 时,它会打印系统调用,直到遇到

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

调用 ptrace(PT_DENY_ATTACH, 0, 0, 0); 时会发生这种情况 为什么调用 PT_DENY_ATTACH

更新 3

我跟踪了 ptrace 系统调用到这个函数:mono_assembly_init_with_opt,它发生在程序生命周期的早期。该函数所做的只是调用 ptrace,因此如果我只是 return 从该函数的早期开始,我就可以使用 lldb 进行调试。

基本上我能做到:

(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

现在我可以愉快地使用 lldb 进行调试了。

但是,我不应该这样做。我的项目配置有问题吗(我可以使用 lldb 调试更简单的应用程序)或者 Xamarin 是邪恶的?

您是否尝试过使用来自 Activity 监视器的 pid?只需在 Activity Monitor when 运行 it in Debug.

的搜索框中输入您的应用程序名称

如果它仍然不起作用,您能否尝试创建一个新项目并附加到该项目以排除任何项目配置。

Mac OS X 上的协同设计应用程序只有在其应用程序列表中设置了特定属性时才能进行调试。你想要的东西看起来像:

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

您可以查看 taskgated 的手册页,了解有关此过程的简要说明。

通常对于 Xcode 项目,此属性由 Xcode 设置并插入到您的调试版本中,因此您无需执行任何操作即可实现此目的。

我不知道 Xamarin 是如何工作的,但有可能它没有设置这个属性。在旧的 OS X 系统上,root 可以调试任何东西,所以你可以尝试 sudo -s 然后从那里调试。但是从 Yosemite 开始,不被调试的请求得到了更广泛的尊重...

这恰好是 Xamarin 在试用版中施加的限制。升级到付费许可证后,这不再是问题。尽管 Xamarin 的网站说:

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

这显然不是完整的功能集,因为如果您使用本机库,它们会明确禁止将 lldb 附加到应用程序。我不确定这样做的原因,也许 Xamarin 的人可以对此发表评论。

说明

感谢 Jim Ingham 为我指明了正确的方向。 Xamarin 事件调试器附加到应用程序的方式是使用 PT_DENY_ATTACH 调用 ptrace。该系统调用使进程能够拒绝调试请求。 (Detailed Explanation)。

此外,Xamarin 没有直接调用 ptrace 函数,而是尝试使用 syscall 方法 (link) 隐藏调用。

解决方法

如果您确实需要调试您的应用并且仍在使用试用版,这里有一个解决方法。 ptrace 系统调用是在函数 mono_assembly_init_with_opt 中进行的,它发生在程序生命周期的早期。该函数不执行任何其他操作,可以跳过。由于该函数在进程开始时被调用,因此我们需要在调用该函数之前附加 lldb。

步骤如下:

  1. 启动 lldb 并等待应用启动。
  2. 应用程序启动时,为mono_assembly_init_with_opt添加断点
  3. 恢复应用程序,当它停在该功能时,return提早不执行该功能。
  4. 在此之后,您可以使用 lldb 或将 Xcode 附加到应用程序并像往常一样调试您的本机代码。

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