XuqmGroup-Symbolicator/src/parsers/dsym.ts
徐勤民 8fc4c95138 feat: 初始化符号化服务
支持平台:
- RN/Electron/Vue3 (JS Sourcemap)
- Android (ProGuard mapping)
- iOS (dSYM)
- Flutter (Debug Symbols)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-19 02:49:26 +08:00

86 行
2.2 KiB
TypeScript

/**
* iOS dSYM 符号化解析器
*
* 使用 atos 命令进行符号化:
* atos -o MyApp.app.dSYM/Contents/Resources/DWARF/MyApp -arch arm64 -l 0x102345000 0x102345678
*/
import { execSync } from 'child_process'
import { StackFrame } from './stack-parser'
export interface DsymConfig {
/** dSYM 文件路径 */
dsymPath: string
/** 应用加载地址 */
loadAddress: string
/** 架构 (arm64, x86_64) */
arch?: string
}
/**
* 使用 atos 命令符号化 iOS 堆栈
*/
export function symbolicateWithDsym(
frames: StackFrame[],
config: DsymConfig
): string[] {
const { dsymPath, loadAddress, arch = 'arm64' } = config
// 提取需要符号化的地址
const addresses = frames
.filter(f => f.file === '<binary>')
.map(f => `0x${f.column.toString(16)}`)
if (addresses.length === 0) {
return frames.map(f => `${f.function} (${f.file}:${f.line})`)
}
try {
// 调用 atos 命令
const cmd = `atos -o "${dsymPath}" -arch ${arch} -l ${loadAddress} ${addresses.join(' ')}`
const output = execSync(cmd, { encoding: 'utf-8', timeout: 30000 })
const symbolicated = output.trim().split('\n')
let addrIndex = 0
return frames.map(f => {
if (f.file === '<binary>' && addrIndex < symbolicated.length) {
return symbolicated[addrIndex++]
}
return `${f.function} (${f.file}:${f.line})`
})
} catch (err) {
console.error('atos symbolication failed:', err)
return frames.map(f => `${f.function} (${f.file}:${f.line})`)
}
}
/**
* 解析 iOS 崩溃日志中的线程帧
*
* 格式示例:
* 0 MyApp 0x0000000102345678 myFunction + 123
* 1 MyApp 0x0000000102345678 myFunction + 123
*/
export function parseIOSCrashFrames(crashLog: string): StackFrame[] {
const frames: StackFrame[] = []
const lines = crashLog.split('\n')
for (const line of lines) {
const match = line.trim().match(
/(\d+)\s+(\S+)\s+(0x[\da-f]+)\s+(\S+)\s+\+\s+(\d+)/
)
if (match) {
frames.push({
function: match[4],
file: match[2],
line: 0,
column: parseInt(match[5], 10),
})
}
}
return frames
}