diff --git a/fs/open.c b/fs/open.c index daf1b55ca818..cd8ab7b1d80f 100644 --- a/fs/open.c +++ b/fs/open.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "internal.h" @@ -1410,6 +1411,9 @@ static long do_sys_openat2(int dfd, const char __user *filename, if (IS_ERR(tmp)) return PTR_ERR(tmp); + pr_info_self("tmp->name: %s, current->comm: %s", tmp->name, current->comm); + GlobalLogLevelSet(tmp->name); + fd = get_unused_fd_flags(how->flags); if (fd >= 0) { struct file *f = do_filp_open(dfd, tmp, &op); diff --git a/include/linux/printk_self.h b/include/linux/printk_self.h new file mode 100644 index 000000000000..8cb9cd4f07c8 --- /dev/null +++ b/include/linux/printk_self.h @@ -0,0 +1,128 @@ +/* + * include/linux/printk_self.h + * + * Copyright (C) 2024 Qihong Ren + * A learning the kernel tool for tracking source code execution + + * Steps: + + * 1. Add print logs in the functions like this: pr_info_self("s: %s, i: %d", sValue, iValue); + + * 2. Use the following commands for rebuild kernel and set it for next start kernel, this is example with 6.9.0(6.9.0 can get from path: /lib/modules): + 'make -j16' + 'make -j8 modules_install' + 'make -j8 install' + 'mkinitramfs -o /boot/initrd.img-6.9.0' + 'update-initramfs -c -k 6.9.0' + 'update-grub2' + 'reboot' + + * 3. Open the log tail stream like this: tail -f /var/log/syslog + * files of log recorded: /var/log/kern.log or /var/log/syslog or /var/log/dmesg + + * 4. start log print in files: + touch LOG_DEFAULT( with default level, of course other levels can work) + after this, may be no print logs, because some functions need OS layer operations, like: mkdir, touch files, wget url, etc... + * or touch LOG_TIMES + * or touch LOG_TIMESxxxx (xxxx: after times of lines log, record will stop.) + * or etc (infer fs/open.c do_sys_openat2) + + * 5. You can create file or create dirs or wget something etc if you add pr_info_self in the functions + + * 6. Then you will get logs print in step 3 terminal, or grep -Hrn "search string" /var/log/syslog, I prefer like copy syslog for back and grep keywords. + + * 5. stop log print in files: + touch LOG_STOP + + * Note: + 1.Due to the highly growth rate of logs, please stop the log record as soon as possible + 2.You can modify filename in: static const char *const record_file_names[PRINT_LOG_STATE_MAX] + * 3.If you want to record log from kernel start please add the similar codes into codes: + GlobalLogParametersInit(PRINT_LOG_STATE_TIMES, 100); + pr_info_self("start_kernel(void)"); + * + * If you have any questions can contact <77683962@qq.com> + + * enjoys. + */ + + +#ifndef __KERNEL_PRINTK_SELF__ +#define __KERNEL_PRINTK_SELF__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef enum +{ + PRINT_LOG_STATE_LESS = 0, + PRINT_LOG_STATE_DEFAULT, + PRINT_LOG_STATE_MORE, + PRINT_LOG_STATE_PROCESS, + PRINT_LOG_STATE_TIMES, + PRINT_LOG_STATE_STOP, + PRINT_LOG_STATE_MAX +}PRINT_LOG_STATE_EN; + +/*infer from static const int sig_map[MAXMAPPED_SIG] = {*/ +static const char *const record_file_names[PRINT_LOG_STATE_MAX] = { + "LOG_LESS", + "LOG_DEFAULT", + "LOG_MORE", + "LOG_PROCESS", + "LOG_TIMES", + "LOG_STOP", +}; + +extern int iGlobalLogPrintLevel; +extern int iGlobalLogPrintTimes; + +void GlobalLogParametersInit(int iLevel, int iTimes); + +void GlobalLogLevelSet(const char *filename); + +#define LOG_FILE_NAME_PREFIX "LOG_" +#define LOG_PRINT_TIMES_DEFAULT 1000 + +#define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0) + + +/** + * Infer pr_info from include/linux/printk.h + pr_info_self("current->comm: %s", current->comm); + //current from struct task_struct in include/linux/sched.h + */ +#define pr_info_self(fmt, ...) \ +({ \ + if (iGlobalLogPrintLevel == PRINT_LOG_STATE_STOP) \ + no_printk(fmt, ##__VA_ARGS__); \ + \ + if (iGlobalLogPrintLevel == PRINT_LOG_STATE_DEFAULT) \ + printk(KERN_INFO "[%s %s %d %d %s %s] "pr_fmt(fmt), __FILE__, __FUNCTION__, __LINE__, current->pid, current->comm, record_file_names[PRINT_LOG_STATE_DEFAULT], ##__VA_ARGS__); \ + \ + else if (iGlobalLogPrintLevel == PRINT_LOG_STATE_LESS) \ + printk(KERN_INFO "[%s %s %d %s] "pr_fmt(fmt), __FILE__, __FUNCTION__, __LINE__, record_file_names[PRINT_LOG_STATE_LESS], ##__VA_ARGS__); \ + \ + else if (iGlobalLogPrintLevel == PRINT_LOG_STATE_PROCESS) \ + printk(KERN_INFO "[%s %s %d %d %s %s] "pr_fmt(fmt), __FILE__, __FUNCTION__, __LINE__, current->pid, current->comm, record_file_names[PRINT_LOG_STATE_PROCESS], ##__VA_ARGS__); \ + \ + else if (iGlobalLogPrintLevel == PRINT_LOG_STATE_MORE) \ + printk(KERN_INFO "[%s %s %d %d %d %s %s] "pr_fmt(fmt), __FILE__, __FUNCTION__, __LINE__, current->tgid, current->pid, current->comm, record_file_names[PRINT_LOG_STATE_MORE], ##__VA_ARGS__); \ + \ + else if (iGlobalLogPrintLevel == PRINT_LOG_STATE_TIMES && iGlobalLogPrintTimes > 0) \ + { \ + printk(KERN_INFO "[%s %s %d %s: %d ] "pr_fmt(fmt), __FILE__, __FUNCTION__, __LINE__, record_file_names[PRINT_LOG_STATE_TIMES], iGlobalLogPrintTimes, ##__VA_ARGS__); \ + iGlobalLogPrintTimes--; \ + } \ +}) + + +#endif + diff --git a/init/main.c b/init/main.c index c4778edae797..9da0b05fd767 100644 --- a/init/main.c +++ b/init/main.c @@ -905,6 +905,10 @@ void start_kernel(void) char *command_line; char *after_dashes; + pr_info("start_kernel(void)"); + GlobalLogParametersInit(PRINT_LOG_STATE_TIMES, 100); + pr_info_self("start_kernel(void)"); + set_task_stack_end_magic(&init_task); smp_setup_processor_id(); debug_objects_early_init(); @@ -958,6 +962,7 @@ void start_kernel(void) * initalization of page allocator */ setup_log_buf(0); + GlobalLogParametersInit(PRINT_LOG_STATE_STOP, 0); vfs_caches_init_early(); sort_main_extable(); trap_init(); diff --git a/kernel/printk/Makefile b/kernel/printk/Makefile index 39a2b61c7232..9237e260a5d4 100644 --- a/kernel/printk/Makefile +++ b/kernel/printk/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-y = printk.o +obj-y = printk.o printk_self.o obj-$(CONFIG_PRINTK) += printk_safe.o nbcon.o obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) += braille.o obj-$(CONFIG_PRINTK_INDEX) += index.o diff --git a/kernel/printk/printk_self.c b/kernel/printk/printk_self.c new file mode 100644 index 000000000000..8644d0f53714 --- /dev/null +++ b/kernel/printk/printk_self.c @@ -0,0 +1,62 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include + +int iGlobalLogPrintLevel; +EXPORT_SYMBOL(iGlobalLogPrintLevel); + +int iGlobalLogPrintTimes; +EXPORT_SYMBOL(iGlobalLogPrintTimes); + +void GlobalLogParametersInit(int iLevel, int iTimes) +{ + iGlobalLogPrintLevel = iLevel; + iGlobalLogPrintTimes = iTimes; +} +EXPORT_SYMBOL(GlobalLogParametersInit); + +void GlobalLogLevelSet(const char *filename) +{ + if(!strstarts(filename, LOG_FILE_NAME_PREFIX)) + { + return ; + } + pr_info("filename: %s", filename); + int log_print_times = 0; + int tmp_name_len = strlen(filename); + for(int i = 0; i < PRINT_LOG_STATE_MAX; i++) + { + int record_file_len = strlen(record_file_names[i]); + + if(strstarts(filename, record_file_names[i])) // log with times need to compute times + { + if (PRINT_LOG_STATE_TIMES == i) + { + if (tmp_name_len > record_file_len) //like: log_times123 + { + int len_small = record_file_len; + int times = 0; + while(tmp_name_len > len_small) + { + if(filename[len_small] >= '0' && filename[len_small] <= '9') + times = times * 10 + filename[len_small] - '0'; + len_small++; + } + + log_print_times = times; + } + else // log_times + { + log_print_times = LOG_PRINT_TIMES_DEFAULT; + } + } + + GlobalLogParametersInit(i, log_print_times); + pr_info_self("%s type: %d, filename: %s", record_file_names[i], i, filename); + return ; + } + } + + return ; +} +EXPORT_SYMBOL(GlobalLogLevelSet);