diff options
| -rw-r--r-- | runtime/openjdkjvmti/OpenjdkJvmTi.cc | 2 | ||||
| -rw-r--r-- | runtime/openjdkjvmti/ti_method.cc | 59 | ||||
| -rw-r--r-- | runtime/openjdkjvmti/ti_method.h | 5 | ||||
| -rw-r--r-- | test/911-get-stack-trace/expected.txt | 358 | ||||
| -rw-r--r-- | test/911-get-stack-trace/stack_trace.cc | 48 |
5 files changed, 291 insertions, 181 deletions
diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc index 1ad3f0814f..5f97b60079 100644 --- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc +++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc @@ -700,7 +700,7 @@ class JvmtiFunctions { jmethodID method, jint* entry_count_ptr, jvmtiLineNumberEntry** table_ptr) { - return ERR(NOT_IMPLEMENTED); + return MethodUtil::GetLineNumberTable(env, method, entry_count_ptr, table_ptr); } static jvmtiError GetMethodLocation(jvmtiEnv* env, diff --git a/runtime/openjdkjvmti/ti_method.cc b/runtime/openjdkjvmti/ti_method.cc index ffa5ac7e32..a0a09239fa 100644 --- a/runtime/openjdkjvmti/ti_method.cc +++ b/runtime/openjdkjvmti/ti_method.cc @@ -130,4 +130,63 @@ jvmtiError MethodUtil::GetMethodModifiers(jvmtiEnv* env ATTRIBUTE_UNUSED, return ERR(NONE); } +using LineNumberContext = std::vector<jvmtiLineNumberEntry>; + +static bool CollectLineNumbers(void* void_context, const art::DexFile::PositionInfo& entry) { + LineNumberContext* context = reinterpret_cast<LineNumberContext*>(void_context); + jvmtiLineNumberEntry jvmti_entry = { static_cast<jlocation>(entry.address_), + static_cast<jint>(entry.line_) }; + context->push_back(jvmti_entry); + return false; // Collect all, no early exit. +} + +jvmtiError MethodUtil::GetLineNumberTable(jvmtiEnv* env, + jmethodID method, + jint* entry_count_ptr, + jvmtiLineNumberEntry** table_ptr) { + if (method == nullptr) { + return ERR(NULL_POINTER); + } + art::ArtMethod* art_method = art::jni::DecodeArtMethod(method); + DCHECK(!art_method->IsRuntimeMethod()); + + const art::DexFile::CodeItem* code_item; + const art::DexFile* dex_file; + { + art::ScopedObjectAccess soa(art::Thread::Current()); + + if (art_method->IsProxyMethod()) { + return ERR(ABSENT_INFORMATION); + } + if (art_method->IsNative()) { + return ERR(NATIVE_METHOD); + } + if (entry_count_ptr == nullptr || table_ptr == nullptr) { + return ERR(NULL_POINTER); + } + + code_item = art_method->GetCodeItem(); + dex_file = art_method->GetDexFile(); + DCHECK(code_item != nullptr) << art_method->PrettyMethod() << " " << dex_file->GetLocation(); + } + + LineNumberContext context; + bool success = dex_file->DecodeDebugPositionInfo(code_item, CollectLineNumbers, &context); + if (!success) { + return ERR(ABSENT_INFORMATION); + } + + unsigned char* data; + jlong mem_size = context.size() * sizeof(jvmtiLineNumberEntry); + jvmtiError alloc_error = env->Allocate(mem_size, &data); + if (alloc_error != ERR(NONE)) { + return alloc_error; + } + *table_ptr = reinterpret_cast<jvmtiLineNumberEntry*>(data); + memcpy(*table_ptr, context.data(), mem_size); + *entry_count_ptr = static_cast<jint>(context.size()); + + return ERR(NONE); +} + } // namespace openjdkjvmti diff --git a/runtime/openjdkjvmti/ti_method.h b/runtime/openjdkjvmti/ti_method.h index 43f11f97ec..fb2fbb2b27 100644 --- a/runtime/openjdkjvmti/ti_method.h +++ b/runtime/openjdkjvmti/ti_method.h @@ -52,6 +52,11 @@ class MethodUtil { static jvmtiError GetMethodModifiers(jvmtiEnv* env, jmethodID method, jint* modifiers_ptr); + + static jvmtiError GetLineNumberTable(jvmtiEnv* env, + jmethodID method, + jint* entry_count_ptr, + jvmtiLineNumberEntry** table_ptr); }; } // namespace openjdkjvmti diff --git a/test/911-get-stack-trace/expected.txt b/test/911-get-stack-trace/expected.txt index 77c77ca21e..f8c97ce475 100644 --- a/test/911-get-stack-trace/expected.txt +++ b/test/911-get-stack-trace/expected.txt @@ -3,206 +3,206 @@ ################### From top --------- - getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 - print (Ljava/lang/Thread;II)V 0 - printOrWait (IILMain$ControlData;)V 6 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - doTest ()V 38 - main ([Ljava/lang/String;)V 6 ---------- - print (Ljava/lang/Thread;II)V 0 - printOrWait (IILMain$ControlData;)V 6 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - doTest ()V 42 - main ([Ljava/lang/String;)V 6 ---------- - getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 - print (Ljava/lang/Thread;II)V 0 - printOrWait (IILMain$ControlData;)V 6 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 - bar (IIILMain$ControlData;)J 0 ---------- - printOrWait (IILMain$ControlData;)V 6 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 + getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 -2 + print (Ljava/lang/Thread;II)V 0 124 + printOrWait (IILMain$ControlData;)V 6 151 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + doTest ()V 38 34 + main ([Ljava/lang/String;)V 6 24 +--------- + print (Ljava/lang/Thread;II)V 0 124 + printOrWait (IILMain$ControlData;)V 6 151 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + doTest ()V 42 35 + main ([Ljava/lang/String;)V 6 24 +--------- + getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 -2 + print (Ljava/lang/Thread;II)V 0 124 + printOrWait (IILMain$ControlData;)V 6 151 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 + bar (IIILMain$ControlData;)J 0 136 +--------- + printOrWait (IILMain$ControlData;)V 6 151 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 From bottom --------- - main ([Ljava/lang/String;)V 6 + main ([Ljava/lang/String;)V 6 24 --------- - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - doTest ()V 65 - main ([Ljava/lang/String;)V 6 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + doTest ()V 65 41 + main ([Ljava/lang/String;)V 6 24 --------- - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 ################################ ### Other thread (suspended) ### ################################ From top --------- - wait ()V -1 - printOrWait (IILMain$ControlData;)V 24 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - run ()V 4 ---------- - printOrWait (IILMain$ControlData;)V 24 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - run ()V 4 ---------- - wait ()V -1 - printOrWait (IILMain$ControlData;)V 24 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 ---------- - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 157 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + run ()V 4 54 +--------- + printOrWait (IILMain$ControlData;)V 24 157 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + run ()V 4 54 +--------- + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 157 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 +--------- + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 From bottom --------- - run ()V 4 + run ()V 4 54 --------- - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - run ()V 4 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + run ()V 4 54 --------- - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 ########################### ### Other thread (live) ### ########################### From top --------- - printOrWait (IILMain$ControlData;)V 44 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - run ()V 4 ---------- - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - run ()V 4 ---------- - printOrWait (IILMain$ControlData;)V 44 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 ---------- - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 + printOrWait (IILMain$ControlData;)V 44 164 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + run ()V 4 88 +--------- + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + run ()V 4 88 +--------- + printOrWait (IILMain$ControlData;)V 44 164 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 +--------- + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 From bottom --------- - run ()V 4 + run ()V 4 88 --------- - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - run ()V 4 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + run ()V 4 88 --------- - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 - foo (IIILMain$ControlData;)I 0 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 - bar (IIILMain$ControlData;)J 0 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 + foo (IIILMain$ControlData;)I 0 131 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + bar (IIILMain$ControlData;)J 0 136 diff --git a/test/911-get-stack-trace/stack_trace.cc b/test/911-get-stack-trace/stack_trace.cc index b5b5678f54..9092f2f7d3 100644 --- a/test/911-get-stack-trace/stack_trace.cc +++ b/test/911-get-stack-trace/stack_trace.cc @@ -32,6 +32,23 @@ namespace art { namespace Test911GetStackTrace { +static jint FindLineNumber(jint line_number_count, + jvmtiLineNumberEntry* line_number_table, + jlocation location) { + if (line_number_table == nullptr) { + return -2; + } + + jint line_number = -1; + for (jint i = 0; i != line_number_count; ++i) { + if (line_number_table[i].start_location > location) { + return line_number; + } + line_number = line_number_table[i].line_number; + } + return line_number; +} + extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getStackTrace( JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jthread thread, jint start, jint max) { std::unique_ptr<jvmtiFrameInfo[]> frames(new jvmtiFrameInfo[max]); @@ -61,6 +78,26 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getStackTrace( } } + jint line_number_count; + jvmtiLineNumberEntry* line_number_table; + { + jvmtiError line_result = jvmti_env->GetLineNumberTable(frames[method_index].method, + &line_number_count, + &line_number_table); + if (line_result != JVMTI_ERROR_NONE) { + // Accept absent info and native method errors. + if (line_result != JVMTI_ERROR_ABSENT_INFORMATION && + line_result != JVMTI_ERROR_NATIVE_METHOD) { + char* err; + jvmti_env->GetErrorName(line_result, &err); + printf("Failure running GetLineNumberTable: %s\n", err); + return nullptr; + } + line_number_table = nullptr; + line_number_count = 0; + } + } + auto inner_callback = [&](jint component_index) -> jstring { switch (component_index) { case 0: @@ -69,11 +106,17 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getStackTrace( return (sig == nullptr) ? nullptr : env->NewStringUTF(sig); case 2: return env->NewStringUTF(StringPrintf("%" PRId64, frames[method_index].location).c_str()); + case 3: { + jint line_number = FindLineNumber(line_number_count, + line_number_table, + frames[method_index].location); + return env->NewStringUTF(StringPrintf("%d", line_number).c_str()); + } } LOG(FATAL) << "Unreachable"; UNREACHABLE(); }; - jobjectArray inner_array = CreateObjectArray(env, 3, "java/lang/String", inner_callback); + jobjectArray inner_array = CreateObjectArray(env, 4, "java/lang/String", inner_callback); if (name != nullptr) { jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(name)); @@ -84,6 +127,9 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getStackTrace( if (gen != nullptr) { jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(gen)); } + if (line_number_table != nullptr) { + jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(line_number_table)); + } return inner_array; }; |