僅僅是提供一種思路去解決編譯出的so庫在loadlibrary時找不到符號的問題。
這裡以查詢靜態庫檔案為例,首先基本可以認為需要的.a庫檔案都是可以在ndk中找到的,連線後生成的so在執行時發生錯誤大部分是因為沒有連線到一些需要的庫,如libz、libm等,所以會有找不到"***"符號的問題。
以找不到"__aeabi_uidiv"符號為例,用如下的方法看一下:
進入ndk的根目錄,輸入:
grep -r "\b__aeabi_uidiv\b" ./ |
grep
"\.a\b"
|egrep -o "\./.+"
|xargs nm |
egrep
"(\.a\b)|(t __aeabi_uidiv\b)"
這條命令的意思是:
1.從當前目錄及其子目錄下找到匹配"\b__aeabi_uidiv\b"(\b表示空格,因為可能會有其它的符號影響查詢,例如搜尋cos時cosh也會作為結果)模式的字串的檔案,目的是找到包含__aeabi_uidiv符號的二進位制檔案,如果找到時,會輸出字串"匹配到二進位制檔案 ******xx(檔案路徑)"
2.從上一步的結果中匹配".a"字尾,以去除無用的檔名
3.上一步的結果中去除"匹配到二進位制檔案"這樣的修飾字串,提取出檔名
4.對這些檔案執行nm命令
5.從輸出結果中找出匹配"t __aeabi_uidiv"的行,意思是要尋找"__aeabi_uidiv"符號,且該符號的型別應該為t,也即在**區中的符號。平常報找不到符號的問題,基本都是因為在編出來的庫中,這些符號是未定義的,也就是u(undefined)。所以需要找到包含這些符號的庫檔案。
前面-l指定庫檔案的路徑,後面的-l指定庫的名稱,這裡的庫檔案為libgcc.a,去掉字尾.a及字首的lib,其庫的名稱為gcc,表示需要連線到gcc庫。
另外這裡可以看到多個libgcc.a檔案,具體應該選擇哪個就需要看經驗或者做其它檢測了。以現在的情況舉例,針對armv7-a平台進行編譯時,可以推斷出應該選擇arm-linux-androideabi工具鏈下的檔案,其中路徑中有thumb的表示與arm的thumb指令集相關(沒用過,不是很了解,但應該在編譯時指定了-mthumb引數才會需要這個),路徑中有hard的可能是與浮點數(軟浮點/硬浮點)的計算方式相關,還沒求證,只是推斷。所以理論上普通編譯的話應當選擇:
./toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a
或者./toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/armv7-a/libgcc.a
根據經驗應該選擇/armv7-a路徑下的libgcc.a。
那如果真的有強迫症,怎麼看這兩個檔案有什麼區別呢?
可以通過工具鏈(./toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin)路徑下的ar來解壓.a檔案來展開其中的.o檔案,再使用objdump工具或readelf工具檢視並比對,首先新建兩個路徑:
mkdir /mnt/unpack01
mkdir /mnt/unpack02
然後進入路徑中呼叫ar工具解壓.a檔案:
這裡的$toolchain是環境變數,其值為大致為"android-ndk-r15c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64"
cd /mnt/unpack01
$toolchain/bin/arm-linux-androideabi-ar -x $toolchain/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a
cd /mnt/unpack02
$toolchain/bin/arm-linux-androideabi-ar -x $toolchain/lib/gcc/arm-linux-androideabi/4.9.x/armv7-a/libgcc.a
然後通過readelf工具檢視任意兩個.o檔案並進行對比
$toolchain/bin/arm-linux-androideabi-readelf -all /mnt/unpack_01/_udivuda.o > /mnt/1.txt
$toolchain/bin/arm-linux-androideabi-readelf -all /mnt/unpack_02/_udivuda.o > /mnt/2.txt
開啟1.txt及2.txt對比後,可以發現1.txt中有:
file attributes
tag_cpu_name: 「5te」
tag_cpu_arch: v5te
而2.txt中為:
file attributes
tag_cpu_name: 「7-a」
tag_cpu_arch: v7
故可以知道兩個libgcc.a對應的cpu平台有差別,按一般的需求而言都是需要armv7-a的庫,所以需要的也就是armv7-a路徑下的libgcc.a。
上面的做法比較複雜,在預先知道需要檢視的內容後,可以直接通過readelf命令並通過-a引數檢視架構相關的資訊,如:
$toolchain/bin/arm-linux-androideabi-readelf -a $toolchain/lib/gcc/arm-linux-androideabi/4.9.x/armv7-a/libgcc.a > /mnt/1.txt
輸出的是所有.o檔案的資訊,但是只需要看最後面乙個檔案的就好 linux中的查詢
無論在哪個作業系統,查詢都是常用操作,本文說一下linux中的查詢。1.find find最常用,引數也一大把,舉個最常用的 find type f name c exec grep l 這個就是在當前目錄 查詢所有含有 字串的c程式原始檔,通過這個例子,大家應該會用了。find功能很強大,有興趣自...
LInux中的查詢
三 awk global regular expression print,表示全域性正規表示式版本。grep 命令用於查詢檔案裡符合條件的字串的一列。若不指定任何檔名稱,或是所給予的檔名為 則 grep 指令會從標準輸入裝置讀取資料。1 查詢時不區分字串的大小寫 grep i 2 查詢時使用正規表...
Linux中的查詢命令
1 which cmd shows the full path of shell commands 顯示某個命令的完整路徑 例如 which touch 輸出 bin touch 2 whereis 選項 檔名 locates source binary and manual sections fo...