• 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 +
                ' ' +
                ' \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 dyndbg==p

    echo "module +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

    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

    "
        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

  • 相关阅读:
    Kubernetes禁止调度
    生成包含10个随机字母或数字的字符串,然后统计每个字符的出现次数
    《Python数据分析与挖掘实战》chapter8代码修复
    学习笔记-ACL
    idea导入tomcat8源码搭建源码调试环境
    《QEMU/KVM源码分析与应用》读书笔记2 —— 第一章 QEMU与KVM概述
    大型网站系统架构演化实例_8.业务拆分
    UDP 报文结构与注意事项全解析
    GeoServer(配合Tomcat)安装与配置
    jmeter全局变量有的线程组引用不成功
  • 原文地址:https://blog.csdn.net/zoosenpin/article/details/126802055