发布网友 发布时间:2022-04-30 01:57
共4个回答
懂视网 时间:2022-04-30 06:18
pr_debug:
#if defined(CONFIG_DYNAMIC_DEBUG)
/* dynamic_pr_debug() uses pr_fmt() internally so we don‘t need it here */
#define pr_debug(fmt, ...)
dynamic_pr_debug(fmt, ##__VA_ARGS__)
#elif defined(DEBUG)
#define pr_debug(fmt, ...)
printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#else
#define pr_debug(fmt, ...)
no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#endif
dev_dbg:
#if defined(CONFIG_DYNAMIC_DEBUG)
#define dev_dbg(dev, format, ...)
do {
dynamic_dev_dbg(dev, format, ##__VA_ARGS__);
} while (0)
#elif defined(DEBUG)
#define dev_dbg(dev, format, arg...)
dev_printk(KERN_DEBUG, dev, format, ##arg)
#else
#define dev_dbg(dev, format, arg...)
({
if (0)
dev_printk(KERN_DEBUG, dev, format, ##arg);
0;
})
#endif
从上面的宏定义可以看出,要使用dynamic_*的话需要配置CONFIG_DYNAMIC_DEBUG。
Kernel hacking --->
printk and dmesg options --->
[*] Enable dynamic printk() support
在[*] Enable dynamic printk() support 上点击h,可以看到帮助信息。
我们以pr_debug为例分析,
1: #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)
2: static struct _ddebug __aligned(8)
3: __attribute__((section("__verbose"))) name = {
4: .modname = KBUILD_MODNAME,
5: .function = __func__,
6: .filename = __FILE__,
7: .format = (fmt),
8: .lineno = __LINE__,
9: .flags = _DPRINTK_FLAGS_DEFAULT,
10: }
11:
12: #define dynamic_pr_debug(fmt, ...)
13: do {
14: DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);
15: if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT))
16: __dynamic_pr_debug(&descriptor, pr_fmt(fmt),
17: ##__VA_ARGS__);
18: } while (0)
pr_fmt:
1: #ifndef pr_fmt
2: #define pr_fmt(fmt) fmt
3: #endif
所以,如果把pr_debug展开,那么就是:
1: do {
2: static struct _ddebug __aligned(8)
3: __attribute__((section("__verbose"))) descriptor = {
4: .modname = KBUILD_MODNAME,
5: .function = __func__,
6: .filename = __FILE__,
7: .format = (fmt),
8: .lineno = __LINE__,
9: .flags = _DPRINTK_FLAGS_DEFAULT,
10: }
11: if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT))
12: __dynamic_pr_debug(&descriptor, fmt,
13: ##__VA_ARGS__);
14: } while (0)
其中flags的赋值_DPRINTK_FLAGS_DEFAULT依赖DEBUG宏,
1: #if defined DEBUG
2: #define _DPRINTK_FLAGS_DEFAULT _DPRINTK_FLAGS_PRINT
3: #else
4: #define _DPRINTK_FLAGS_DEFAULT 0
5: #endif
即,如果没有定义DEBUG宏,pr_debug默认无法打印出来,需要按照下面介绍的方法。
此外还定义了static类型的变量descriptor,它在编译链接时会被放到__verbose段,可以看看arch/arm/kernel/vmlinux.lds:
1: OUTPUT_ARCH(arm)
2: ENTRY(stext)
3: jiffies = jiffies_64;
4: SECTIONS
5: {
6: /*
7: * XXX: The linker does not define how output sections are
8: * assigned to input sections when there are multiple statements
9: * matching the same input section name. There is no documented
10: * order of matching.
11: *
12: * unwind exit sections must be discarded before the rest of the
13: * unwind sections get included.
14: */
15: /DISCARD/ : {
16: *(.ARM.exidx.exit.text)
17: *(.ARM.extab.exit.text)
18: *(.ARM.exidx.cpuexit.text)
19: *(.ARM.extab.cpuexit.text)
20:
21:
22: *(.exitcall.exit)
23: *(.alt.smp.init)
24: *(.discard)
25: *(.discard.*)
26: }
27: . = 0xC0000000 + 0x00008000;
28: .head.text : {
29: _text = .;
30: *(.head.text)
31: }
32: .text : { /* Real text segment */
33: _stext = .; /* Text and read-only data */
34: __exception_text_start = .;
35: *(.exception.text)
36: __exception_text_end = .;
37:
38: . = ALIGN(8); *(.text.hot) *(.text) *(.ref.text) *(.text.unlikely)
39: . = ALIGN(8); __sched_text_start = .; *(.sched.text) __sched_text_end = .;
40: . = ALIGN(8); __lock_text_start = .; *(.spinlock.text) __lock_text_end = .;
41: . = ALIGN(8); __kprobes_text_start = .; *(.kprobes.text) __kprobes_text_end = .;
42: . = ALIGN(8); __idmap_text_start = .; *(.idmap.text) __idmap_text_end = .; . = ALIGN(32); __hyp_idmap_text_start = .; *(.hyp.idmap.text) __hyp_idmap_text_end = .;
43: *(.fixup)
44: *(.gnu.warning)
45: *(.glue_7)
46: *(.glue_7t)
47: . = ALIGN(4);
48: *(.got) /* Global offset table */
49:
50: }
51: . = ALIGN(((1 << 12))); .rodata : AT(ADDR(.rodata) - 0) { __start_rodata = .; *(.rodata) *(.rodata.*) *(__vermagic) . = ALIGN(8); __start___tracepoints_ptrs = .; *(__tracepoints_ptrs) __stop___tracepoints_ptrs = .; *(__tracepoints_strings) } .rodata1 : AT(ADDR(.rodata1) - 0) { *(.rodata1) } . = ALIGN(8); __bug_table : AT(ADDR(__bug_table) - 0) { __start___bug_table = .; *(__bug_table) __stop___bug_table = .; } .pci_fixup : AT(ADDR(.pci_fixup) - 0) { __start_pci_fixups_early = .; *(.pci_fixup_early) __end_pci_fixups_early = .; __start_pci_fixups_header = .; *(.pci_fixup_header) __end_pci_fixups_header = .; __start_pci_fixups_final = .; *(.pci_fixup_final) __end_pci_fixups_final = .; __start_pci_fixups_enable = .; *(.pci_fixup_enable) __end_pci_fixups_enable = .; __start_pci_fixups_resume = .; *(.pci_fixup_resume) __end_pci_fixups_resume = .; __start_pci_fixups_resume_early = .; *(.pci_fixup_resume_early) __end_pci_fixups_resume_early = .; __start_pci_fixups_suspend = .; *(.pci_fixup_suspend) __end_pci_fixups_suspend = .; } .builtin_fw : AT(ADDR(.builtin_fw) - 0) { __start_builtin_fw = .; *(.builtin_fw) __end_builtin_fw = .; } __ksymtab : AT(ADDR(__ksymtab) - 0) { __start___ksymtab = .; *(SORT(___ksymtab+*)) __stop___ksymtab = .; } __ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - 0) { __start___ksymtab_gpl = .; *(SORT(___ksymtab_gpl+*)) __stop___ksymtab_gpl = .; } __ksymtab_unused : AT(ADDR(__ksymtab_unused) - 0) { __start___ksymtab_unused = .; *(SORT(___ksymtab_unused+*)) __stop___ksymtab_unused = .; } __ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - 0) { __start___ksymtab_unused_gpl = .; *(SORT(___ksymtab_unused_gpl+*)) __stop___ksymtab_unused_gpl = .; } __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - 0) { __start___ksymtab_gpl_future = .; *(SORT(___ksymtab_gpl_future+*)) __stop___ksymtab_gpl_future = .; } __kcrctab : AT(ADDR(__kcrctab) - 0) { __start___kcrctab = .; *(SORT(___kcrctab+*)) __stop___kcrctab = .; } __kcrctab_gpl : AT(ADDR(__kcrctab_gpl) - 0) { __start___kcrctab_gpl = .; *(SORT(___kcrctab_gpl+*)) __stop___kcrctab_gpl = .; } __kcrctab_unused : AT(ADDR(__kcrctab_unused) - 0) { __start___kcrctab_unused = .; *(SORT(___kcrctab_unused+*)) __stop___kcrctab_unused = .; } __kcrctab_unused_gpl : AT(ADDR(__kcrctab_unused_gpl) - 0) { __start___kcrctab_unused_gpl = .; *(SORT(___kcrctab_unused_gpl+*)) __stop___kcrctab_unused_gpl = .; } __kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - 0) { __start___kcrctab_gpl_future = .; *(SORT(___kcrctab_gpl_future+*)) __stop___kcrctab_gpl_future = .; } __ksymtab_strings : AT(ADDR(__ksymtab_strings) - 0) { *(__ksymtab_strings) } __init_rodata : AT(ADDR(__init_rodata) - 0) { *(.ref.rodata) } __param : AT(ADDR(__param) - 0) { __start___param = .; *(__param) __stop___param = .; } __modver : AT(ADDR(__modver) - 0) { __start___modver = .; *(__modver) __stop___modver = .; . = ALIGN(((1 << 12))); __end_rodata = .; } . = ALIGN(((1 << 12)));
52: . = ALIGN(4);
53: __ex_table : AT(ADDR(__ex_table) - 0) {
54: __start___ex_table = .;
55: *(__ex_table)
56: __stop___ex_table = .;
57: }
58: /*
59: * Stack unwinding tables
60: */
61: . = ALIGN(8);
62: .ARM.unwind_idx : {
63: __start_unwind_idx = .;
64: *(.ARM.exidx*)
65: __stop_unwind_idx = .;
66: }
67: .ARM.unwind_tab : {
68: __start_unwind_tab = .;
69: *(.ARM.extab*)
70: __stop_unwind_tab = .;
71: }
72: .notes : AT(ADDR(.notes) - 0) { __start_notes = .; *(.note.*) __stop_notes = .; }
73: _etext = .; /* End of text and rodata section */
74: . = ALIGN((1 << 12));
75: __init_begin = .;
76: /*
77: * The vectors and stubs are relocatable code, and the
78: * only thing that matters is their relative offsets
79: */
80: __vectors_start = .;
81: .vectors 0 : AT(__vectors_start) {
82: *(.vectors)
83: }
84: . = __vectors_start + SIZEOF(.vectors);
85: __vectors_end = .;
86: __stubs_start = .;
87: .stubs 0x1000 : AT(__stubs_start) {
88: *(.stubs)
89: }
90: . = __stubs_start + SIZEOF(.stubs);
91: __stubs_end = .;
92: . = ALIGN(8); .init.text : AT(ADDR(.init.text) - 0) { _sinittext = .; *(.init.text) *(.meminit.text) _einittext = .; }
93: .exit.text : {
94: *(.exit.text) *(.memexit.text)
95: }
96: .init.proc.info : {
97: . = ALIGN(4); __proc_info_begin = .; *(.proc.info.init) __proc_info_end = .;
98: }
99: .init.arch.info : {
100: __arch_info_begin = .;
101: *(.arch.info.init)
102: __arch_info_end = .;
103: }
104: .init.tagtable : {
105: __tagtable_begin = .;
106: *(.taglist.init)
107: __tagtable_end = .;
108: }
109: .init.pv_table : {
110: __pv_table_begin = .;
111: *(.pv_table)
112: __pv_table_end = .;
113: }
114: .init.data : {
115: *(.init.data) *(.meminit.data) *(.init.rodata) *(.meminit.rodata) . = ALIGN(32); __dtb_start = .; *(.dtb.init.rodata) __dtb_end = .;
116: . = ALIGN(16); __setup_start = .; *(.init.setup) __setup_end = .;
117: __initcall_start = .; *(.initcallearly.init) __initcall0_start = .; *(.initcall0.init) *(.initcall0s.init) __initcall1_start = .; *(.initcall1.init) *(.initcall1s.init) __initcall2_start = .; *(.initcall2.init) *(.initcall2s.init) __initcall3_start = .; *(.initcall3.init) *(.initcall3s.init) __initcall4_start = .; *(.initcall4.init) *(.initcall4s.init) __initcall5_start = .; *(.initcall5.init) *(.initcall5s.init) __initcallrootfs_start = .; *(.initcallrootfs.init) *(.initcallrootfss.init) __initcall6_start = .; *(.initcall6.init) *(.initcall6s.init) __initcall7_start = .; *(.initcall7.init) *(.initcall7s.init) __initcall_end = .;
118: __con_initcall_start = .; *(.con_initcall.init) __con_initcall_end = .;
119: __security_initcall_start = .; *(.security_initcall.init) __security_initcall_end = .;
120: . = ALIGN(4); __initramfs_start = .; *(.init.ramfs) . = ALIGN(8); *(.init.ramfs.info)
121: }
122: .exit.data : {
123: *(.exit.data) *(.memexit.data) *(.memexit.rodata)
124: }
125: __init_end = .;
126: . = ALIGN(8192);
127: __data_loc = .;
128: .data : AT(__data_loc) {
129: _data = .; /* address in memory */
130: _sdata = .;
131: /*
132: * first, the init task union, aligned
133: * to an 8192 byte boundary.
134: */
135: . = ALIGN(8192); *(.data..init_task)
136: . = ALIGN((1 << 12)); __nosave_begin = .; *(.data..nosave) . = ALIGN((1 << 12)); __nosave_end = .;
137: . = ALIGN((1 << 5)); *(.data..cacheline_aligned)
138: . = ALIGN((1 << 5)); *(.data..read_mostly) . = ALIGN((1 << 5));
139: /*
140: * and the usual data section
141: */
142: *(.data) *(.ref.data) *(.data..shared_aligned) *(.data.unlikely) . = ALIGN(32); *(__tracepoints) . = ALIGN(8); __start___jump_table = .; *(__jump_table) __stop___jump_table = .; . = ALIGN(8);__start___verbose = .; *(__verbose) __stop___verbose = .;
143: CONSTRUCTORS
144: _edata = .;
145: }
146: _edata_loc = __data_loc + SIZEOF(.data);
147: . = ALIGN(0); __bss_start = .; . = ALIGN(0); .sbss : AT(ADDR(.sbss) - 0) { *(.sbss) *(.scommon) } . = ALIGN(0); .bss : AT(ADDR(.bss) - 0) { *(.bss..page_aligned) *(.dynbss) *(.bss) *(COMMON) } . = ALIGN(0); __bss_stop = .;
148: _end = .;
149: .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } .comment 0 : { *(.comment) }
150: .comment 0 : { *(.comment) }
151: }
可以看到,将__verbose段链接到了__start__verbose和__stop__verbose之间,也就是将来可以利用__start_verbose和__stop_verbose这两个符号来找到__verbose段。
一般我们使用debugfs的时候,在系统启动时挂载debugfs文件系统:
1: [root@TQ2440 /]# mount
2: rootfs on / type rootfs (rw)
3: /dev/root on / type yaffs2 (rw,relatime)
4: proc on /proc type proc (rw,relatime)
5: tmpfs on /tmp type tmpfs (rw,relatime)
6: sysfs on /sys type sysfs (rw,relatime)
7: tmpfs on /dev type tmpfs (rw,relatime)
8: debugfs on /sys/kernel/debug type debugfs (rw,relatime)
9: devpts on /dev/pts type devpts (rw,relatime,mode=600)
上面我们将debugfs挂载到了/sys/kernel/debug目录下面。
如果我们想打开某个文件中的pr_debug,如demo.c,可以如下操作:
echo -n "file demo.c +p" > /sys/kernel/debug/dynamic_debug/control
关闭的话:
echo -n "file demo.c -p" > /sys/kernel/debug/dynamic_debug/control
如果想分析一下为什么这样操作就可以实现将某个文件中的pr_debug打开,就需要分析背后的原理,如control节点的创建.
上面pr_debug展开后的descriptor变量被链接到了__verbose段,那么系统一定会有解析这个段的代码。
具体的代码位置是lib/dynamic_debug.c
__verbose的解析:
1: static int __init dynamic_debug_init(void)
2: {
3: struct _ddebug *iter, *iter_start;
4: const char *modname = NULL;
5: char *cmdline;
6: int ret = 0;
7: int n = 0, entries = 0, modct = 0;
8: int verbose_bytes = 0;
9:
10: // __start___verbose 和 __stop___verbose 之间存放的都是struct _ddebug类型的静态变量,
11: // pr_debug展开后的descriptor就在这里。
12: if (__start___verbose == __stop___verbose) {
13: pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build ");
14: return 1;
15: }
16:
17: // 下面这段代码完成的任务是解析__verbose段。
18: iter = __start___verbose;
19: modname = iter->modname;
var cpro_id = "u6292429";热心网友 时间:2022-04-30 03:26
破解一般都是两种方法:
1.动态调试(使用如OllyDBG等调试软件)
2.静态分析(使用如W32dsm等反汇编软件)
两种方法都需要有扎实的汇编基本功,水平的高低决定破解的可能性及时间。追问应该是方法不同吧
热心网友 时间:2022-04-30 04:44
565哇嘎嘎嘎嘎热心网友 时间:2022-04-30 06:19
反编译