Giter VIP home page Giter VIP logo

Comments (16)

wanam avatar wanam commented on July 16, 2024

I think it's not 1c062f6 after all, the crash came a bit too late after reverting this commit :(

I will try to investigate more on this issue.

By the way i cannot reproduce this crash on @romracer build.

from android_art.

romracer avatar romracer commented on July 16, 2024

Let me know if you reproduce this on my build, please. I plan to rebase my branches eventually but I won't do that until we're all sure we get the same results from my code and @rovo89's. I haven't had a chance to compare my android_art branch to his yet.

from android_art.

wanam avatar wanam commented on July 16, 2024

@romracer I don't know what triggered this issue, but i started to get it with my old builds based on your build also! i used those builds for 2 weeks with no such issue.

Maybe it's a Rom related and it's triggered one time per reboot cycle and it may take seconds to hours to appear after the boot complete, i think i will just ignore it for now since it has no apparent effect.

I re-based my build on @rovo89's one, with your last xposed pull request, and it's running fine and clean for now.

Feel free to close this bug @rovo89 and sorry for the inconvenience.

from android_art.

wanam avatar wanam commented on July 16, 2024

Hi again @rovo89 @romracer ,

I rechecked the logs and found this:

09-02 20:57:02.074 I/dex2oat ( 7935): Verification error in void com.a.a.a.d.a()
09-02 20:57:02.074 I/dex2oat ( 7935): void com.a.a.a.d.a() failed to verify: void com.a.a.a.d.a(): [0x5D] Cannot infer method from invoke-virtual-quick
09-02 20:57:02.074 E/dex2oat ( 7935): Verification failed on class com.a.a.a.d in /data/data/com.google.android.gms/app_chimera/chimera-module-root/module-d27787c4e483aadd035a354447c9e84728eb2ab4/MapsModule.apk because: Verifier rejected class com.a.a.a.d due to bad method void com.a.a.a.d.a()

I think the cause of this issue is this commit testwhat/SmaliEx@747f669 on the @testwhat's (aka _riddle on xda) oat2dex tool used to deodex the Rom.

I will try to deodex the Rom again without this commit and get you back.

from android_art.

rovo89 avatar rovo89 commented on July 16, 2024

Could you please upload the failing APK (and odex if that exists)?
If it's really just the APK, I'm wondering why there's an invoke-virtual-quick at all. It usually just exists after optimization. Might also be interesting to compile this on a stock ROM in this case.

Btw, I had even considered a similar approach as @testwhat (read the debug info), but it turned out that in my case, there was an EndLocal before the failing instruction was reached. So I could have only guessed the type from (at that point) outdated register descriptions. Again, it would be good to see the code that's processed here.

from android_art.

wanam avatar wanam commented on July 16, 2024

Unfortunately the crash persists after reverting the last commit.

Here is the apk that fails: https://www.dropbox.com/s/5boua49mgvqkyh6/gms-maps-module-d27787c4e483aadd035a354447c9e84728eb2ab4.tar.gz?dl=0

from android_art.

rovo89 avatar rovo89 commented on July 16, 2024

@romracer @wanam Just to complete the comparison of mine vs. romracer's build, here's a commented diff. I have reverted three of his commits before:
romracer@597b0b8
romracer@e6f0887
romracer@cb71712

The gzip-related ones shouldn't be necessary for Xposed as patchoat isn't used, and the Lint cleanup makes no sense (it was probably cause by the #if 0). On my side, I have included all commits up to b3675bf.

As you can see, there are only minor differences, none of them should make any difference:

diff -rU3 romracer/compiler/driver/compiler_driver.cc rovo89/compiler/driver/compiler_driver.cc
--- romracer/compiler/driver/compiler_driver.cc 2015-09-02 22:40:48.838916356 +0200
+++ rovo89/compiler/driver/compiler_driver.cc   2015-09-02 22:45:43.685412851 +0200
@@ -1167,7 +1167,9 @@
   // invoked, so this can be passed to the out-of-line runtime support code.
   *direct_code = 0;
   *direct_method = 0;
-  bool use_dex_cache = GetCompilerOptions().GetCompilePic();  // Off by default
+  // Direct branching to the method's code offset means that Xposed hooks are not considered.
+  // So we always need to go through the dex cache/ArtMethod.
+  bool use_dex_cache = true;
   const bool compiling_boot = Runtime::Current()->GetHeap()->IsCompilingBoot();
   // TODO This is somewhat hacky. We should refactor all of this invoke codepath.
   const bool force_relocations = (compiling_boot ||
@@ -1184,9 +1186,6 @@
     // TODO: support patching on all architectures.
     use_dex_cache = use_dex_cache || (force_relocations && !support_boot_image_fixup_);
   }
-  // Direct branching to the method's code offset means that Xposed hooks are not considered
-  // So we always need to go through the dex cache/ArtMethod
-  use_dex_cache = true;
   mirror::Class* declaring_class = method->GetDeclaringClass();
   bool method_code_in_boot = (declaring_class->GetClassLoader() == nullptr);
   if (!use_dex_cache) {

Same result, but avoids the unncessary call to GetCompilerOptions().GetCompilePic()

diff -rU3 romracer/runtime/gc/space/image_space.cc rovo89/runtime/gc/space/image_space.cc
--- romracer/runtime/gc/space/image_space.cc    2015-09-02 22:42:06.905538134 +0200
+++ rovo89/runtime/gc/space/image_space.cc      2015-09-02 22:46:06.782066116 +0200
@@ -500,8 +500,7 @@
   // TODO: Consider relocating in the rare case that the system image is already prepared for Xposed

   if (image_filename != nullptr) {
-
-#if 0
+/*
   if (found_image) {
     const std::string* image_filename;
     bool is_system = false;
@@ -574,7 +573,7 @@
         image_filename = &cache_filename;
       }
     }
-#endif
+*/
     {
       // Note that we must not use the file descriptor associated with
       // ScopedFlock::GetFile to Init the image file. We want the file

Just a cosmetic change, easier to use in an editor. Should also avoid wrong Lint warnings.

diff -rU3 romracer/runtime/mirror/art_method.h rovo89/runtime/mirror/art_method.h
--- romracer/runtime/mirror/art_method.h        2015-09-02 22:40:48.842249688 +0200
+++ rovo89/runtime/mirror/art_method.h  2015-09-02 22:45:43.718746165 +0200
@@ -325,7 +325,6 @@
   template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetEntryPointFromQuickCompiledCode(const void* entry_point_from_quick_compiled_code)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(!IsXposedHookedMethod());
     CheckObjectSizeEqualsMirrorSize();
     SetEntryPointFromQuickCompiledCodePtrSize(entry_point_from_quick_compiled_code,
                                               sizeof(void*));
@@ -554,6 +553,21 @@

   ALWAYS_INLINE ArtMethod* GetInterfaceMethodIfProxy() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

+  static size_t SizeWithoutPointerFields(size_t pointer_size) {
+    size_t total = sizeof(ArtMethod) - sizeof(PtrSizedFields);
+#ifdef ART_METHOD_HAS_PADDING_FIELD_ON_64_BIT
+    // Add 4 bytes if 64 bit, otherwise 0.
+    total += pointer_size - sizeof(uint32_t);
+#endif
+    return total;
+  }
+
+  // Size of an instance of java.lang.reflect.ArtMethod not including its value array.
+  static size_t InstanceSize(size_t pointer_size) {
+    return SizeWithoutPointerFields(pointer_size) +
+        (sizeof(PtrSizedFields) / sizeof(void*)) * pointer_size;
+  }
+
   // Xposed
   bool IsXposedHookedMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return (GetAccessFlags() & kAccXposedHookedMethod) != 0;
@@ -577,21 +591,6 @@
   static jclass xposed_callback_class;
   static jmethodID xposed_callback_method;

-  static size_t SizeWithoutPointerFields(size_t pointer_size) {
-    size_t total = sizeof(ArtMethod) - sizeof(PtrSizedFields);
-#ifdef ART_METHOD_HAS_PADDING_FIELD_ON_64_BIT
-    // Add 4 bytes if 64 bit, otherwise 0.
-    total += pointer_size - sizeof(uint32_t);
-#endif
-    return total;
-  }
-
-  // Size of an instance of java.lang.reflect.ArtMethod not including its value array.
-  static size_t InstanceSize(size_t pointer_size) {
-    return SizeWithoutPointerFields(pointer_size) +
-        (sizeof(PtrSizedFields) / sizeof(void*)) * pointer_size;
-  }
-
  protected:
   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
   // The class we are a part of.

The DCHECK is unnecessary because it's done in SetEntryPointFromQuickCompiledCodePtrSize.
The other two methods are just in a different order (Xposed's additional methods should be at the end).

diff -rU3 romracer/runtime/mirror/object.cc rovo89/runtime/mirror/object.cc
--- romracer/runtime/mirror/object.cc   2015-09-02 22:40:48.842249688 +0200
+++ rovo89/runtime/mirror/object.cc     2015-09-02 22:45:43.722079496 +0200
@@ -119,10 +119,6 @@
   DISALLOW_COPY_AND_ASSIGN(CopyObjectVisitor);
 };

-Object* Object::Clone(Thread* self) {
-  return Clone(self, 0);
-}
-
 Object* Object::Clone(Thread* self, size_t num_target_bytes) {
   CHECK(!IsClass()) << "Can't clone classes.";
   // Object::SizeOf gets the right size even if we're an array. Using c->AllocObject() here would
diff -rU3 romracer/runtime/mirror/object.h rovo89/runtime/mirror/object.h
--- romracer/runtime/mirror/object.h    2015-09-02 22:40:48.842249688 +0200
+++ rovo89/runtime/mirror/object.h      2015-09-02 22:45:43.722079496 +0200
@@ -102,8 +102,7 @@
            ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
   size_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

-  Object* Clone(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  Object* Clone(Thread* self, size_t num_target_bytes) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  Object* Clone(Thread* self, size_t num_target_bytes = 0) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

   int32_t IdentityHashCode() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

Easier implementation, same results.

diff -rU3 romracer/runtime/native/dalvik_system_DexFile.cc rovo89/runtime/native/dalvik_system_DexFile.cc
--- romracer/runtime/native/dalvik_system_DexFile.cc    2015-09-02 22:40:48.842249688 +0200
+++ rovo89/runtime/native/dalvik_system_DexFile.cc      2015-09-02 22:45:43.722079496 +0200
@@ -304,6 +304,11 @@
     error_msg.clear();
     return kDexoptNeeded;
   }
+
+  // Pass-up the information about if this is PIC.
+  // TODO: Refactor this function to be less complicated.
+  *oat_is_pic = oat_file->IsPic();
+
   if (!oat_file->GetOatHeader().IsXposedOatVersionValid()) {
     if (kReasonLogging) {
       LOG(INFO) << "DexFile_isDexOptNeeded file " << oat_filename
@@ -312,10 +317,6 @@
     return kDexoptNeeded;
   }

-  // Pass-up the information about if this is PIC.
-  // TODO: Refactor this function to be less complicated.
-  *oat_is_pic = oat_file->IsPic();
-
   bool should_relocate_if_possible = Runtime::Current()->ShouldRelocate();
   uint32_t location_checksum = 0;
   const art::OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(filename, nullptr,

Always fill oat_is_pic, just in case...

from android_art.

rovo89 avatar rovo89 commented on July 16, 2024

@wanam I finally found the time to look into the verification errors. I can reproduce many of them, but with a closer look, I saw that at least the first one of them is because I have a different boot.oat than you have. "vtable@289" for the View class means something totally different here... Could you upload your /system/framework/arm64/boot.oat please? I have a theory that this odex file might have been created with different version of the ROM, which would make it unusable.

It's also strange that MapsModule.apk actually contains the original (not optimized) classes.dex and the odex file is already compiled with Xposed. It's the same situation on my device. So workaround could be to ignore the odex file if the APK file has a classes.dex file. But if my theory is right, this should be prevented much earlier:

  • Each odex file holds an "IMAGE FILE LOCATION OAT CHECKSUM"
  • This checksum has to match the "CHECKSUM" of the boot.oat for the same platform.
  • If it doesn't match, the odex has to be rejected.

Could you see in the log why dex2oat is triggered? Any hints that it might be because of this and now it tries to compile from the existing odex file to the new file?

from android_art.

wanam avatar wanam commented on July 16, 2024

@rovo89 here is the boot.oat from OH8: https://www.dropbox.com/s/72ejrdgoarwjtqc/boot.oat.oh8.zip?dl=0

And here are the logs of the crash on deodexed OH8: https://www.dropbox.com/s/ndytmr9381t56mf/log01-xposed-oh8.txt.tar.gz?dl=0

Let me know if you need to test/debug anything.

from android_art.

rovo89 avatar rovo89 commented on July 16, 2024

Ok, I think I understood the problem now. GMS correctly detects that the odex file is outdated and opens a DexClassLoader to recompile it. This finally ends up in ClassLinker::GenerateOatFile(), where one of the changes for Xposed finds the odex file and uses it for the --dex-file option instead of the APK. Normally, this works fine, but due to compiler-filter=interpret-only, the previous version of the odex has been optimized with more invoke-quick calls, which now fail to resolve with the new boot image.

So the odex-instead-of-APK mechanism has to be restricted to apply only for certain odex files. But for which ones? Maybe just for /system and /vendor? Or when the result is supposed to go to the Dalvik cache (not to a directory in /data/data)? Maybe somehow else? I'll give this some thoughts, feel free to share your opinion if you have any preferences.

from android_art.

rovo89 avatar rovo89 commented on July 16, 2024

Other ideas:

  • Ignore odex if it has been compiled for Xposed already
  • Ignore odex if APK has a classes.dex file
    Both of these would required opening one or the other file though.

from android_art.

wanam avatar wanam commented on July 16, 2024

I have no objection, I prefer the second solution.

from android_art.

rovo89 avatar rovo89 commented on July 16, 2024

Second solution == check whether it goes into the Dalvik cache vs. into a local directory?

from android_art.

wanam avatar wanam commented on July 16, 2024

Yes.

when the result is supposed to go to the Dalvik cache (not to a directory in /data/data)

from android_art.

wanam avatar wanam commented on July 16, 2024

Something like this:

  dex_file_option += (StartsWith(oat_cache_filename, "/data/dalvik-cache/") && OS::FileExists(odex_filename.c_str())) ? odex_filename : dex_filename;

I will try it tonight.

from android_art.

rovo89 avatar rovo89 commented on July 16, 2024

Yes, something like this. The Dalvik cache path is actually calculated like this:

const char* android_data = GetAndroidData();
const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));

Maybe use this to be more exact? Or GetDalvikCacheOrDie("", false)?

from android_art.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.