iOS - 符号化堆栈跟踪符号
Posted
技术标签:
【中文标题】iOS - 符号化堆栈跟踪符号【英文标题】:iOS - Symbolicate Stack trace symbols 【发布时间】:2015-06-16 02:59:45 【问题描述】:我想对使用 [NSThread callStackSymbols] 记录的堆栈跟踪符号进行符号化,以识别完整的堆栈回溯调用。但是,这并没有给出象征性的痕迹。
0 TestApp 0x0029616f TestApp + 1823087
1 TestApp 0x003ef18d TestApp + 3236237
2 UIKit 0x2ab7bb1f <redacted> + 438
3 UIKit 0x2ac0bea3 <redacted> + 306
4 UIKit 0x2ab7bb1f <redacted> + 438
5 CoreFoundation 0x2757546d <redacted> + 48
6 CoreFoundation 0x2756e4c3 <redacted> + 234
7 UIKit 0x2ab7bc9b <redacted> + 818
8 UIKit 0x2ae32799 <redacted> + 584
9 UIKit 0x2abdfbd9 <redacted> + 308
10 UIKit 0x2ab5bdd7 <redacted> + 458
11 CoreFoundation 0x2760fffd <redacted> + 20
12 CoreFoundation 0x2760d6bb <redacted> + 278
13 CoreFoundation 0x2760dac3 <redacted> + 914
14 CoreFoundation 0x2755b3b1 CFRunLoopRunSpecific + 476
15 CoreFoundation 0x2755b1c3 CFRunLoopRunInMode + 106
16 GraphicsServices 0x2eb88201 GSEventRunModal + 136
17 UIKit 0x2abc543d UIApplicationMain + 1440
18 TestApp 0x0031581b TestApp + 2344987
19 libdyld.dylib 0x35a6baaf <redacted> + 2
我在开发和企业构建中都试过这个。都没有解决。反正有什么象征意义吗?我搜索了很多论坛,所有论坛都要求使用下面的 atos 命令执行此操作
atos -arch armv7 -o 'app name.app'/'app name' 0x000000000
但是,我不确定上述命令必须使用的内存地址是什么以及如何获取它。
任何帮助将不胜感激,谢谢。
【问题讨论】:
这个答案可能会对您有所帮助:***.com/a/26461123/4557505 【参考方案1】:你在这里跳过了一些片段。 atos 中的内存地址应该引用加载地址和堆栈地址,并且您还需要 dSYM 文件。
实际上有一篇关于 apteligent 的非常好的文章,名为 Symbolicating an ios Crash Report,关于手动执行此操作。我建议彻底阅读它以了解符号的工作原理。
【讨论】:
链接好像坏了【参考方案2】:这是一个如何在运行时获取二进制图像信息的示例。
以下代码的输出如下所示:
YourApp 0x00000001adb1e000 - arm64e - E9B05479-3D07-390C-BD36-73EEDB2B1F75
CoreGraphics 0x00000001a92dd000 - arm64e - 2F7F6EE8-635C-332A-BAC3-EFDA4894C7E2
CoreImage 0x00000001afc00000 - arm64e - CF56BCB1-9EE3-392D-8922-C8894C9F94C7
然后,您将要符号化其帧的二进制图像的内存地址用作您提到的atos
命令中的参数。
代码:
import Foundation
import MachO
public struct BinaryImagesInspector
#if arch(x86_64) || arch(arm64)
typealias MachHeader = mach_header_64
#else
typealias MachHeader = mach_header
#endif
/// Provides binary infos that are then used with the atos command to symbolicate stack traces
/// - Parameter imageNamesToLog: an optional array of binary image names to restrict the infos to
/// - Returns: An array of strings containing info on loaded binary name, its load address, architecture
/// - Note: Example:
///
/// atos -arch arm64 -o [YOUR-DSYM-ID].dSYM/Contents/Resources/DWARF/[YOUR APP] -l 0x0000000000000000 0x0000000000000000
public static func getBinaryImagesInfo(imageNamesToLog: [String]? = nil) -> [String]
let count = _dyld_image_count()
var stringsToLog = [String]()
for i in 0..<count
guard let dyld = _dyld_get_image_name(i) else continue
let dyldStr = String(cString: dyld)
let subStrings = dyldStr.split(separator: "/")
guard let imageName = subStrings.last else continue
if let imageNamesToLog = imageNamesToLog
guard imageNamesToLog.contains(String(imageName)) else continue
guard let uncastHeader = _dyld_get_image_header(i) else continue
let machHeader = uncastHeader.withMemoryRebound(to: MachHeader.self, capacity: MemoryLayout<MachHeader>.size) $0
guard let info = NXGetArchInfoFromCpuType(machHeader.pointee.cputype, machHeader.pointee.cpusubtype) else continue
guard let archName = info.pointee.name else continue
let uuid = getBinaryImageUUID(machHeader: machHeader)
let logStr = "\(imageName) \(machHeader.debugDescription) - \(String(cString: archName)) - \(uuid ?? "uuid not found")"
stringsToLog.append(logStr)
return stringsToLog
private static func getBinaryImageUUID(machHeader: UnsafePointer<MachHeader>) -> String?
guard var header_ptr = UnsafePointer<UInt8>.init(bitPattern: UInt(bitPattern: machHeader)) else
return nil
header_ptr += MemoryLayout<MachHeader>.size
guard var command = UnsafePointer<load_command>.init(bitPattern: UInt(bitPattern: header_ptr)) else
return nil
for _ in 0..<machHeader.pointee.ncmds
if command.pointee.cmd == LC_UUID
guard let ucmd_ptr = UnsafePointer<uuid_command>.init(bitPattern: UInt(bitPattern: header_ptr)) else continue
let ucmd = ucmd_ptr.pointee
let cuuidBytes = CFUUIDBytes(byte0: ucmd.uuid.0,
byte1: ucmd.uuid.1,
byte2: ucmd.uuid.2,
byte3: ucmd.uuid.3,
byte4: ucmd.uuid.4,
byte5: ucmd.uuid.5,
byte6: ucmd.uuid.6,
byte7: ucmd.uuid.7,
byte8: ucmd.uuid.8,
byte9: ucmd.uuid.9,
byte10: ucmd.uuid.10,
byte11: ucmd.uuid.11,
byte12: ucmd.uuid.12,
byte13: ucmd.uuid.13,
byte14: ucmd.uuid.14,
byte15: ucmd.uuid.15)
guard let cuuid = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, cuuidBytes) else
return nil
let suuid = CFUUIDCreateString(kCFAllocatorDefault, cuuid)
let encoding = CFStringGetFastestEncoding(suuid)
guard let cstr = CFStringGetCStringPtr(suuid, encoding) else
return nil
let str = String(cString: cstr)
return str
header_ptr += Int(command.pointee.cmdsize)
guard let newCommand = UnsafePointer<load_command>.init(bitPattern: UInt(bitPattern: header_ptr)) else continue
command = newCommand
return nil
进一步阅读:
How to determine binary image architecture at runtime? https://github.com/apple/swift/blob/master/stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift https://lowlevelbits.org/parsing-mach-o-files/ https://developer.apple.com/library/archive/technotes/tn2151/_index.html也可以在GitHub 上以 swift 包的形式提供。
【讨论】:
以上是关于iOS - 符号化堆栈跟踪符号的主要内容,如果未能解决你的问题,请参考以下文章
Unity 之 安卓堆栈跟踪和日志工具 (Android Logcat | 符号表解析Bugly捕获)