add syslog printing to xmon debugger.
PATCH 1/1 add syslog printing to xmon debugger.
Hi,
This patch 'dmesg'/printk log buffer printing to xmon. I find this useful because crashes are almost always preceeded by interesting
printk's. This patch is simple & straightforward, except for one
possibly controversial aspect: it embeds a small snippet in kernel/printk.c to return the location of the syslog. This is needed because kallsyms and even CONFIG_KALLSYMS_ALL is not enough
to reveal the location of log_buf. This code is about 90%
cut-n-paste of earlier code from Keith Owens.
Andrew,
Please apply at least the kernel/printk.c part of the patch, if you are feeling at all charitable.
===== arch/ppc64/xmon/xmon.c 1.50 vs edited =====
arch/ppc64/xmon/xmon.c +57 -0
@@ -132,6 +132,7 @@static void bootcmds (void );void dump_segments (void );static void symbol_lookup (void ); +static void xmon_show_dmesg (void );static int emulate_step (struct pt_regs *regs,unsigned int instr);static void xmon_print_symbol (unsigned long address,const char *mid,const char *after);
@@ -175,6 +176,7 @@#endif "\ C checksum\n\ +D show dmesg (printk) buffer\n\ d dump bytes\n\ di dump instructions\n\ df dump float values\n\
@@ -911,6 +913,9 @@case 'd' :dump ();break ; +case 'D' : +xmon_show_dmesg (); +break ;case 'l' :symbol_lookup ();break ;
@@ -2452,6 +2457,58 @@printf (" [%s]" , modname); }printf ("%s" , after); +} + +extern void debugger_syslog_data (char *syslog_data[4 ]); +#define SYSLOG_WRAP (p) if (p < syslog_data[0]) p = syslog_data[1]-1; \ + else if (p >= syslog_data[1]) p = syslog_data[0]; + +static void xmon_show_dmesg (void ) +{ +char *syslog_data[4 ], *start, *end, c; +int logsize; + +/* syslog_data[0,1] physical start, end+1. +* syslog_data[2,3] logical start, end+1. +*/ +debugger_syslog_data (syslog_data); +if (syslog_data[2 ] == syslog_data[3 ]) +return ; + logsize = syslog_data[1 ] - syslog_data[0 ]; + start = syslog_data[0 ] + (syslog_data[2 ] - syslog_data[0 ]) % logsize; + end = syslog_data[0 ] + (syslog_data[3 ] - syslog_data[0 ]) % logsize; + +/* Do a line at a time (max 200 chars) to reduce overhead */ + c ='\0' ; +while (1 ) { +char *p; +int chars =0 ; +if (!*start) { +while (!*start) { + ++start; +SYSLOG_WRAP (start); +if (start == end) +break ; + } +if (start == end) +break ; + } + p = start; +while (*start && chars <200 ) { + c = *start; + ++chars; + ++start; +SYSLOG_WRAP (start); +if (start == end || c =='\n' ) +break ; + } +if (chars) +printf ("%.*s" , chars, p); +if (start == end) +break ; + } +if (c !='\n' ) +printf ("\n" ); }static void debug_trace (void )
===== kernel/printk.c 1.41 vs edited =====
kernel/printk.c +15 -0
@@ -376,6 +376,21 @@return do_syslog (type, buf, len); } +#ifdef CONFIG_DEBUG_KERNEL +/* Its very handy to be able to view the syslog buffer during debug. +* But do_syslog() uses locks so it cannot be used during debugging. +* Instead, provide the start and end of the physical and logical logs. +* This is equivalent to do_syslog(3). +*/ +void debugger_syslog_data (char *syslog_data[4 ]) +{ + syslog_data[0 ] = log_buf; + syslog_data[1 ] = log_buf + __LOG_BUF_LEN; + syslog_data[2 ] = log_buf + log_end - (logged_chars < __LOG_BUF_LEN ? logged_chars : __LOG_BUF_LEN); + syslog_data[3 ] = log_buf + log_end; +} +#endif /* CONFIG_DEBUG_KERNEL */ +/* * Call the console drivers on a range of log_buf */
Linas,
Quoted 4 lines
Andrew,
Please apply at least the
kernel/printk.cpart of the patch, if you are feeling at all charitable.
Did you ever get any reaction to that?
Paul.
Quoted 8 lines · Paul Mackerras
Linas,
Quoted 4 lines
Andrew,
Please apply at least the
kernel/printk.cpart of the patch, if you are feeling at all charitable.Did you ever get any reaction to that?
I see that the printk.c patch was lifted straight from kdb - without any mention of kdb. It even has the same bug as kdb, which was corrected in kdb-v4.4-2.6.9-common-2. The current kdb patch to printk.c is :-
kernel/printk.c +14 -0
@@ -373,6 +373,20 @@ out:return error; } +#ifdef CONFIG_KDB +/* kdb dmesg command needs access to the syslog buffer. do_syslog() uses locks +* so it cannot be used during debugging. Just tell kdb where the start and +* end of the physical and logical logs are. This is equivalent to do_syslog(3). +*/ +void kdb_syslog_data (char *syslog_data[4 ]) +{ + syslog_data[0 ] = log_buf; + syslog_data[1 ] = log_buf + log_buf_len; + syslog_data[2 ] = log_buf + log_end - (logged_chars < log_buf_len ? logged_chars : log_buf_len); + syslog_data[3 ] = log_buf + log_end; +} +#endif /* CONFIG_KDB */ +asmlinkage long sys_syslog (int type,char __user * buf,int len) {return do_syslog (type, buf, len);