[PATCH] x86_64: check bt->bptr before calculate framesize
by Tao Liu
Previously the value of bt->bptr is not checked, which may led to a
wrong prev_sp and framesize. As a result, bt->stackbuf[] will be
accessed out of range, and segfault.
Before:
crash> set debug 1
crash> bt
...snip...
--- <NMI exception stack> ---
#8 [ffffffff9a603e10] __switch_to_asm at ffffffff99800214
rsp: ffffffff9a603e10 textaddr: ffffffff99800214 -> spo: 0 bpo: 0 spr: 0 bpr: 0 type: 0 end: 0
#9 [ffffffff9a603e40] __schedule at ffffffff9960dfb1
rsp: ffffffff9a603e40 textaddr: ffffffff9960dfb1 -> spo: 16 bpo: -16 spr: 4 bpr: 1 type: 0 end: 0
rsp: ffffffff9a603e40 rbp: ffffb9ca076e7ca8 prev_sp: ffffb9ca076e7cb8 framesize: 1829650024
Segmentation fault (core dumped)
(gdb) p/x bt->stackbase
$1 = 0xffffffff9a600000
(gdb) p/x bt->stacktop
$2 = 0xffffffff9a604000
After:
crash> set debug 1
crash> bt
...snip...
--- <NMI exception stack> ---
#8 [ffffffff9a603e10] __switch_to_asm at ffffffff99800214
rsp: ffffffff9a603e10 textaddr: ffffffff99800214 -> spo: 0 bpo: 0 spr: 0 bpr: 0 type: 0 end: 0
#9 [ffffffff9a603e40] __schedule at ffffffff9960dfb1
rsp: ffffffff9a603e40 textaddr: ffffffff9960dfb1 -> spo: 16 bpo: -16 spr: 4 bpr: 1 type: 0 end: 0
#10 [ffffffff9a603e98] schedule_idle at ffffffff9960e87c
rsp: ffffffff9a603e98 textaddr: ffffffff9960e87c -> spo: 8 bpo: 0 spr: 5 bpr: 0 type: 0 end: 0
rsp: ffffffff9a603e98 prev_sp: ffffffff9a603ea8 framesize: 0
...snip...
This patch will check bt->bptr value before calculate framesize. Only bt->bptr
falls into the range of bt->stackbase and bt->stacktop will be
regarded as valid.
Signed-off-by: Tao Liu <ltao(a)redhat.com>
---
x86_64.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/x86_64.c b/x86_64.c
index 8abe39d..ff1ba6e 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -8707,7 +8707,8 @@ x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp, char *stack_
if (CRASHDEBUG(1))
fprintf(fp, "rsp: %lx prev_sp: %lx framesize: %d\n",
rsp, prev_sp, framesize);
- } else if ((korc->sp_reg == ORC_REG_BP) && bt->bptr) {
+ } else if ((korc->sp_reg == ORC_REG_BP) && bt->bptr &&
+ bt->bptr >= bt->stackbase && bt->bptr <= bt->stacktop) {
prev_sp = bt->bptr + korc->sp_offset;
framesize = (prev_sp - (rsp + 8) - 8);
if (CRASHDEBUG(1))
--
2.40.1
8 months, 2 weeks
Re: [PATCH v2] help.c: Remove kmem -l help, messages
by Lianbo Jiang
On 12/15/23 14:57, devel-request(a)lists.crash-utility.osci.io wrote:
> Date: Fri, 15 Dec 2023 10:44:21 +0800
> From: Li Zhijian<lizhijian(a)fujitsu.com>
> Subject: [Crash-utility] [PATCH v2] help.c: Remove kmem -l help
> messages
> To:devel@lists.crash-utility.osci.io
> Cc: Li Zhijian<lizhijian(a)fujitsu.com>
> Message-ID:<20231215024421.2253282-1-lizhijian(a)fujitsu.com>
>
> -l option has existed when crash git project initialization, but its
> help message was not accurate(extra arguments a|i|ic|id was missing).
>
> In addition, these symbols required by -l option was for the very*old old*
> kernels, at least >= 2.6 don't include them. And it looks like this option
> has not been fixed for a long time.
>
> Instead of document this option, hide it from help messages.
Looks good to me. For the v2: Ack.
Thanks.
Lianbo
> Signed-off-by: Li Zhijian<lizhijian(a)fujitsu.com>
> ---
> help.c | 2 --
> 1 file changed, 2 deletions(-)
>
> diff --git a/help.c b/help.c
> index cc7ab20e343e..d80e843703c1 100644
> --- a/help.c
> +++ b/help.c
> @@ -6888,8 +6888,6 @@ char *help_kmem[] = {
> " members of the associated page struct are displayed.",
> " address when used with -c, the address must be a page pointer address;",
> " the page_hash_table entry containing the page is displayed.",
> -" address when used with -l, the address must be a page pointer address;",
> -" the page address is displayed if it is contained with the list.",
> " address when used with -v, the address can be a mapped kernel virtual",
> " address or physical address; the mapped region containing the",
> " address is displayed.\n",
> -- 2.29.2
8 months, 2 weeks
[PATCH] crash add log dmesg PRINTK_CALLER id support
by Edward Chron
From: Edward Chron <echron(a)yahoo.com>
Submission to Project: crash
Component: dmesg
Files: printk.c makedumpfile.c makedumpfile.h
Code level patch applied against: 8.0.4++ - latest code pulled from
https://github.com/crash-utility/crash.git
crash Issue #164
Tested with Kernel version and makedumpfile version:
Linux Kernel Testing: Linux catalina 6.6.6 #4 SMP PREEMPT_DYNAMIC
Tue Dec 12 23:11:30 PST 2023 x86_64 GNU/Linux
Linux 5.4.264 #9 SMP
Thu Dec 21 07:00:08 PST 2023
makedumpfile Testing: makedumpfile: version 1.7.4++
(released on 6 Nov 2023)
Issue 13 for makedumpfile: adds support for
demsg PRINTK_CALLER id field
dmesg Testing: util-linux 2.39.3++
Issue 2609 for sys-utils dmesg: adds support for
dmesg PRINTK_CALLER id field to standard
dmesg kmsg interface
Add support so that dmesg entries include the optional Linux Kernel
debug CONFIG option PRINTK_CALLER which adds an optional dmesg field
that contains the Thread Id or CPU Id that is issuing the printk to
add the message to the kernel ring buffer. If enabled, this CONFIG
option makes debugging simpler as dmesg entries for a specific
thread or CPU can be recognized.
The dmesg command supports printing the PRINTK_CALLER field. The
old syslog format (dmesg -S) and recently support was added for dmesg
using /dev/kmsg interface with util-linux Issue #2609 as we upstreamed
a commit that is under review.
We've upstreamed a patch for makedumpfile that adds support for
the PRINTK_CALLER id field so it will be available with the
commands:
makedumpfile --dump-dmesg /proc/vmcore dmesgfile
makedumpfile --dump-dmesg -x vmlinux /proc/vmcore dmesgfile
The additional field provided by PRINTK_CALLER is only present
if it was configured for the Linux kernel on the running system. The
PRINTK_CALLER is a debug option and not configured by default so the
dmesg output will only change for those kernels where the option was
configured when the kernel was built. For users who went to the
trouble to configure PRINTK_CALLER and have the extra field available
for debugging, having dmesg print the field is very helpful and so
will be makedumpfile and so it would be very useful to have crash
support for dump analysis.
Size of the PRINTK_CALLER field is determined by the maximum number
tasks that can be run on the system which is limited by the value of
/proc/sys/kernel/pid_max as pid values are from 0 to value - 1.
This value determines the number of id digits needed by the caller id.
The PRINTK_CALLER field is printed as T<id> for a Task Id or C<id>
for a CPU Id for a printk in CPU context. The values are left space
padded and enclosed in parentheses such as:
[ T123] or [ C16]
Displaying the PRINTK_CALLER field in the log/dmesg record output:
-----------------------------------------------------------------
Given the layout of log/dmesg records printed by crash, for example:
crash> log -m
...
[ 0.000000] <7>e820: remove [mem 0xff000000-0xffffffff] reserved
[ 0.000000] <6>SMBIOS 3.4.0 present.
...
[ 0.014179] <6>Secure boot disabled
[ 0.014179] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]
...
[ 663.328848] <6>sysrq: Trigger a crash
[ 663.328859] <0>Kernel panic - not syncing: sysrq triggered crash
Our patch adds the PRINTK_CALLER field after the timestamp if the
printk_caller log / dmesg option (-P) is selected:
crash> log -m -P
...
[ 0.014179] [ T1] <6>Secure boot disabled
[ 0.014179] [ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]
...
This is consistent placement with dmesg and makedumpfile.
To produce dmesg output with the PRINTK_CALLER id included, we add
a new log / dmesg command option: -P
The PRINTK_CALLER id field is printed only if the -P option is selected.
The description of the log -P option that is seen in the help is:
crash> log help
log
dump system message buffer
[-TtdmasP]
...
...
-P Display the PRINTK_CALLER id field that identifies the thread id or
the CPU id of the task that issued the printk to add the message to
the kernel ring buffer. Displaying this field is only possible for
Linux kernels that are Linux 5.1 or newer since kernels prior to
Linux 5.1 did not provide a PRINTK_CALLER field. So, this option is
ignored for kernels older than Linux 5.1. The CONFIG_PRINTK_CALLER
kernel configuration option should be selected to make the caller_id
field available and for vmcore files your version of makedumpfile
must support dumping the caller_id field for it to be available here.
Also seen in the help file :
On systems that are properly configured to make the log caller_id field
available to the crash utility, you can select to print log records and
include the caller_id field with each log record. The log PRINTK_CALLER
id option (-P) will print either the Thread id or the CPU id depending on
the context of the process at the time the printk request was made. The
output of the thread id (begins with T) or the CPU id (begins with C) is
placed inside square brackets and is padded with leading space to keep
alignment. The caller_id field follows the timestamp field if that field
is selected:
crash> log -P
...
[ 0.014179] [ T1] Secure boot disabled
[ 0.014179] [ T29] RAMDISK: [mem 0x3cf4f000-0x437bbfff]
[ 0.198789] [ C0] DMAR: DRHD: handling fault status reg 3
...
crash> log -P -m
...
[ 0.014179] [ T1] <6>Secure boot disabled
[ 0.014179] [ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]
[ 0.198789] [ C0] <6>DMAR: DRHD: handling fault status reg 3
...
crash> log -t -P -m
...
[ T1] <6>Secure boot disabled
[ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]
[ C0] <6>DMAR: DRHD: handling fault status reg 3
...
crash> log -T -P -m
...
[Tue Dec 12 23:25:03 PST 2023] [ T1] <6>Secure boot disabled
[Tue Dec 12 23:25:03 PST 2023] [ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]
[Tue Dec 12 23:25:03 PST 2023] [ C0] <6>DMAR: DRHD: handling fault status reg 3
...
Signed-off-by: Ivan Delalande <colona(a)arista.com>
Signed-off-by: Edward Chron <echron(a)arista.com>
---
defs.h | 15 +++++++++------
help.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++--
kernel.c | 47 +++++++++++++++++++++++++++++++++++++++++++++--
printk.c | 39 +++++++++++++++++++++++++++++++++++++++
symbols.c | 2 ++
6 files changed, 150 insertions(+), 19 deletions(-)
diff --git a/defs.h b/defs.h
index 20237b7..a61e832 100644
--- a/defs.h
+++ b/defs.h
@@ -784,6 +784,7 @@ struct kernel_table { /* kernel data */
long log_len_OFFSET;
long log_text_len_OFFSET;
long log_dict_len_OFFSET;
+ ulong log_caller_id_OFFSET;
ulong phys_base_SYMBOL;
ulong _stext_SYMBOL;
} vmcoreinfo;
@@ -1943,6 +1944,7 @@ struct offset_table { /* stash of commonly-used offsets */
long log_dict_len;
long log_level;
long log_flags_level;
+ long log_caller_id;
long timekeeper_xtime_sec;
long neigh_table_hash_mask;
long sched_rt_entity_my_q;
@@ -6037,12 +6039,13 @@ void dump_log(int);
void parse_kernel_version(char *);
#define LOG_LEVEL(v) ((v) & 0x07)
-#define SHOW_LOG_LEVEL (0x1)
-#define SHOW_LOG_DICT (0x2)
-#define SHOW_LOG_TEXT (0x4)
-#define SHOW_LOG_AUDIT (0x8)
-#define SHOW_LOG_CTIME (0x10)
-#define SHOW_LOG_SAFE (0x20)
+#define SHOW_LOG_LEVEL (0x1)
+#define SHOW_LOG_DICT (0x2)
+#define SHOW_LOG_TEXT (0x4)
+#define SHOW_LOG_AUDIT (0x8)
+#define SHOW_LOG_CTIME (0x10)
+#define SHOW_LOG_SAFE (0x20)
+#define SHOW_LOG_CALLER (0x40)
void set_cpu(int);
void clear_machdep_cache(void);
struct stack_hook *gather_text_list(struct bt_info *);
diff --git a/help.c b/help.c
index cc7ab20..1de1292 100644
--- a/help.c
+++ b/help.c
@@ -4023,7 +4023,7 @@ NULL
char *help_log[] = {
"log",
"dump system message buffer",
-"[-Ttdmas]",
+"[-TtdmasP]",
" This command dumps the kernel log_buf contents in chronological order. The",
" command supports the older log_buf formats, which may or may not contain a",
" timestamp inserted prior to each message, as well as the newer variable-length",
@@ -4046,7 +4046,16 @@ char *help_log[] = {
" been copied out to the user-space audit daemon.",
" -s Dump the printk logs remaining in kernel safe per-CPU buffers that",
" have not been flushed out to log_buf.",
-" ",
+" -P Display the PRINTK_CALLER id field that identifies the thread id or",
+" the CPU id of the task that issued the printk to add the message to",
+" the kernel ring buffer. Displaying this field is only possible for",
+" Linux kernels that are Linux 5.1 or newer since kernels prior to",
+" Linux 5.1 did not provide a PRINTK_CALLER field. So, this option is",
+" ignored for kernels older than Linux 5.1. The CONFIG_PRINTK_CALLER",
+" kernel configuration option should be selected to make the caller_id",
+" field available and for vmcore files your version of makedumpfile",
+" must support dumping the caller_id field for it to be available here.",
+" ",
"\nEXAMPLES",
" Dump the kernel message buffer:\n",
" %s> log",
@@ -4214,6 +4223,41 @@ char *help_log[] = {
" CPU: 0 ADDR: ffff8ca4fbc1ad00 LEN: 0 MESSAGE_LOST: 0",
" (empty)",
" ...",
+" ",
+" On systems that are properly configured to make the log caller_id field",
+" available to the crash utility, you can select to print log records and",
+" include the caller_id field with each log record. The log PRINTK_CALLER",
+" id option (-P) will print either the Thread id or the CPU id depending on",
+" the context of the process at the time the printk request was made. The",
+" output of the thread id (begins with T) or the CPU id (begins with C) is",
+" placed inside square brackets and is padded with leading space to keep",
+" alignment. The caller_id field follows the timestamp field if that field",
+" is selected:\n",
+" %s> log -P",
+" ...",
+" [ 0.014179] [ T1] Secure boot disabled",
+" [ 0.014179] [ T29] RAMDISK: [mem 0x3cf4f000-0x437bbfff]",
+" [ 0.198789] [ C0] DMAR: DRHD: handling fault status reg 3",
+" ...",
+" %s> log -P -m",
+" ...",
+" [ 0.014179] [ T1] <6>Secure boot disabled",
+" [ 0.014179] [ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]",
+" [ 0.198789] [ C0] <6>DMAR: DRHD: handling fault status reg 3",
+" ...",
+" %s> log -t -P -m",
+" ...",
+" [ T1] <6>Secure boot disabled",
+" [ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]",
+" [ C0] <6>DMAR: DRHD: handling fault status reg 3",
+" ...",
+" %s> log -T -P -m",
+" ...",
+" [Tue Dec 12 23:25:03 PST 2023] [ T1] <6>Secure boot disabled",
+" [Tue Dec 12 23:25:03 PST 2023] [ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]",
+" [Tue Dec 12 23:25:03 PST 2023] [ C0] <6>DMAR: DRHD: handling fault status reg 3",
+" ...",
+
NULL
};
diff --git a/kernel.c b/kernel.c
index 6dcf414..0475b07 100644
--- a/kernel.c
+++ b/kernel.c
@@ -29,6 +29,9 @@
#endif
#include "bfd.h"
+#define PID_CHARS_MAX 16 /* Max Number of PID characters */
+#define PID_CHARS_DEFAULT 8 /* Default number of PID characters */
+
static void do_module_cmd(ulong, char *, ulong, char *, char *);
static void show_module_taint(void);
static char *find_module_objfile(char *, char *, char *);
@@ -5089,7 +5092,7 @@ cmd_log(void)
msg_flags = 0;
- while ((c = getopt(argcnt, args, "Ttdmas")) != EOF) {
+ while ((c = getopt(argcnt, args, "TtdmasP")) != EOF) {
switch(c)
{
case 'T':
@@ -5110,6 +5113,9 @@ cmd_log(void)
case 's':
msg_flags |= SHOW_LOG_SAFE;
break;
+ case 'P':
+ msg_flags |= SHOW_LOG_CALLER;
+ break;
default:
argerrs++;
break;
@@ -5369,6 +5375,29 @@ dump_log_entry(char *logptr, int msg_flags)
fprintf(fp, "%s", buf);
}
+ /* The PRINTK_CALLER id field was introduced with Linux-5.1 so if
+ * requested, Kernel version >= 5.1 and field exists print caller_id.
+ */
+ if (msg_flags & SHOW_LOG_CALLER &&
+ kt->kernel_version[0] >= 5 &&
+ kt->kernel_version[1] >= 1 &&
+ VALID_MEMBER(log_caller_id)) {
+ const unsigned int cpuid = 0x80000000;
+ char cidbuf[PID_CHARS_MAX];
+ unsigned int pkc;
+ char idtype;
+
+ /* Get id type, isolate id value in pkc for print */
+ pkc = UINT(logptr + OFFSET(log_caller_id));
+ idtype = (pkc & cpuid) ? 'C' : 'T';
+ pkc &= ~cpuid;
+ sprintf(cidbuf, "%c%d", idtype, pkc);
+ sprintf(buf, "[%*s] ", PID_CHARS_DEFAULT, cidbuf);
+
+ ilen += strlen(buf);
+ fprintf(fp, "%s", buf);
+ }
+
level = LOG_LEVEL(level);
if (msg_flags & SHOW_LOG_LEVEL) {
@@ -5424,8 +5453,13 @@ dump_variable_length_record_log(int msg_flags)
* from log to printk_log. See 62e32ac3505a0cab.
*/
log_struct_name = "printk_log";
- } else
+ if (MEMBER_EXISTS("printk_log", "caller_id"))
+ MEMBER_OFFSET_INIT(log_caller_id, "printk_log",
+ "caller_id");
+ } else {
log_struct_name = "log";
+ INVALID_MEMBER(log_caller_id);
+ }
STRUCT_SIZE_INIT(log, log_struct_name);
MEMBER_OFFSET_INIT(log_ts_nsec, log_struct_name, "ts_nsec");
@@ -11132,6 +11166,15 @@ get_log_from_vmcoreinfo(char *file)
vmc->log_dict_len_OFFSET);
free(string);
}
+ /* The caller_id field exists only in printk_log if kernel >= 5.1
+ * and if CONFIG_PRINTK_CALLER was set in the kernel config file*/
+ if ((string = pc->read_vmcoreinfo("OFFSET(printk_log.caller_id"))) {
+ vmc->log_dict_len_OFFSET = dtol(string, RETURN_ON_ERROR, NULL);
+ if (CRASHDEBUG(1))
+ fprintf(fp, "OFFSET(printk_log.caller_id): %ld\n",
+ vmc->log_caller_id_OFFSET);
+ free(string);
+ }
if ((string = pc->read_vmcoreinfo("SIZE(log)"))) {
vmc->log_SIZE = dtol(string, RETURN_ON_ERROR, NULL);
if (CRASHDEBUG(1))
diff --git a/printk.c b/printk.c
index 8658016..d1b3f40 100644
--- a/printk.c
+++ b/printk.c
@@ -9,6 +9,7 @@ struct prb_map {
unsigned long desc_ring_count;
char *descs;
char *infos;
+ unsigned int pid_max_chars;
char *text_data_ring;
unsigned long text_data_ring_size;
@@ -37,6 +38,9 @@ enum desc_state {
#define DESC_ID_MASK (~DESC_FLAGS_MASK)
#define DESC_ID(sv) ((sv) & DESC_ID_MASK)
+#define PID_CHARS_MAX 16 /* Max Number of PID characters */
+#define PID_CHARS_DEFAULT 8 /* Default number of PID characters */
+
/*
* get_desc_state() taken from kernel source:
*
@@ -162,6 +166,27 @@ dump_record(struct prb_map *m, unsigned long id, int msg_flags)
fprintf(fp, "%s", buf);
}
+ /*
+ * The lockless ringbuffer introduced in Linux-5.10 always has
+ * the caller_id field available, so if requested, print it.
+ */
+ if (msg_flags & SHOW_LOG_CALLER) {
+ const unsigned int cpuid = 0x80000000;
+ char cidbuf[PID_CHARS_MAX];
+ unsigned int pkc;
+ char idtype;
+
+ /* Get id type, isolate id value in pkc for print */
+ pkc = UINT(info + OFFSET(printk_info_caller_id));
+ idtype = (pkc & cpuid) ? 'C' : 'T';
+ pkc &= ~cpuid;
+ sprintf(cidbuf, "%c%d", idtype, pkc);
+ sprintf(buf, "[%*s] ", PID_CHARS_DEFAULT, cidbuf);
+
+ ilen += strlen(buf);
+ fprintf(fp, "%s", buf);
+ }
+
if (msg_flags & SHOW_LOG_LEVEL) {
level = UCHAR(info + OFFSET(printk_info_level)) >> 5;
sprintf(buf, "<%x>", level);
@@ -262,6 +287,20 @@ dump_lockless_record_log(int msg_flags)
goto out_text_data;
}
+ /* Get pid_max and fill it in if we need it */
+ if (msg_flags & SHOW_LOG_CALLER) {
+ char pid_chars[PID_CHARS_MAX];
+ size_t pc_size = sizeof(pid_chars);
+ size_t pid_chars_length;
+ unsigned int pid_max;
+
+ get_symbol_data("pid_max", sizeof(pid_max), &pid_max);
+ pid_chars_length = snprintf(pid_chars, pc_size, "%u", &pid_max);
+ m.pid_max_chars = pid_chars_length + 1;
+ } else {
+ m.pid_max_chars = PID_CHARS_DEFAULT;
+ }
+
/* ready to go */
tail_id = ULONG(m.desc_ring + OFFSET(prb_desc_ring_tail_id) +
diff --git a/symbols.c b/symbols.c
index 5d91991..7969409 100644
--- a/symbols.c
+++ b/symbols.c
@@ -11521,6 +11521,8 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(log_level));
fprintf(fp, " log_flags_level: %ld\n",
OFFSET(log_flags_level));
+ fprintf(fp, " log_caller_id: %ld\n",
+ OFFSET(log_caller_id));
fprintf(fp, " printk_info_seq: %ld\n", OFFSET(printk_info_seq));
fprintf(fp, " printk_info_ts_nseq: %ld\n", OFFSET(printk_info_ts_nsec));
--
2.43.0
8 months, 2 weeks
crash utility: add log / dmesg PRINTK_CALLER id support
by echron@yahoo.com
Submission to Project: crash
Component: dmesg
Files: printk.c makedumpfile.c help.c makedumpfile.h
Code level patch applied against: 8.0.4++ - latest code pulled from
https://github.com/crash-utility/crash.git
crash Issue #164 at https://github.com/crash-utility/crash/issues/164
Tested with several Kernel versions, and udated makedumpfile and updated util-linux dmesg versions:
Linux Kernel Testing: Linux 6.6.6 #4 SMP PREEMPT_DYNAMIC
Tue Dec 12 23:11:30 PST 2023 x86_64 GNU/Linux
Linux 5.4.264 #9 SMP
Thu Dec 21 07:00:08 PST 2023
makedumpfile Testing: makedumpfile: version 1.7.4++
(released on 6 Nov 2023) with commit sent for PRINTK_CALLER support
See #Issue 13 for makedumpfile: add support for demsg PRINTK_CALLER id field
dmesg Testing: util-linux 2.39.3++ with commit sent for PRINTK_CALLER support
See Issue 2609 for util-linux: add support for dmesg PRINTK_CALLER id field to standard dmesg kmsg interface
Add support so that dmesg entries include the optional Linux Kernel
debug CONFIG option PRINTK_CALLER which adds an optional dmesg field
that contains the Thread Id or CPU Id that is issued the printk to
add the message to the kernel ring buffer. If enabled, this CONFIG
option makes debugging simpler as dmesg entries for a specific thread or CPU
can be recognized for each log entry.
The dmesg command supports printing the PRINTK_CALLER field. The
old syslog format (dmesg -S) and recently support was added for dmesg
using /dev/kmsg interface with util-linux Issue #2609 and we upstreamed a
commit that is under review.
We've upstreamed a patch for makedumpfile that adds support for
the PRINTK_CALLER id field so it will be available with the
commands:
makedumpfile --dump-dmesg /proc/vmcore dmesgfile
makedumpfile --dump-dmesg -x vmlinux /proc/vmcore dmesgfile
The additional field provided by PRINTK_CALLER is only present
if it was configured for the Linux kernel on the running system. The
PRINTK_CALLER is a debug option and not configured by default so the
dmesg output will only change for those kernels where the option was
configured when the kernel was built. For users who went to the
trouble to configure PRINTK_CALLER and have the extra field available.
for debugging, having dmesg print the field is very helpful and so
will be makedumpfile and so it would be very useful to have crash
support for dump analysis.
Size of the PRINTK_CALLER field is determined by the maximum number
tasks that can be run on the system which is limited by the value of
/proc/sys/kernel/pid_max as pid values are from 0 to value - 1.
This value determines the number of id digits needed by the caller id.
The PRINTK_CALLER field is printed as T for a Task Id or C
for a CPU Id for a printk in CPU context. The values are left space
padded and enclosed in parentheses such as:
[ T123] or [ C16]
Displaying the PRINTK_CALLER field in the log/dmesg record output:
Given the layout of log/dmesg records printed by crash, for example:
crash> log -m
...
[ 0.000000] <7>e820: remove [mem 0xff000000-0xffffffff] reserved
[ 0.000000] <6>SMBIOS 3.4.0 present.
...
[ 0.014179] <6>Secure boot disabled
[ 0.014179] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]
...
[ 663.328848] <6>sysrq: Trigger a crash
[ 663.328859] <0>Kernel panic - not syncing: sysrq triggered crash
Our patch adds the PRINTK_CALLER field after the timestamp if the
printk_caller log / dmesg option (-P) is selected:
crash> log -m -P
...
[ 0.014179] [ T1] <6>Secure boot disabled
[ 0.014179] [ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]
...
This is consistent placement with dmesg and makedumpfile.
To produce dmesg output with the PRINTK_CALLER id included, we add
a new log / dmesg command option: -P
The PRINTK_CALLER id field is printed only if the -P option is selected.
The description of the log -P option that is seen in the help is:
crash> log help
log
dump system message buffer
[-TtdmasP]
...
...
-P Display the PRINTK_CALLER id field that identifies the thread id or
the CPU id of the task that issued the printk to add the message to
the kernel ring buffer. Displaying this field is only possible for
Linux kernels that are Linux 5.1 or newer since kernels prior to
Linux 5.1 did not provide a PRINTK_CALLER field. So, this option is
ignored for kernels older than Linux 5.1. The CONFIG_PRINTK_CALLER
kernel configuration option should be selected to make the caller_id
field available and for vmcore files your version of makedumpfile
must support dumping the caller_id field for it to be available here.
Also seen in the help file :
On systems that are properly configured to make the log caller_id field
available to the crash utility, you can select to print log records and
include the caller_id field with each log record. The log PRINTK_CALLER
id option (-P) will print either the Thread id or the CPU id depending on
the context of the process at the time the printk request was made. The
output of the thread id (begins with T) or the CPU id (begins with C) is
placed inside square brackets and is padded with leading space to keep
alignment. The caller_id field follows the timestamp field if that field
is selected:
crash> log -P
...
[ 0.014179] [ T1] Secure boot disabled
[ 0.014179] [ T29] RAMDISK: [mem 0x3cf4f000-0x437bbfff]
[ 0.198789] [ C0] DMAR: DRHD: handling fault status reg 3
...
crash> log -P -m
...
[ 0.014179] [ T1] <6>Secure boot disabled
[ 0.014179] [ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]
[ 0.198789] [ C0] <6>DMAR: DRHD: handling fault status reg 3
...
crash> log -t -P -m
...
[ T1] <6>Secure boot disabled
[ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]
[ C0] <6>DMAR: DRHD: handling fault status reg 3
...
crash> log -T -P -m
...
[Tue Dec 12 23:25:03 PST 2023] [ T1] <6>Secure boot disabled
[Tue Dec 12 23:25:03 PST 2023] [ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]
[Tue Dec 12 23:25:03 PST 2023] [ C0] <6>DMAR: DRHD: handling fault status reg 3
...
Signed-off-by: Ivan Delalande colona(a)arista.com
Signed-off-by: Edward Chron echron(a)arista.com
8 months, 2 weeks
[PATCH] crash add log dmesg PRINTK_CALLER id support
by Edward Chron
Submission to Project: crash
Component: dmesg
Files: printk.c makedumpfile.c makedumpfile.h
Code level patch applied against: 8.0.4++ - latest code pulled from
https://github.com/crash-utility/crash.git
crash Issue #164
Tested with Kernel version and makedumpfile version:
Linux Kernel Testing: Linux catalina 6.6.6 #4 SMP PREEMPT_DYNAMIC
Tue Dec 12 23:11:30 PST 2023 x86_64 GNU/Linux
Linux 5.4.264 #9 SMP
Thu Dec 21 07:00:08 PST 2023
makedumpfile Testing: makedumpfile: version 1.7.4++
(released on 6 Nov 2023)
Issue 13 for makedumpfile: adds support for
demsg PRINTK_CALLER id field
dmesg Testing: util-linux 2.39.3++
Issue 2609 for sys-utils dmesg: adds support for
dmesg PRINTK_CALLER id field to standard
dmesg kmsg interface
Add support so that dmesg entries include the optional Linux Kernel
debug CONFIG option PRINTK_CALLER which adds an optional dmesg field
that contains the Thread Id or CPU Id that is issuing the printk to
add the message to the kernel ring buffer. If enabled, this CONFIG
option makes debugging simpler as dmesg entries for a specific
thread or CPU can be recognized.
The dmesg command supports printing the PRINTK_CALLER field. The
old syslog format (dmesg -S) and recently support was added for dmesg
using /dev/kmsg interface with util-linux Issue #2609 as we upstreamed
a commit that is under review.
We've upstreamed a patch for makedumpfile that adds support for
the PRINTK_CALLER id field so it will be available with the
commands:
makedumpfile --dump-dmesg /proc/vmcore dmesgfile
makedumpfile --dump-dmesg -x vmlinux /proc/vmcore dmesgfile
The additional field provided by PRINTK_CALLER is only present
if it was configured for the Linux kernel on the running system. The
PRINTK_CALLER is a debug option and not configured by default so the
dmesg output will only change for those kernels where the option was
configured when the kernel was built. For users who went to the
trouble to configure PRINTK_CALLER and have the extra field available
for debugging, having dmesg print the field is very helpful and so
will be makedumpfile and so it would be very useful to have crash
support for dump analysis.
Size of the PRINTK_CALLER field is determined by the maximum number
tasks that can be run on the system which is limited by the value of
/proc/sys/kernel/pid_max as pid values are from 0 to value - 1.
This value determines the number of id digits needed by the caller id.
The PRINTK_CALLER field is printed as T<id> for a Task Id or C<id>
for a CPU Id for a printk in CPU context. The values are left space
padded and enclosed in parentheses such as:
[ T123] or [ C16]
Displaying the PRINTK_CALLER field in the log/dmesg record output:
-----------------------------------------------------------------
Given the layout of log/dmesg records printed by crash, for example:
crash> log -m
...
[ 0.000000] <7>e820: remove [mem 0xff000000-0xffffffff] reserved
[ 0.000000] <6>SMBIOS 3.4.0 present.
...
[ 0.014179] <6>Secure boot disabled
[ 0.014179] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]
...
[ 663.328848] <6>sysrq: Trigger a crash
[ 663.328859] <0>Kernel panic - not syncing: sysrq triggered crash
Our patch adds the PRINTK_CALLER field after the timestamp if the
printk_caller log / dmesg option (-P) is selected:
crash> log -m -P
...
[ 0.014179] [ T1] <6>Secure boot disabled
[ 0.014179] [ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]
...
This is consistent placement with dmesg and makedumpfile.
To produce dmesg output with the PRINTK_CALLER id included, we add
a new log / dmesg command option: -P
The PRINTK_CALLER id field is printed only if the -P option is selected.
The description of the log -P option that is seen in the help is:
crash> log help
log
dump system message buffer
[-TtdmasP]
...
...
-P Display the PRINTK_CALLER id field that identifies the thread id or
the CPU id of the task that issued the printk to add the message to
the kernel ring buffer. Displaying this field is only possible for
Linux kernels that are Linux 5.1 or newer since kernels prior to
Linux 5.1 did not provide a PRINTK_CALLER field. So, this option is
ignored for kernels older than Linux 5.1. The CONFIG_PRINTK_CALLER
kernel configuration option should be selected to make the caller_id
field available and for vmcore files your version of makedumpfile
must support dumping the caller_id field for it to be available here.
Also seen in the help file :
On systems that are properly configured to make the log caller_id field
available to the crash utility, you can select to print log records and
include the caller_id field with each log record. The log PRINTK_CALLER
id option (-P) will print either the Thread id or the CPU id depending on
the context of the process at the time the printk request was made. The
output of the thread id (begins with T) or the CPU id (begins with C) is
placed inside square brackets and is padded with leading space to keep
alignment. The caller_id field follows the timestamp field if that field
is selected:
crash> log -P
...
[ 0.014179] [ T1] Secure boot disabled
[ 0.014179] [ T29] RAMDISK: [mem 0x3cf4f000-0x437bbfff]
[ 0.198789] [ C0] DMAR: DRHD: handling fault status reg 3
...
crash> log -P -m
...
[ 0.014179] [ T1] <6>Secure boot disabled
[ 0.014179] [ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]
[ 0.198789] [ C0] <6>DMAR: DRHD: handling fault status reg 3
...
crash> log -t -P -m
...
[ T1] <6>Secure boot disabled
[ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]
[ C0] <6>DMAR: DRHD: handling fault status reg 3
...
crash> log -T -P -m
...
[Tue Dec 12 23:25:03 PST 2023] [ T1] <6>Secure boot disabled
[Tue Dec 12 23:25:03 PST 2023] [ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]
[Tue Dec 12 23:25:03 PST 2023] [ C0] <6>DMAR: DRHD: handling fault status reg 3
...
Signed-off-by: Ivan Delalande <colona(a)arista.com>
Signed-off-by: Edward Chron <echron(a)arista.com>
---
defs.h | 15 +++++++++------
help.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++--
kernel.c | 47 +++++++++++++++++++++++++++++++++++++++++++++--
printk.c | 39 +++++++++++++++++++++++++++++++++++++++
symbols.c | 2 ++
6 files changed, 150 insertions(+), 19 deletions(-)
diff --git a/defs.h b/defs.h
index 20237b7..a61e832 100644
--- a/defs.h
+++ b/defs.h
@@ -784,6 +784,7 @@ struct kernel_table { /* kernel data */
long log_len_OFFSET;
long log_text_len_OFFSET;
long log_dict_len_OFFSET;
+ ulong log_caller_id_OFFSET;
ulong phys_base_SYMBOL;
ulong _stext_SYMBOL;
} vmcoreinfo;
@@ -1943,6 +1944,7 @@ struct offset_table { /* stash of commonly-used offsets */
long log_dict_len;
long log_level;
long log_flags_level;
+ long log_caller_id;
long timekeeper_xtime_sec;
long neigh_table_hash_mask;
long sched_rt_entity_my_q;
@@ -6037,12 +6039,13 @@ void dump_log(int);
void parse_kernel_version(char *);
#define LOG_LEVEL(v) ((v) & 0x07)
-#define SHOW_LOG_LEVEL (0x1)
-#define SHOW_LOG_DICT (0x2)
-#define SHOW_LOG_TEXT (0x4)
-#define SHOW_LOG_AUDIT (0x8)
-#define SHOW_LOG_CTIME (0x10)
-#define SHOW_LOG_SAFE (0x20)
+#define SHOW_LOG_LEVEL (0x1)
+#define SHOW_LOG_DICT (0x2)
+#define SHOW_LOG_TEXT (0x4)
+#define SHOW_LOG_AUDIT (0x8)
+#define SHOW_LOG_CTIME (0x10)
+#define SHOW_LOG_SAFE (0x20)
+#define SHOW_LOG_CALLER (0x40)
void set_cpu(int);
void clear_machdep_cache(void);
struct stack_hook *gather_text_list(struct bt_info *);
diff --git a/help.c b/help.c
index cc7ab20..1de1292 100644
--- a/help.c
+++ b/help.c
@@ -4023,7 +4023,7 @@ NULL
char *help_log[] = {
"log",
"dump system message buffer",
-"[-Ttdmas]",
+"[-TtdmasP]",
" This command dumps the kernel log_buf contents in chronological order. The",
" command supports the older log_buf formats, which may or may not contain a",
" timestamp inserted prior to each message, as well as the newer variable-length",
@@ -4046,7 +4046,16 @@ char *help_log[] = {
" been copied out to the user-space audit daemon.",
" -s Dump the printk logs remaining in kernel safe per-CPU buffers that",
" have not been flushed out to log_buf.",
-" ",
+" -P Display the PRINTK_CALLER id field that identifies the thread id or",
+" the CPU id of the task that issued the printk to add the message to",
+" the kernel ring buffer. Displaying this field is only possible for",
+" Linux kernels that are Linux 5.1 or newer since kernels prior to",
+" Linux 5.1 did not provide a PRINTK_CALLER field. So, this option is",
+" ignored for kernels older than Linux 5.1. The CONFIG_PRINTK_CALLER",
+" kernel configuration option should be selected to make the caller_id",
+" field available and for vmcore files your version of makedumpfile",
+" must support dumping the caller_id field for it to be available here.",
+" ",
"\nEXAMPLES",
" Dump the kernel message buffer:\n",
" %s> log",
@@ -4214,6 +4223,41 @@ char *help_log[] = {
" CPU: 0 ADDR: ffff8ca4fbc1ad00 LEN: 0 MESSAGE_LOST: 0",
" (empty)",
" ...",
+" ",
+" On systems that are properly configured to make the log caller_id field",
+" available to the crash utility, you can select to print log records and",
+" include the caller_id field with each log record. The log PRINTK_CALLER",
+" id option (-P) will print either the Thread id or the CPU id depending on",
+" the context of the process at the time the printk request was made. The",
+" output of the thread id (begins with T) or the CPU id (begins with C) is",
+" placed inside square brackets and is padded with leading space to keep",
+" alignment. The caller_id field follows the timestamp field if that field",
+" is selected:\n",
+" %s> log -P",
+" ...",
+" [ 0.014179] [ T1] Secure boot disabled",
+" [ 0.014179] [ T29] RAMDISK: [mem 0x3cf4f000-0x437bbfff]",
+" [ 0.198789] [ C0] DMAR: DRHD: handling fault status reg 3",
+" ...",
+" %s> log -P -m",
+" ...",
+" [ 0.014179] [ T1] <6>Secure boot disabled",
+" [ 0.014179] [ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]",
+" [ 0.198789] [ C0] <6>DMAR: DRHD: handling fault status reg 3",
+" ...",
+" %s> log -t -P -m",
+" ...",
+" [ T1] <6>Secure boot disabled",
+" [ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]",
+" [ C0] <6>DMAR: DRHD: handling fault status reg 3",
+" ...",
+" %s> log -T -P -m",
+" ...",
+" [Tue Dec 12 23:25:03 PST 2023] [ T1] <6>Secure boot disabled",
+" [Tue Dec 12 23:25:03 PST 2023] [ T29] <6>RAMDISK: [mem 0x3cf4f000-0x437bbfff]",
+" [Tue Dec 12 23:25:03 PST 2023] [ C0] <6>DMAR: DRHD: handling fault status reg 3",
+" ...",
+
NULL
};
diff --git a/kernel.c b/kernel.c
index 6dcf414..0475b07 100644
--- a/kernel.c
+++ b/kernel.c
@@ -29,6 +29,9 @@
#endif
#include "bfd.h"
+#define PID_CHARS_MAX 16 /* Max Number of PID characters */
+#define PID_CHARS_DEFAULT 8 /* Default number of PID characters */
+
static void do_module_cmd(ulong, char *, ulong, char *, char *);
static void show_module_taint(void);
static char *find_module_objfile(char *, char *, char *);
@@ -5089,7 +5092,7 @@ cmd_log(void)
msg_flags = 0;
- while ((c = getopt(argcnt, args, "Ttdmas")) != EOF) {
+ while ((c = getopt(argcnt, args, "TtdmasP")) != EOF) {
switch(c)
{
case 'T':
@@ -5110,6 +5113,9 @@ cmd_log(void)
case 's':
msg_flags |= SHOW_LOG_SAFE;
break;
+ case 'P':
+ msg_flags |= SHOW_LOG_CALLER;
+ break;
default:
argerrs++;
break;
@@ -5369,6 +5375,29 @@ dump_log_entry(char *logptr, int msg_flags)
fprintf(fp, "%s", buf);
}
+ /* The PRINTK_CALLER id field was introduced with Linux-5.1 so if
+ * requested, Kernel version >= 5.1 and field exists print caller_id.
+ */
+ if (msg_flags & SHOW_LOG_CALLER &&
+ kt->kernel_version[0] >= 5 &&
+ kt->kernel_version[1] >= 1 &&
+ VALID_MEMBER(log_caller_id)) {
+ const unsigned int cpuid = 0x80000000;
+ char cidbuf[PID_CHARS_MAX];
+ unsigned int pkc;
+ char idtype;
+
+ /* Get id type, isolate id value in pkc for print */
+ pkc = UINT(logptr + OFFSET(log_caller_id));
+ idtype = (pkc & cpuid) ? 'C' : 'T';
+ pkc &= ~cpuid;
+ sprintf(cidbuf, "%c%d", idtype, pkc);
+ sprintf(buf, "[%*s] ", PID_CHARS_DEFAULT, cidbuf);
+
+ ilen += strlen(buf);
+ fprintf(fp, "%s", buf);
+ }
+
level = LOG_LEVEL(level);
if (msg_flags & SHOW_LOG_LEVEL) {
@@ -5424,8 +5453,13 @@ dump_variable_length_record_log(int msg_flags)
* from log to printk_log. See 62e32ac3505a0cab.
*/
log_struct_name = "printk_log";
- } else
+ if (MEMBER_EXISTS("printk_log", "caller_id"))
+ MEMBER_OFFSET_INIT(log_caller_id, "printk_log",
+ "caller_id");
+ } else {
log_struct_name = "log";
+ INVALID_MEMBER(log_caller_id);
+ }
STRUCT_SIZE_INIT(log, log_struct_name);
MEMBER_OFFSET_INIT(log_ts_nsec, log_struct_name, "ts_nsec");
@@ -11132,6 +11166,15 @@ get_log_from_vmcoreinfo(char *file)
vmc->log_dict_len_OFFSET);
free(string);
}
+ /* The caller_id field exists only in printk_log if kernel >= 5.1
+ * and if CONFIG_PRINTK_CALLER was set in the kernel config file*/
+ if ((string = pc->read_vmcoreinfo("OFFSET(printk_log.caller_id"))) {
+ vmc->log_dict_len_OFFSET = dtol(string, RETURN_ON_ERROR, NULL);
+ if (CRASHDEBUG(1))
+ fprintf(fp, "OFFSET(printk_log.caller_id): %ld\n",
+ vmc->log_caller_id_OFFSET);
+ free(string);
+ }
if ((string = pc->read_vmcoreinfo("SIZE(log)"))) {
vmc->log_SIZE = dtol(string, RETURN_ON_ERROR, NULL);
if (CRASHDEBUG(1))
diff --git a/printk.c b/printk.c
index 8658016..d1b3f40 100644
--- a/printk.c
+++ b/printk.c
@@ -9,6 +9,7 @@ struct prb_map {
unsigned long desc_ring_count;
char *descs;
char *infos;
+ unsigned int pid_max_chars;
char *text_data_ring;
unsigned long text_data_ring_size;
@@ -37,6 +38,9 @@ enum desc_state {
#define DESC_ID_MASK (~DESC_FLAGS_MASK)
#define DESC_ID(sv) ((sv) & DESC_ID_MASK)
+#define PID_CHARS_MAX 16 /* Max Number of PID characters */
+#define PID_CHARS_DEFAULT 8 /* Default number of PID characters */
+
/*
* get_desc_state() taken from kernel source:
*
@@ -162,6 +166,27 @@ dump_record(struct prb_map *m, unsigned long id, int msg_flags)
fprintf(fp, "%s", buf);
}
+ /*
+ * The lockless ringbuffer introduced in Linux-5.10 always has
+ * the caller_id field available, so if requested, print it.
+ */
+ if (msg_flags & SHOW_LOG_CALLER) {
+ const unsigned int cpuid = 0x80000000;
+ char cidbuf[PID_CHARS_MAX];
+ unsigned int pkc;
+ char idtype;
+
+ /* Get id type, isolate id value in pkc for print */
+ pkc = UINT(info + OFFSET(printk_info_caller_id));
+ idtype = (pkc & cpuid) ? 'C' : 'T';
+ pkc &= ~cpuid;
+ sprintf(cidbuf, "%c%d", idtype, pkc);
+ sprintf(buf, "[%*s] ", PID_CHARS_DEFAULT, cidbuf);
+
+ ilen += strlen(buf);
+ fprintf(fp, "%s", buf);
+ }
+
if (msg_flags & SHOW_LOG_LEVEL) {
level = UCHAR(info + OFFSET(printk_info_level)) >> 5;
sprintf(buf, "<%x>", level);
@@ -262,6 +287,20 @@ dump_lockless_record_log(int msg_flags)
goto out_text_data;
}
+ /* Get pid_max and fill it in if we need it */
+ if (msg_flags & SHOW_LOG_CALLER) {
+ char pid_chars[PID_CHARS_MAX];
+ size_t pc_size = sizeof(pid_chars);
+ size_t pid_chars_length;
+ unsigned int pid_max;
+
+ get_symbol_data("pid_max", sizeof(pid_max), &pid_max);
+ pid_chars_length = snprintf(pid_chars, pc_size, "%u", &pid_max);
+ m.pid_max_chars = pid_chars_length + 1;
+ } else {
+ m.pid_max_chars = PID_CHARS_DEFAULT;
+ }
+
/* ready to go */
tail_id = ULONG(m.desc_ring + OFFSET(prb_desc_ring_tail_id) +
diff --git a/symbols.c b/symbols.c
index 5d91991..7969409 100644
--- a/symbols.c
+++ b/symbols.c
@@ -11521,6 +11521,8 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(log_level));
fprintf(fp, " log_flags_level: %ld\n",
OFFSET(log_flags_level));
+ fprintf(fp, " log_caller_id: %ld\n",
+ OFFSET(log_caller_id));
fprintf(fp, " printk_info_seq: %ld\n", OFFSET(printk_info_seq));
fprintf(fp, " printk_info_ts_nseq: %ld\n", OFFSET(printk_info_ts_nsec));
--
2.43.0
8 months, 2 weeks
[PATCH] arm64: support ramdump for HW Tag-Based KASAN(MTE) mode
by qiwu.chen@transsion.com
Kernel commit 11167161e553d("kasan, arm64: implement HW_TAGS runtime") introduce a Hardware Tag-Based KASAN(MTE) mode for ARMv8.5 later CPUs, which uses the Top Byte Ignore (TBI) feature of arm64 CPUs to store a pointer tag in the top byte of kernel pointers.
Currently, crash utility cannot load MTE ramdump due to access the invalid HW Tag-Based kvaddr. Here's the example error message:
please wait... (gathering kmem slab cache data)
crash: invalid kernel virtual address: f1ffff80c000201c type: "kmem_cache objsize/object_size"
please wait... (gathering task table data)
crash: invalid kernel virtual address: f9ffff8239c2cde0 type: "xa_node shift"
This patch replace the orignal generic_is_kvaddr() with arm64_is_kvaddr(), which check the validity for a HW Tag-Based kvaddr. mte_tag_reset() is used to convert a Tag-Based kvaddr to untaggged kvaddr in arm64_VTOP() and arm64_IS_VMALLOC_ADDR().
Signed-off-by: chenqiwu <qiwu.chen(a)transsion.com>
---
arm64.c | 48 +++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 45 insertions(+), 3 deletions(-)
diff --git a/arm64.c b/arm64.c
index 2b6b0e5..18d1627 100644
--- a/arm64.c
+++ b/arm64.c
@@ -101,6 +101,42 @@ struct kernel_range { static struct kernel_range *arm64_get_va_range(struct machine_specific *ms); static void arm64_get_struct_page_size(struct machine_specific *ms);
+typedef unsigned char u8;
+/* mte tag shift bit */
+#define MTE_TAG_SHIFT 56
+/* native kernel pointers tag */
+#define KASAN_TAG_KERNEL 0xFF
+/* minimum value for random tags */
+#define KASAN_TAG_MIN 0xF0
+/* right shift the tag to MTE_TAG_SHIFT bit */
+#define mte_tag_shifted(tag) ((ulong)(tag) << MTE_TAG_SHIFT)
+/* get the top byte value of the original kvaddr */
+#define mte_tag_get(addr) (u8)((ulong)(addr) >> MTE_TAG_SHIFT)
+/* reset the top byte to get an untaggged kvaddr */
+#define mte_tag_reset(addr) ((ulong)addr & ~mte_tag_shifted(KASAN_TAG_KERNEL) | mte_tag_shifted(KASAN_TAG_KERNEL))
+
+static inline bool is_mte_kvaddr(ulong addr) {
+ /* check for mte enabled */
+ if (!symbol_exists("cpu_enable_mte"))
+ return false;
+
+ /* check for HW Tag-Based kvaddr */
+ if (mte_tag_get(addr) >= KASAN_TAG_MIN && mte_tag_get(addr) < KASAN_TAG_KERNEL)
+ return true;
+
+ return false;
+}
+
+static int arm64_is_kvaddr(ulong addr)
+{
+ /* Check for the untaggged kvaddr for HW tag-based KASAN mode */
+ if (is_mte_kvaddr(addr))
+ return (mte_tag_reset(addr) >= (ulong)(machdep->kvbase));
+
+ return (addr >= (ulong)(machdep->kvbase)); }
+
static void arm64_calc_kernel_start(void) {
struct machine_specific *ms = machdep->machspec; @@ -268,7 +304,7 @@ arm64_init(int when)
machdep->kvbase = ARM64_VA_START;
ms->userspace_top = ARM64_USERSPACE_TOP;
}
- machdep->is_kvaddr = generic_is_kvaddr;
+ machdep->is_kvaddr = arm64_is_kvaddr;
machdep->kvtop = arm64_kvtop;
/* The defaults */
@@ -1023,7 +1059,7 @@ arm64_dump_machdep_table(ulong arg)
fprintf(fp, " dis_filter: arm64_dis_filter()\n");
fprintf(fp, " cmd_mach: arm64_cmd_mach()\n");
fprintf(fp, " get_smp_cpus: arm64_get_smp_cpus()\n");
- fprintf(fp, " is_kvaddr: generic_is_kvaddr()\n");
+ fprintf(fp, " is_kvaddr: arm64_is_kvaddr()\n");
fprintf(fp, " is_uvaddr: arm64_is_uvaddr()\n");
fprintf(fp, " value_to_symbol: generic_machdep_value_to_symbol()\n");
fprintf(fp, " init_kernel_pgd: arm64_init_kernel_pgd\n");
@@ -1642,6 +1678,9 @@ ulong arm64_PTOV(ulong paddr) ulong arm64_VTOP(ulong addr) {
+ if (is_mte_kvaddr(addr))
+ addr = mte_tag_reset(addr);
+
if (machdep->flags & NEW_VMEMMAP) {
if (machdep->machspec->VA_START &&
(addr >= machdep->machspec->kimage_text) && @@ -4571,7 +4610,10 @@ int arm64_IS_VMALLOC_ADDR(ulong vaddr) {
struct machine_specific *ms = machdep->machspec;
-
+
+ if (is_mte_kvaddr(vaddr))
+ vaddr = mte_tag_reset(vaddr);
+
if ((machdep->flags & NEW_VMEMMAP) &&
(vaddr >= machdep->machspec->kimage_text) &&
(vaddr <= machdep->machspec->kimage_end))
--
2.25.1
8 months, 2 weeks
Re: [PATCH V2 1/2] RISCV64: Dump NT_PRSTATUS in,'help -n'
by Lianbo Jiang
Hi, Song
Thank you for the patch series.
On 12/13/23 09:57, devel-request(a)lists.crash-utility.osci.io wrote:
> Date: Tue, 12 Dec 2023 18:20:50 +0800
> From: Song Shuai<songshuaishuai(a)tinylab.org>
> Subject: [Crash-utility] [PATCH V2 1/2] RISCV64: Dump NT_PRSTATUS in
> 'help -n'
> To:k-hagio-ab@nec.com,xianting.tian@linux.alibaba.com
> Cc:devel@lists.crash-utility.osci.io, Song Shuai
> <songshuaishuai(a)tinylab.org>
> Message-ID:<20231212102051.527160-1-songshuaishuai(a)tinylab.org>
>
> With the patch we can get full dump of "struct elf_prstatus" in 'help -n':
>
> ```
> crash> help -n
> <snip>
> Elf64_Nhdr:
> n_namesz: 5 ("CORE")
> n_descsz: 376
> n_type: 1 (NT_PRSTATUS)
> si.signo: 0 si.code: 0 si.errno: 0
> cursig: 0 sigpend: 0 sighold: 0
> pid: 1 ppid: 0 pgrp: 0 sid:0
> utime: 0.000000 stime: 0.000000
> cutime: 0.000000 cstime: 0.000000
> epc: ffffffff8000a1dc ra: ffffffff800af958 sp: ff6000001fc501c0
> gp: ffffffff81515d38 tp: ff600000000d8000 t0: 6666666666663c5b
> t1: ff600000000d88c8 t2: 666666666666663c s0: ff6000001fc50320
> s1: ffffffff815170d8 a0: ff6000001fc501c8 a1: c0000000ffffefff
> a2: 0000000000000000 a3: 0000000000000001 a4: 0000000000000000
> a5: ff60000001782c00 a6: 000000000130e0f0 a7: 0000000000000000
> s2: ffffffff81517820 s3: ff6000001fc501c8 s4: 000000000000000f
> s5: 0000000000000000 s6: ff20000000013e60 s7: 0000000000000000
> s8: ff60000000861000 s9: 00007fffc3641694 s10: 00007fffc3641690
> s11: 00005555796ed240 t3: 0000000000010297 t4: ffffffff80c17810
> t5: ffffffff8195e7b8 t6: ff6000001fc50048
> 0000000000000000 0000000000000000
> 0000000000000000 0000000000000000
> 0000000000000001 0000000000000000
> 0000000000000000 0000000000000000
> 0000000000000000 0000000000000000
> 0000000000000000 0000000000000000
> 0000000000000000 0000000000000000
> ffffffff8000a1dc ffffffff800af958
> ff6000001fc501c0 ffffffff81515d38
> ff600000000d8000 6666666666663c5b
> <snip>
> ```
>
> Signed-off-by: Song Shuai<songshuaishuai(a)tinylab.org>
> ---
> Changes since V1:
> https://lore.kernel.org/kexec/20231204105015.2341055-1-songshuaishuai@tin...
> - patch1: add the missing "s5-s7" format string back
> - patch2: add Acked-by from Kazuhito Hagio
> - Resend to the new crash list address
I can not do the tests, seems the kexec-tools does not support the
riscv64 arch yet:
[root@fedora-riscv kexec-tools]# ./configure
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking build system type... riscv64-unknown-linux-gnu
checking host system type... riscv64-unknown-linux-gnu
checking target system type... riscv64-unknown-linux-gnu
configure: error: unsupported architecture riscv64
[root@fedora-riscv kexec-tools]#
Anyway, the v2 looks good to me, so: Ack
BTW: I have a request: could you please provide a patched
kexec-tools(link) for riscv64 arch? That could be useful for testing
patches.
Thanks
Lianbo
> ---
> netdump.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 84 insertions(+)
>
> diff --git a/netdump.c b/netdump.c
> index 3907863..32586b6 100644
> --- a/netdump.c
> +++ b/netdump.c
> @@ -2578,6 +2578,8 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
> display_ELF_note(EM_PPC64, PRSTATUS_NOTE, note, nd->ofp);
> if (machine_type("ARM64") && (note->n_type == NT_PRSTATUS))
> display_ELF_note(EM_AARCH64, PRSTATUS_NOTE, note, nd->ofp);
> + if (machine_type("RISCV64") && (note->n_type == NT_PRSTATUS))
> + display_ELF_note(EM_RISCV, PRSTATUS_NOTE, note, nd->ofp);
> }
> for (i = lf = 0; i < note->n_descsz/sizeof(ulonglong); i++) {
> if (((i%2)==0)) {
> @@ -3399,6 +3401,80 @@ display_prstatus_arm64(void *note_ptr, FILE *ofp)
> space(sp), pr->pr_reg[33], pr->pr_fpvalid);
> }
>
> +struct riscv64_elf_siginfo {
> + int si_signo;
> + int si_code;
> + int si_errno;
> +};
> +
> +struct riscv64_elf_prstatus {
> + struct riscv64_elf_siginfo pr_info;
> + short pr_cursig;
> + unsigned long pr_sigpend;
> + unsigned long pr_sighold;
> + pid_t pr_pid;
> + pid_t pr_ppid;
> + pid_t pr_pgrp;
> + pid_t pr_sid;
> + struct timeval pr_utime;
> + struct timeval pr_stime;
> + struct timeval pr_cutime;
> + struct timeval pr_cstime;
> +/* elf_gregset_t pr_reg; => typedef struct user_regs_struct elf_gregset_t; */
> + unsigned long pr_reg[32];
> + int pr_fpvalid;
> +};
> +
> +static void
> +display_prstatus_riscv64(void *note_ptr, FILE *ofp)
> +{
> + struct riscv64_elf_prstatus *pr;
> + Elf64_Nhdr *note;
> + int sp;
> +
> + note = (Elf64_Nhdr *)note_ptr;
> + pr = (struct riscv64_elf_prstatus *)(
> + (char *)note + sizeof(Elf64_Nhdr) + note->n_namesz);
> + pr = (struct riscv64_elf_prstatus *)roundup((ulong)pr, 4);
> + sp = nd->num_prstatus_notes ? 25 : 22;
> +
> + fprintf(ofp,
> + "%ssi.signo: %d si.code: %d si.errno: %d\n"
> + "%scursig: %d sigpend: %lx sighold: %lx\n"
> + "%spid: %d ppid: %d pgrp: %d sid:%d\n"
> + "%sutime: %01lld.%06d stime: %01lld.%06d\n"
> + "%scutime: %01lld.%06d cstime: %01lld.%06d\n",
> + space(sp), pr->pr_info.si_signo, pr->pr_info.si_code, pr->pr_info.si_errno,
> + space(sp), pr->pr_cursig, pr->pr_sigpend, pr->pr_sighold,
> + space(sp), pr->pr_pid, pr->pr_ppid, pr->pr_pgrp, pr->pr_sid,
> + space(sp), (long long)pr->pr_utime.tv_sec, (int)pr->pr_utime.tv_usec,
> + (long long)pr->pr_stime.tv_sec, (int)pr->pr_stime.tv_usec,
> + space(sp), (long long)pr->pr_cutime.tv_sec, (int)pr->pr_cutime.tv_usec,
> + (long long)pr->pr_cstime.tv_sec, (int)pr->pr_cstime.tv_usec);
> + fprintf(ofp,
> + "%sepc: %016lx ra: %016lx sp: %016lx\n"
> + "%s gp: %016lx tp: %016lx t0: %016lx\n"
> + "%s t1: %016lx t2: %016lx s0: %016lx\n"
> + "%s s1: %016lx a0: %016lx a1: %016lx\n"
> + "%s a2: %016lx a3: %016lx a4: %016lx\n"
> + "%s a5: %016lx a6: %016lx a7: %016lx\n"
> + "%s s2: %016lx s3: %016lx s4: %016lx\n"
> + "%s s5: %016lx s6: %016lx s7: %016lx\n"
> + "%s s8: %016lx s9: %016lx s10: %016lx\n"
> + "%ss11: %016lx t3: %016lx t4: %016lx\n"
> + "%s t5: %016lx t6: %016lx\n",
> + space(sp), pr->pr_reg[0], pr->pr_reg[1], pr->pr_reg[2],
> + space(sp), pr->pr_reg[3], pr->pr_reg[4], pr->pr_reg[5],
> + space(sp), pr->pr_reg[6], pr->pr_reg[7], pr->pr_reg[8],
> + space(sp), pr->pr_reg[9], pr->pr_reg[10], pr->pr_reg[11],
> + space(sp), pr->pr_reg[12], pr->pr_reg[13], pr->pr_reg[14],
> + space(sp), pr->pr_reg[15], pr->pr_reg[16], pr->pr_reg[17],
> + space(sp), pr->pr_reg[18], pr->pr_reg[19], pr->pr_reg[20],
> + space(sp), pr->pr_reg[21], pr->pr_reg[22], pr->pr_reg[23],
> + space(sp), pr->pr_reg[24], pr->pr_reg[25], pr->pr_reg[26],
> + space(sp), pr->pr_reg[27], pr->pr_reg[28], pr->pr_reg[29],
> + space(sp), pr->pr_reg[30], pr->pr_reg[31]);
> +}
>
> void
> display_ELF_note(int machine, int type, void *note, FILE *ofp)
> @@ -3449,6 +3525,14 @@ display_ELF_note(int machine, int type, void *note, FILE *ofp)
> break;
> }
> break;
> + case EM_RISCV:
> + switch (type)
> + {
> + case PRSTATUS_NOTE:
> + display_prstatus_riscv64(note, ofp);
> + break;
> + }
> + break;
>
> default:
> return;
> -- 2.20.1
8 months, 3 weeks
[PATCH v4 0/5] Improve stack unwind on ppc64
by Aditya Gupta
The Problem:
============
Currently crash is unable to show function arguments and local variables, as
gdb can do. And functionality for moving between frames ('up'/'down') is not
working in crash.
Crash has 'gdb passthroughs' for things gdb can do, but the gdb passthroughs
'bt', 'frame', 'info locals', 'up', 'down' are not working either, due to
gdb not getting the register values from `crash_target::fetch_registers`,
which then uses `machdep->get_cpu_reg`, which is not implemented for PPC64
Proposed Solution:
==================
Fix the gdb passthroughs by implementing "machdep->get_cpu_reg" for PPC64.
This way, "gdb mode in crash" will support this feature for both ELF and
kdump-compressed vmcore formats, while "gdb" would only have supported ELF
format
This way other features of 'gdb', such as seeing
backtraces/registers/variables/arguments/local variables, moving up and
down stack frames, can be used with any ppc64 vmcore, irrespective of
being ELF format or kdump-compressed format.
Note: This doesn't support live debugging on ppc64, since registers are not
available to be read
Implications on Architectures:
====================================
No architecture other than PPC64 has been affected, other than in case of
'frame' command
As mentioned in patch #2, since frame will not be prohibited, so it will print:
crash> frame
#0 <unavailable> in ?? ()
Instead of before prohibited message:
crash> frame
crash: prohibited gdb command: frame
Major change will be in 'gdb mode' on PPC64, that it will print the frames, and
local variables, instead of failing with errors showing no frame, or showing
that couldn't get PC, it will be able to give all this information.
Testing:
========
Git tree with this patch series applied:
https://github.com/adi-g15-ibm/crash/tree/stack-unwind-v4
To test various gdb passthroughs:
(crash) set
(crash) set gdb on
gdb> thread
gdb> bt
gdb> info threads
gdb> info threads
gdb> info locals
gdb> info variables irq_rover_lock
gdb> info args
gdb> thread 2
gdb> set gdb off
(crash) set
(crash) set -c 6
(crash) gdb thread
(crash) bt
(crash) gdb bt
(crash) frame
(crash) up
(crash) down
(crash) info locals
Known Issues:
=============
1. In gdb mode, 'bt' might fail to show backtrace in few vmcores collected
from older kernels. This is a known issue due to register mismatch, and
its fix has been merged upstream:
This can also cause some 'invalid kernel virtual address' errors during gdb
unwinding the stack registers
Commit: https://github.com/torvalds/linux/commit/b684c09f09e7a6af3794d4233ef78581...
Fixing GDB passthroughs on other architectures
==============================================
Much of the work for making gdb passthroughs like 'gdb bt', 'gdb
thread', 'gdb info locals' etc. has been done by the patches introducing
'machdep->get_cpu_reg' and this series fixing some issues in that.
Other architectures should be able to fix these gdb functionalities by
simply implementing 'machdep->get_cpu_reg (cpu, regno, ...)'.
The reasoning behind that has been explained with a diagram in commit
description of patch #1
I will assist with my findings/observations fixing it on ppc64 whenever needed.
Additional Notes:
=================
Sorry, it took a long time to send this version. Tried fixing 'info
threads' but wasn't able to. Gave it time again, and was able to fix it
this time after multiple days of debugging.
Some other things from last version review:
* 'info rv' not working:
It's not supported in gdb, instead we need to use 'info locals rv' or
'info variables rv'
* 'info variables' command hangs... and prints nothing after hanging for long
It likely hangs due to a lot of symbols being there, and it's trying to
get all gdb's output and page it, so Control+C messes it up, but if we pass
a regex filter to limit the output, eg. info variables rq, then it doesn't
hang, and prints the variables/symbols.
Even with gdb, ie. simply running 'gdb vmlinux vmcore' also hangs due
to the lot of symbols
* making crashing thread as default in gdb:
This is implemented now, along with synchronising crash & gdb contexts, in
patch #3
* 'info threads' not working:
This turned to be due to a bug in gdb_interface. I fixed 'info
threads' in 2 patches, to simplify it, first for the gdb_interface,
and another patch for setting the context correctly in crash
* other info commands:
I tested all the info commands, in crash along with this patch.
Most of those that fail in crash are due to gdb itself not supporting
them with vmcores, and other than that is the 'info pretty' command,
which might not be needed in crash anyways
* live debugging showing only one thread:
I tried it with crash, crash shows only the current thread, ie.
itself, so it does not have information of registers for the other
CPUs. Similarly gdb does not support live kernel debugging (without
connecting to a gdbstub/QEMU etc.).
If you need I can make it show the current thread id correctly for
the one thread, but I don't think it might help much with live
debugging
Hope, I set the context, thanks for the reviews, I replied and worked
on your suggestions, but got stuck there due to 'info threads'
Changelog:
==========
V4:
+ fix segmentation fault in live debugging (change in patch #1)
+ mention live debugging not supported in cover letter and patch #1
+ fixed some checkpatch warnings (change in patch #5)
V3:
+ default gdb thread will be the crashing thread, instead of being
thread '0'
+ synchronise crash cpu and gdb thread context
+ fix bug in gdb_interface, that replaced gdb's output stream, losing
output in some cases, such as info threads and extra output in info
variables
+ fix 'info threads'
RFC V2:
- removed patch implementing 'frame', 'up', 'down' in crash
- updated the cover letter by removing the mention of those commands other
than the respective gdb passthrough
Aditya Gupta (5):
ppc64: correct gdb passthroughs by implementing machdep->get_cpu_reg
remove 'frame' from prohibited commands list
synchronise cpu context changes between crash/gdb
fix gdb_interface: restore gdb's output streams at end of
gdb_interface
fix 'info threads' command
crash_target.c | 44 ++++++++++++++++
defs.h | 130 +++++++++++++++++++++++++++++++++++++++++++++++-
gdb-10.2.patch | 110 +++++++++++++++++++++++++++++++++++++++-
gdb_interface.c | 2 +-
kernel.c | 47 +++++++++++++++--
ppc64.c | 95 +++++++++++++++++++++++++++++++++--
task.c | 14 ++++++
tools.c | 2 +-
8 files changed, 434 insertions(+), 10 deletions(-)
--
2.41.0
8 months, 3 weeks
[PATCH v3 1/2] arm64: rewrite the arm64_get_vmcoreinfo_ul to arm64_get_vmcoreinfo
by Huang Shijie
Rewrite the arm64_get_vmcoreinfo_ul to arm64_get_vmcoreinfo,
add a new parameter "base" for it.
Also use it to simplify the arm64 code.
Signed-off-by: Huang Shijie <shijie(a)os.amperecomputing.com>
---
v2 --> v3:
Do not change the generic code, only change the arm64 code.
---
arm64.c | 99 +++++++++++++++++++++++----------------------------------
1 file changed, 39 insertions(+), 60 deletions(-)
diff --git a/arm64.c b/arm64.c
index 2b6b0e5..57965c6 100644
--- a/arm64.c
+++ b/arm64.c
@@ -92,6 +92,7 @@ static void arm64_get_crash_notes(void);
static void arm64_calc_VA_BITS(void);
static int arm64_is_uvaddr(ulong, struct task_context *);
static void arm64_calc_KERNELPACMASK(void);
+static int arm64_get_vmcoreinfo(unsigned long *vaddr, const char *label, int base);
struct kernel_range {
unsigned long modules_vaddr, modules_end;
@@ -124,7 +125,6 @@ void
arm64_init(int when)
{
ulong value;
- char *string;
struct machine_specific *ms;
#if defined(__x86_64__)
@@ -160,11 +160,8 @@ arm64_init(int when)
if (!ms->kimage_voffset && STREQ(pc->live_memsrc, "/dev/crash"))
ioctl(pc->mfd, DEV_CRASH_ARCH_DATA, &ms->kimage_voffset);
- if (!ms->kimage_voffset &&
- (string = pc->read_vmcoreinfo("NUMBER(kimage_voffset)"))) {
- ms->kimage_voffset = htol(string, QUIET, NULL);
- free(string);
- }
+ if (!ms->kimage_voffset)
+ arm64_get_vmcoreinfo(&ms->kimage_voffset, "NUMBER(kimage_voffset)", NUM_HEX);
if (ms->kimage_voffset ||
(ACTIVE() && (symbol_value_from_proc_kallsyms("kimage_voffset") != BADVAL))) {
@@ -185,11 +182,8 @@ arm64_init(int when)
if (kernel_symbol_exists("kimage_voffset"))
machdep->flags |= NEW_VMEMMAP;
- if (!machdep->pagesize &&
- (string = pc->read_vmcoreinfo("PAGESIZE"))) {
- machdep->pagesize = atoi(string);
- free(string);
- }
+ if (!machdep->pagesize && arm64_get_vmcoreinfo(&value, "PAGESIZE", NUM_DEC))
+ machdep->pagesize = (unsigned int)value;
if (!machdep->pagesize) {
/*
@@ -443,9 +437,8 @@ arm64_init(int when)
arm64_get_section_size_bits();
if (!machdep->max_physmem_bits) {
- if ((string = pc->read_vmcoreinfo("NUMBER(MAX_PHYSMEM_BITS)"))) {
- machdep->max_physmem_bits = atol(string);
- free(string);
+ if (arm64_get_vmcoreinfo(&machdep->max_physmem_bits, "NUMBER(MAX_PHYSMEM_BITS)", NUM_DEC)) {
+ /* nothing */
} else if (machdep->machspec->VA_BITS == 52) /* guess */
machdep->max_physmem_bits = _MAX_PHYSMEM_BITS_52;
else if (THIS_KERNEL_VERSION >= LINUX(3,17,0))
@@ -573,16 +566,28 @@ static int arm64_get_struct_page_max_shift(struct machine_specific *ms)
}
/* Return TRUE if we succeed, return FALSE on failure. */
-static int arm64_get_vmcoreinfo_ul(unsigned long *vaddr, const char* label)
+static int
+arm64_get_vmcoreinfo(unsigned long *vaddr, const char *label, int base)
{
+ int err = 0;
char *string = pc->read_vmcoreinfo(label);
if (!string)
return FALSE;
- *vaddr = strtoul(string, NULL, 0);
+ switch (base) {
+ case NUM_HEX:
+ *vaddr = strtoul(string, NULL, 16);
+ break;
+ case NUM_DEC:
+ *vaddr = strtoul(string, NULL, 10);
+ break;
+ default:
+ err++;
+ error(INFO, "Unknown type:%#x, (NUM_HEX|NUM_DEC)\n", base);
+ }
free(string);
- return TRUE;
+ return err ? FALSE: TRUE;
}
/*
@@ -594,21 +599,21 @@ static struct kernel_range *arm64_get_range_v5_18(struct machine_specific *ms)
struct kernel_range *r = &tmp_range;
/* Get the MODULES_VADDR ~ MODULES_END */
- if (!arm64_get_vmcoreinfo_ul(&r->modules_vaddr, "NUMBER(MODULES_VADDR)"))
+ if (!arm64_get_vmcoreinfo(&r->modules_vaddr, "NUMBER(MODULES_VADDR)", NUM_HEX))
return NULL;
- if (!arm64_get_vmcoreinfo_ul(&r->modules_end, "NUMBER(MODULES_END)"))
+ if (!arm64_get_vmcoreinfo(&r->modules_end, "NUMBER(MODULES_END)", NUM_HEX))
return NULL;
/* Get the VMEMMAP_START ~ VMEMMAP_END */
- if (!arm64_get_vmcoreinfo_ul(&r->vmemmap_vaddr, "NUMBER(VMEMMAP_START)"))
+ if (!arm64_get_vmcoreinfo(&r->vmemmap_vaddr, "NUMBER(VMEMMAP_START)", NUM_HEX))
return NULL;
- if (!arm64_get_vmcoreinfo_ul(&r->vmemmap_end, "NUMBER(VMEMMAP_END)"))
+ if (!arm64_get_vmcoreinfo(&r->vmemmap_end, "NUMBER(VMEMMAP_END)", NUM_HEX))
return NULL;
/* Get the VMALLOC_START ~ VMALLOC_END */
- if (!arm64_get_vmcoreinfo_ul(&r->vmalloc_start_addr, "NUMBER(VMALLOC_START)"))
+ if (!arm64_get_vmcoreinfo(&r->vmalloc_start_addr, "NUMBER(VMALLOC_START)", NUM_HEX))
return NULL;
- if (!arm64_get_vmcoreinfo_ul(&r->vmalloc_end, "NUMBER(VMALLOC_END)"))
+ if (!arm64_get_vmcoreinfo(&r->vmalloc_end, "NUMBER(VMALLOC_END)", NUM_HEX))
return NULL;
return r;
@@ -888,12 +893,7 @@ range_failed:
/* Get the size of struct page {} */
static void arm64_get_struct_page_size(struct machine_specific *ms)
{
- char *string;
-
- string = pc->read_vmcoreinfo("SIZE(page)");
- if (string)
- ms->struct_page_size = atol(string);
- free(string);
+ arm64_get_vmcoreinfo(&ms->struct_page_size, "SIZE(page)", NUM_DEC);
}
/*
@@ -1469,16 +1469,12 @@ arm64_calc_phys_offset(void)
physaddr_t paddr;
ulong vaddr;
struct syment *sp;
- char *string;
if ((machdep->flags & NEW_VMEMMAP) &&
ms->kimage_voffset && (sp = kernel_symbol_search("memstart_addr"))) {
if (pc->flags & PROC_KCORE) {
- if ((string = pc->read_vmcoreinfo("NUMBER(PHYS_OFFSET)"))) {
- ms->phys_offset = htol(string, QUIET, NULL);
- free(string);
+ if (arm64_get_vmcoreinfo(&ms->phys_offset, "NUMBER(PHYS_OFFSET)", NUM_HEX))
return;
- }
vaddr = symbol_value_from_proc_kallsyms("memstart_addr");
if (vaddr == BADVAL)
vaddr = sp->value;
@@ -1560,9 +1556,8 @@ arm64_get_section_size_bits(void)
} else
machdep->section_size_bits = _SECTION_SIZE_BITS;
- if ((string = pc->read_vmcoreinfo("NUMBER(SECTION_SIZE_BITS)"))) {
- machdep->section_size_bits = atol(string);
- free(string);
+ if (arm64_get_vmcoreinfo(&machdep->section_size_bits, "NUMBER(SECTION_SIZE_BITS)", NUM_DEC)) {
+ /* nothing */
} else if (kt->ikconfig_flags & IKCONFIG_AVAIL) {
if ((ret = get_kernel_config("CONFIG_MEMORY_HOTPLUG", NULL)) == IKCONFIG_Y) {
if ((ret = get_kernel_config("CONFIG_HOTPLUG_SIZE_BITS", &string)) == IKCONFIG_STR)
@@ -1581,15 +1576,11 @@ arm64_get_section_size_bits(void)
static int
arm64_kdump_phys_base(ulong *phys_offset)
{
- char *string;
struct syment *sp;
physaddr_t paddr;
- if ((string = pc->read_vmcoreinfo("NUMBER(PHYS_OFFSET)"))) {
- *phys_offset = htol(string, QUIET, NULL);
- free(string);
+ if (arm64_get_vmcoreinfo(phys_offset, "NUMBER(PHYS_OFFSET)", NUM_HEX))
return TRUE;
- }
if ((machdep->flags & NEW_VMEMMAP) &&
machdep->machspec->kimage_voffset &&
@@ -4592,10 +4583,9 @@ static int
arm64_set_va_bits_by_tcr(void)
{
ulong value;
- char *string;
- if ((string = pc->read_vmcoreinfo("NUMBER(TCR_EL1_T1SZ)")) ||
- (string = pc->read_vmcoreinfo("NUMBER(tcr_el1_t1sz)"))) {
+ if (arm64_get_vmcoreinfo(&value, "NUMBER(TCR_EL1_T1SZ)", NUM_HEX) ||
+ arm64_get_vmcoreinfo(&value, "NUMBER(tcr_el1_t1sz)", NUM_HEX)) {
/* See ARMv8 ARM for the description of
* TCR_EL1.T1SZ and how it can be used
* to calculate the vabits_actual
@@ -4604,10 +4594,9 @@ arm64_set_va_bits_by_tcr(void)
* Basically:
* vabits_actual = 64 - T1SZ;
*/
- value = 64 - strtoll(string, NULL, 0);
+ value = 64 - value;
if (CRASHDEBUG(1))
fprintf(fp, "vmcoreinfo : vabits_actual: %ld\n", value);
- free(string);
machdep->machspec->VA_BITS_ACTUAL = value;
machdep->machspec->VA_BITS = value;
machdep->machspec->VA_START = _VA_START(machdep->machspec->VA_BITS_ACTUAL);
@@ -4623,13 +4612,8 @@ arm64_calc_VA_BITS(void)
int bitval;
struct syment *sp;
ulong vabits_actual, value;
- char *string;
- if ((string = pc->read_vmcoreinfo("NUMBER(VA_BITS)"))) {
- value = atol(string);
- free(string);
- machdep->machspec->CONFIG_ARM64_VA_BITS = value;
- }
+ arm64_get_vmcoreinfo(&machdep->machspec->CONFIG_ARM64_VA_BITS, "NUMBER(VA_BITS)", NUM_DEC);
if (kernel_symbol_exists("vabits_actual")) {
if (pc->flags & PROC_KCORE) {
@@ -4754,9 +4738,7 @@ arm64_calc_virtual_memory_ranges(void)
ulong PUD_SIZE = UNINITIALIZED;
if (!machdep->machspec->CONFIG_ARM64_VA_BITS) {
- if ((string = pc->read_vmcoreinfo("NUMBER(VA_BITS)"))) {
- value = atol(string);
- free(string);
+ if (arm64_get_vmcoreinfo(&value, "NUMBER(VA_BITS)", NUM_DEC)) {
machdep->machspec->CONFIG_ARM64_VA_BITS = value;
} else if (kt->ikconfig_flags & IKCONFIG_AVAIL) {
if ((ret = get_kernel_config("CONFIG_ARM64_VA_BITS",
@@ -4852,11 +4834,8 @@ arm64_swp_offset(ulong pte)
static void arm64_calc_KERNELPACMASK(void)
{
ulong value;
- char *string;
- if ((string = pc->read_vmcoreinfo("NUMBER(KERNELPACMASK)"))) {
- value = htol(string, QUIET, NULL);
- free(string);
+ if (arm64_get_vmcoreinfo(&value, "NUMBER(KERNELPACMASK)", NUM_HEX)) {
machdep->machspec->CONFIG_ARM64_KERNELPACMASK = value;
if (CRASHDEBUG(1))
fprintf(fp, "CONFIG_ARM64_KERNELPACMASK: %lx\n", value);
--
2.40.1
8 months, 3 weeks
[PATCH v2] help.c: Remove kmem -l help messages
by Li Zhijian
-l option has existed when crash git project initialization, but its
help message was not accurate(extra arguments a|i|ic|id was missing).
In addition, these symbols required by -l option was for the very *old old*
kernels, at least >= 2.6 don't include them. And it looks like this option
has not been fixed for a long time.
Instead of document this option, hide it from help messages.
Signed-off-by: Li Zhijian <lizhijian(a)fujitsu.com>
---
help.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/help.c b/help.c
index cc7ab20e343e..d80e843703c1 100644
--- a/help.c
+++ b/help.c
@@ -6888,8 +6888,6 @@ char *help_kmem[] = {
" members of the associated page struct are displayed.",
" address when used with -c, the address must be a page pointer address;",
" the page_hash_table entry containing the page is displayed.",
-" address when used with -l, the address must be a page pointer address;",
-" the page address is displayed if it is contained with the list.",
" address when used with -v, the address can be a mapped kernel virtual",
" address or physical address; the mapped region containing the",
" address is displayed.\n",
--
2.29.2
8 months, 3 weeks