查看so是32/64、debug/release
- 64位示例:
file libopenal.so libopenal.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, with debug_info, not stripped
- 32位示例:
file libopenal.so libopenal.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /system/bin/linker, with debug_info, not stripped
编码实现查看so的位数
QString AsssistPanel::getDllBit(const char* dllFullpath) { QString ret = ""; // 以只读方式打开文件 HANDLE hFile = CreateFile(dllFullpath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { ret = "Failed to open file!"; return ret; } // 获取文件的大小 DWORD dwFileSize = GetFileSize(hFile, NULL); if (dwFileSize == INVALID_FILE_SIZE) { CloseHandle(hFile); ret = "Failed to get file size!"; return ret; } // 创建文件映射视图 HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if (hMapping == NULL) { CloseHandle(hFile); ret = "Failed to create file mapping!"; return ret; } LPVOID lpBaseAddress = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); if (lpBaseAddress == NULL) { CloseHandle(hMapping); CloseHandle(hFile); ret = "Failed to map view of file!"; return ret; } // 获取NT头指针 PIMAGE_NT_HEADERS pNtHeader = ImageNtHeader(lpBaseAddress); if (pNtHeader == NULL) { UnmapViewOfFile(lpBaseAddress); CloseHandle(hMapping); CloseHandle(hFile); ret = "Failed to get NT header!"; return ret; } // 获取文件头指针 PIMAGE_FILE_HEADER pFileHeader = &pNtHeader->FileHeader; // 判断DLL文件的位数 if (pFileHeader->Machine == IMAGE_FILE_MACHINE_I386) ret = "32-bit"; else if (pFileHeader->Machine == IMAGE_FILE_MACHINE_AMD64) ret = "64-bit"; else ret = "Unknown machine type."; // 释放资源 UnmapViewOfFile(lpBaseAddress); CloseHandle(hMapping); CloseHandle(hFile); return ret; }
查看so所使用的ndk版本
readelf
是Linux/Unix系统下的一个命令行工具,用于查看ELF(Executable and Linkable Format)文件的信息。ELF是一种可执行文件和共享库的标准格式,是Linux系统下常见的二进制文件格式,它包含了程序的代码、数据、符号表、动态链接信息等。
readelf
可以以多种不同的方式展示ELF文件的内容,例如显示文件头、节头、符号表、重定位表等等。使用readelf
可以快速有效地了解一个ELF文件的内部结构和特征,同时也可以了解它的依赖关系和调试信息等。
下面是一些常用的readelf
命令选项:
-h
显示ELF文件头信息。
-S
显示节头信息,包括各个节的类型、名称、大小、偏移地址等。
-s
显示符号表信息,包括函数、变量、定义和引用等。
-r
显示重定位表信息,包括重定位类型、符号、偏移等信息。
-d
显示动态节信息,包括动态链接器所需要的信息。
-A
显示文件属性,包括系统架构、字节序、OS版本等。
-V
显示版本信息。
-x <section>
显示指定节(section)的内容。
readelf
命令非常有用,尤其是在调试和分析ELF文件时。正因为如此,它也是GNU Binutils工具包中的一个重要组成部分,被广泛应用于Linux和Unix系统中。
readelf -p
是readelf
命令的一个选项,用于显示ELF文件中的某个特定段(program section)的数据内容。最常见的用法是使用readelf -p .rodata
来查看只读数据段(read-only data section)的内容。
在ELF文件中,程序段是代码和数据的块,可以有多个段。每个段都有一个段头(section header),用于记录段的大小、偏移量、访问权限等信息。在.rodata
这个只读数据段中,通常存储着程序中的常量、字符串和其他静态数据。
readelf -p ".comment" libavcodec.so String dump of section '.comment': [ 0] Android (5220042 based on r346389c) clang version 8.0.7 (https://android.googlesource.com/toolchain/clang b55f2d4ebfd35bf643d27dbca1bb228957008617) (https://android.googlesource.com/toolchain/llvm 3c393fe7a7e13b0fba4ac75a01aa683d7a5b11cd) (based on LLVM 8.0.7svn)
这里查询到clang version 8.0.7,那么我们只需要看下ndk里面的,NDK历史版本
# toolchains/llvm/prebuilt/xxx/bin/clang clang -v
每个ndk版本所携带的编译器版本都会发生变化,以下是我收集的ndk和clang的对应关系:
ndk version | clang version | .so case |
r10c | 3.4 | |
r14b | 3.8.275480 | |
4.4.3 | libcocos2dlua.so | |
4.6 | ||
4.8 | libGCloudVoice.so | |
4.9 | libBugly.so | |
r15c、r15 | 5.0.3 | |
r16b | 5.0.300080 | |
r17c | 6.0.2 | |
r20b | 8.0.7 | |
21 | 9.0.8 |