[英]How to determine ABI of Android .so file (i.e. armeabi or armeabi-v7a)?
I have a .so file provided by a third-party vendor that is to be included in my Android application.我有一个由第三方供应商提供的 .so 文件,该文件将包含在我的 Android 应用程序中。 I do not have access to the source code nor can I (easily) contact the vendor.我无权访问源代码,也无法(轻松)联系供应商。
Is there a way for me to figure out by examining the .so file whether or not it was compiled targeting the armeabi or armeabi-v7a ABI?我有没有办法通过检查 .so 文件来确定它是否是针对armeabi或armeabi-v7a ABI 编译的?
I'm asking for two reasons.我问有两个原因。 First, I prefer for it to have been compiled targeting the armeabi-v7a ABI to get the improved performance compared to armeabi;首先,我更喜欢针对 armeabi-v7a ABI 编译它,以获得比 armeabi 更高的性能; knowing this will give me confidence that I'm getting the best possible performance.知道这会让我有信心获得最佳性能。 Also, I would like to name the directory in which the .so files live appropriately (ie name the folder "armeabi" or "armeabi-v7a" corresponding to the ABI that it was compiled targeting).另外,我想适当地命名 .so 文件所在的目录(即,将文件夹命名为“armeabi”或“armeabi-v7a”,与它编译的目标 ABI 相对应)。
readelf in Android SDK should solve something like this easier: Android SDK 中的 readelf 应该更容易解决这样的问题:
PATH ( may change based on your own platform ): sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-readelf PATH (可能会根据您自己的平台更改):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
I ended up disassembling the .so files using the arm-linux-androideabi-objdump
program from the Android NDK.我最终使用 Android NDK 中的arm-linux-androideabi-objdump
程序反汇编了 .so 文件。 In the disassembled code I found the vmaxnm.f32
instruction, which is present in the armeabi-v7a instruction set but not in armeabi.在反汇编的代码中,我找到了vmaxnm.f32
指令,它存在于 armeabi-v7a 指令集中,但不存在于 armeabi 中。 Based on that I concluded that the .so was compiled targeting armeabi-v7a.基于此,我得出结论,.so 是针对 armeabi-v7a 编译的。 There are probably other instructions that I could have looked for but I'm not at all familiar with the ARM instruction set to be able to tell.可能还有其他我可以寻找的指令,但我对 ARM 指令集一点也不熟悉,无法分辨。 I got lucky that this one was fairly obvious (being that it is a floating point operation, one of the major differences between armeabi and armeabi-v7a).我很幸运,这是一个相当明显的(因为它是一个浮点运算,这是 armeabi 和 armeabi-v7a 之间的主要区别之一)。 Thanks for the ideas to those who posted.感谢那些发帖的人的想法。
Yes you can find ABI version of .SO file using ReadElf.java.是的,您可以使用 ReadElf.java 找到 .SO 文件的 ABI 版本。
Reference- https://android.googlesource.com/platform/cts/+/17fcb6c/libs/deviceutil/src/android/cts/util/ReadElf.java参考 - https://android.googlesource.com/platform/cts/+/17fcb6c/libs/deviceutil/src/android/cts/util/ReadElf.java
I have made a sample Android app which finds ABI of provided .SO libs using ReadElf.java.我制作了一个示例 Android 应用程序,它使用 ReadElf.java 查找提供的 .SO 库的 ABI。
GitHub Link : https://github.com/robust12/ArchFinderBLStack GitHub 链接: https : //github.com/robust12/ArchFinderBLStack
public class MainActivity extends AppCompatActivity {公共类 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);
}
} }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.