本文介绍了如何使用printf调试linux内核的汇编代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

这是我正在尝试的文件通过放置 printf/printk 语句进行调试.

This is the file that I am trying to debug by putting printf/printk statements.

代码是汇编.

 79         __HEAD
 80 ENTRY(stext)
 81  ARM_BE8(setend be )                    @ ensure we are in BE8 mode
 82
 83  THUMB( adr     r9, BSYM(1f)    )       @ Kernel is always entered in ARM.
 84  THUMB( bx      r9              )       @ If this is a Thumb-2 kernel,
 85  THUMB( .thumb                  )       @ switch to Thumb now.
 86  THUMB(1:                       )
 87
 88 #ifdef CONFIG_ARM_VIRT_EXT
 89         bl      __hyp_stub_install
 90 #endif
 91         @ ensure svc mode and all interrupts masked
 92         safe_svcmode_maskall r9
 93
 94         mrc     p15, 0, r9, c0, c0              @ get processor id
 95         bl      __lookup_processor_type         @ r5=procinfo r9=cpuid
 96         movs    r10, r5                         @ invalid processor (r5=0)?
 97  THUMB( it      eq )            @ force fixup-able long branch encoding
 98         beq     __error_p                       @ yes, error 'p'
 99
100 #ifdef CONFIG_ARM_LPAE
101         mrc     p15, 0, r3, c0, c1, 4           @ read ID_MMFR0
102         and     r3, r3, #0xf                    @ extract VMSA support
103         cmp     r3, #5                          @ long-descriptor translation table format?
104  THUMB( it      lo )                            @ force fixup-able long branch encoding
105         blo     __error_lpae                    @ only classic page table format
106 #endif
107
108 #ifndef CONFIG_XIP_KERNEL
109         adr     r3,

我只是想从这个文件向控制台发送一些消息.此代码适用于 ARM.

I simply want to put some messages to console from this file. This code is for ARM.

我尝试在此类代码块中使用 printk,但无法编译.

I tried using printk in such code blocks but it fails to compile.

有什么建议吗?

推荐答案

答案在 ARM 启动常见问题.您需要启用配置菜单项Kernel Hacking|Kernel low-level debugging functions.例如,代码 __error_p 然后将在您的控制台 UART 上显示一些内容.例如,elinux.org 的打印调试在内核无法匹配您的机器 ID.

The answer is given in ARM booting FAQ. You need to enable the config menu item Kernel Hacking|Kernel low-level debugging functions. For instance, the code __error_p will then display something on your console UART. For instance, elinux.org's Debugging by printing shows an error message when the kernel can not match your machine id.

DEBUG_LL 创建函数 extern void printascii(char *);,您也可以使用它检测 vprintk_emit().

DEBUG_LL creates the function extern void printascii(char *); which you can also instrument vprintk_emit() with.

--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1483,6 +1483,8 @@ static size_t cont_print_text(char *text, size_t size)
        return textlen;
 }

+extern void printascii(char*);
+
 asmlinkage int vprintk_emit(int facility, int level,
                            const char *dict, size_t dictlen,
                            const char *fmt, va_list args)
@@ -1541,6 +1543,7 @@ asmlinkage int vprintk_emit(int facility, int level,
         * prefix which might be passed-in as a parameter.
         */
        text_len = vscnprintf(text, sizeof(textbuf), fmt, args);
+       printascii(text);

        /* mark and strip a trailing newline */
        if (text_len && text[text_len-1] == '\n') {

这和内核命令行initcall_debug 将有助于诊断启动问题.

This and the kernel command line initcall_debug will be useful to diagnose boot issue.

如果您的平台不支持 DEBUG_LL,则实现支持它所需的轮询 UART 例程相当容易.

If you platform doesn't support the DEBUG_LL, it is fairly easy to implement the polled UART routines needed to support it.

通常,printk() 在早期启动期间被缓冲,并且在控制台驱动程序处于活动状态之前不会真正打印出来.因此,无需修补 vprintk_emit(),您可以在 UART 驱动程序运行之前的任何地方崩溃/停止,并且在正常配置下看不到任何内容.

Normally, printk() is buffered during early boot and doesn't actually print out until the console driver is active. So, without patching the vprintk_emit(), you can crash/halt anywhere before the UART driver runs and see nothing with a normal configuration.

head.S 之类的调试,需要在汇编器中进行.error_p 实现有一些示例代码,这里是另一个,

For debugging of head.S and the like, you need to do this in assembler. The error_p implementation has some sample code and here is another,

 #ifdef CONFIG_DEBUG_LL
         /* Save some registers? */
         adr     r0, prefix
         bl      printascii
         mov     r0, r9
         bl      printhex8
         adr     r0, tail
         bl      printascii
         b       1f
 prefix: .asciz  "\nTrace 1 gives "
 tail:   .asciz  "\n"
 1:  /* Perhaps halt here, due to register clobbers */
 #endif

根据head.S 中的上下文,您在使用寄存器方面受到限制.通常,此代码的唯一问题是您没有执行 ARM 启动文档.

You are limited in the use of registers depending on the context in head.S. Often the only issue with this code is you didn't do something described in the ARM booting documentation.

您也可以直接使用 arch/arm/include/debug.宏是,

You may also use the macros directly which are defined in arch/arm/include/debug. The macros are,

  • addruart - 将 uart 的地址获取到参数 1 (phys), 2 (virt), (3rd 是宏的 tmp).
  • senduart - 将字符参数 1 写入地址(虚拟或物理).
  • waituart - 参数 1 (tmp),参数 2 地址(virt 或 phys).准备好了吗?
  • busyuart - 参数 1 (tmp),参数 2 地址(virt 或 phys).空?
  • addruart - get the addresses of the uarts to parameter 1 (phys), 2 (virt), (3rd is a tmp for macro).
  • senduart - write character param 1 to address (virtual or physical).
  • waituart - parm 1 (tmp), param 2 address (virt or phys). Ready?
  • busyuart - parm 1 (tmp), param 2 address (virt or phys). Empty?

可以看到printasii().

ENTRY(printascii)
        addruart_current r3, r1, r2   @ phys address to r3
        b   2f
1:      waituart r2, r3   @ ready (r2 is tmp, r3 is phys address)
        senduart r1, r3   @ transmit r1 character
        busyuart r2, r3   @ wait for character to finish tx.
        teq r1, #'\n'
        moveq   r1, #'\r' @ insert carriage return if new line.
        beq 1b
2:      teq r0, #0    @ NULL pointer?
        ldrneb  r1, [r0], #1  @ next char
        teqne   r1, #0        @ end of string?
        bne     1b            @ send another.
        mov pc, lr
ENDPROC(printascii)

head.S等汇编器中,您可以使用带有各种寄存器参数的宏来避免使用中的寄存器(例如r0-r3)的破坏.它们通常可供使用,并且可以直接调用printascii().

In the assembler of head.S and others, you can use the macros with various register arguments to avoid clobbers of in-use registers such as r0-r3. They are usually available for use and printascii() can be called directly.

这篇关于如何使用printf调试linux内核的汇编代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-07 02:24