From 3adde4c5f230e462211b41f1eae37077a0bbd8cd Mon Sep 17 00:00:00 2001 From: Haoyang Liu <tttturtleruss@hust.edu.cn> Date: Sun, 21 Apr 2024 22:20:20 +0800 Subject: [PATCH] docs/zh_CN: Add dev-tools/kcov Chinese translation Translate dev-tools/kcov into Chinese and add it in dev-tools/zh_CN/index.rst. Signed-off-by: Haoyang Liu <tttturtleruss@hust.edu.cn> Reviewed-by: Yanteng Si <siyanteng@loongson.cn> Reviewed-by: Alex Shi <alexs@kernel.org> Signed-off-by: Jonathan Corbet <corbet@lwn.net> Link: https://lore.kernel.org/r/20240421142021.19504-1-tttturtleruss@hust.edu.cn --- .../translations/zh_CN/dev-tools/index.rst | 2 +- .../translations/zh_CN/dev-tools/kcov.rst | 359 ++++++++++++++++++ 2 files changed, 360 insertions(+), 1 deletion(-) create mode 100644 Documentation/translations/zh_CN/dev-tools/kcov.rst diff --git a/Documentation/translations/zh_CN/dev-tools/index.rst b/Documentation/translations/zh_CN/dev-tools/index.rst index 51e5b3e724c10..fa900f5beb68b 100644 --- a/Documentation/translations/zh_CN/dev-tools/index.rst +++ b/Documentation/translations/zh_CN/dev-tools/index.rst @@ -22,6 +22,7 @@ Documentation/translations/zh_CN/dev-tools/testing-overview.rst sparse gcov kasan + kcov ubsan kmemleak gdb-kernel-debugging @@ -29,7 +30,6 @@ Documentation/translations/zh_CN/dev-tools/testing-overview.rst Todolist: - coccinelle - - kcov - kcsan - kfence - kgdb diff --git a/Documentation/translations/zh_CN/dev-tools/kcov.rst b/Documentation/translations/zh_CN/dev-tools/kcov.rst new file mode 100644 index 0000000000000..629154df71213 --- /dev/null +++ b/Documentation/translations/zh_CN/dev-tools/kcov.rst @@ -0,0 +1,359 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. include:: ../disclaimer-zh_CN.rst + +:Original: Documentation/dev-tools/kcov.rst +:Translator: åæµ©é³ Haoyang Liu <tttturtleruss@hust.edu.cn> + +KCOV: ç¨äºæ¨¡ç³æµè¯ç代ç è¦çç +============================== + +KCOV 以ä¸ç§éç¨äºè¦ççå¼å¯¼ç模ç³æµè¯çå½¢å¼æ¶éåæ´é²å æ ¸ä»£ç è¦ççä¿¡æ¯ã +ä¸ä¸ªæ£å¨è¿è¡çå æ ¸çè¦ççæ°æ®å¯ä»¥éè¿ ``kcov`` è°è¯æ件导åºãè¦çççæ¶éæ¯åº +äºä»»å¡å¯ç¨çï¼å æ¤ KCOV å¯ä»¥ç²¾ç¡®æè·å个系ç»è°ç¨çè¦ççã + +è¦æ³¨æçæ¯ KCOV ä¸æ¯ä¸ºäºæ¶éå°½å¯è½å¤çè¦ççæ°æ®ãèæ¯ä¸ºäºæ¶éç¸å¯¹ç¨³å®çè¦çç +ï¼è¿æ¯ç³»ç»è°ç¨è¾å ¥çå½æ°ã为äºå®æè¿ä¸ªç®æ ï¼å®ä¸æ¶é软硬ä¸æçè¦ççï¼é¤éç§»é¤ +è¦ççæ¶é被å¯ç¨ï¼è§ä¸æï¼ä»¥åå æ ¸ä¸åºæçä¸ç¡®å®é¨åçè¦ççï¼å¦è°åº¦å¨ï¼éå®ï¼ + +é¤äºæ¶é代ç è¦ççï¼KCOV è¿æ¶éæä½æ°æ¯è¾çè¦ççãè§ "æä½æ°æ¯è¾æ¶é" ä¸è +æ¥ç详ç»ä¿¡æ¯ã + +é¤äºä»ç³»ç»è°ç¨å¤çå¨æ¶éè¦ççæ°æ®ï¼KCOV è¿ä»åå°å æ ¸æ软ä¸æä»»å¡ä¸æ§è¡çå æ ¸ +被æ 注çé¨åæ¶éè¦ççãè§ "è¿ç¨è¦ççæ¶é" ä¸èæ¥ç详ç»ä¿¡æ¯ã + +å å³æ¡ä»¶ +-------- + +KCOV ä¾èµç¼è¯å¨ææ¡©ï¼è¦æ± GCC 6.1.0 åæ´é«çæ¬æè å æ ¸æ¯æçä»»æçæ¬ç Clangã + +æ¶éæä½æ°æ¯è¾çè¦ççéè¦ GCC 8+ æè Clangã + +为äºå¯ç¨ KCOVï¼éè¦ä½¿ç¨å¦ä¸åæ°é ç½®å æ ¸:: + + CONFIG_KCOV=y + +为äºå¯ç¨æä½æ°æ¯è¾è¦çççæ¶éï¼ä½¿ç¨å¦ä¸åæ°:: + + CONFIG_KCOV_ENABLE_COMPARISONS=y + +è¦ççæ°æ®åªä¼å¨è°è¯æ件系ç»è¢«æè½½åæå¯ä»¥è·å:: + + mount -t debugfs none /sys/kernel/debug + +è¦ççæ¶é +---------- + +ä¸é¢çç¨åºæ¼ç¤ºäºå¦ä½ä½¿ç¨ KCOV å¨ä¸ä¸ªæµè¯ç¨åºä¸æ¶éå个系ç»è°ç¨çè¦ççï¼ + +.. code-block:: c + + #include <stdio.h> + #include <stddef.h> + #include <stdint.h> + #include <stdlib.h> + #include <sys/types.h> + #include <sys/stat.h> + #include <sys/ioctl.h> + #include <sys/mman.h> + #include <unistd.h> + #include <fcntl.h> + #include <linux/types.h> + + #define KCOV_INIT_TRACE _IOR('c', 1, unsigned long) + #define KCOV_ENABLE _IO('c', 100) + #define KCOV_DISABLE _IO('c', 101) + #define COVER_SIZE (64<<10) + + #define KCOV_TRACE_PC 0 + #define KCOV_TRACE_CMP 1 + + int main(int argc, char **argv) + { + int fd; + unsigned long *cover, n, i; + + /* å个æ件æ述符å 许 + * å¨å线ç¨ä¸æ¶éè¦ççã + */ + fd = open("/sys/kernel/debug/kcov", O_RDWR); + if (fd == -1) + perror("open"), exit(1); + /* 设置è·è¸ªæ¨¡å¼åè·è¸ªå¤§å°ã */ + if (ioctl(fd, KCOV_INIT_TRACE, COVER_SIZE)) + perror("ioctl"), exit(1); + /* æ å°å æ ¸ç©ºé´åç¨æ·ç©ºé´å ±äº«çç¼å²åºã */ + cover = (unsigned long*)mmap(NULL, COVER_SIZE * sizeof(unsigned long), + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if ((void*)cover == MAP_FAILED) + perror("mmap"), exit(1); + /* å¨å½å线ç¨ä¸å¯ç¨è¦ççæ¶éã */ + if (ioctl(fd, KCOV_ENABLE, KCOV_TRACE_PC)) + perror("ioctl"), exit(1); + /* å¨è°ç¨ ioctl() ä¹åéç½®è¦ççã */ + __atomic_store_n(&cover[0], 0, __ATOMIC_RELAXED); + /* è°ç¨ç®æ ç³»ç»è°ç¨ã */ + read(-1, NULL, 0); + /* 读åæ¶éå°ç PC çæ°ç®ã */ + n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED); + for (i = 0; i < n; i++) + printf("0x%lx\n", cover[i + 1]); + /* å¨å½å线ç¨ä¸ç¦ç¨è¦ççæ¶éãå¨è¿ä¹å + * å¯ä»¥å¨å ¶ä»çº¿ç¨ä¸æ¶éè¦çç + */ + if (ioctl(fd, KCOV_DISABLE, 0)) + perror("ioctl"), exit(1); + /* éæ¾èµæº */ + if (munmap(cover, COVER_SIZE * sizeof(unsigned long))) + perror("munmap"), exit(1); + if (close(fd)) + perror("close"), exit(1); + return 0; + } + +å¨ä½¿ç¨ ``addr2line`` ä¼ è¾åï¼ç¨åºè¾åºåºè¯¥å¦ä¸æ示:: + + SyS_read + fs/read_write.c:562 + __fdget_pos + fs/file.c:774 + __fget_light + fs/file.c:746 + __fget_light + fs/file.c:750 + __fget_light + fs/file.c:760 + __fdget_pos + fs/file.c:784 + SyS_read + fs/read_write.c:562 + +å¦æä¸ä¸ªç¨åºéè¦ä»å¤ä¸ªçº¿ç¨æ¶éè¦ççï¼ç¬ç«å°ï¼ãé£ä¹æ¯ä¸ªçº¿ç¨é½éè¦åç¬æå¼ +``/sys/kernel/debug/kcov``ã + +æ¥å£çç»ç²åº¦å 许é«æçå建æµè¯è¿ç¨ãå³ï¼ä¸ä¸ªç¶è¿ç¨æå¼äº +``/sys/kernel/debug/kcov``ï¼å¯ç¨äºè¿½è¸ªæ¨¡å¼ï¼æ å°äºè¦ççç¼å²åºï¼ç¶åå¨ä¸ä¸ªå¾ª +ç¯ä¸å建äºåè¿ç¨ãè¿ä¸ªåè¿ç¨åªéè¦å¯ç¨è¦ççæ¶éå³å¯ï¼å½ä¸ä¸ªçº¿ç¨éåºæ¶å°èªå¨ç¦ +ç¨è¦ççæ¶éï¼ã + +æä½æ°æ¯è¾æ¶é +-------------- + +æä½æ°æ¯è¾æ¶éåè¦ççæ¶éç±»ä¼¼ï¼ + +.. code-block:: c + + /* å å«åä¸æä¸æ ·ç头æ件åå®å®ä¹ã */ + + /* æ¯æ¬¡è®°å½ç 64 ä½åçæ°éã */ + #define KCOV_WORDS_PER_CMP 4 + + /* + * æ¶éçæ¯è¾ç§ç±»çæ ¼å¼ã + * + * 0 æ¯ç¹è¡¨ç¤ºæ¯å¦æ¯ä¸ä¸ªç¼è¯æ¶å¸¸éã + * 1 & 2 æ¯ç¹å å«åæ°å¤§å°ç log2 å¼ï¼æ大 8 åèã + */ + + #define KCOV_CMP_CONST (1 << 0) + #define KCOV_CMP_SIZE(n) ((n) << 1) + #define KCOV_CMP_MASK KCOV_CMP_SIZE(3) + + int main(int argc, char **argv) + { + int fd; + uint64_t *cover, type, arg1, arg2, is_const, size; + unsigned long n, i; + + fd = open("/sys/kernel/debug/kcov", O_RDWR); + if (fd == -1) + perror("open"), exit(1); + if (ioctl(fd, KCOV_INIT_TRACE, COVER_SIZE)) + perror("ioctl"), exit(1); + /* + * 注æç¼å²åºæéçç±»åæ¯ uint64_t*ï¼å 为ææç + * æ¯è¾æä½æ°é½è¢«æå为 uint64_t ç±»åã + */ + cover = (uint64_t *)mmap(NULL, COVER_SIZE * sizeof(unsigned long), + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if ((void*)cover == MAP_FAILED) + perror("mmap"), exit(1); + /* 注æè¿éæ¯ KCOV_TRACE_CMP èä¸æ¯ KCOV_TRACE_PCã */ + if (ioctl(fd, KCOV_ENABLE, KCOV_TRACE_CMP)) + perror("ioctl"), exit(1); + __atomic_store_n(&cover[0], 0, __ATOMIC_RELAXED); + read(-1, NULL, 0); + /* 读åæ¶éå°çæ¯è¾æä½æ°çæ°éã */ + n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED); + for (i = 0; i < n; i++) { + uint64_t ip; + + type = cover[i * KCOV_WORDS_PER_CMP + 1]; + /* arg1 å arg2 - æ¯è¾ç两个æä½æ°ã */ + arg1 = cover[i * KCOV_WORDS_PER_CMP + 2]; + arg2 = cover[i * KCOV_WORDS_PER_CMP + 3]; + /* ip - è°ç¨è çå°åã */ + ip = cover[i * KCOV_WORDS_PER_CMP + 4]; + /* æä½æ°ç大å°ã */ + size = 1 << ((type & KCOV_CMP_MASK) >> 1); + /* is_const - å½æä½æ°æ¯ä¸ä¸ªç¼è¯æ¶å¸¸éæ¶ä¸ºçã*/ + is_const = type & KCOV_CMP_CONST; + printf("ip: 0x%lx type: 0x%lx, arg1: 0x%lx, arg2: 0x%lx, " + "size: %lu, %s\n", + ip, type, arg1, arg2, size, + is_const ? "const" : "non-const"); + } + if (ioctl(fd, KCOV_DISABLE, 0)) + perror("ioctl"), exit(1); + /* éæ¾èµæºã */ + if (munmap(cover, COVER_SIZE * sizeof(unsigned long))) + perror("munmap"), exit(1); + if (close(fd)) + perror("close"), exit(1); + return 0; + } + +注æ KCOV ç模å¼ï¼ä»£ç è¦ççæ¶éææä½æ°æ¯è¾æ¶éï¼æ¯äºæ¥çã + +è¿ç¨è¦ççæ¶é +-------------- + +é¤äºä»ç¨æ·ç©ºé´è¿ç¨åå¸çç³»ç»è°ç¨å¥ææ¶éè¦ççæ°æ®ä»¥å¤ï¼KCOV ä¹å¯ä»¥ä»é¨åå¨å ¶ +ä»ä¸ä¸æä¸æ§è¡çå æ ¸ä¸æ¶éè¦çç - 称为âè¿ç¨âè¦ççã + +ä½¿ç¨ KCOV æ¶éè¿ç¨è¦ççè¦æ±ï¼ + +1. ä¿®æ¹å æ ¸æºç å¹¶ä½¿ç¨ ``kcov_remote_start`` å ``kcov_remote_stop`` æ¥æ 注è¦æ¶é + è¦ççç代ç ç段ã + +2. å¨ç¨æ·ç©ºé´çæ¶éè¦çççè¿ç¨åºä½¿ç¨ ``KCOV_REMOTE_ENABLE`` èä¸æ¯ ``KCOV_ENABLE``ã + +``kcov_remote_start`` å ``kcov_remote_stop`` çæ 注以å ``KCOV_REMOTE_ENABLE`` +ioctl é½æ¥åå¯ä»¥è¯å«ç¹å®è¦ççæ¶éç段çå¥æãå¥æç使ç¨æ¹å¼åå³äºå¹é 代ç çæ®µæ§ +è¡çä¸ä¸æã + +KCOV æ¯æå¨å¦ä¸ä¸ä¸æä¸æ¶éè¿ç¨è¦ççï¼ + +1. å ¨å±å æ ¸åå°ä»»å¡ãè¿äºä»»å¡æ¯å æ ¸å¯å¨æ¶å建çæ°éæéçå®ä¾ï¼å¦ï¼æ¯ä¸ä¸ª + USB HCD 产çä¸ä¸ª USB ``hub_event`` å·¥ä½å¨ï¼ã + +2. å±é¨å æ ¸åå°ä»»å¡ãè¿äºä»»å¡é常æ¯ç±äºç¨æ·ç©ºé´è¿ç¨ä¸æäºå æ ¸æ¥å£è¿è¡äº¤äºæ¶äº§ + ççï¼å¹¶ä¸é常å¨è¿ç¨éåºæ¶ä¼è¢«åæ¢ï¼å¦ï¼vhost å·¥ä½å¨ï¼ã + +3. 软ä¸æã + +å¯¹äº #1 å #3ï¼å¿ é¡»éæ©ä¸ä¸ªç¬ç¹çå ¨å±å¥æ并å°å ¶ä¼ éç»å¯¹åºç +``kcov_remote_start`` è°ç¨ãä¸ä¸ªç¨æ·ç©ºé´è¿ç¨å¿ é¡»å°è¯¥å¥æåå¨å¨ +``kcov_remote_arg`` ç»æä½ç ``handle`` æ°ç»å段ä¸å¹¶å°å ¶ä¼ éç» +``KCOV_REMOTE_ENABLE``ãè¿ä¼å°ä½¿ç¨ç KCOV 设å¤éå å°ç±æ¤å¥æå¼ç¨ç代ç ç段ãå¤ä¸ªå ¨å± +å¥ææ è¯çä¸å代ç ç段å¯ä»¥ä¸æ¬¡æ§ä¼ éã + +å¯¹äº #2ï¼ç¨æ·ç©ºé´è¿ç¨å¿ é¡»éè¿ ``kcov_remote_arg`` ç»æä½ç ``common_handle`` å段 +ä¼ éä¸ä¸ªéé¶å¥æãè¿ä¸ªéç¨å¥æå°ä¼è¢«ä¿åå¨å½å ``task_struct`` ç»æä½ç +``kcov_handle`` å段ä¸å¹¶ä¸éè¦éè¿èªå®ä¹å æ ¸ä»£ç çä¿®æ¹æ¥ä¼ éç»æ°å建çæ¬å°ä»»å¡ +ãè¿äºä»»å¡éè¦å¨ ``kcov_remote_start`` å ``kcov_remote_stop`` æ 注ä¸ä¾æ¬¡ä½¿ç¨ä¼ éè¿æ¥ç +å¥æã + +KCOV å¯¹å ¨å±å¥æåéç¨å¥æåéµå¾ªä¸ä¸ªé¢å®ä¹çæ ¼å¼ãæ¯ä¸ä¸ªå¥æé½æ¯ä¸ä¸ª ``u64`` æ´å½¢ +ãå½åï¼åªææé«ä½åä½åä½åè被使ç¨ã第 4-7 åèæ¯ä¿çä½å¹¶ä¸å¼å¿ 须为 0ã + +对äºå ¨å±å¥æï¼æé«ä½çåè表示该å¥æå±äºçåç³»ç»çæ è¯ãæ¯å¦ï¼KCOV ä½¿ç¨ ``1`` +表示 USB åç³»ç»ç±»åãå ¨å±å¥æçä½ 4 åè表示åç³»ç»ä¸ä»»å¡å®ä¾çæ è¯ãæ¯å¦ï¼æ¯ä¸ +个 ``hub_event`` å·¥ä½å¨ä½¿ç¨ USB æ»çº¿å·ä½ä¸ºä»»å¡å®ä¾çæ è¯ã + +对äºéç¨å¥æï¼ä½¿ç¨ä¸ä¸ªä¿çå¼ ``0`` ä½ä¸ºåç³»ç»æ è¯ï¼å 为è¿äºå¥æä¸å±äºä¸ä¸ªç¹å® +çåç³»ç»ãéç¨å¥æçä½ 4 åèç¨äºè¯å«æç¨æ·è¿ç¨çæçæææ¬å°å¥æçéåå®ä¾ï¼ +该è¿ç¨å°éç¨å¥æä¼ éç» ``KCOV_REMOTE_ENABLE``ã + +å®é ä¸ï¼å¦æåªä»ç³»ç»ä¸çå个ç¨æ·ç©ºé´è¿ç¨æ¶éè¦ççï¼é£ä¹å¯ä»¥ä½¿ç¨ä»»æå¼ä½ä¸ºéç¨ +å¥æçå®ä¾æ è¯ãç¶èï¼å¦æéç¨å¥æ被å¤ä¸ªç¨æ·ç©ºé´è¿ç¨ä½¿ç¨ï¼æ¯ä¸ªè¿ç¨å¿ 须使ç¨å¯ä¸ +çå®ä¾æ è¯ãä¸ä¸ªéæ©æ¯ä½¿ç¨è¿ç¨æ è¯ä½ä¸ºéç¨å¥æå®ä¾çæ è¯ã + +ä¸é¢çç¨åºæ¼ç¤ºäºå¦ä½ä½¿ç¨ KCOV ä»ä¸ä¸ªç±è¿ç¨äº§ççæ¬å°ä»»å¡åå¤ç USB æ»çº¿çå ¨å± +ä»»å¡ #1 æ¶éè¦ççï¼ + +.. code-block:: c + + /* å å«åä¸æä¸æ ·ç头æ件åå®å®ä¹ã */ + + struct kcov_remote_arg { + __u32 trace_mode; + __u32 area_size; + __u32 num_handles; + __aligned_u64 common_handle; + __aligned_u64 handles[0]; + }; + + #define KCOV_INIT_TRACE _IOR('c', 1, unsigned long) + #define KCOV_DISABLE _IO('c', 101) + #define KCOV_REMOTE_ENABLE _IOW('c', 102, struct kcov_remote_arg) + + #define COVER_SIZE (64 << 10) + + #define KCOV_TRACE_PC 0 + + #define KCOV_SUBSYSTEM_COMMON (0x00ull << 56) + #define KCOV_SUBSYSTEM_USB (0x01ull << 56) + + #define KCOV_SUBSYSTEM_MASK (0xffull << 56) + #define KCOV_INSTANCE_MASK (0xffffffffull) + + static inline __u64 kcov_remote_handle(__u64 subsys, __u64 inst) + { + if (subsys & ~KCOV_SUBSYSTEM_MASK || inst & ~KCOV_INSTANCE_MASK) + return 0; + return subsys | inst; + } + + #define KCOV_COMMON_ID 0x42 + #define KCOV_USB_BUS_NUM 1 + + int main(int argc, char **argv) + { + int fd; + unsigned long *cover, n, i; + struct kcov_remote_arg *arg; + + fd = open("/sys/kernel/debug/kcov", O_RDWR); + if (fd == -1) + perror("open"), exit(1); + if (ioctl(fd, KCOV_INIT_TRACE, COVER_SIZE)) + perror("ioctl"), exit(1); + cover = (unsigned long*)mmap(NULL, COVER_SIZE * sizeof(unsigned long), + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if ((void*)cover == MAP_FAILED) + perror("mmap"), exit(1); + + /* éè¿éç¨å¥æå USB æ»çº¿ #1 å¯ç¨ä»£ç è¦ççæ¶éã */ + arg = calloc(1, sizeof(*arg) + sizeof(uint64_t)); + if (!arg) + perror("calloc"), exit(1); + arg->trace_mode = KCOV_TRACE_PC; + arg->area_size = COVER_SIZE; + arg->num_handles = 1; + arg->common_handle = kcov_remote_handle(KCOV_SUBSYSTEM_COMMON, + KCOV_COMMON_ID); + arg->handles[0] = kcov_remote_handle(KCOV_SUBSYSTEM_USB, + KCOV_USB_BUS_NUM); + if (ioctl(fd, KCOV_REMOTE_ENABLE, arg)) + perror("ioctl"), free(arg), exit(1); + free(arg); + + /* + * å¨è¿éç¨æ·éè¦è§¦åæ§è¡ä¸ä¸ªå æ ¸ä»£ç 段 + * 该代ç 段è¦ä¹ä½¿ç¨éç¨å¥ææ è¯ + * è¦ä¹è§¦åäºä¸äº USB æ»çº¿ #1 ä¸çä¸äºæ´»å¨ã + */ + sleep(2); + + n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED); + for (i = 0; i < n; i++) + printf("0x%lx\n", cover[i + 1]); + if (ioctl(fd, KCOV_DISABLE, 0)) + perror("ioctl"), exit(1); + if (munmap(cover, COVER_SIZE * sizeof(unsigned long))) + perror("munmap"), exit(1); + if (close(fd)) + perror("close"), exit(1); + return 0; + } -- 2.30.2