可可 可用于评估各种程序的覆盖范围。在这里,我们展示了 Linux内核模块.
先决条件
本演示使用Debian OS上的Linux Kernel版本4.19.0-9。作为前提条件,必须在计算机上安装用于构建内核和使用Coco的软件包。
Linux模块构建系统
The build system contains different steps that are necessary 至 build a .ko
kernel module file, displayed graphically below:
生成文件示例
ifneq ($(KERNELRELEASE),) obj-m := my_module.o my_module-y := foo.o bar.o else KDIR := /lib/modules/`uname -r`/build PWD := $(shell pwd) all: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: $(MAKE) -C $(KDIR) M=$(PWD) clean endif
调整代码
We’我们已经为静态内存分配和覆盖数据的处理创建了相应的代码。“coverage.h”,可从下面下载。唯一必要的步骤是将以下行添加到现有模块源代码中:
#include <linux/module.h> #include <linux/init.h> #include <linux/device.h> #include <linux/cdev.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/slab.h> #ifdef __COVERAGESCANNER__ #include "coverage.h" #endif ..... static int __init my_module_init(void) { #ifdef __COVERAGESCANNER__ coverage_init(NULL, NULL); #endif ..... } ..... static void __exit my_module_exit(void) { ..... #ifdef __COVERAGESCANNER__ coverage_exit(); #endif return; } ..... module_init( my_module_init ); module_exit( my_module_exit ); .....
使包含可用于
链接器需要一些使用Coco时未提供的库:
ln -s /usr/src/linux-headers-$(uname -r)-common/arch/x86/include/asm/ \ /usr/src/linux-headers-$(uname -r)-common/include/
ln -s /usr/src/linux-headers-$(uname -r)-common/arch/x86/include/uapi/asm/ \ /usr/src/linux-headers-$(uname -r)-common/include/uapi/
ln -s /usr/lib/gcc/x86_64-linux-gnu/8/include/stdarg.h \ /usr/src/linux-headers-$(uname -r)-common/include/stdarg.h
调整对象工具
由于构建系统会临时更改构建中的.o文件的名称,因此 .tmp_filename.o 至 文件名,我们需要让Coco更改相应名称 .csmes 文件。为此,我们将 objtool 用一个小的bash脚本。但首先,我们需要重命名 objtool 至 orig_objtool 为这个脚本工作。
我们将以下脚本放在文件夹中 /usr/lib/linux-kbuild-4.19/tools/objtool/ 名称 objtool.
#! /bin/bash ## This wrapper basically takes the last command and renames the corresponding .tmp_(NAME).csmes file 至 the name that 可可 expects LASTCOMMAND=${@: -1} ## Cutting the ".tmp_" out of the csmes file for the target B=$( echo "$LASTCOMMAND" | sed -rn 's/(.*)\.tmp_(.*)$/\1\2/p' ) B="$B.csmes" ## Renaming the csmes file mv $LASTCOMMAND.csmes $B &> /dev/null ## Normal 处理essing D=$(dirname "$0") $D/orig_objtool [email protected]
This script should have the x
flag. You can revert the changes by invoking:
sudo apt-get install linux-kbuild-4.19 --reinstall
重新安装 objtool.
添加正确的.cspro文件开关
将以下行添加到 /opt/SquishCoco/bin/gcc.cspro:
DEACTIVATE_COVERAGESCANNER_OPTION_NO_ARG[LinuxKernel]=-M;-MM;-;-S;-dumpversion;-dumpmachine;-E;--version;-print-file-name=include
将以下行添加到 /opt/SquishCoco/bin/ld.cspro:
COMPILER_CMD[LinuxKernel]=gcc -c -O2 $LIBGEN$ -w $SOURCE$ -o $DESTINATION$ -fno-common CUSTOM_SETUP[LinuxKernel]=NONE DEACTIVATE_COVERAGESCANNER_OPTION_ONE_ARG[LinuxKernel]=--build-id LINK_ADDITIONAL_ARGUMENTS[LinuxKernel]= PLUGIN_REGISTRATION_API[LinuxKernel]=NO FILE_FORMAT_SPECIFIER[LinuxKernel]=NO
使用可可’使用静态内存的功能
可可 usually makes use of the user-space functions malloc
and free
至 allocate memory for coverage data. Those calls could be replaced with the kmalloc
and kfree
Kernel variants. But for simplicity we will allocate a static memory buffer. For that purpose, we need 至 set the environment variable COVERAGESCANNER_ARGS.
为了更容易设置 COVERAGESCANNER_ARGS,我们可以使用一个简短的脚本, 环境变量:
#!/bin/bash export COVERAGESCANNER_ARGS="--cs-architecture=LinuxKernel --cs-memory-pool=64000 --cs-exclude=coverage.h"
更改文件夹的权限
由于Coco在标头文件夹中创建临时文件,因此我们需要允许Coco写入标头文件夹。为此,请键入以下命令并更改 用户 您的用户名的空格:
sudo chown 用户:USER -R /usr/src/linux-headers-4.19.0-9-*
使用环境变量调用make
source 环境变量
Now invoke make
with:
make CC=csgcc LD=csld
现在按预期安装模块
insmod my_module.ko
输出覆盖率数据
在此展示中,可通过 处理 目录。通过运行以下命令,将当前coverage写入特定文件:
cat /proc/coverage/coverage_file > my_module.csexe
Now the generated my_module.o.csmes
file and the my_module.csexe
can be loaded and viewed in the 浏览器 或通过Coco命令行工具进行计算。
在这里获取coverage.h:
下载‘coverage.h’支持
如果对Coco或本演示有任何疑问,请随时给我们写一封电子邮件 [email protected].