[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:
+2
@@ -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>(
|
||||
|
||||
+1
@@ -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
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -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.
|
||||
|
||||
+2
@@ -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
|
||||
|
||||
+4
@@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
#define RUNTIME_PURE __attribute__((pure))
|
||||
#define RUNTIME_USED __attribute__((used))
|
||||
#define RUNTIME_WEAK __attribute__((weak))
|
||||
#define RUNTIME_NODEBUG __attribute__((nodebug))
|
||||
|
||||
#define ALWAYS_INLINE __attribute__((always_inline))
|
||||
#define NO_INLINE __attribute__((noinline))
|
||||
|
||||
@@ -320,7 +320,7 @@ constexpr int CALLED_LLVM_BUILTIN = -2;
|
||||
* should not be accessed. So before guard checking we need to check is thread destructor is running,
|
||||
* which requires special handling of recursive calls from this check.
|
||||
*/
|
||||
extern "C" RUNTIME_NOTHROW void Kotlin_mm_checkStateAtExternalFunctionCall(const char* caller, const char *callee, const void *calleePtr) noexcept {
|
||||
extern "C" RUNTIME_NOTHROW RUNTIME_NODEBUG void Kotlin_mm_checkStateAtExternalFunctionCall(const char* caller, const char *callee, const void *calleePtr) noexcept {
|
||||
if (reinterpret_cast<int64_t>(calleePtr) == MSG_SEND_TO_NULL) return; // objc_sendMsg called on nil, it does nothing, so it's ok
|
||||
if (konan::isOnThreadExitNotSetOrAlreadyStarted()) return;
|
||||
static thread_local bool recursiveCallGuard = false;
|
||||
|
||||
Reference in New Issue
Block a user