Android内核模块编译

CONFIG_USB_STORAGE=m
CONFIG_USB_STORAGE_REALTEK=m
CONFIG_REALTEK_AUTOPM=y
dmesg | grep -E "SCSI|Bulk"
内核虚拟地址打印方式:强制转换成uintptr_t类型,然后使用%lx打印即可。或者直接使用%px打印内核虚拟地址。
Tool: Binary Viewer, 010editor

1 Android 8.0 build kernel module
1.1 Makefile
# [RFC] kbuild: add CLANG_TRIPLE to prevent clang from compiling with wrong --target
# ARCH=arm64 or x86_64
# apt install linux-headers-$(uname -r)
# PC KDIR = /lib/modules/$(uname -r)/build
PREFIX=/path/to/android
KDIR=$(PREFIX)/out/target/product/$(TARGET_PRODUCT)/obj/kernel
# should not add prefix ./, otherwise fail to build
MOD_SRC=drivers/usb/storage
KO=usb-storage.ko

# obj-m = usb-storage.ko
all:
        make -C $(KDIR) \
        ARCH=x86_64 \
        LLVM=1 \
        M=$(MOD_SRC) \
        KBUILD_EXTRA_SYMBOLS=\
        $(KDIR)/Module.symvers \
        V=1 \
        CONFIG_USB_STORAGE=m \
        modules
        $(call sign_module)
clean:
        make -C $(KDIR) \
        M=$(MOD_SRC) \
        clean

aarch64-poky-linux-strip -S xxx.ko
$STRIP -S xxx.ko
After this change, it's easy to use ZMODEM file transfer.

1.2 sign module
qcom AndroidKernelModule.mk sign module.
PEM: Privacy Enhanced Mail

modinfo /path/to/usb-storage.ko
zcat /proc/config.gz |grep SIG_

define sign_module
    cp $(KDIR)/drivers/usb/storage/$(KO) .
    $(KDIR)/scripts/sign-file sha512 \
    $(KDIR)/certs/signing_key.pem \
    $(KDIR)/certs/signing_key.x509 \
    $(KO)
    hexdump -C $(KO) | tail
endef

1.3 How to get ko keyring files?
./scripts/extract-sys-certs.pl /PATH/TO/vmlinux /tmp/signing_key.x509
openssl x509 -pubkey -noout -inform der -in /tmp/signing_key.x509 -out /tmp/signing_key.pem

2 ko modversion
2.1 Module.symvers
modprobe --dump-modversions xxx.ko | grep module_layout
cat Module.symvers | grep module_layout

.tmp_versions: rename all .mod to .xxx under .tmp_versions
vmlinux: rename vmlinux to vmlinux-bak
after the above two change, make -C will use Module.symvers to generate ko modversion.

2.2 SA8155 extract-symvers
modprobe --dump-modversions xxx.ko > nm.symvers
python extract-symvers.py nm.symvers Module.symvers

import sys,os
def my_replace(src_file, line_in):
    arr_in = line_in.split()
    f = open(src_file, 'r')
    for line in f:
        arr = line.split()
        if (arr[1] == arr_in[1]):
            f.close()
            arr_in[0] = arr[0]
            mstr = '\t'
            mstr = mstr.join(str(i) for i in arr_in)
            return (mstr + '\t' + '\n')
    f.close()
    return line_in

def run_replace(src_file, dst_file):
    tmp_f = open('tmp.txt', 'w')
    f = open(dst_file, 'r')
    for line in f:
        tmp_f.writelines(my_replace(
            src_file, line))
    tmp_f.close()
    f.close()
    os.rename(dst_file, "Module_orig.symvers")
    os.rename('tmp.txt', "Module.symvers")

def main():
    arg0_proc_name = sys.argv[0]
    if sys.argv[0].rfind(
            os.path.sep) > 0 :
        index = sys.argv[0].rfind(
            os.path.sep)
        arg0_proc_name = \
            sys.argv[0][index + 1:]
    if len(sys.argv) < 3:
        print('\nUsage: python ' +
            arg0_proc_name +
            ' <src_file>' +
            ' <dst_file>\n')
        sys.exit(0)
    run_replace(sys.argv[1],
        sys.argv[2])

if __name__ == '__main__':
    main()

3 kernel module debug
3.1 module log
# p: enable pr_debug
insmod <module_name> dyndbg==p

echo "module <module_name> +p" > \
/sys/kernel/debug/dynamic_debug/control

get module_name from lsmod

3.2 ko objdump
init_module+0x7c/0xeb0
func+offset/last_addr

aarch64-poky-linux-objdump -l -C -S xxx.ko > deasm.log
vi deasm.log
输入#00 Frame前面显示的pc指向的地址(需要去掉前面的多个0)
ARM64汇编中,x0 - x7用来传递函数第一到第八个参数,超出的参数通过堆栈来传递。

3.3 ARM64汇编
sub sp, sp, #0x80 // 分配stack局部空间,大小是0x80字节,准备存放函数局部变量

ldr x0, [x1]; // 从x1指向的地址里面取出一个64位大小的数存入x0
ldp x1, x2, [x10, #0x10]; // 从x10 + 0x10指向的地址里面取出2个64位的数,分别存入x1,x2
str x5, [sp, #24]; // 把x5的值(64位数值)存到sp + 24指向的内存地址上
stp x29, x30, [sp, #-16]!; // 把x29,x30的值存到sp - 16的地址上,并且把sp -= 16
ldp x29, x30, [sp], #16;  // 从sp地址取出2个64位数,分别存入x29,x30,然后sp += 16

4 Android-T
4.1 GKI
Open .config to find clang version from CONFIG_CC_VERSION_TEXT, then export clang and pahole (poke a hole) binaries to PATH.
define sign_module
    $(KDIR)/scripts/sign-file sha1 \
    $(KDIR)/certs/signing_key.pem \
    $(KDIR)/certs/signing_key.x509 \
    xxx.ko
endef
make -C $(KDIR) \
    M=$(PWD) \
    LLVM=1 \
    ARCH=arm64 \
    modules
llvm-strip -S xxx.ko
$(call sign_module)

4.2 vendorbootimage
boot.img: GKI kernel
vendor_boot.img: dtb.img, bootconfig and vendor_ramdisk.img
make vendorbootimage
lpdump super.img
lpunpack super.img output_dir

4.3 ninja build
all Android.mk -> out/build-$TARGET_PRODUCT.ninja
all Android.bp -> out/soong/build.ninja
Then build-$TARGET_PRODUCT.ninja and build.ninja are merged to
out/combined-$TARGET_PRODUCT.ninja
ln -sf out/combined-$TARGET_PRODUCT.ninja build.ninja
cp prebuilts/build-tools/linux-x86/bin/ninja \
out/host/linux-x86/bin
cp prebuilts/build-tools/linux-x86/lib64/libc++.so \
out/host/linux-x86/lib64
cp prebuilts/build-tools/linux-x86/lib64/libjemalloc5.so \
out/host/linux-x86/lib64

ninja <LOCAL_MODULE>

4.4 sparse and checkpatch
# make C=2
# C=2 will calls sparse binary to check sparse.
# checkpatch_all.sh
#!/bin/bash
LOG_NAME=./sparse.log
read_dir()
{
    for file in $(ls $1)
    do
        if [ -d $1"/"$file ]; then
            if [[ $file != '.' && \
                $file != '..' ]]; then
                read_dir $1"/"$file
            fi
        else
            my_f=$1"/"$file
            ./scripts/checkpatch.pl \
            --no-tree -f $my_f >> \
            $LOG_NAME
        fi
    done
}

if [ -f $LOG_NAME ]; then
    rm $LOG_NAME
fi
if [ $# -lt 1 ]; then
    echo "$0 <DIR>"
    exit
fi
read_dir $1
echo "log file: $LOG_NAME"

5 Abbreviations
GKI: Generic Kernel Image, from android11-5.4
KMI: Kernel Module Interface
QSSI: Android-T Qualcomm Single System Image

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值