summaryrefslogtreecommitdiff
path: root/runtime/openjdkjvmti/transform.cc
diff options
context:
space:
mode:
author Alex Light <allight@google.com> 2017-01-19 14:57:28 -0800
committer Alex Light <allight@google.com> 2017-01-20 11:32:03 -0800
commita7e38d8aaacfca85b40b5df654f85c0979968672 (patch)
tree34322c79fc328a608fc17303453c8ec1f38b9eaa /runtime/openjdkjvmti/transform.cc
parent05778764cb11162b6f3ff72386135ed45a07af33 (diff)
Use original dex file for retransformation.
The spec requires us to pass the dex file as it appeared before any retransformation-capable agents had modified it to the ClassFileLoadHooks when RetransformClasses is called. We do this by saving the initial dex file bytes into the class as a byte[]. Bug: 32369916 Test: mma -j40 test-art-host Change-Id: Ic6af3738cd2a831e91ba1144f502fa58b3c333e4
Diffstat (limited to 'runtime/openjdkjvmti/transform.cc')
-rw-r--r--runtime/openjdkjvmti/transform.cc42
1 files changed, 28 insertions, 14 deletions
diff --git a/runtime/openjdkjvmti/transform.cc b/runtime/openjdkjvmti/transform.cc
index 2809cb6926..af4fb7187a 100644
--- a/runtime/openjdkjvmti/transform.cc
+++ b/runtime/openjdkjvmti/transform.cc
@@ -47,6 +47,7 @@
#include "mem_map.h"
#include "mirror/array.h"
#include "mirror/class-inl.h"
+#include "mirror/class_ext.h"
#include "mirror/class_loader-inl.h"
#include "mirror/string-inl.h"
#include "oat_file.h"
@@ -138,28 +139,41 @@ jvmtiError GetClassLocation(ArtJvmTiEnv* env, jclass klass, /*out*/std::string*
return OK;
}
-// TODO Implement this for real once transformed dex data is actually saved.
+static jvmtiError CopyDataIntoJvmtiBuffer(ArtJvmTiEnv* env,
+ const unsigned char* source,
+ jint len,
+ /*out*/unsigned char** dest) {
+ jvmtiError res = env->Allocate(len, dest);
+ if (res != OK) {
+ return res;
+ }
+ memcpy(reinterpret_cast<void*>(*dest),
+ reinterpret_cast<const void*>(source),
+ len);
+ return OK;
+}
+
jvmtiError Transformer::GetDexDataForRetransformation(ArtJvmTiEnv* env,
art::Handle<art::mirror::Class> klass,
/*out*/jint* dex_data_len,
/*out*/unsigned char** dex_data) {
+ art::StackHandleScope<2> hs(art::Thread::Current());
+ art::Handle<art::mirror::ClassExt> ext(hs.NewHandle(klass->GetExtData()));
+ if (!ext.IsNull()) {
+ art::Handle<art::mirror::ByteArray> orig_dex(hs.NewHandle(ext->GetOriginalDexFileBytes()));
+ if (!orig_dex.IsNull()) {
+ *dex_data_len = static_cast<jint>(orig_dex->GetLength());
+ return CopyDataIntoJvmtiBuffer(env,
+ reinterpret_cast<const unsigned char*>(orig_dex->GetData()),
+ *dex_data_len,
+ /*out*/dex_data);
+ }
+ }
// TODO De-quicken the dex file before passing it to the agents.
LOG(WARNING) << "Dex file is not de-quickened yet! Quickened dex instructions might be present";
- LOG(WARNING) << "Caching of initial dex data is not yet performed! Dex data might have been "
- << "transformed by agent already";
const art::DexFile& dex = klass->GetDexFile();
*dex_data_len = static_cast<jint>(dex.Size());
- unsigned char* new_dex_data = nullptr;
- jvmtiError alloc_error = env->Allocate(*dex_data_len, &new_dex_data);
- if (alloc_error != OK) {
- return alloc_error;
- }
- // Copy the data into a temporary buffer.
- memcpy(reinterpret_cast<void*>(new_dex_data),
- reinterpret_cast<const void*>(dex.Begin()),
- *dex_data_len);
- *dex_data = new_dex_data;
- return OK;
+ return CopyDataIntoJvmtiBuffer(env, dex.Begin(), *dex_data_len, /*out*/dex_data);
}
// TODO Move this function somewhere more appropriate.