3

我想符号化使用 [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

但是,我不确定上述命令必须使用的内存地址是什么以及如何获取它。

任何帮助将不胜感激,谢谢。

4

2 回答 2

1

你在这里跳过了一些片段。atos 中的内存地址应该引用加载地址和堆栈地址,并且您还需要 dSYM 文件。

实际上,关于 apteligent 有一篇非常好的文章,名为Symbolicating an iOS Crash Report,关于手动执行此操作。我建议彻底阅读它以了解符号化的工作原理。

于 2016-04-08T15:16:52.347 回答
0

这是一个如何在运行时获取二进制图像信息的示例。

下面代码的输出如下所示:

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
    }
}

进一步阅读:

也可作为GitHub 上的 swift 包使用。

于 2021-08-17T19:07:57.513 回答