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

7
我有一个由第三方供应商提供的.so文件,需要将其包含在我的Android应用程序中。我无法访问源代码,也不能(轻松地)联系供应商。
是否有一种方法通过检查.so文件来确定它是否针对armeabi或armeabi-v7a ABI进行编译?
我问这个问题有两个原因。首先,我希望它已经针对armeabi-v7a ABI进行了编译,以获得与armeabi相比改进的性能;知道这一点将使我有信心获得最佳性能。此外,我想适当地命名包含.so文件的目录(即根据所针对的ABI命名文件夹为“armeabi”或“armeabi-v7a”)。

2
你是否尝试在某个Linux发行版上运行fileobjdumpreadelf命令来查看你的.so文件? - Basile Starynkevitch
1
可能最权威的objdump或readelf要使用的是提供在Android NDK发行版中的那个。 - Chris Stratton
3个回答

6

在Android SDK中,readelf可以更轻松地解决类似这样的问题:

路径(可能根据您自己的平台而变化): sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-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

我该如何解释这个输出?(因为我没有直接看到任何armeabi。)谢谢! - ch271828n
对于 armeabi-v7a,输出将为:文件:./shared_libs/armeabi-v7a/libscimd_lib.so 属性部分:aeabi 文件属性 Tag_CPU_name: "ARM v7" Tag_CPU_arch: v7 - drlolly

2

我最终使用来自Android NDK的arm-linux-androideabi-objdump程序对.so文件进行了反汇编。在反汇编代码中,我发现了vmaxnm.f32指令,该指令出现在armeabi-v7a指令集中但出现在armeabi中。基于此,我得出结论,.so是针对armeabi-v7a编译的。可能还有其他指令可以查找,但我对ARM指令集不太熟悉,无法确定。幸运的是,这一个比较明显(它是浮点操作之一,是armeabi和armeabi-v7a之间的主要区别)。感谢那些发布意见的人。


2
是的,验证库未构建为arm-v6比相反容易。应该提到,一些奇怪的构建使用arm-v7指令,但仍然构建为armeabi。它们使用运行时CPU检测并避免会导致崩溃的指令(参见例如https://dev59.com/Amsz5IYBdhLWcg3wwKuh)。libx264甚至更进一步:他们尝试发出一个arm-v7指令并捕获异常,这样他们就可以决定哪个指令集可用。 - Alex Cohn
如果你查看一个编译为armeabi-v7a的共享库,你会在末尾看到类似于"GCC: (GNU) 4.7 GNUgold 1.11A=aeabi3ARM v7 A"的内容。相应的armeabi数据类似于"GCC: (GNU) 4.8 GNUgold 1.11A*aeabi 5TE"。这只是一个猜测,但是'v7'和'5TE'的模式似乎分别适用于编译为armeabi-v7a和armeabi的库。完全透露,我对ARM架构细节知之甚少。 - CCJ

-1

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

Reference-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

public class MainActivity extends 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);
}

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接