Symbolication sample (#2479)

This commit is contained in:
Nikolay Igotti
2018-12-20 13:47:15 +03:00
committed by GitHub
parent baaf6edba7
commit 0369a282c8
10 changed files with 186 additions and 8 deletions
+1
View File
@@ -42,6 +42,7 @@ if (MPPTools.isMacos() || MPPTools.isLinux()) {
if (MPPTools.isMacos()) {
include ':objc'
include ':opengl'
include ':symbolication'
include ':uikit'
}
+4
View File
@@ -0,0 +1,4 @@
# Backtrace symbolication tool
Produces more verbose backtrace symbolication with file name and line number.
Only works on debug .dSYM binaries on macOS at the moment.
+23
View File
@@ -0,0 +1,23 @@
plugins {
id 'kotlin-multiplatform'
}
// Determine host preset.
def hostPreset = MPPTools.defaultHostPreset(project)
kotlin {
targets {
fromPreset(hostPreset, 'symbolication') {
compilations.main.outputKinds 'EXECUTABLE'
compilations.main.entryPoint 'symbolication.main'
compilations.main.cinterops {
coreSymbolication {
}
}
}
}
}
MPPTools.createRunTask(project, 'runProgram', kotlin.targets.symbolication) {
//args "./test.kexe.dSYM/Contents/Resources/DWARF/test.kexe"
}
+2
View File
@@ -0,0 +1,2 @@
kotlin.code.style=official
kotlin.import.noCommonSourceSets=true
@@ -0,0 +1,68 @@
package = CoreSymbolication
linkerOpts.osx = -F /System/Library/PrivateFrameworks -framework CoreSymbolication
headerFilter = **
language=Objective-C
---
#include <CoreServices/CoreServices.h>
#include <mach/mach.h>
typedef struct {
unsigned long type;
void* contents;
} CSTypeRef;
typedef CSTypeRef CSSymbolicatorRef;
typedef CSTypeRef CSSymbolOwnerRef;
typedef CSTypeRef CSSymbolRef;
typedef CSTypeRef CSSourceInfoRef;
typedef struct {
unsigned long long location;
unsigned long long length;
} CSRange;
typedef unsigned long long CSArchitecture;
#define kCSNow LONG_MAX
cpu_type_t CSArchitectureGetCurrent();
CSSymbolicatorRef CSSymbolicatorCreateWithPid(pid_t pid);
CSSymbolicatorRef CSSymbolicatorCreateWithPathAndArchitecture(const char* path, cpu_type_t type);
CSArchitecture CSSymbolicatorGetArchitecture(CSSymbolicatorRef symbolicator);
CSSymbolOwnerRef CSSymbolicatorGetSymbolOwnerWithNameAtTime(
CSSymbolicatorRef symbolicator, const char* name, long time);
CSSymbolOwnerRef CSSymbolicatorGetSymbolOwnerWithAddressAtTime(
CSSymbolicatorRef symbolicator, unsigned long long address, long time);
CSSymbolOwnerRef CSSymbolicatorGetSymbolOwner(CSSymbolicatorRef cs);
CSSymbolRef CSSymbolicatorGetSymbolWithNameAtTime(
CSSymbolicatorRef symbolicator, const char* name, long time);
const char* CSSymbolOwnerGetName(CSSymbolOwnerRef owner);
unsigned long long CSSymbolOwnerGetBaseAddress(CSSymbolOwnerRef owner);
CSSourceInfoRef CSSymbolOwnerGetSourceInfoWithAddress(
CSSymbolOwnerRef owner, unsigned long long address);
const char* CSSymbolGetName(CSSymbolRef symbol);
CSRange CSSymbolGetRange(CSSymbolRef symbol);
const char* CSSourceInfoGetPath(CSSourceInfoRef info);
const char* CSSourceInfoGetFilename(CSSourceInfoRef info);
uint32_t CSSourceInfoGetLineNumber(CSSourceInfoRef info);
CSTypeRef CSRetain(CSTypeRef);
void CSRelease(CSTypeRef);
bool CSIsNull(CSTypeRef);
@@ -0,0 +1,58 @@
package symbolication
import platform.darwin.*
import kotlinx.cinterop.*
import CoreSymbolication.*
fun main(args: Array<String>) {
val program = if (args.size > 0 && args[0].isNotEmpty())
args[0] else throw Error("please specify .dSYM path as the first argument")
val arch = if (args.size > 1 && args[1].isNotEmpty()) args[1] else "current"
val input = generateSequence { readLine() }
analyzeTrace(program, arch, input)
}
fun archToCpuName(arch: String): cpu_type_t = when (arch) {
"x64", "x86_64" -> CPU_TYPE_X86_64
"arm32" -> CPU_TYPE_ARM
"arm64" -> CPU_TYPE_ARM64
"current" -> CSArchitectureGetCurrent()
else -> TODO("unsupported $arch")
}
fun analyzeTrace(program: String, arch: String, input: Sequence<String>) {
val symbolicator = CSSymbolicatorCreateWithPathAndArchitecture(program, archToCpuName(arch))
if (CSIsNull(symbolicator)) throw Error("Cannot create \"$arch\" symbolicator for $program")
val owner = CSSymbolicatorGetSymbolOwner(symbolicator)
// Format is like
// at 14 test.kexe 0x0000000106a2e071 Konan_run_start + 113
val matcher = "(at \\d+\\s+\\S+\\s+0x[0-9a-f]+\\s+)([^+]+)\\+\\s(\\d+)".toRegex()
for (line in input) {
val match = matcher.find(line)
var result = line
if (match != null) {
val atPart = match.groupValues[1]
val functionName = match.groupValues[2].trim()
val offsetInFunction = match.groupValues[3].toUInt()
val symbol = CSSymbolicatorGetSymbolWithNameAtTime(symbolicator, functionName, kCSNow)
if (!CSIsNull(symbol)) {
CSSymbolGetRange(symbol).useContents {
val address = this.location + offsetInFunction
val sourceInfo = CSSymbolOwnerGetSourceInfoWithAddress(owner, address)
if (!CSIsNull(sourceInfo)) {
val filePath = CSSourceInfoGetPath(sourceInfo)?.toKString()
// or val fileName = CSSourceInfoGetFilename(sourceInfo)?.toKString()
val lineNumber = CSSourceInfoGetLineNumber(sourceInfo)
val lineNumberString = if (lineNumber != 0u) lineNumber.toString() else "<unknown>"
if (filePath != null)
result = matcher.replaceFirst(line,
"$atPart$functionName $filePath:$lineNumberString")
}
}
}
}
println(result)
}
CSRelease(symbolicator)
}
+22
View File
@@ -0,0 +1,22 @@
fun f(p: Int) {
if (p == 0) throw Error()
f(p - 1)
}
fun g1(p: Int) {
if (p == 0) throw Error()
g2(p - 1)
}
fun g2(p: Int) {
g1(p - 1)
}
fun main() {
try {
f(10)
} catch (e: Throwable) {
e.printStackTrace()
}
g1(10)
}