對于在Windows上寫代碼寫習慣的人,調試是必不可少的手段,但是轉到Android以後,發現調試手段異常簡陋,跟Windows簡直不是一個級别,特别是Android的核心調試,網上資料也相對較少,不過通過一段時間的倒騰,我終于找到了還算靠譜的調試方法.就是利用Emulator + Eclipse進行Android Linux核心調試.
1.系統預裝環境
在目前為止,都是使用的最新版本的Android開發環境
Ubuntu 14.04
Android SDK( adt-bundle-linux-x86_64-20140702 )
Android NDK( android-ndk32-r10b-linux-x86_64 )
安裝好這幾個環境以後,設定一下環境變量
export PATH=$PATH:ANDROID_NDK_HOME/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin
ANDROID_NDK_HOME鍵值為Android NDK安裝目錄,設定這個環境變量的目的主要是為了使用gcc 4.6版本編譯linux核心.
export PATH=$PATH:ANDROID_SDK_HOME/sdk/tools
ANDROID_SDK_HOME是Android SDK的安裝目錄,設定這個環境變量的目的是友善使用emulator指令!
萬事具備.使用前面安裝的Android SDK建立一個虛拟的裝置.并且確定 emulator -avd Device_Test這條指令可以啟動Android 模拟器.先熱身下.

2.Android Linux核心編譯
2.1 下載下傳GoldFish 源碼
mkdir kernel
cd kernel
git clone http://android.googlesource.com/kernel/goldfish.git
GoldFish是适配模拟器的核心源碼,如果是要具體适配其他機型,請選擇其他源碼,這邊不展開了,詳情參考連結有說明. 如果失敗了,換https.我換https是因為使用了代理,現在google被牆,不使用代理搞不動!
git clone https://android.googlesource.com/kernel/goldfish.git
下載下傳過程看你的代理速度了,而且不能中斷.中斷了就要重新來,特别的麻煩和惡心!是以我上傳了一份到百度雲. 和上面goldfish出來的一樣.可以考慮去下載下傳
http://pan.baidu.com/s/1i3yzhbv
下載下傳或者解壓完成以後會在kernel目錄下會生成一個goldfish檔案夾,進入此目錄.檢視所有分支
可以看到, 有很多的版本, 2.6.29和3.4我都測試過. 編譯和運作沒有任何問題. 是以這邊我們拉2.6.29的源碼
git checkout remotes/origin/android-goldfish-2.6.29
然後目錄下就有很多檔案了,說明Android Linux的源碼下載下傳成功!
3.2 編譯GoldFish 源碼
編譯源碼之前,請确認已經将NDK的編譯工具設定到環境變量中.我們将使用上述這個目錄下的交叉編譯器arm-linux-androideabi-gcc
export PATH=$PATH:ANDROID_NDK_HOME/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin
然後在glodfish目錄下用gedit打開Makefile檔案,找到這兩行文字:
#ARCH ?= $(SUBARCH)
#CROSS_COMPILE ?=
修改成
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-androideabi-
儲存檔案, 然後
make goldfish_armv7_defconfig
注:用$make goldfish_defconfig這樣配置也可以編譯通過,模拟器也可以啟動,但是Android的開機畫機就顯示不了,$adb shell也死活連不上,原因就是這個goldfish_defconfig這個配置檔案問題.
Android Linux的基本編譯就設定完成了.我們先make 一下
make
這就表示編譯成功了,Linux的源碼是Linux上少有的一鍵make過去的軟體,比編譯其他Linux應用簡單不少.當然到這裡編譯出來的這個zImage已經可以運作了,但是離我們用來做調試的還是有差距.我們還要開啟核心調試和關閉優化.
3.3 開啟調試選項
開啟Linux核心的調試選項, 先安裝依賴性
sudo apt-get install ncurses-dev
然後
make menuconfig
進入核心配置界面,勾選下列選項,同時關閉優化
General setup —>
[ ] Optimize for size,進行開啟/關閉
[*] Kernel hacking
[*] Compile the kernel with debug info
[*] KGDB: kernel debugging with remote gdb —>
[*] Enable dynamic printk() call support
關閉Linux核心優化比較麻煩.我通過和朋友讨論,以及網絡搜尋還沒有找到很好的解決辦法,原因是預設的Linux核心編譯是開啟-O2優化的,這種模式之下會造成gdb和實際的源碼對不上,相信使用過windbg調試-O2的朋友都有這個經曆,是以我們需要關閉Linux的-O2,不過目前還沒有很好的解決辦法下面這篇文章讨論的解決辦法是.針對檔案進行關閉優化.下面這兩篇文章的讨論都非常有意義:
http://www.lenky.info/archives/2013/03/2238
http://www.ibm.com/developerworks/cn/linux/l-kdb/
這邊我們将-Os 和-O2都調成-O.針對具體檔案關閉優化,這邊就不搞了.具體到自己的調試任務的時候再看.
再進行編譯,
make -B
選項-B以強制所有核心源檔案全部重新編譯(因為我前面編譯過一次了,為了保險起見,就讓目标檔案全部重新生成吧)當出現這個畫面,就表示編譯成功了
4.Android Linux核心調試
使用emulator 啟動我們編譯的核心試試
emulator -verbose -show-kernel -kernel ~/kernel/goldfish/arch/arm/boot/zImage -avd Device_Test
沒錯, 啟動的就是我們的核心2.6.29 時間也對的上.說明我們編譯的核心是可以運作的.下一步使用這條指令
emulator -verbose -show-kernel -kernel -netfast ~/kernel/goldfish/arch/arm/boot/zImage -avd Device_Test -qemu -gdb tcp::1234,ipv4, -S
這條指令會在tcp端口的1234監聽.加了-S還會暫停下來,等待着gdb連結上來.這時候我們開啟NDK目錄下面的gdb.鍊上去然後
target remote localhost:1234
還可以測試幾條指令, 看看源碼是否跟上了.
到這裡為止,基本上是用gdb連上emulator 進行核心調試應該沒問題了.但是僅僅到這裡那離windbg的調試還是差好幾條街.是以我們還是需要一個更好的調試方法.是用eclipse來作為調試的前端!
5.Eclipse前端
是用Eclipse作為前端的好處是,無論是在windows,在linux下面都沒有問題.可以在一台windows的機器上,遠端調試android核心.是以為了截圖友善,我下面的操作都是在windows上弄的,在Linux上也是一樣!當然要在windows上進行調試,首先要将上面的gold目錄複制到windows的機器上,或者是共享給windows.這裡就不展開了!
運作Eclipse,點選菜單Help->Install New Software… 在彈出的對話框裡點選Work with:後面的下拉按鈕,選擇Kepler – http://download.eclipse.org/releases/kepler
不同的Eclipse版本選擇不一樣,與自己下載下傳的版本一緻一即可.然後在下面的選擇框中将以下選項安裝上
Programming Languages
C/C++ Autotools support
C/C++ Visual C++ Support
C/C++ Development Tools
C/C++ Development Tools SDK
Linux Tools
GDB Tracepoint Analysis
Mobile and Device Development
C/C++ GDB Hardware Debugging
安裝好後自動重新開機Eclipse即可.再配置點選菜單Window -> Preferences在彈出的對話框中,點選左邊的General->Workspace将右邊的Build automatically複選框不選中.
再點選對話框左邊的C/C++->Indexer,将右邊的Enable indexer和Automatically update the index兩複選框不選中.
接下來就簡單了.建立一個工程,點選菜單File->New->Project…在彈出的對話框中選擇C/C++->C Project再點選Next >按鈕
其中Project name:為工程名,可自定義.而Location:則為工程檔案所在路徑,此處設定為我們下載下傳的源碼路徑而Project type:則設定為Makefile project/Empty Project, Toolchains:則設定為Linux GCC,如果是windows設定成Android GCC最後點選Finish即可.
接下來Windows和Linux都一樣,進行DEBUG配置,在Project Explorer裡右擊剛建立的Linux_Kernel項目,在右鍵菜單中點選Debug As->Debug Configurations…在彈出的對話框中輕按兩下GDB Hardware Debugging 然後配置調試選項如下圖
将C/C++ Application:欄設定為Linux Kernel源碼編譯出來的vmlinux檔案所在路徑(包含檔案名),然後将Disable auto build選上,切換到Debugger頁,修改配置如下截圖.
這裡是設定gdb的路徑還有遠端位址和端口. Gdb的路徑在ndk安裝目錄下的如下路徑
\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin
遠端位址,我的ubuntu機器是192.168.1.2這個随機應變即可.端口是我們運作emulator指令定義的端口.搞定這個切換到Startup頁面
将Reset and Delay(seconds)和 Halt 還有Load image複選框的勾都去掉.然後點選Debug,這時候就停在第一條指令了
這時候還不能按F5, F6單步.我們在Execut視窗指定到main.c 然後在 start_kernel上下個斷點也可以再Console視窗敲指令break start_kernel. 然後敲入指令C.
這時候就停在了Linux核心的入口函數start_kernel.也可以使用F5,F6了.寄存器顯示各方面都可以了.如果在Windows上,有一個毛病,源檔案都要自己重新指定路徑.不然認不到. 預設都是編譯路徑/home/xxx什麼的.要重新指定成Windows的盤符形式.不過在Linux上調試就沒有這個問題了!
這個調試差不多是搞起走了.如果是分析Android的源碼,看一看跟一下還是很不錯的.不過還是有一個問題沒有解決,關于彙編和符号不對應的問題.大家可以群策群力搞一下!
參考連結:
http://wenku.baidu.com/view/95c69448e518964bcf847c2f.html
http://blog.csdn.net/flydream0/article/details/7070392
http://www.lenky.info/archives/2013/03/2238
http://blog.csdn.net/liushuaikobe/article/details/8646555
http://x-slam.com/da_jian_eclipse_qemu_gdb_diao_shi_linux_kernel_huan_jing
菊子曰:專業的 部落格管理軟體
文章發表于 2014-09-27 15:21:24, 所屬分類 Android 。您可以通過訂閱RSS 2.0來跟蹤該文章的評論。 本文Trackback位址:http://www.joenchen.com/archives/1093/trackback。
網友評論:
-
Android Linux核心編譯調試 Rover12421 2014-10-10 10:30:33 說:
不建議修改Makefile檔案.可以在make指令後面添加參數
make ARCH=arm CROSS_COMPILE=arm-linux-androideabi- goldfish_armv7_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-androideabi-
make的時候順便加上-j參數,多線程編譯加快速度
make ARCH=arm CROSS_COMPILE=arm-linux-androideabi- -j8
-
Android Linux核心編譯調試 Rover12421 2014-10-10 11:36:49 說:
emulator -verbose -show-kernel -kernel -netfast ~/kernel/goldfish/arch/arm/boot/zImage -avd Device_Test -qemu -gdb tcp::1234,ipv4, -S
指令有誤,修改如下:
emulator -verbose -show-kernel -netfast -kernel ~/kernel/goldfish/arch/arm/boot/zImage -avd Device_Test -qemu -gdb tcp::1234,ipv4 -S
-
Android Linux核心編譯調試 Joen 2014-10-13 13:15:23 說:
你說的對, -netfast 和-kernel 要調換下順序, 可能是我寫文章的時候寫錯了!
-
Android Linux核心編譯調試 joen 2015-09-02 15:39:01 說:
今天為了研究linux的slub配置設定器.編譯了um來調試.但是由于linux核心預設情況下使用-O2,而最低要求需要-O1才能編譯成功.在打開優化的情況下,調試起來源代碼會亂跳.為了解決這個問題,我折騰了幾分鐘.發現有三個地方需要修改就可以了
第一處 include/linux/compiler-gcc.h 在裡面inline __inline這些定義之後都有 aways_inline的attribute,要把這個屬性删除
另一處, 在menuconfig裡,kernel hack裡面不選中”Force gcc to inline functions marked inline”
當然,最後,Makefile裡面那個-O2要删除掉,也就是不用任何優化來編譯(貌似這個時候就是-O0)
之後用make ARCH=um 就可以編譯成功了. 我精簡過的um編譯出來大概15M.(選擇了compile the kernel with debug info)
-
Android Linux核心編譯調試 老蝸牛 2016-03-17 10:52:21 說:
樓主你好,我是新手,按照你的步驟一步步進行核心調試。預裝環境與文章一緻,linux核心用的3.4,在進行eclipse核心調試時,提示no source available for “0x0”,且 在executables中沒有init 的main函數。請問如何破解?
原文位址: http://www.joenchen.com/archives/1093