使用lldb调试Xamarin的本地库

13

Xamarin调试文档指出:

使用Xamarin Studio的本地调试支持来调试C#和其他托管语言的代码,当您需要调试C,C ++或Objective C代码时(这些可能与您的Xamarin.iOS项目链接),请使用LLDB。

然而,我找不到任何关于如何使用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:启用探测ID 2475(ID 194:syscall :: ptrace:return)时出错:在DIF偏移量0处的动作#5中访问无效用户

这是在某些调用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有问题?


将lldb附加到pid应该可以正常工作,我经常这样做。您确定正在使用正确的pid吗?您从哪里获取它的? - Rolf Bjarne Kvinge
从Xcode中,调试 -> 附加到进程 -> 可能的目标列表中列出了我的应用程序及其pid。ps auxwww | grep App给出了相同的pid。应用程序需要处于特定状态吗? - Kostub Deshmukh
我几乎可以确定你正在尝试调试错误的pid。你能展示一下完整的 ps auxwww | grep App 输出以便确认你要附加的pid吗? - Rolf Bjarne Kvinge
嗯?在评论之前,您应该查看一些其他答案/评论和问题的更新。我百分之百确定我正在调试正确的pid。 - Kostub Deshmukh
ps aux|grep App 通常会显示多个进程(如果从 IDE 启动),而在其他评论中,您没有给出任何关于此事实的指示,也没有说明您是如何在它们之间进行选择的。您能否在项目的 iOS 构建选项中添加 "-v -v -v -v" 到额外的 mtouch 参数,并提供构建日志?如果构建输出中有私人信息,则可以提交私人错误报告(http://bugzilla.xamarin.com),我们可以在那里继续讨论。 - Rolf Bjarne Kvinge
请查看被接受的答案。这是Xamarin在试用版本上强制执行的限制。不确定为什么,也许你可以告诉我,因为你在那里工作。 - Kostub Deshmukh
3个回答

2

在Mac OS X上,如果codesigned应用程序没有在其应用程序plist中设置特定属性,则无法进行调试。您需要类似以下内容的东西:

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

您可以查看taskgated的手册,以获取该进程的简短描述。
通常,在Xcode项目中,此属性由Xcode组合并插入您的调试版本中,因此您无需执行任何操作即可实现此操作。
我不知道Xamarin是如何工作的,但可能它没有设置此属性。在旧的OS X系统上,root用户可以调试任何内容,因此您可以尝试使用sudo -s从那里开始调试。但从Yosemite开始,更广泛地遵循了不允许被调试的请求...

1
非常奇怪。lldb使用一个调试代理(称为debugserver),实际上管理被调试的程序。尝试运行失败的调试会话,然后在Console.app中查看系统日志并搜索debugserver。您应该会看到来自debugserver的一些日志输出,通常如果有任何安全问题来自其他守护进程(通常是taskgated)负责执行这些策略,那么它们将在同一时间左右记录一些日志。可能会有一些提示出现,可以解释出现问题的原因。 - Jim Ingham
1
这个崩溃是因为你正在尝试调试的应用程序已经通过调用ptrace函数并使用“PT_DENY_ATTACH”控件请求不被调试。当debugserver(或任何调试代理)试图附加到标记了此方式的进程时,附加调用(在您的崩溃日志中的__ptrace)将像您的示例一样崩溃 - 这是一种强制执行方法,但它具有难以绕过的优点。显然有人 - 可能是Xamarin的人们 - 正在竭尽全力阻止您调试该应用程序...您尝试过问他们应该如何做吗? - Jim Ingham
哇。好的,有趣的是Xamarin文档说我应该使用lldb。其次,我尝试在Xamarin中创建另一个简单的项目,并且我可以使用lldb附加到它上面。所以这个项目有些问题。有没有办法撤销ptrace调用?也许在我的代码中调用一些东西? - Kostub Deshmukh
应用程序似乎在ptrace处没有崩溃。我使用lldb得到了这个结果。应用程序在短时间内以状态45退出。(lldb) b ptrace 断点1:位置=libsystem_kernel.dylib`__ptrace,地址=0x08c456e4 (lldb) c 进程11155正在恢复 进程11155以状态=45 (0x0000002d)退出 - Kostub Deshmukh
1
看起来dtruss有一个“-s”选项,当探针触发时会打印回溯。这可能会告诉你一些信息。 - Jim Ingham
显示剩余6条评论

1

你是否尝试过使用“活动监视器”中的pid?只需在Debug模式下将您的应用程序名称键入“活动监视器”的搜索框即可。

如果仍无法解决问题,您可以尝试创建一个新项目并附加到该项目,以排除任何项目配置问题。


在“活动监视器”中的pid与我使用ps获取的pid相同。但是,我尝试创建一个新的空项目,并且可以使用lldb附加到该应用程序。那么我的项目配置有什么问题呢? - Kostub Deshmukh

1
这实际上是Xamarin试用版所强制施加的限制。升级到付费许可证后,这将不再是问题。尽管Xamarin的网站上说:
“当您开始使用Xamarin试用版时,您可以在30天内获得完整的Xamarin Business功能集。”
但很显然这不是完整的功能集,因为如果您使用本地库,他们明确禁用了将lldb连接到应用程序。我不确定这样做的原因,也许Xamarin的某个人可以发表评论。 说明 感谢Jim Ingham指导我正确方向。Xamarin事件调试器阻止连接到应用程序的方法是通过使用PT_DENY_ATTACH调用ptrace。这个系统调用使进程拒绝调试请求。(详细说明)。
此外,Xamarin 试图通过使用 syscall 方法(link)来隐藏调用,而不是直接调用 ptrace 函数。
解决方法:
如果您确实需要调试应用程序并仍在使用试用版,则可以使用以下解决方法。 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接