[K/N] Add opt-in flag to use debug info from native libs

Unfortunately, llvm removes full debug info from module on any error.
Different version debug info in bitcode is not always compatible, also
it adds this debug info additional requirements on generated debug info.

So this feature is quite unstable and shouldn't be enabled by default,
although it has almost no downsides when worked correctly.
This commit is contained in:
Pavel Kunyavskiy
2021-08-25 16:56:08 +03:00
committed by Space
parent 18f1610442
commit 98e4d67900
9 changed files with 58 additions and 1 deletions
@@ -17,6 +17,8 @@ object BinaryOptions : BinaryOptionRegistry() {
val memoryModel by option<MemoryModel>()
val freezing by option<Freezing>()
val stripDebugInfoFromNativeLibs by booleanOption()
}
open class BinaryOption<T : Any>(
@@ -56,6 +56,7 @@ class CacheSupport(
configuration.getBoolean(KonanConfigKeys.OPTIMIZATION) -> "for optimized compilation"
configuration.get(BinaryOptions.memoryModel) == MemoryModel.EXPERIMENTAL -> "with experimental memory model"
configuration.getBoolean(KonanConfigKeys.PROPERTY_LAZY_INITIALIZATION) -> "with experimental lazy top levels initialization"
configuration.get(BinaryOptions.stripDebugInfoFromNativeLibs) == false -> "with native libs debug info"
else -> null
}
@@ -185,6 +185,9 @@ internal fun produceOutput(context: Context) {
private fun parseAndLinkBitcodeFile(context: Context, llvmModule: LLVMModuleRef, path: String) {
val parsedModule = parseBitcodeFile(path)
if (!context.shouldUseDebugInfoFromNativeLibs()) {
LLVMStripModuleDebugInfo(parsedModule)
}
val failed = llvmLinkModules2(context, llvmModule, parsedModule)
if (failed != 0) {
throw Error("failed to link $path") // TODO: retrieve error message from LLVM.
@@ -443,6 +443,8 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
fun shouldContainDebugInfo() = config.debug
fun shouldContainLocationDebugInfo() = shouldContainDebugInfo() || config.lightDebug
fun shouldContainAnyDebugInfo() = shouldContainDebugInfo() || shouldContainLocationDebugInfo()
fun shouldUseDebugInfoFromNativeLibs() = shouldContainAnyDebugInfo() &&
config.configuration.get(BinaryOptions.stripDebugInfoFromNativeLibs) == false
fun shouldOptimize() = config.configuration.getBoolean(KonanConfigKeys.OPTIMIZATION)
fun ghaEnabled() = ::globalHierarchyAnalysisResult.isInitialized
@@ -25,6 +25,10 @@ internal fun linkObjC(context: Context) {
patchBuilder.buildAndApply(parsedModule)
if (!context.shouldUseDebugInfoFromNativeLibs()) {
LLVMStripModuleDebugInfo(parsedModule)
}
val failed = llvmLinkModules2(context, context.llvmModule!!, parsedModule)
if (failed != 0) {
throw Error("failed to link $bitcodeFile")
@@ -2618,6 +2618,13 @@ standaloneTest("stack_trace_inline") {
source = "runtime/exceptions/stack_trace_inline.kt"
}
standaloneTest("stack_trace_out_of_bounds") {
disabled = !isAppleTarget(project) || project.globalTestArgs.contains('-opt') || (project.testTarget == 'ios_arm64')
flags = ['-g', '-Xg-generate-debug-trampoline=enable', '-Xbinary=stripDebugInfoFromNativeLibs=false']
source = "runtime/exceptions/stack_trace_out_of_bounds.kt"
}
standaloneTest("kt-37572") {
disabled = !isAppleTarget(project) || project.globalTestArgs.contains('-opt') || (project.testTarget == 'ios_arm64')
flags = ['-g']
@@ -0,0 +1,37 @@
import kotlin.text.Regex
import kotlin.test.*
fun main() {
try {
val array = intArrayOf(1, 2, 3, 4)
println(array[4])
}
catch (e:Exception) {
val stackTrace = e.getStackTrace()
stackTrace.take(goldValues.size).forEach(::checkFrame)
}
}
internal val regex = Regex("^(\\d+)\\ +.*/(.*):(\\d+):.*$")
internal val goldValues = arrayOf(
"Throwable.kt" to null,
"Exceptions.kt" to null,
"Exceptions.kt" to null,
"Exceptions.kt" to null,
"Exceptions.kt" to null,
"RuntimeUtils.kt" to null,
"Arrays.cpp" to null,
"stack_trace_out_of_bounds.kt" to 7,
"stack_trace_out_of_bounds.kt" to 4,
"launcher.cpp" to null,
)
internal fun checkFrame(value:String) {
val (pos, file, line) = regex.find(value)!!.destructured
goldValues[pos.toInt()]?.let{
assertEquals(it.first, file)
if (it.second != null) {
assertEquals(it.second, line.toInt())
}
}
}