編譯可在Android上運行的qemu user mode

前言

本文在Ubuntu 64位系統上對qemu項目進行交叉編譯,而且只編譯與qemu user mode有關的代碼。php

下文中的」NDK」若無特殊說明均指」Android NDK」。vue

下文中」$NDK」表示的是NDK的根目錄。linux

 

步驟

1. 下載並安裝Android NDK

下載並安裝Android NDK的過程在這裏不作介紹。android

 

2. 下載qemu

 

3. 設置NDK工具的環境變量

爲交叉編譯設置Android NDK環境變量:NDK、SYSROOTc++

 

4. 編譯依賴庫

glibgit

編譯可在Android上運行的glib庫github

編譯參考資料:編譯可在Android上運行的glib庫vim

libpng12api

下載地址:https://sourceforge.net/projects/libpng/files/libpng12/安全

編譯參考資料:編譯可在Android上運行的libffi庫

 

5. 建立pkg-config的軟連接

ln命令中的源路徑是pkg-config工具的源路徑。

若是不建立這個軟連接,當執行configure腳本時會報下面的錯誤:

 

6. 修改configure

添加arm的PIE支持

找到下面的代碼:

將」i386-Linux|x86_64-Linux|x32-Linux|i386-OpenBSD|x86_64-OpenBSD」更改成」i386-Linux|x86_64-Linux|x32-Linux|i386-OpenBSD|x86_64-OpenBSD|arm-Linux」。

若是不這麼作的後果,使用」readelf -S qemu-arm」查看編譯出來的qemu-arm可執行文件的段,能夠發現全部在運行時可加載段的地址均以0x60000000爲基址。

在configure中有這麼一段代碼:

若是textseg_addr」這個命令行選項,這個命令行選項指定text段的基址。在腳本的後面textseg_ldflags會被添加到ldflags中。

若是qemu-arm可加載段的基址爲0x60000000,當qemu-arm在Android設備上運行時將會發生」Segmentation fault」,詳情請參考Android上可執行ELF文件中的段不能有基址

 

7. 運行configure

 

命令行解析

configure腳本會在終端輸出一些關鍵的信息,如:用什麼編譯器,flags等。

 

PKG_CONFIG_PATH

上面命令中的PKG_CONFIG_PATH="$SYSROOT/usr/lib/pkgconfig"是必要的,若是不設置這個宏,configure腳本輸出」CFLAGS」的內容見下:

 

關注」-I」後的路徑,首先說一下這個路徑是怎麼來的,configure腳本中有下面的代碼:

 

「glib_cflags=$pkg_config --cflags $i「語句會得到glib的包含目錄,看這篇文章的人若是電腦上安裝有glib2.0能夠經過這個命令進行查看輸出內容:pkg-config –cflags glib-2.0。然而這個路徑並非我想要的,由於我如今是交叉編譯,目標是ARM,因此我在這裏將一個新的pkgconfig目錄路徑設置到PKG_CONFIG_PATH宏,輸入下面的命令查看輸出內容:

 

輸出內容:

 

會發現此時」-I」後的路徑有了改變。

注意:pkgconfig是一個目錄,在這個目錄中包含了步驟5中安裝的依賴庫的信息。

 

–target-list –cpu

–target-list arm-linux-user 意味着編譯出來的qemu程序用於user mode,能夠執行arm指令,而且這個arm指令的可執行程序的執行環境基於linux系統。 
–cpu=arm 意味着編譯出的qemu程序只能在arm機器上執行。

 

–disable-system –disable-bsd-user

–disable-system:不編譯system mode的代碼。 
–disable-bsd-user:不編譯bsd user mode的代碼。

 

–cross-prefix

交叉編譯工具的前綴,在當前命令行中它的值爲」arm-linux-androideabi-「,那麼configure腳本會去查找名爲arm-linux-androideabi-gcc、arm-linux-androideabi-g++等工具。

 

–disable-tools

當命令行中有–disable-tools選項時,腳本中的禁用want_tools宏將被設置爲」no」,這個宏默認爲」yes」。當want_tools宏爲」yes」時,會對tools宏進行設置,下面是與want_tools有關的設置tools宏的代碼:

configure腳本會將tools宏的內容寫入config-host.mak文件。

 

–disable-guest-agent

當沒有這個選項時,編譯會報下面的錯誤:

爲PC編譯qemu項目沒有這個命令選項時不會報這個錯誤,然而lockf函數在Android上並不存在,因此爲Android編譯qemu項目時會報這個錯誤。

 

編譯錯誤排除

ld: error: cannot find -lutil

將根目錄下的Makefile文件中下面的內容註釋:

 

ifaddrs.h: No such file or directory

錯誤信息

修復辦法:將這個連接中的源文件都下載下來:android-ifaddrs,將下載下來的文件拷貝到qga/目錄下。而後找到qga/Makefile.objs文件,將」ifaddrs.o」插入」qga-obj-$(CONFIG_POSIX)」宏中。

 

mqueue.h: No such file or directory

錯誤信息

修復辦法:將」#include <mqueue.h>」更改成」#include <linux/mqueue.h>」。

 

char __unused[128 - sizeof(target_sigset_t)];

錯誤信息

修復辦法:將__unused更改成_unused。

 

syscall.c:4108:9: error: dereferencing pointer to incomplete type

錯誤信息


修復辦法


改成

 

disas/arm-a64.cc:67: error: undefined reference to ‘__cxa_end_cleanup’

錯誤信息


解決辦法 :在configure中找到下面的代碼:


將這些代碼註釋掉:

緣由分析 :目前在Android NDK中沒有64位版本的object。

 

syscall.c中找不到符號

錯誤信息

 解決辦法:在syscall.c文件中寫下面的內容

 

編譯清理命令

執行下面兩個命令:

make clean

make distclean

 

編譯debug版

調用configure腳本的命令行中添加」–enable-debug」命令選項。

 

做者:尋禹@阿里聚安全,更多技術文章,請訪問阿里聚安全博客

相關文章
相關標籤/搜索