kernel

下载和编译内核步骤

Android 9.0内核编译

下载内核

cd kernel
git clone https://android.googlesource.com/kernel/goldfish

执行完这两条命令后就可以看到kernel目录下有一个goldfish目录了,goldfish内核专门是提供给emulator用的.

cd goldfish
git branch -r
git checkout origin/android-goldfish-4.4-dev -b android-goldfish-4.4-dev

这里涉及到要下载哪个版本的内核,emulator命令默认用的是qemu内核, 一般跟这个版本的内核一样就可以了,可以直接启用emulator然后进入到Settings->System->About phone->点击Android version,里面就有内核版本号.

编译内核

一定要和Android编译时lunch选的一样, 可以进入到out/target/product目录下查看自己编的是什么版本, 如果是generic_x86_64,那lunch的就是aosp_x86_64_eng的,其他版本依此类推. 接下来就可以编译了,下面我提供了几个编译的脚本大家可以进行对比和参照,lunch不同的版本对应的脚本是不一样的,即使编译通过了,也不能运行,我因为这个浪费了很长的时间 使用方法:

  1. 在goldfish目录下创建一个build.sh文件
  2. 将脚本里面的内容复制到build.sh中,或者根据脚本自己写, 注意lunch的版本
  3. 执行chmod a+rx build.sh并且执行./build.sh.

aosp_x86-eng

#指定编译的内核类型
export ARCH=x86
#指定的gcc编译器的前缀, 就是下面PATH中的x86_64-linux-android-4.9的前缀
export CROSS_COMPILE=x86_64-linux-android-
export REAL_CROSS_COMPILE=x86_64-linux-android-
#这里android_root要写是android根目录的绝对地址例如: ~/google/android-9.0
PATH=$PATH:/home/zhenghuan/Android/Source/android-9.0.0_r3/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin
#编译的配置,在arch/x86/configs目录下,
make x86_64_ranchu_defconfig
#编译内核命令
make -j16

编译内核大概10来分钟就可以完成了,之后会生成一个arch/x86_64/boot/bzImage的东西,不同kernel生成的是不一样的,要看清楚. 最后回到android根目录执行emulator -kernel kernel/goldfish/arch/x86/boot/bzImage启动虚拟机

启动虚拟机

~/Android/Source/android-9.0.0_r3$ emulator -show-kernel -kernel /home/zhenghuan/Android/Source/kernel/goldfish/arch/x86/boot/bzImage -qemu -s

  • -kernel use specific emulated kernel 指定模拟器的内核,这里指定我们自己编译的内核arch/x86/boot/bzImage
  • -qemu args... pass arguments to qemu 传递qemu参数,emulator就是基于qemu开发的
  • -s 是qemu参数,等同于-gdb tcp::1234,意思就是通过tcp的1234端口,gdb可以连接到内核中的kgdb。一般连接kgdb都要通过串口来连接,但是qemu通过指定-gdb tcp::1234就可以了,不知到原理是什么。

调试android内核

使用Android模拟器调试linux内核

如何在Android上调试内核

在Android上调试内核,一般都要借助于内核中的kgdb。kgdb是内核对gdb的支持,通过编译配置kgdb和其他相关配置,可以通过gdb远程连接到内核中的kgdb。kgdb只能远程调试,也就是说,要有一台被调试的机器(target machine)和一台开发机器(develop machine)。如果真机调试,target就是手机,develop就是ubuntu主机。如果是模拟器调试,target就是模拟器,develop是ubuntu主机。

步骤

goldfish/.config编译选项

CONFIG_DEBUG_KERNEL=y 打开这个选项后,vmlinux 才有符号
CONFIG_DEBUG_INFO=y
CONFIG_FRAME_POINTER=y
//开启kgdb
CONFIG_KGDB=y 
CONFIG_DEBUG_RODATA=n
CONFIG_RANDOMIZE_BASE=n

CONFIG_DEBUG_RODATA这个选项我们虽然手动设置为n,但是执行make后会被覆盖,所以我们要改以下两个文件,确保CONFIG_DEBUG_RODATA不开启:

zhangjg@zjg:~/deve/open_source/android-kernel/goldfish$ git diff
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 41218867a9a6..e67810313d97 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -1052,7 +1052,7 @@ config ARM_KERNMEM_PERMS
 config DEBUG_RODATA
        bool "Make kernel text and rodata read-only"
        depends on ARM_KERNMEM_PERMS
-       default y
+       default n
        help
          If this is set, kernel text and rodata will be made read-only. This
          is to help catch accidental or malicious attempts to change the
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ad1f3bfafe75..50fa4dc68eff 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -307,7 +307,7 @@ config FIX_EARLYCON_MEM
        def_bool y
 
 config DEBUG_RODATA
-       def_bool y
+       def_bool n
 
 config PGTABLE_LEVELS
        int

注意,一定确保CONFIG_DEBUG_RODATACONFIG_RANDOMIZE_BASE不开启,如果开启这两个选项,通过gdb不能设置断点,报如下错误:

(gdb) b vfs_write
Breakpoint 1 at 0xffffffff803474d8: file fs/read_write.c, line 524.
(gdb) c
Continuing.
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0xffffffff803474d8

make -j16

Serial console over KGDB NMI debugger port (SERIAL_KGDB_NMI) [N/y/?] (NEW) N
KGDB: kernel debugger (KGDB) [Y/n/?] y
KGDB: use kgdb over the serial console (KGDB_SERIAL_CONSOLE) [Y/n/m/?] (NEW) n
KGDB: internal test suite (KGDB_TESTS) [N/y/?] (NEW) N
KGDB: Allow debugging with traps in notifiers (KGDB_LOW_LEVEL_TRAP) [N/y/?] (NEW) N
KGDB_KDB: include kdb frontend for kgdb (KGDB_KDB) [N/y/?] (NEW) y
KDB: Select kdb command functions to be enabled by default (KDB_DEFAULT_ENABLE) [0x1] (NEW) 0x1
KGDB_KDB: keyboard as input device (KDB_KEYBOARD) [N/y/?] (NEW) y
KDB: continue after catastrophic errors (KDB_CONTINUE_CATASTROPHIC) [0] (NEW) 0

Kernel: arch/x86/boot/bzImage is ready  (#2)
ton在内核源码根目录生成vmlinux文件

启动虚拟机

gdb /path/to/vmlinux

最好使用aosp/prebuilts/gdb/linux-x86里的gdb,这个版本的gdb是兼容所有体系结构的。 gdb命令在aosp/prebuilts/gdb/linux-x86/bin目录中

~/Android/Source/kernel/goldfish$ export PATH=/home/zhenghuan/Android/Source/android-9.0.0_r3/prebuilts/gdb/linux-x86/bin:$PATH
~/Android/Source/kernel/goldfish$ which gdb
/home/zhenghuan/Android/Source/android-9.0.0_r3/prebuilts/gdb/linux-x86/bin/gdb

~/Android/Source/kernel/goldfish$ gdb ./vmlinux
GNU gdb (GDB) 7.11
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./vmlinux...done.

(gdb) target remote :1234
Remote debugging using :1234
0xffffffff834345e8 in ?? ()
(gdb) bt
#0  0xffffffff834345e8 in ?? ()
#1  0xffffffff84003ec8 in ?? ()
#2  0xffffffff8340c0d9 in ?? ()
#3  0x0000000000000000 in ?? ()

调试效果

可以设置断点并进入断点停下,但无法next和step(step有概率能成功)单步跳转,总是跳转到apic模块,考虑使用走读+断点调试的方式研究

其他

全局修改编译优化,位于goldfish/Makefile:

#ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
#KBUILD_CFLAGS	+= $(call cc-option,-Oz,-Os)
#else
#ifdef CONFIG_PROFILE_ALL_BRANCHES
#KBUILD_CFLAGS	+= -O2
#else
#KBUILD_CFLAGS   += -O2
#endif
#endif

KBUILD_CFLAGS   += -Og

https://github.com/torvalds/linux

https://source.android.com/setup/build/building-kernels

https://source.android.com/devices/architecture/kernel

https://android.googlesource.com/kernel/common/

下载时Repo Branches选择common-android-4.14

Building Kernels

This page details the process of building custom kernels for Android devices. The following instructions guide you through the process of selecting the right sources, building the kernel, and embedding the results into a system image built from the Android Open Source Project (AOSP).


android版本与linux内核版本对应关系

https://blog.csdn.net/ly890700/article/details/75040704/

6.0 Marshmallow |23 |3.18.10

Android安卓版本 | API级别 | Linux内核版本 ——————————————————————- 1.5 Cupcake | 3 | 2.6.27 1.6 Donut | 4 | 2.6.29 2.0/1 Eclair | 5-7 | 2.6.29 2.2.x Froyo | 8 | 2.6.32 2.3.x Gingerbread | 9, 10 | 2.6.35 3.x.x Honeycomb | 11-13 | 2.6.36 4.0.x Ice Cream San | 14, 15 | 3.0.1 4.1.x Jelly Bean | 16 | 3.0.31 4.2.x Jelly Bean | 17 | 3.4.0 4.3 Jelly Bean | 18 | 3.4.39 4.4 Kit Kat | 19, 20 | 3.10 5.x Lollipop | 21, 22 | 3.16.1 6.0 Marshmallow | 23 | 3.18.10 7.0 Nougat | 24 | 4.4.1 7.1 Nougat | 25 | 4.4.1 8.0 Oreo | 26 | 4.10 8.1 Oreo | 27 | 4.10 9.0 Pie | 28 | 4.4, 4.9 and 4.14