【问题标题】:How can I detect when Android x86 is emulating ARM?如何检测 Android x86 何时模拟 ARM?
【发布时间】:2014-07-25 08:18:18
【问题描述】:

我有一个可以在大多数 Android 设备(ARMv5、ARMv7 和 x86)上良好运行的 JNI 库。

我在 ARMv7 上使用 NEON 指令,但我不想用条件/重复的源代码弄乱代码,而是想在库加载时检测 Java 中的非 NEON ARMv7,并改为加载 v5 库:慢速 CPU 是慢。

我发现一个帖子建议我在 /proc/cpuinfo 中寻找“neon”功能,所以我正在解析它,通常加载 libthing.so,如果设备声称是没有 NEON 的 ARMv7。这在 ARM 上运行良好。

不幸的是,x86 不仅模拟 ARM /proc/cpuinfo(!),如果它认为它不理解 NEON,那么它还会从 armeabiv7a 目录中挖出 libthing-v5.so,并使用它,因为没有在 x86 目录中没有一个。

我目前的解决方法是将 x86 库复制到 libthing.so 和 libthing-v5.so 中,所以如果 x86 假装是无 NEON 的 ARMv7 芯片,它无论如何都会得到 x86 库。

除了基于 Yeppp 或 Android 自己的 cpufeatures 制作我自己的小型独立架构检测库之外,有没有办法从 Java 中确定真正的本地架构?


@ph0b:这里是 Razr i 的输出,显示模拟器已确定应用程序已安装为“ABI2 58”,并且需要伪造 /proc/cpuinfo。

鉴于 x86 和 armeabi* 目录都提供这两个共享库,我不明白为什么该设备决定成为 ARM。我可能会就此询问我在英特尔的联系人。

06-05 10:58:41.360 17807 18053 D dalvikvm: Trying to load lib /data/data/com.company.android/lib/libmp.so 0x42409cb0
06-05 10:58:41.360 17807 18053 D dalvikvm: Added shared lib /data/data/com.company.android/lib/libmp.so 0x42409cb0
06-05 10:58:41.370 17807 18053 D dalvikvm: No JNI_OnLoad found in /data/data/com.company.android/lib/libmp.so 0x42409cb0, skipping init
06-05 10:58:41.420 17807 18053 D         : Searching package installed with ABI2 with Uid: 10109 
06-05 10:58:41.420 17807 18053 D         : Apps with ABI2 58 accessing /proc/cpuinfo 
06-05 10:58:41.430 17807 18053 I System.out: #Here's most of /proc/cpuinfo
06-05 10:58:41.430 17807 18053 I System.out: #Thu Jun 05 10:58:41 GMT+01:00 2014
06-05 10:58:41.430 17807 18053 I System.out: Serial=0000000000000001
06-05 10:58:41.430 17807 18053 I System.out: Revision=0001
06-05 10:58:41.430 17807 18053 I System.out: CPU=revision\t\: 1
06-05 10:58:41.430 17807 18053 I System.out: BogoMIPS=1500
06-05 10:58:41.430 17807 18053 I System.out: Hardware=placeholder
06-05 10:58:41.430 17807 18053 I System.out: Features=vfp swp half thumb fastmult edsp vfpv3 
06-05 10:58:41.430 17807 18053 I System.out: Processor=ARMv7 processor rev 1 (v7l)
06-05 10:58:41.430 17807 18053 I NativeWahooLibrary: Detected ARMv7 processor rev 1 (v7l) (=ARMv7, true) with (neon@-1) vfp swp half thumb fastmult edsp vfpv3 
06-05 10:58:41.430 17807 18053 D dalvikvm: Trying to load non-neon lib /data/data/com.company.android/lib/libwahoo-v5.so 0x42409cb0

【问题讨论】:

    标签: android-ndk x86 arm


    【解决方案1】:

    我怀疑 x86 模拟 ARM /proc/cpuinfo !?

    无论如何,为了从Java中检测本地架构,你可以依赖Build.CPU_ABIBuild.CPU_ABI2:http://developer.android.com/reference/android/os/Build.html#CPU_ABI,然后继续解析/proc/cpuinfo寻找neon,前提是CPU_ABI和CPU_ABI2是arm */armeabi-v7a

    【讨论】:

    • Razri 的奇怪输出见上文,其中显示了 ARM /proc/cpuinfo。它为我的测试应用程序发出 x86 /proc/cpuinfo。除此之外,我方便的两台英特尔设备上的 CPU_ABI=x86 和 CPU_ABI2=armeabi-v7a ;我真正的 ARM 设备有 CPU_ABI=armeabi-v7a 和 CPU_ABI2=armeabi,除了一个意外地变成英特尔的设备(!)。
    • @ph0b 如果我们尝试编译应用程序在没有 NDK 的情况下输出 Build.CPU_ABI* ,它将显示正确的结果,即 x86armeabi-v7a ,对此有什么想法吗?
    • 如果应用程序包含正在 x86 设备上安装的 x86 库(或根本没有库),Build.CPU_ABI 应该返回 x86,否则设备上的构建有问题.有时在 Zenfone 上,实际安装的库是 arm 库,因为它认为缺少一些 x86 库,所以它回退到 arm 库。您可以使用我的应用程序轻松确定这一点:play.google.com/store/apps/…
    【解决方案2】:

    您不能依赖 proc/cpuinfo、getProperty("os.arch") 或 Build.CPU_ABI(2)。如果仿真处于活动状态,它们都是假的。我进行检测的方式是解析 /proc/cpuinfo 以查找单词“占位符”。它在“硬件:”行中。通常有一个真正的公司名称,如三星 Galaxy 的“Samsung”,但在 x86 上的 ARM 仿真的情况下,我看到 /proc/cpuinfo 中的硬件行中只有“占位符”。我还没有在很多设备型号上测试过,所以不能说这种方式有多可靠。

    【讨论】:

      【解决方案3】:

      这听起来很可怕,如果您有不同的 ARM 和 x86 本地库列表,那么像 ARM 模拟器这样的设备会自动切换到在 ARM 模拟器下运行应用程序。

      https://software.intel.com/en-us/forums/android-applications-on-intel-architecture/topic/518471

      【讨论】:

        【解决方案4】:

        您还可以检索 ELF 文件头中定义的 e_machine 值,例如文件 libc.so,以检测指定的架构。

        https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header

        代码sn-p:

        File libc = new File(Environment.getRootDirectory(), "lib/libc.so"); // or 'lib64' if 64 bit
        // assert libc file exsits
        RandomAccessFile file = new RandomAccessFile(libc, "r");
        file.seek(0x12); // 'e_machine' offset
        byte[] buf = new byte[2]; // 2 bytes size
        file.readFully(buf);
        int em = (buf[0] & 0xff) | ((buf[1] & 0xff) << 8);
        file.close();
        if(em == 0x03 || em == 0x3E) {
            // x86!
        }
        

        Build.CPU_ABI 表明你在ARM 上运行,但与x86 em 冲突时,它正在模拟!

        【讨论】:

          猜你喜欢
          • 2013-08-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-23
          • 2023-03-14
          • 2012-05-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多