使用lldb使用Xamarin调试本机库



Xamarin调试文档表明:

使用Xamarin Studio的本机调试支持来调试C#和其他托管语言编码,并在需要调试C时使用LLDB,您可能正在与Xamarin.iOS链接的C++或Objective C代码项目

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

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

使用Xcode附加也不起作用。我尝试了attach的不同变体,但都不起作用。

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

更新

每当我使用lldb连接到二进制文件时,debugserver进程似乎都会崩溃。以下是debugserver故障报告的链接: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,所以如果我只是从该函数中提前返回,我就可以使用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是邪恶的?

Mac OS X上的代码签名应用程序只有在其应用程序plist中设置了特定属性时才能进行调试。你想要的东西看起来像:

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

您可以查看taskgated的手册页,以获得对该过程的简要描述。

通常,对于Xcode项目,这个属性会被保存起来,并由Xcode插入到调试构建中,所以您不需要做任何事情来实现这一点。

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

您是否尝试过使用活动监视器中的pid?在"调试"中运行应用程序时,只需在"活动监视器"的搜索框中键入应用程序名称即可。

如果它仍然不起作用,你可以试着创建一个新项目并附加到它上,以排除任何项目配置。

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

当你开始Xamarin试用时,你可以获得完整的Xamarin30天的商务功能集。

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

解释

感谢吉姆·英格姆为我指明了正确的方向。Xamarin事件调试器连接到应用程序的方法是使用PT_DENY_ATTACH调用ptrace。此系统调用使进程能够拒绝调试请求。(详细说明(。

此外,Xamarin没有直接调用ptrace函数,而是试图通过使用syscall方法(链接(来隐藏调用。

解决方案

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

步骤如下:

  1. 启动lldb并等待应用程序启动
  2. 当应用程序启动时,为mono_assembly_init_with_opt添加一个断点
  3. 恢复应用程序,当它停止该功能时,提前返回而不执行该功能
  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

最新更新