Tôi đã thành công trong việc trả lời câu hỏi của mình. Đối với những gì tôi có thể hiểu được từ mã nguồn có 3 điểm vào tốt cho các cuộc gọi java:
- ArtMethod :: Gọi (nghệ thuật/runtime/gương/art_method.cc)
- Execute (nghệ thuật/runtime /interpreter/interpreter.cc)
- DoCall (nghệ thuật/runtime/phiên dịch/interpreter_common.cc)
ArtMethod :: Invoke dường như được sử dụng cho phản xạ và cho gọi phương thức trực tiếp với một con trỏ đến OAT phần mã. (Một lần nữa, không có tài liệu, nó có thể không chính xác).
Thực hiện kết thúc cuộc gọi DoCall nói chung.
Có một số tối ưu hóa ART làm cho việc nghiên cứu các cuộc gọi Java trở nên khó khăn, như phương thức nội tuyến và gọi địa chỉ offset trực tiếp.
Bước đầu tiên là vô hiệu hóa những tối ưu hóa:
Trong thiết bị/thương hiệu/mô hình/device.mk (trong trường hợp thiết bị của tôi/LGE/búa/device.mk cho một mối quan hệ 5):
Thêm tùy chọn "chỉ diễn giải" vào dex2oat. Với tùy chọn này, ART chỉ biên dịch classpath khởi động, vì vậy các ứng dụng sẽ không được biên dịch trong OAT.
PRODUCT_PROPERTY_OVERRIDES := \
dalvik.vm.dex2oat-filter=interpret-only
Bước thứ hai là để vô hiệu hóa nội tuyến trong nghệ thuật/biên dịch/dex/frontend.cc:
Bỏ ghi chú "kSuppressMethodInlining".
/* Default optimizer/debug setting for the compiler. */
static uint32_t kCompilerOptimizerDisableFlags = 0 | // Disable specific optimizations
(1 << kLoadStoreElimination) |
// (1 << kLoadHoisting) |
// (1 << kSuppressLoads) |
// (1 << kNullCheckElimination) |
// (1 << kClassInitCheckElimination) |
(1 << kGlobalValueNumbering) |
// (1 << kPromoteRegs) |
// (1 << kTrackLiveTemps) |
// (1 << kSafeOptimizations) |
// (1 << kBBOpt) |
// (1 << kMatch) |
// (1 << kPromoteCompilerTemps) |
// (1 << kSuppressExceptionEdges) |
(1 << kSuppressMethodInlining) |
0;
Bước cuối cùng là để vô hiệu hóa đang bù đắp gọi trực tiếp trong nghệ thuật/biên dịch/lái xe/compiler_driver.cc:
-bool use_dex_cache = GetCompilerOptions().GetCompilePic();
+bool use_dex_cache = true;
Với những thay đổi các cuộc gọi tất cả khác nhau sẽ rơi vào các chức năng DoCall nơi chúng ta có thể cuối cùng thêm thói quen ghi nhật ký được nhắm mục tiêu của chúng tôi.
Trong nghệ thuật/runtime/phiên dịch/interpreter_common.h, thêm ngay từ đầu trong những bao gồm:
#ifdef HAVE_ANDROID_OS
#include "cutils/properties.h"
#endif
Trong nghệ thuật/runtime/phiên dịch/interpreter_common.cc, thêm vào đầu của hàm DoCall:
#ifdef HAVE_ANDROID_OS
char targetAppVar[92];
property_get("target.app.pid", targetAppVar, "0");
int targetAppPID = atoi(targetAppVar);
if(targetAppPID != 0 && targetAppPID == getpid())
LOG(INFO) << "DoCall - " << PrettyMethod(method, true);
#endif
Để nhắm mục tiêu ứng dụng tôi sử dụng thuộc tính đặt pid được nhắm mục tiêu. Đối với điều này chúng ta cần hệ thống lib/core/libcutils và lib này chỉ có sẵn khi AOSP được biên dịch cho một điện thoại thực (mà không gây rối với các makefiles hiện tại).
Vì vậy, giải pháp sẽ không hoạt động đối với trình giả lập. (
Chỉ đoán, không bao giờ thử
EDIT: đã xác nhận, "cutils/properties.h" không thể được thêm vào bản dựng trình mô phỏng).
Sau khi biên dịch và nhấp nháy AOSP đã vá, khởi động ứng dụng, ps | grep cho việc tìm kiếm các PID và thiết lập thuộc tính trong root:
[email protected]:/ # ps | grep contacts
u0_a2 4278 129 1234668 47356 ffffffff 401e8318 S com.android.contacts
[email protected]:/ # setprop target.app.pid 4278
[email protected]:/ # logcat
[...]
I/art (4278): DoCall - int android.view.View.getId()
I/art (4278): DoCall - void com.android.contacts.activities.PeopleActivity$ContactsUnavailableFragmentListener.onCreateNewContactAction()
I/art (4278): DoCall - void android.content.Intent.<init>(java.lang.String, android.net.Uri)
I/art (4278): DoCall - void android.app.Activity.startActivity(android.content.Intent)
I/ActivityManager( 498): START u0 {act=android.intent.action.INSERT dat=content://com.android.contacts/contacts cmp=com.android.contacts/.activities.ContactEditorActivity} from uid 10002 on display 0
V/WindowManager( 498): addAppToken: AppWindowToken{3a82282b token=Token{dc3f87a ActivityRecord{c0aaca5 u0 com.android.contacts/.activities.ContactEditorActivity t4}}} to stack=1 task=4 at 1
I/art (4278): DoCall - void android.app.Fragment.onPause()
I/art (4278): DoCall - void com.android.contacts.common.list.ContactEntryListFragment.removePendingDirectorySearchRequests()
I/art (4278): DoCall - void android.os.Handler.removeMessages(int)
I/art (4278): DoCall - void com.android.contacts.list.ProviderStatusWatcher.stop()
I/art (4278): DoCall - boolean com.android.contacts.list.ProviderStatusWatcher.isStarted()
I/art (4278): DoCall - void android.os.Handler.removeCallbacks(java.lang.Runnable)
I/art (4278): DoCall - android.content.ContentResolver com.android.contacts.ContactsActivity.getContentResolver()
I/art (4278): DoCall - void android.content.ContentResolver.unregisterContentObserver(android.database.ContentObserver)
I/art (4278): DoCall - void android.app.Activity.onPause()
I/art (4278): DoCall - void android.view.ViewGroup.drawableStateChanged()
I/art (4278): DoCall - void com.android.contacts.ContactsActivity.<init>()
I/art (4278): DoCall - void com.android.contacts.common.activity.TransactionSafeActivity.<init>()
I/art (4278): DoCall - void android.app.Activity.<init>()
I/art (4278): DoCall - void com.android.contacts.util.DialogManager.<init>(android.app.Activity)
I/art (4278): DoCall - void java.lang.Object.<init>()
[...]
Khi nó kết thúc:
[email protected]:/ # setprop target.app.pid 0
Voila!
Quá tải không đáng chú ý từ quan điểm của người dùng, nhưng bản ghi nhật ký sẽ được điền nhanh chóng.
PS: Đường dẫn tệp và tên khớp với phiên bản Android 5 (Lollipop), chúng có thể khác với phiên bản cao cấp.
PS ': Nếu người ta muốn in các đối số của các phương pháp, tôi sẽ khuyên bạn nên xem art/runtime/utils.cc cho phương thức PrettyArguments và tìm một số thực hiện thực tế ở đâu đó trong mã.
Cảm ơn bạn rất nhiều vì đã giải thích điều này. Tôi có một câu hỏi. Nếu tôi muốn vá mã AOSP khi bạn giải thích và xây dựng hình ảnh hệ thống Android cho trình mô phỏng, tôi nên thêm tùy chọn "chỉ diễn giải" ở đâu? Tôi không thể tìm thấy tệp device.mk cho trình mô phỏng. Vui lòng cho tôi biết. – aMa
Thiết bị mục tiêu của bạn là gì? Tôi là một hammerhead nexus 5 nên con đường của tôi là /device/lge/hammerhead/device.mk. –
Sry, tôi vừa đọc quá nhanh. Tôi chưa bao giờ thử làm giả lập và có thể bạn sẽ gặp phải các vấn đề với libcutils cho hàm property_get. Bạn đã thử mà không có sự sửa đổi của device.mk chưa? Nó sẽ làm việc mà không có nó trong trường hợp xấu nhất. Nếu không có nó, điều tồi tệ nhất có thể xảy ra là bạn bỏ lỡ một số cuộc gọi. –