OS X内核紧急诊断.如何转换回溯地址 [英] OS X kernel panic diagnostics. How to translate backtrace addresses

查看:123
本文介绍了OS X内核紧急诊断.如何转换回溯地址的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在调试导致Mac内核转储的驱动程序.它显示了由一系列地址组成的长回溯:

I'm debugging a driver that cause kernel dump on my mac. It shows long backtrace composed out of series of addresses:

panic(cpu 6 caller 0xffffff8004dc9986): trying to interlock destroyed mutex  
(0xffffff8049deedb0)
Backtrace (CPU 6), Frame : Return Address
0xffffff93b1c8bb50 : 0xffffff8004ce5307 
0xffffff93b1c8bbd0 : 0xffffff8004dc9986 
0xffffff93b1c8bbe0 : 0xffffff8004d099eb 
0xffffff93b1c8bc20 : 0xffffff7f85604899 
0xffffff93b1c8bc50 : 0xffffff800519776b 
0xffffff93b1c8bc90 : 0xffffff80051f336c 
0xffffff93b1c8be00 : 0xffffff8005205fb3 
0xffffff93b1c8bef0 : 0xffffff80052028a6 
0xffffff93b1c8bf60 : 0xffffff800522afd1 
0xffffff93b1c8bfb0 : 0xffffff8004df4b16 

我假设由于计算机进行了重新引导,因此地址转换现在已无用,因为每次引导迭代后内存映射可能会有所不同.

I assume that since the computer underwent a reboot, the addresses translation is useless now since the memory mapping may be different after each booting iteration.

是否可以选择使相关方法与每个地址相匹配,或者可以预先设置适当的配置? 谢谢

Is there any option to match the relevant method to each address in retrospect, or set an appropriate configuration in advance ? thanks

推荐答案

是的,您可以肯定地用符号表示内核恐慌跟踪,但是要追溯地执行此操作,您不仅需要原始堆栈跟踪,还需要恐慌日志中的更多信息.如您所说,这些地址仅相对于加载地址有意义.

Yes, you can definitely symbolicate kernel panic traces, but to do it retroactively, you need more information from the panic log than just the raw stack trace. As you say, the addresses only make sense relative to the load addresses.

有关此主题的苹果官方文档 TN2063 是有点过时了.它给出的示例来自Darwin 9,即OS X 10.5,此后发生了一些变化,引入了内核ASLR和kext UUID.我会尽力为您提供最新的指南.

Apple's official documentation on the topic, TN2063 is a little outdated. The example it gives is from Darwin 9, i.e. OS X 10.5, and things have changed a bit since then, with the introduction of Kernel ASLR and kext UUIDs. I'll try to give you a very quick up to date guide.

1.简便方法

如果您的恐慌是可重现的,那么最简单的方法就是让内核为您代入它的象征.使用内核引导参数keepsyms=1意味着内核不会丢弃存储在内核和kext映像中的任何符号,并且在出现紧急情况时将在堆栈跟踪中查找返回指针.

If your panic is reproducible, the easiest thing to do is to get the kernel to symbolicate it for you. Using the kernel boot argument keepsyms=1 means the kernel won't discard whatever symbols are stored in the kernel and kext images, and will look up the return pointers in the stack trace in case of a panic.

只需将keepsyms=1添加到/Library/Preferences/SystemConfiguration/com.apple.Boot.plist中的内核标志"设置中,或添加到boot-args NVRAM变量中即可.重新启动,任何随后的紧急情况将被自动表示.您可以通过c++filt命令行实用工具运行损坏的C ++符号,以获得正确的C ++函数签名.例如,

Just add keepsyms=1 to either the Kernel Flags setting in /Library/Preferences/SystemConfiguration/com.apple.Boot.plist, or to the boot-args NVRAM variable. Reboot, and any subsequent panics will be automatically symbolicated. You can run mangled C++ symbols through the c++filt command line utility to get the proper C++ function signatures. For example,

$ echo __ZN32IOPCIMessagedInterruptController17registerInterruptEP9IOServiceiPvPFvS2_S2_S2_iES2_ | c++filt
IOPCIMessagedInterruptController::registerInterrupt(IOService*, int, void*, void (*)(void*, void*, void*, int), void*)

2.手动方式

如果您有一种无法表达的神秘恐慌,您似乎无法重现,那么简单的方法就无济于事.

If you've got an unsymbolicated, mysterious panic you can't seem to reproduce, the easy way isn't much help.

立即在堆栈跟踪中,在紧急日志中查找以"backtrace中的内核扩展:"开头的部分.这将列出紧急情况中涉及的所有kext,包括其加载地址,版本和UUID.地址是一个范围;起始地址在->的左侧,并在@之后.最后一个地址在箭头的右边.有了这些信息,您应该能够识别堆栈跟踪中列出的每个代码地址(右侧的十六进制数字)所在的kext.

Immediately following the stack trace, look for a section starting with "Kernel Extensions in backtrace:" in the panic log. This will list any kexts involved in the panic, including their load addresses, versions and UUIDs. The addresses are given as a range; the start address is to the left of the -> and following the @. The last address is to the right of the arrow. With this information you should be able to identify the kext in which each code address (the hex number on the right) listed in the stack trace is located.

除了其中一些不会匹配任何kext.除非在某些特殊情况下,否则它们将来自内核本身.内核映像(内核或mach_kernel)的加载地址进一步向下,显示为内核文本库:"

Except some of them won't match any kext. Except in some odd circumstances, these will be from the kernel itself. The kernel image (kernel or mach_kernel) load address is further down, where it says "Kernel text base:"

一旦您知道要查看哪个可执行映像,即可使用atos命令将每个地址符号化.

Once you know which executable image to look in, the atos command will let you symbolicate each address.

例如,假设我们对此行感到恐慌:

For example, let's say we have this line in a panic:

…
0xffffff8098c1bba0 : 0xffffff7f80c343f2
…

我们还发现:

  Kernel Extensions in backtrace:
     com.apple.iokit.IOPCIFamily(2.9)[BDA92C3B-AD86-33E5-A7F1-1603465350A7]@0xffffff7f80c1a000->0xffffff7f80c4dfff

请注意,0xffffff7f80c343f2大于(或等于)0xffffff7f80c1a000且小于(或等于)0xffffff7f80c4dfff,因此相关代码在IOPCIFamily中.

Notice that 0xffffff7f80c343f2 is greater than (or equal to) 0xffffff7f80c1a000 and less than (or equal to) 0xffffff7f80c4dfff, so the code in question is in IOPCIFamily.

这导致我进入以下命令(及其输出):

This leads me to the following command (and its output):

$ atos -o /Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Extensions/IOPCIFamily.kext/IOPCIFamily -l 0xffffff7f80c1a000 0xffffff7f80c343f2
IOPCIMessagedInterruptController::registerInterrupt(IOService*, int, void*, void (*)(void*, void*, void*, int), void*) (in IOPCIFamily) (IOPCIMessagedInterruptController.cpp:85)

-o指定可执行文件.这通常位于.kext包的Contents/MacOS/子目录中,但是某些Apple的kexts将其直接放在.kext目录中.对于内核本身中的功能,请提供内核映像,例如/Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Kernels/kernel.

-o specifies the executable file. This is generally in the Contents/MacOS/ subdirectory of the .kext package, but some of Apple's kexts have it directly inside the .kext directory. For functions in the kernel itself, provide the kernel image, e.g. /Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Kernels/kernel.

-l参数指定加载地址. IE.开始/文字库.

The -l argument specifies the load address. I.e. start/text base.

最后,只列出要在该文件中符号化的所有地址.在这种情况下,只有一个,但是您可以列出多个.您也可以从stdin读取它们(如果命令行上未列出).

Finally, just list all the addresses you want to symbolicate in that file. In this case, just one, but you can list multiple. You can also read them from stdin (if none are listed on the command line).

有了它,您应该能够解码整个跟踪.

With this, you should be able to decode your whole trace.

关于UUID的说明

您会注意到,跟踪中的每个kext以及内核本身都列出了一个UUID.这对于确保您使用正确的版本进行符号表示非常方便.这是Mach-O二进制文件中LC_UUID加载程序命令中的UUID.您可以使用以下命令检查kext的UUID:

You'll notice that each kext in the trace, and the kernel itself, have a UUID listed. This is handy for making sure you're using the right version for symbolicating. This is the UUID from the LC_UUID loader command in the Mach-O binary file. You can check the UUID for a kext using:

$ otool -l /Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Extensions/IOPCIFamily.kext/IOPCIFamily | grep uuid
    uuid BDA92C3B-AD86-33E5-A7F1-1603465350A7

要确认用于符号化的kext确实与紧急情况中的kext匹配.当您遇到奇怪的版本控制问题,或者遇到kext缓存问题时,这非常有用.

To confirm that the kext being used for symbolication does indeed match the one in the panic. This is great when you're ending up with weird versioning issues, or if you're having trouble with the kext cache.

这篇关于OS X内核紧急诊断.如何转换回溯地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆