如何确定Android .so文件的ABI(即armeabi或armeabi-v7a)?

时间:2014-03-24 21:10:48

标签: android android-ndk

我有一个第三方供应商提供的.so文件,该文件将包含在我的Android应用程序中。我无法访问源代码,也不能(轻松)联系供应商。

我有没有办法通过检查.so文件来确定是否针对 armeabi armeabi-v7a ABI进行了编译?

我要问两个原因。首先,我更倾向于针对armeabi-v7a ABI进行编译,以获得与armeabi相比改进的性能;知道这会让我相信我会获得最佳表现。另外,我想命名.so文件正确存在的目录(即命名文件夹“armeabi”或“armeabi-v7a”,对应于编译目标的ABI)。

3 个答案:

答案 0 :(得分:3)

Android SDK中的readelf应该更容易解决这个问题:

路径可能会根据您自己的平台进行更改):sdk / ndk-bundle / toolchains / arm-linux-androideabi-4.9 / prebuilt / darwin-x86_64 /箱/臂-Linux的androideabi-readelf

$ arm-linux-androideabi-readelf -A liba.so
Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "5TE"
  Tag_CPU_arch: v5TE
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-1
  Tag_FP_arch: VFPv2
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-byte
  Tag_ABI_enum_size: int
  Tag_ABI_optimization_goals: Aggressive Speed
  Tag_DIV_use: Not allowed

答案 1 :(得分:2)

我最终使用Android NDK中的arm-linux-androideabi-objdump程序反汇编.so文件。在反汇编代码中,我找到了vmaxnm.f32指令,该指令存在于armeabi-v7a指令集中,但在armeabi中。基于此,我得出结论,.so是针对armeabi-v7a编制的。可能有其他指令我可以查找,但我并不熟悉ARM指令集能够分辨。我很幸运,这个是相当明显的(因为它是一个浮点运算,armeabi和armeabi-v7a之间的主要区别之一)。感谢发布者的想法。

答案 2 :(得分:-1)

是的,您可以使用ReadElf.java找到.SO文件的ABI版本。

参考-https://android.googlesource.com/platform/cts/+/17fcb6c/libs/deviceutil/src/android/cts/util/ReadElf.java

我制作了一个示例Android应用,该应用使用ReadElf.java查找提供的.SO库的ABI。
GitHub链接: https://github.com/robust12/ArchFinderBLStack

公共类MainActivity扩展了AppCompatActivity {

private final String TAG = "MainActivity";

private final String ARMV7ABI = "armeabi-v7a";
private final String X86 = "x86";
private final String MIPS = "mips";
private final String X86_64 = "x86_64";
private final String ARM64_V8 = "arm64-v8a";
private final String ARMABI = "armeabi";
private String result = "";

private File[] libFilesArray;
private int request_code = 1;
HashMap<Integer, String> typeMap;
private TextView textView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textView = findViewById(R.id.textViewId);
    typeMap = new HashMap<>();
    initializeMap();
    readFilesFromStorage();
    textView.setText(result);
}

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
private void readFilesFromStorage() throws NullPointerException {
    String filePath = Environment.getExternalStorageDirectory() + "/test-input/";
    File readSOFILE = new File(filePath);
    if(!readSOFILE.exists()) {
        result = getString(R.string.path_not_exist);
        return;
    }
    libFilesArray = readSOFILE.listFiles();
    if(libFilesArray == null) {
        result = getString(R.string.error);
        return;
    }
    findAbiType();
}

private void findAbiType() {
    int count = libFilesArray.length;
    int soCount = 0;
    result = "";
    Log.e(TAG, "Count  is  " + count);
    for (int i = 0; i < count; i++) {
        try {
            if (libFilesArray[i].isFile()) {
                int type = ReadElf.read(libFilesArray[i]).getType();
                if (type == 3) {
                    soCount++;
                    int archCode = ReadElf.e_machine;
                    result += libFilesArray[i].getName() + " - " + typeMap.get(archCode) + "\n\n";
                    Log.e(TAG, "Code  is  " + archCode);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    if(soCount != 0) {
        result += "Total Libs Count: " + soCount + "\n\n";
    } else{
        result = getString(R.string.incorrect_type_libs);
    }
}

private void initializeMap() {
    typeMap.put(40, ARMV7ABI);
    typeMap.put(3, X86);
    typeMap.put(8, MIPS);
    typeMap.put(62, X86_64);
    typeMap.put(183, ARM64_V8);
    typeMap.put(164, ARMABI);
}

}