Re: [PATCH] bpf: Implement ringbuf_map memory usage calculation
by lijiang
On Mon, Sep 15, 2025 at 1:16 PM <devel-request(a)lists.crash-utility.osci.io>
wrote:
> Date: Thu, 11 Sep 2025 15:20:23 +1200
> From: Tao Liu <ltao(a)redhat.com>
> Subject: [Crash-utility] [PATCH] bpf: Implement ringbuf_map memory
> usage calculation
> To: devel(a)lists.crash-utility.osci.io
> Cc: Tao Liu <ltao(a)redhat.com>
> Message-ID: <20250911032023.16833-1-ltao(a)redhat.com>
> Content-Type: text/plain; charset="US-ASCII"; x-default=true
>
> This patch replicates the kernel code for bpf ringbuf_map mm usage
> calculation.
>
> $ bpftool map create /sys/fs/bpf/rb0 type ringbuf key 0 value 0 entries
> $((1<<24)) name rb0
>
> Before:
> crash> bpf -m 12
> ID BPF_MAP BPF_MAP_TYPE MAP_FLAGS
> 12 ffff8dc4d7c0ed00 RINGBUF 00000000
> KEY_SIZE: 0 VALUE_SIZE: 0 MAX_ENTRIES: 16777216 MEMLOCK:
> (unknown)
> NAME: "rb0" UID: (unused)
>
> After:
> crash> bpf -m 12
> ID BPF_MAP BPF_MAP_TYPE MAP_FLAGS
> 12 ffff8dc4d7c0ed00 RINGBUF 00000000
> KEY_SIZE: 0 VALUE_SIZE: 0 MAX_ENTRIES: 16777216 MEMLOCK: 16855320
> NAME: "rb0" UID: (unused)
>
> Thus, the output will be the same as bpftool:
>
> $ bpftool map show id 12
> 12: ringbuf name rb0 flags 0x0
> key 0B value 0B max_entries 16777216 memlock 16855320B
>
> Signed-off-by: Tao Liu <ltao(a)redhat.com>
> ---
> bpf.c | 30 +++++++++++++++++++++++++++++-
> defs.h | 5 +++++
> symbols.c | 5 +++++
> 3 files changed, 39 insertions(+), 1 deletion(-)
>
> diff --git a/bpf.c b/bpf.c
> index 466b244..43e4ff5 100644
> --- a/bpf.c
> +++ b/bpf.c
> @@ -121,6 +121,26 @@ static ulong bpf_map_memory_size(int map_type, uint
> value_size,
> return roundup((max_entries * size), PAGESIZE());
> }
>
> +/*
> + * Code replicated from kernel/bpf/ringbuf.c:ringbuf_map_mem_usage()
> +*/
> +static ulong ringbuf_map_mem_usage(struct bpf_info *bpf, int i)
> +{
> + ulong nr_pages;
> + ulong usage = SIZE(bpf_ringbuf_map);
> + ulong rb = (ulong)(bpf->maplist[i].value) -
> OFFSET(bpf_ringbuf_map_map)
> + + OFFSET(bpf_ringbuf_map_rb);
> + readmem(rb, KVADDR, &rb, sizeof(ulong), "bpf_ringbuf *",
> RETURN_ON_ERROR);
>
It should be good to use the "FAULT_ON_ERROR" in readmem(), or you can
check the returned error(if any) here. Both are fine to me.
+ readmem(rb + OFFSET(bpf_ringbuf_nr_pages), KVADDR, &nr_pages,
> + sizeof(ulong), "bpf_ringbuf.nr_pages", RETURN_ON_ERROR);
>
Ditto.
Other changes are good for me.
Thanks
Lianbo
+ usage += (nr_pages << PAGESHIFT());
> + ulong nr_meta_pages = (OFFSET(bpf_ringbuf_consumer_pos) >>
> PAGESHIFT()) + 2;
> + ulong nr_data_pages = UINT(bpf->bpf_map_buf +
> OFFSET(bpf_map_max_entries)) >> PAGESHIFT();
> + usage += (nr_meta_pages + 2 * nr_data_pages) * sizeof(void *);
> +
> + return usage;
> +}
> +
> void
> cmd_bpf(void)
> {
> @@ -217,6 +237,7 @@ bpf_init(struct bpf_info *bpf)
> STRUCT_SIZE_INIT(bpf_prog_aux, "bpf_prog_aux");
> STRUCT_SIZE_INIT(bpf_map, "bpf_map");
> STRUCT_SIZE_INIT(bpf_insn, "bpf_insn");
> + STRUCT_SIZE_INIT(bpf_ringbuf_map, "bpf_ringbuf_map");
> MEMBER_OFFSET_INIT(bpf_prog_aux, "bpf_prog", "aux");
> MEMBER_OFFSET_INIT(bpf_prog_type, "bpf_prog", "type");
> MEMBER_OFFSET_INIT(bpf_prog_tag, "bpf_prog", "tag");
> @@ -228,6 +249,10 @@ bpf_init(struct bpf_info *bpf)
> MEMBER_OFFSET_INIT(bpf_map_map_flags, "bpf_map",
> "map_flags");
> MEMBER_OFFSET_INIT(bpf_prog_aux_used_maps, "bpf_prog_aux",
> "used_maps");
> MEMBER_OFFSET_INIT(bpf_prog_aux_used_map_cnt,
> "bpf_prog_aux", "used_map_cnt");
> + MEMBER_OFFSET_INIT(bpf_ringbuf_map_map, "bpf_ringbuf_map",
> "map");
> + MEMBER_OFFSET_INIT(bpf_ringbuf_map_rb, "bpf_ringbuf_map",
> "rb");
> + MEMBER_OFFSET_INIT(bpf_ringbuf_consumer_pos,
> "bpf_ringbuf", "consumer_pos");
> + MEMBER_OFFSET_INIT(bpf_ringbuf_nr_pages, "bpf_ringbuf",
> "nr_pages");
> if (!VALID_STRUCT(bpf_prog) ||
> !VALID_STRUCT(bpf_prog_aux) ||
> !VALID_STRUCT(bpf_map) ||
> @@ -664,7 +689,10 @@ do_map_only:
> fprintf(fp, "%d\n", map_pages *
> PAGESIZE());
> } else if ((msize = bpf_map_memory_size(type,
> value_size, key_size, max_entries)))
> fprintf(fp, "%ld\n", msize);
> - else
> +#define BPF_MAP_TYPE_RINGBUF (0x1BUL)
> + else if (type == BPF_MAP_TYPE_RINGBUF) {
> + fprintf(fp, "%ld\n",
> ringbuf_map_mem_usage(bpf, i));
> + } else
> fprintf(fp, "(unknown)");
>
> fprintf(fp, " NAME: ");
> diff --git a/defs.h b/defs.h
> index 4fecb83..498c262 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -2274,6 +2274,10 @@ struct offset_table { /* stash
> of commonly-used offsets */
> long request_queue_tag_set;
> long blk_mq_tag_set_flags;
> long blk_mq_tag_set_shared_tags;
> + long bpf_ringbuf_map_map;
> + long bpf_ringbuf_map_rb;
> + long bpf_ringbuf_consumer_pos;
> + long bpf_ringbuf_nr_pages;
> };
>
> struct size_table { /* stash of commonly-used sizes */
> @@ -2452,6 +2456,7 @@ struct size_table { /* stash of
> commonly-used sizes */
> long vmap_node;
> long cpumask_t;
> long task_struct_exit_state;
> + long bpf_ringbuf_map;
> };
>
> struct array_table {
> diff --git a/symbols.c b/symbols.c
> index ce0b441..19e1316 100644
> --- a/symbols.c
> +++ b/symbols.c
> @@ -11868,6 +11868,10 @@ dump_offset_table(char *spec, ulong makestruct)
> fprintf(fp, " thread_struct_gsbase: %ld\n",
> OFFSET(thread_struct_gsbase));
> fprintf(fp, " thread_struct_fs: %ld\n",
> OFFSET(thread_struct_fs));
> fprintf(fp, " thread_struct_gs: %ld\n",
> OFFSET(thread_struct_gs));
> + fprintf(fp, " bpf_ringbuf_map_map: %ld\n",
> OFFSET(bpf_ringbuf_map_map));
> + fprintf(fp, " bpf_ringbuf_map_rb: %ld\n",
> OFFSET(bpf_ringbuf_map_rb));
> + fprintf(fp, " bpf_ringbuf_consumer_pos: %ld\n",
> OFFSET(bpf_ringbuf_consumer_pos));
> + fprintf(fp, " bpf_ringbuf_nr_pages: %ld\n",
> OFFSET(bpf_ringbuf_nr_pages));
>
> fprintf(fp, "\n size_table:\n");
> fprintf(fp, " page: %ld\n", SIZE(page));
> @@ -12148,6 +12152,7 @@ dump_offset_table(char *spec, ulong makestruct)
>
> fprintf(fp, " percpu_counter: %ld\n",
> SIZE(percpu_counter));
> fprintf(fp, " cpumask_t: %ld\n",
> SIZE(cpumask_t));
> + fprintf(fp, " bpf_ringbuf_map: %ld\n",
> SIZE(bpf_ringbuf_map));
>
> fprintf(fp, "\n array_table:\n");
> /*
> --
> 2.47.0
>
1 month, 1 week
Re: [PATCH] Fix the misleading uncompress error message
by lijiang
On Tue, Oct 7, 2025 at 7:37 PM <devel-request(a)lists.crash-utility.osci.io>
wrote:
> Date: Tue, 7 Oct 2025 16:52:40 +1300
> From: Tao Liu <ltao(a)redhat.com>
> Subject: [Crash-utility] [PATCH] Fix the misleading uncompress error
> message
> To: devel(a)lists.crash-utility.osci.io
> Cc: Tao Liu <ltao(a)redhat.com>
> Message-ID: <20251007035240.28260-1-ltao(a)redhat.com>
> Content-Type: text/plain; charset="US-ASCII"; x-default=true
>
> The "unxz" is missing for uncompressing fail message. Fix [1].
>
> [1]: https://github.com/crash-utility/crash/issues/220
Can you add the Resolves tag before Sob, E.g:
Resolves: https://github.com/crash-utility/crash/issues/220
Signed-off-by: Tao Liu <ltao(a)redhat.com>
And this looks good to me: Ack.
Thanks
Lianbo
>
> Signed-off-by: Tao Liu <ltao(a)redhat.com>
> ---
> symbols.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/symbols.c b/symbols.c
> index ee3cba1..e6af38b 100644
> --- a/symbols.c
> +++ b/symbols.c
> @@ -4481,8 +4481,9 @@ is_compressed_kernel(char *file, char **tmp)
> }
> if (system(command) < 0) {
> please_wait_done();
> - error(INFO, "%s of %s failed\n",
> - type == GZIP ? "gunzip" : "bunzip2", file);
> + error(INFO, "%s of %s failed\n",
> + type == GZIP ? "gunzip" :
> + (type == BZIP2 ? "bunzip2" : "unxz"),
> file);
> free(tempname);
> return FALSE;
> }
> --
> 2.47.0
>
1 month, 1 week
[PATCH v4] Add "log -R" to display human readable Rust symbol name
by Lianbo Jiang
Currently, the log command will display human readable Rust
symbol name by default if any, but, sometimes still want to
print the original messages from the log buffer(do not demangle).
In addition, if the log buffer has lines like "_R ... +" which
are not Rust symbols unexpectedly, probably the output will be
missed, that is unexpected.
To fix above cases, add "log -R" to display human readable Rust
symbol name, otherwise still print the original messages.
With the patch:
crash> log -R
...
[ 2174.289360] Tainted: [S]=CPU_OUT_OF_SPEC, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
[ 2174.297322] Hardware name: Intel Corporation S2600CWR/S2600CWR, BIOS SE5C610.86B.01.01.0018.072020161249 07/20/2016
[ 2174.308966] Call Trace:
[ 2174.311693] <TASK>
[ 2174.314033] dump_stack_lvl+0x5d/0x80
[ 2174.318125] panic+0x156/0x32a
[ 2174.321539] rust_panic::area_in_hp+0xf7/0x120 [rust_panic]
[ 2174.329700] ? console_unlock+0x9c/0x140
[ 2174.334080] ? irq_work_queue+0x2d/0x50
[ 2174.338352] ? __pfx_init_module+0x10/0x10 [rust_panic]
[ 2174.344183] <rust_panic::HelloPanic>::step_two+0x20/0xe0 [rust_panic]
[ 2174.353698] ? _printk+0x6b/0x90
[ 2174.357303] init_module+0x57/0xff0 [rust_panic]
[ 2174.362456] ? __pfx_init_module+0x10/0x10 [rust_panic]
...
Link: https://www.mail-archive.com/devel@lists.crash-utility.osci.io/msg01652.html
Suggested-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
defs.h | 1 +
help.c | 24 ++++++++++++++++-
kernel.c | 5 +++-
printk.c | 79 ++++++++++++++++++++++++++++++++++++--------------------
4 files changed, 79 insertions(+), 30 deletions(-)
diff --git a/defs.h b/defs.h
index 3fd7d897c781..c434a5cae702 100644
--- a/defs.h
+++ b/defs.h
@@ -6229,6 +6229,7 @@ void parse_kernel_version(char *);
#define SHOW_LOG_CTIME (0x10)
#define SHOW_LOG_SAFE (0x20)
#define SHOW_LOG_CALLER (0x40)
+#define SHOW_LOG_RUST (0x80)
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 4f071e0bd0a0..78d7a5c70e30 100644
--- a/help.c
+++ b/help.c
@@ -4026,7 +4026,7 @@ NULL
char *help_log[] = {
"log",
"dump system message buffer",
-"[-Ttdmasc]",
+"[-TtdmascR]",
" 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",
@@ -4053,6 +4053,8 @@ char *help_log[] = {
" the CPU id (if in CPU context) that called printk(), if available.",
" Generally available on Linux 5.1 to 5.9 kernels configured with",
" CONFIG_PRINTK_CALLER or Linux 5.10 and later kernels.",
+" -R Display the message text with human readable Rust symbol name if any,",
+" otherwise still print the original message text.",
" ",
"\nEXAMPLES",
" Dump the kernel message buffer:\n",
@@ -4231,6 +4233,26 @@ char *help_log[] = {
" [ 0.014179] [ T29] RAMDISK: [mem 0x3cf4f000-0x437bbfff]",
" [ 0.198789] [ C0] DMAR: DRHD: handling fault status reg 3",
" ...",
+" ",
+" Display the message text with human readable Rust symbol name if any,",
+" otherwise still print the original message text.\n",
+" %s> log -R",
+" ...",
+" [ 2174.289360] Tainted: [S]=CPU_OUT_OF_SPEC, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE",
+" [ 2174.297322] Hardware name: Intel Corporation S2600CWR/S2600CWR, BIOS SE5C610.86B.01.01.0018.072020161249 07/20/2016",
+" [ 2174.308966] Call Trace:",
+" [ 2174.311693] <TASK>",
+" [ 2174.314033] dump_stack_lvl+0x5d/0x80",
+" [ 2174.318125] panic+0x156/0x32a",
+" [ 2174.321539] rust_panic::area_in_hp+0xf7/0x120 [rust_panic]",
+" [ 2174.329700] ? console_unlock+0x9c/0x140",
+" [ 2174.334080] ? irq_work_queue+0x2d/0x50",
+" [ 2174.338352] ? __pfx_init_module+0x10/0x10 [rust_panic]",
+" [ 2174.344183] <rust_panic::HelloPanic>::step_two+0x20/0xe0 [rust_panic]",
+" [ 2174.353698] ? _printk+0x6b/0x90",
+" [ 2174.357303] init_module+0x57/0xff0 [rust_panic]",
+" [ 2174.362456] ? __pfx_init_module+0x10/0x10 [rust_panic]",
+" ...",
NULL
};
diff --git a/kernel.c b/kernel.c
index e4213d7a663e..e077275d7ed6 100644
--- a/kernel.c
+++ b/kernel.c
@@ -5136,7 +5136,7 @@ cmd_log(void)
msg_flags = 0;
- while ((c = getopt(argcnt, args, "Ttdmasc")) != EOF) {
+ while ((c = getopt(argcnt, args, "TtdmascR")) != EOF) {
switch(c)
{
case 'T':
@@ -5160,6 +5160,9 @@ cmd_log(void)
case 'c':
msg_flags |= SHOW_LOG_CALLER;
break;
+ case 'R':
+ msg_flags |= SHOW_LOG_RUST;
+ break;
default:
argerrs++;
break;
diff --git a/printk.c b/printk.c
index 51b618e2a434..50cc2449dd69 100644
--- a/printk.c
+++ b/printk.c
@@ -116,7 +116,7 @@ dump_record(struct prb_map *m, unsigned long id, int msg_flags)
uint64_t ts_nsec;
ulonglong nanos;
ulonglong seq;
- int ilen = 0, i;
+ int ilen = 0, i, nlines;
char *desc, *info, *text, *p;
ulong rem;
@@ -202,44 +202,67 @@ dump_record(struct prb_map *m, unsigned long id, int msg_flags)
text = m->text_data + begin;
- if (text_len > BUFSIZE) {
+ if ((msg_flags & SHOW_LOG_RUST) && (text_len > BUFSIZE)) {
error(WARNING, "\nThe messages could be truncated!\n");
text_len = BUFSIZE;
}
- for (i = 0, p = text; i < text_len; i++, p++) {
- if (*p == '\n')
+ for (i = 0, nlines = 0, p = text; i < text_len; i++, p++) {
+ if (*p == '\n') {
+ /*
+ * When printing disassembly code blocks in the log, saw number
+ * of empty lines printed and some disassembly code was missed.
+ * So far I haven't got better solution to handle the current
+ * case(when the input data contains several lines, those '\n'
+ * are written one by one), here try to check if there are multiple
+ * line breaks to decide what to do next.
+ */
+ if ((msg_flags & SHOW_LOG_RUST) && (i != text_len - 1)) {
+ nlines++;
+ if (strlen(buf)) {
+ fprintf(fp, "%s", buf);
+ memset(buf, 0, strlen(buf));
+ }
+ }
fprintf(fp, "\n%s", space(ilen));
- else if (isprint(*p) || isspace(*p))
- sprintf(&buf[i], "%c", *p);
+ } else if ((msg_flags & SHOW_LOG_RUST) && (isprint(*p) || isspace(*p))) {
+ if (nlines >= 1)
+ fputc(*p, fp);
+ else
+ sprintf(&buf[i], "%c", *p);
+ } else if (isprint(*p) || isspace(*p))
+ fputc(*p, fp);
else
fputc('.', fp);
}
/*
* Try to demangle a mangled Rust symbol(calltrace) from log buffer
*/
- char *p1 = strstr(buf, "_R");
- if (!p1)
- p1 = strstr(buf, "_ZN");
- char *p2 = strrchr(buf, '+');
- if (p1 && p2) {
- char mangled[BUFSIZE] = {0};
- char demangled[BUFSIZE] = {0};
- char *res;
- size_t slen = p1 - buf;
-
- if (slen)
- memcpy(demangled, buf, slen);
-
- memcpy(mangled, p1, p2-p1);
- res = rust_demangle(mangled, DMGL_RUST);
- if (res) {
- snprintf(demangled+slen, BUFSIZE-slen, "%s%s", res, p2);
- fprintf(fp, "%s",demangled);
- free(res);
- }
- } else
- fprintf(fp, "%s", buf);
+ if (msg_flags & SHOW_LOG_RUST) {
+ char *p1 = strstr(buf, "_R");
+ if (!p1)
+ p1 = strstr(buf, "_ZN");
+ char *p2 = strrchr(buf, '+');
+ if (p1 && p2) {
+ char mangled[BUFSIZE] = {0};
+ char demangled[BUFSIZE] = {0};
+ char *res;
+ size_t slen = p1 - buf;
+
+ if (slen)
+ memcpy(demangled, buf, slen);
+
+ memcpy(mangled, p1, p2-p1);
+ res = rust_demangle(mangled, DMGL_RUST);
+ if (res) {
+ snprintf(demangled+slen, BUFSIZE-slen, "%s%s", res, p2);
+ fprintf(fp, "%s",demangled);
+ free(res);
+ } else
+ fprintf(fp, "%s", buf);
+ } else
+ fprintf(fp, "%s", buf);
+ }
if (msg_flags & SHOW_LOG_DICT) {
text = info + OFFSET(printk_info_dev_info) +
--
2.50.1
1 month, 1 week
[PATCH v2] vtop: Translate IEP flag for s390 region, segment and page entries
by Mikhail Zaslonko
Translate and print the IEP (Instruction Execution Protection) flag for
Region-Third-Table entries and Segment-Table entries of Format
Control 1 and also for Page-Table entries. Display the flags in s390x 'vtop'
command output like shown below:
STE: 0000000033be8ac0 => 0000000015803503 (flags = 03503)
flags in binary : AV=0; ACC=0011; F=0; FC=1; P=0; IEP=1; I=0; CS=0; TT=0
or
PTE: 00000000031c6fd8 => 000000000842e13d (flags = 13d)
flags in binary : I=0; P=0; IEP=1
Suggested-by: Heiko Carstens <hca(a)linux.ibm.com>
Signed-off-by: Mikhail Zaslonko <zaslonko(a)linux.ibm.com>
Reviewed-by: Heiko Carstens <hca(a)linux.ibm.com>
---
s390x.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/s390x.c b/s390x.c
index 0e8e2b3..8c0bba4 100644
--- a/s390x.c
+++ b/s390x.c
@@ -29,6 +29,7 @@
#define S390X_PTE_FLAG_BITS 0xfffULL /* Page table entry flag bits */
#define S390X_PAGE_PRESENT 0x001ULL /* set: loaded in physical memory
* clear: not loaded in physical mem */
+#define S390X_PAGE_IEP 0x100ULL /* Instruction-execution protection */
#define S390X_PAGE_RO 0x200ULL /* HW read-only */
#define S390X_PAGE_INVALID 0x400ULL /* HW invalid */
#define S390X_PAGE_INVALID_MASK 0x601ULL /* for linux 2.6 */
@@ -65,6 +66,7 @@
#define S390X_RTE_TF 0xc0ULL
#define S390X_RTE_TF_10 0x80ULL
#define S390X_RTE_TF_01 0x40ULL
+#define S390X_RTE_IEP 0x100ULL
#define S390X_RTE_P 0x200ULL
#define S390X_RTE_FC 0x400ULL
#define S390X_RTE_F 0x800ULL
@@ -82,6 +84,7 @@
#define S390X_STE_TT_01 0x4ULL
#define S390X_STE_CS 0x10ULL
#define S390X_STE_I 0x20ULL
+#define S390X_STE_IEP 0x100ULL
#define S390X_STE_P 0x200ULL
#define S390X_STE_FC 0x400ULL
#define S390X_STE_F 0x800ULL
@@ -979,7 +982,7 @@ static inline int s390x_pte_present(unsigned long x){
/* Print flags of Segment-Table entry with format control = 1 */
static void print_segment_entry_fc1(ulong val)
{
- fprintf(fp, "AV=%u; ACC=%u%u%u%u; F=%u; FC=%u; P=%u; I=%u; CS=%u; TT=%u%u\n",
+ fprintf(fp, "AV=%u; ACC=%u%u%u%u; F=%u; FC=%u; P=%u; IEP=%u; I=%u; CS=%u; TT=%u%u\n",
!!(val & S390X_STE_AV),
!!(val & S390X_STE_ACC_1000),
!!(val & S390X_STE_ACC_0100),
@@ -988,6 +991,7 @@ static void print_segment_entry_fc1(ulong val)
!!(val & S390X_STE_F),
!!(val & S390X_STE_FC),
!!(val & S390X_STE_P),
+ !!(val & S390X_STE_IEP),
!!(val & S390X_STE_I),
!!(val & S390X_STE_CS),
!!(val & S390X_STE_TT_10),
@@ -1009,7 +1013,7 @@ static void print_segment_entry_fc0(ulong val)
/* Print flags of Region-Third-Table entry with format control = 1 */
static void print_region_third_entry_fc1(ulong val)
{
- fprintf(fp, "AV=%u; ACC=%u%u%u%u; F=%u; FC=%u; P=%u; I=%u; CR=%u; TT=%u%u\n",
+ fprintf(fp, "AV=%u; ACC=%u%u%u%u; F=%u; FC=%u; P=%u; IEP=%u; I=%u; CR=%u; TT=%u%u\n",
!!(val & S390X_RTE_AV),
!!(val & S390X_RTE_ACC_1000),
!!(val & S390X_RTE_ACC_0100),
@@ -1018,6 +1022,7 @@ static void print_region_third_entry_fc1(ulong val)
!!(val & S390X_RTE_F),
!!(val & S390X_RTE_FC),
!!(val & S390X_RTE_P),
+ !!(val & S390X_RTE_IEP),
!!(val & S390X_RTE_I),
!!(val & S390X_RTE_CR),
!!(val & S390X_RTE_TT_10),
@@ -1151,8 +1156,10 @@ static ulong _kl_pg_table_deref_s390x(ulong vaddr, ulong table, int verbose)
if (verbose) {
fprintf(fp, "%5s: %016lx => %016lx (flags = %03llx)\n",
"PTE", addr, entry, entry & S390X_PTE_FLAG_BITS);
- fprintf(fp, " flags in binary : I=%u; P=%u\n",
- !!(entry & S390X_PAGE_INVALID), !!(entry & S390X_PAGE_RO));
+ fprintf(fp, " flags in binary : I=%u; P=%u; IEP=%u\n",
+ !!(entry & S390X_PAGE_INVALID),
+ !!(entry & S390X_PAGE_RO),
+ !!(entry & S390X_PAGE_IEP));
fprintf(fp, "%5s: %016llx\n", "PAGE", entry & ~S390X_PTE_FLAG_BITS);
}
/*
--
2.49.0
1 month, 1 week
Re: [PATCH v2 2/2] eppic.patch: Add customized functions to eppic
by lijiang
On Mon, Sep 29, 2025 at 12:11 PM <devel-request(a)lists.crash-utility.osci.io>
wrote:
> Date: Mon, 29 Sep 2025 17:08:10 +1300
> From: Tao Liu <ltao(a)redhat.com>
> Subject: [Crash-utility] [PATCH v2 2/2] eppic.patch: Add customized
> functions to eppic
> To: devel(a)lists.crash-utility.osci.io
> Cc: jbrisson(a)linux.ibm.com
> Message-ID: <20250929040810.25718-3-ltao(a)redhat.com>
> Content-Type: text/plain; charset="US-ASCII"; x-default=true
>
> This patch will add the following functions to eppic:
>
> 1) Allow main() as the entry for any eppic program. Previously only func()
> which companied by func_help() & func_usage() is regarded as the main
> entry of the eppic program. This constraint only makes sense for
> creating
> a crash-like cmd. If users only want to create a oneshot run program for
> fast testing, then the constraint is misleading. So this patch will add
> main() as entry for eppic programs.
>
> 2) Add new command "eppic" for oneshot run eppic programs. Previously eppic
> expect programs to run as the form of crash-like cmd, and it is not
> convenient for oneshot run programs. With "eppic" command, people can
> use "edit -f" or any other editors to create eppic programs, then run
> it via "eppic myfile.c".
>
> 3) Add a template for any new eppic program files. If "edit -f" a new
> file, a
> template with an example will be written into the new file. So users can
> refer to it when writting any eppic programs.
>
> Signed-off-by: Tao Liu <ltao(a)redhat.com>
> ---
> extensions/eppic.mk | 13 ++-
> extensions/eppic.patch | 210 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 222 insertions(+), 1 deletion(-)
> create mode 100644 extensions/eppic.patch
>
>
I don't have much comment on this, only one thing:
For the eppic.patch, I would suggest using the same style with
gdb-16.2.patch. E.g:
...
--- gdb-16.2/gdb/c-typeprint.c.orig
+++ gdb-16.2/gdb/c-typeprint.c
@@ -1066,6 +1066,9 @@ c_type_print_base_struct_union (struct type *type,
struct ui_file *stream,
= podata->end_bitpos
- type->field (i).type ()->length () * TARGET_CHAR_BIT;
}
+ else if (strlen(type->field(i).name()) == 0)
+ /* crash: Print details for unnamed struct and union. */
+ newshow = show;
c_print_type_1 (type->field (i).type (),
type->field (i).name (),
...
(I just pasted a section from the gdb-16.2.patch)
> diff --git a/extensions/eppic.mk b/extensions/eppic.mk
> index 9435793..b175df5 100644
> --- a/extensions/eppic.mk
> +++ b/extensions/eppic.mk
> @@ -53,7 +53,18 @@ all:
> fi; \
> if [ -f $(APPFILE) ]; \
> then \
> - make -f eppic.mk eppic.so; \
> + pushd eppic >/dev/null; \
> + if patch --dry-run -N -p0 < ../eppic.patch
> >/dev/null ; then \
> + patch -N -p0 < ../eppic.patch; \
> + popd >/dev/null; \
> + make -f eppic.mk eppic.so; \
> + elif patch --dry-run -N -p0 -R <
> ../eppic.patch >/dev/null ; then \
> + popd >/dev/null; \
> + make -f eppic.mk eppic.so; \
> + else \
> + popd >/dev/null; \
> + echo "eppic.so: apply eppic.patch
> error"; \
> + fi; \
> else \
> echo "eppic.so: failed to pull eppic code
> from git repo"; \
> fi; \
> diff --git a/extensions/eppic.patch b/extensions/eppic.patch
> new file mode 100644
> index 0000000..9e43665
> --- /dev/null
> +++ b/extensions/eppic.patch
> @@ -0,0 +1,210 @@
> +--- applications/crash/eppic.c
> ++++ applications/crash/eppic.c
> +@@ -20,6 +20,7 @@
> + #include "defs.h"
> +
> + #include <eppic_api.h>
> ++#include "eppic.h"
> +
> + /*
> + * Global data (global_data.c)
> +@@ -788,6 +789,39 @@ char *sclass_help[]={
> + NULL
> + };
> +
> ++char *eppic_help[]={
> ++ "eppic",
> ++ "Run eppic program(es).",
> ++ "<fileName1.c>[, <fileName2.c>]",
> ++ " Oneshot run eppic program(es) which with a main()
> entry each.",
> ++ NULL
> ++};
> ++
> ++void
> ++eppic_command(void)
> ++{
> ++ char *buf;
> ++ optind = 1;
> ++
> ++ if (!args[optind]) {
> ++ cmd_usage(crash_global_cmd(), SYNOPSIS);
> ++ return;
> ++ }
> ++
> ++ while(args[optind]) {
> ++ buf = eppic_filempath(args[optind]);
> ++ if (!buf) {
> ++ eppic_msg("eppic_filempath error on %s\n",
> args[optind]);
> ++ return;
> ++ }
> ++ eppic_load(buf);
> ++ if (eppic_findfile(buf, 0))
> ++ eppic_unload(buf);
> ++ eppic_free(buf);
> ++ optind++;
> ++ }
> ++}
> ++
> + #define NCMDS 200
> + static struct command_table_entry command_table[NCMDS] = {
> +
> +@@ -797,6 +831,7 @@ static struct command_table_entry
> command_table[NCMDS] = {
> + {"sdebug", sdebug_cmd, sdebug_help},
> + {"sname", sname_cmd, sname_help},
> + {"sclass", sclass_cmd, sclass_help},
> ++ {"eppic", eppic_command, eppic_help},
> + {(char *)0 }
> + };
> +
> +@@ -885,6 +920,13 @@ char **help=malloc(sizeof *help * 5);
> + }
> + }
> + free(help);
> ++
> ++ if (load && !strcmp(name, "main")) {
> ++ int optind_save = optind;
> ++ eppic_cmd(name, NULL, 0);
> ++ optind = optind_save;
> ++ }
> ++
> + return;
> + }
> +
> +--- libeppic/eppic_api.h
> ++++ libeppic/eppic_api.h
> +@@ -16,6 +16,9 @@
> + /* minor and major version number
> + 4.0 switch to new Eppic name and use of fully typed symbols.
> + */
> ++#ifndef EPPIC_API_H
> ++#define EPPIC_API_H
> ++
> + #define S_MAJOR 5
> + #define S_MINOR 0
> +
> +@@ -298,3 +301,5 @@ void eppic_dbg_named(int class, char *name, int
> level, char *, ...);
> +
> + /* parsers debug flags */
> + extern int eppicdebug, eppicppdebug;
> ++
> ++#endif
> +\ No newline at end of file
> +--- libeppic/eppic_func.c
> ++++ libeppic/eppic_func.c
> +@@ -22,6 +22,8 @@
> + #include <sys/types.h>
> + #include <time.h>
> + #include <sys/stat.h>
> ++#include <fcntl.h>
> ++#include <unistd.h>
> + #include "eppic.h"
> +
> + /*
> +@@ -793,6 +795,42 @@ char *ed=getenv("EDITOR");
> + if(!system(buf)) eppic_load(fname);
> + }
> +
> ++static const char *example[] = {
> ++"/*
> ",
> ++" * Example: Print all tasks' PID & command
> ",
> ++" *
> ",
> ++" * // Kernel's global variables and data structures can be used
> directly without",
> ++" * // pre-define it in kernel header. If any are within kernel modules,
> should",
> ++" * // preload the .ko first via \"mod -S/-s\" cmd in crash before
> invoke your",
> ++" * // eppic program.
> ",
> ++" * //
> ",
> ++" * // Eppic program's syntax is similar to C but with slight
> differences. ",
> ++" * // Code samples:
> ",
> ++" * //
> https://github.com/lucchouina/eppic/tree/master/applications/crash/code",
> ++" * // Available eppic functions:
> ",
> ++" * //
> https://github.com/lucchouina/eppic/blob/master/libeppic/eppic_builtin.c#...
> ",
> ++" *
> ",
> ++" * int main(void)
> ",
> ++" * {
> ",
> ++" * struct task_struct *p;
> ",
> ++" * unsigned long offset;
> ",
> ++" *
> ",
> ++" * p = (struct task_struct *)&init_task;
> ",
> ++" * offset = (unsigned long)&(p->tasks) - (unsigned long)p;
> ",
> ++" *
> ",
> ++" * do {
> ",
> ++" * printf(\"PID: %d Command: %s\\n\", (int)(p->pid),
> getstr((char *)&(p->comm[0])));",
> ++" * p = (struct task_struct *)((unsigned long)(p->tasks.next) -
> offset);",
> ++" * } while(p != &init_task);
> ",
> ++" *
> ",
> ++" * return 0;
> ",
> ++" * }
> ",
> ++" *
> ",
> ++" * crash> eppic program_file.c
> ",
> ++" */
> ",
> ++};
>
This looks very helpful.
Thanks
Lianbo
> ++
> ++char *eppic_get_func_file(char *);
> + /*
> + This funciton is called to start a vi session on a function
> + (file=0) or a file (file=1);
> +@@ -800,24 +838,31 @@ char *ed=getenv("EDITOR");
> + void
> + eppic_vi(char *fname, int file)
> + {
> +-int line, freeit=0;
> ++int line=1, freeit=0, fd;
> + char *filename;
> ++char newline = '\n';
> +
> + if(file) {
> +
> + filename=eppic_filempath(fname);
> +
> + if(!filename) {
> +-
> +- eppic_msg("File not found : %s\n", fname);
> +- return;
> +-
> +- }
> +-
> +- line=1;
> +- freeit=1;
> +-
> +-
> ++ fd = creat(fname, 0644);
> ++ if (fd < 0) {
> ++ eppic_msg("File not found : %s\n", fname);
> ++ return;
> ++ } else {
> ++ for (int i = 0; i < sizeof(example)/sizeof(char *); i++) {
> ++ write(fd, example[i], strlen(example[i]));
> ++ write(fd, &newline, sizeof(newline));
> ++ }
> ++ close(fd);
> ++ filename = fname;
> ++ freeit=0;
> ++ }
> ++ } else {
> ++ freeit=1;
> ++ }
> + } else {
> +
> + func *f=eppic_getfbyname(fname, 0);
> +@@ -837,6 +882,10 @@ char *filename;
> +
> + eppic_exevi(filename, line);
> +
> ++ char *fi_name = eppic_get_func_file("main");
> ++ if (fi_name)
> ++ eppic_deletefile(fi_name);
> ++
> + if(freeit) eppic_free(filename);
> +
> + }
> +@@ -1184,3 +1233,10 @@ eppic_runcmd(char *fname, var_t*args)
> + return 0;
> + }
> +
> ++char *eppic_get_func_file(char *funcname)
> ++{
> ++ func *fn = eppic_getfbyname(funcname, 0);
> ++ if (!fn)
> ++ return NULL;
> ++ return fn->file->fname;
> ++}
> --
> 2.47.0
>
>
1 month, 2 weeks
Re: [PATCH v2 1/2] extensions: Search all possible paths
by lijiang
Hi, Tao
Thank you for the update.
On Mon, Sep 29, 2025 at 12:11 PM <devel-request(a)lists.crash-utility.osci.io>
wrote:
> Date: Mon, 29 Sep 2025 17:08:09 +1300
> From: Tao Liu <ltao(a)redhat.com>
> Subject: [Crash-utility] [PATCH v2 1/2] extensions: Search all
> possible paths
> To: devel(a)lists.crash-utility.osci.io
> Cc: jbrisson(a)linux.ibm.com
> Message-ID: <20250929040810.25718-2-ltao(a)redhat.com>
> Content-Type: text/plain; charset="US-ASCII"; x-default=true
>
> Search all possible paths for extensions. Previously if one path, e.g.
> "/usr/lib64/crash/extensions" exists, but no extensions found within,
> crash will not search any later paths, e.g. "./extensions". This patch
> will let crash continue to search any later paths.
>
> Signed-off-by: Tao Liu <ltao(a)redhat.com>
> ---
> extensions.c | 63 ++++++++++++++++++++++++++++++----------------------
> 1 file changed, 36 insertions(+), 27 deletions(-)
>
> diff --git a/extensions.c b/extensions.c
> index d23b1e3..0493f19 100644
> --- a/extensions.c
> +++ b/extensions.c
> @@ -19,7 +19,7 @@
> #include <dlfcn.h>
>
> static int in_extensions_library(char *, char *);
> -static char *get_extensions_directory(char *);
> +static char *get_extensions_directory(char *, bool *);
> static void show_all_extensions(void);
> static void show_extensions(char *);
>
> @@ -395,32 +395,33 @@ in_extensions_library(char *lib, char *buf)
> * Look for an extensions directory using the proper order.
> */
> static char *
> -get_extensions_directory(char *dirbuf)
> +get_extensions_directory(char *dirbuf, bool *end)
> {
> - char *env;
> + static int index = 0;
> + char *dirs[] = {
> + getenv("CRASH_EXTENSIONS"),
> + "/usr/lib64/crash/extensions",
> + "/usr/lib/crash/extensions",
> + "./extensions",
> + };
> + char *dir;
>
> - if ((env = getenv("CRASH_EXTENSIONS"))) {
> - if (is_directory(env)) {
> - strcpy(dirbuf, env);
> - return dirbuf;
> - }
> +retry:
> + if (index >= sizeof(dirs) / sizeof(char *)) {
> + *end = true;
> + return NULL;
> }
> -
> - if (BITS64()) {
> - sprintf(dirbuf, "/usr/lib64/crash/extensions");
> - if (is_directory(dirbuf))
> - return dirbuf;
> + *end = false;
> + dir = dirs[index++];
> + if (is_directory(dir)) {
> + if (!BITS64() && strstr(dir, "lib64")) {
> + goto retry;
> + }
> + snprintf(dirbuf, BUFSIZE - 1, "%s", dir);
> + return dir;
> + } else {
> + return NULL;
> }
> -
> - sprintf(dirbuf, "/usr/lib/crash/extensions");
> - if (is_directory(dirbuf))
> - return dirbuf;
> -
> - sprintf(dirbuf, "./extensions");
> - if (is_directory(dirbuf))
> - return dirbuf;
> -
> - return NULL;
> }
>
> The above code attempts to use a goto loop, this is hard to understand and
debug.
I refactored the original get_extensions_directory() as below, but I
haven't tested it. Can you try it?
+static char* get_extensions_directory(char *dirbuf, size_t sz)
+{
+ const char *dirs[] = {
+ getenv("CRASH_EXTENSIONS"),
+ BITS64() ? "/usr/lib64/crash/extensions" :
"/usr/lib/crash/extensions",
+ "./extensions",
+ NULL
+ };
+
+ for (const char **p = dirs; *p; ++p) {
+ if (is_directory(*p)) {
+ snprintf(dirbuf, sz, "%s", *p);
+ return dirbuf;
+ }
+ }
+ return NULL;
+}
And also modify the is_directory(), for example:
int
-is_directory(char *file)
+is_directory(const char *file)
{
struct stat sbuf;
Anyway I'm still not sure if that can meet your needs.
Thanks
Lianbo
> @@ -432,14 +433,20 @@ preload_extensions(void)
> char dirbuf[BUFSIZE];
> char filename[BUFSIZE*2];
> int found;
> + bool end;
>
> - if (!get_extensions_directory(dirbuf))
> - return;
> +next_dir:
> + if (!get_extensions_directory(dirbuf, &end)) {
> + if (end)
> + return;
> + else
> + goto next_dir;
> + }
>
> dirp = opendir(dirbuf);
> if (!dirp) {
> error(INFO, "%s: %s\n", dirbuf, strerror(errno));
> - return;
> + goto next_dir;
> }
>
> pc->curcmd = pc->program_name;
> @@ -461,10 +468,12 @@ preload_extensions(void)
>
> if (found)
> fprintf(fp, "\n");
> - else
> + else {
> error(NOTE,
> "%s: no extension modules found in directory\n\n",
> dirbuf);
> + goto next_dir;
> + }
> }
>
> /*
> --
> 2.47.0
>
1 month, 2 weeks
[PATCH v3] Add "log -R" to display human readable Rust symbol name
by Lianbo Jiang
Currently, the log command will display human readable Rust
symbol name by default if any, but, sometimes still want to
print the original messages from the log buffer(do not demangle).
In addition, if the log buffer has lines like "_R ... +" which
are not Rust symbols unexpectedly, probably the output will be
missed, that is unexpected.
To fix above cases, add "log -R" to display human readable Rust
symbol name, otherwise still print the original messages.
With the patch:
crash> log -R
...
[ 2174.289360] Tainted: [S]=CPU_OUT_OF_SPEC, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
[ 2174.297322] Hardware name: Intel Corporation S2600CWR/S2600CWR, BIOS SE5C610.86B.01.01.0018.072020161249 07/20/2016
[ 2174.308966] Call Trace:
[ 2174.311693] <TASK>
[ 2174.314033] dump_stack_lvl+0x5d/0x80
[ 2174.318125] panic+0x156/0x32a
[ 2174.321539] rust_panic::area_in_hp+0xf7/0x120 [rust_panic]
[ 2174.329700] ? console_unlock+0x9c/0x140
[ 2174.334080] ? irq_work_queue+0x2d/0x50
[ 2174.338352] ? __pfx_init_module+0x10/0x10 [rust_panic]
[ 2174.344183] <rust_panic::HelloPanic>::step_two+0x20/0xe0 [rust_panic]
[ 2174.353698] ? _printk+0x6b/0x90
[ 2174.357303] init_module+0x57/0xff0 [rust_panic]
[ 2174.362456] ? __pfx_init_module+0x10/0x10 [rust_panic]
...
Suggested-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
defs.h | 1 +
help.c | 24 ++++++++++++++++++-
kernel.c | 5 +++-
printk.c | 71 ++++++++++++++++++++++++++++++++++----------------------
4 files changed, 71 insertions(+), 30 deletions(-)
diff --git a/defs.h b/defs.h
index 3fd7d897c781..c434a5cae702 100644
--- a/defs.h
+++ b/defs.h
@@ -6229,6 +6229,7 @@ void parse_kernel_version(char *);
#define SHOW_LOG_CTIME (0x10)
#define SHOW_LOG_SAFE (0x20)
#define SHOW_LOG_CALLER (0x40)
+#define SHOW_LOG_RUST (0x80)
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 4f071e0bd0a0..78d7a5c70e30 100644
--- a/help.c
+++ b/help.c
@@ -4026,7 +4026,7 @@ NULL
char *help_log[] = {
"log",
"dump system message buffer",
-"[-Ttdmasc]",
+"[-TtdmascR]",
" 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",
@@ -4053,6 +4053,8 @@ char *help_log[] = {
" the CPU id (if in CPU context) that called printk(), if available.",
" Generally available on Linux 5.1 to 5.9 kernels configured with",
" CONFIG_PRINTK_CALLER or Linux 5.10 and later kernels.",
+" -R Display the message text with human readable Rust symbol name if any,",
+" otherwise still print the original message text.",
" ",
"\nEXAMPLES",
" Dump the kernel message buffer:\n",
@@ -4231,6 +4233,26 @@ char *help_log[] = {
" [ 0.014179] [ T29] RAMDISK: [mem 0x3cf4f000-0x437bbfff]",
" [ 0.198789] [ C0] DMAR: DRHD: handling fault status reg 3",
" ...",
+" ",
+" Display the message text with human readable Rust symbol name if any,",
+" otherwise still print the original message text.\n",
+" %s> log -R",
+" ...",
+" [ 2174.289360] Tainted: [S]=CPU_OUT_OF_SPEC, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE",
+" [ 2174.297322] Hardware name: Intel Corporation S2600CWR/S2600CWR, BIOS SE5C610.86B.01.01.0018.072020161249 07/20/2016",
+" [ 2174.308966] Call Trace:",
+" [ 2174.311693] <TASK>",
+" [ 2174.314033] dump_stack_lvl+0x5d/0x80",
+" [ 2174.318125] panic+0x156/0x32a",
+" [ 2174.321539] rust_panic::area_in_hp+0xf7/0x120 [rust_panic]",
+" [ 2174.329700] ? console_unlock+0x9c/0x140",
+" [ 2174.334080] ? irq_work_queue+0x2d/0x50",
+" [ 2174.338352] ? __pfx_init_module+0x10/0x10 [rust_panic]",
+" [ 2174.344183] <rust_panic::HelloPanic>::step_two+0x20/0xe0 [rust_panic]",
+" [ 2174.353698] ? _printk+0x6b/0x90",
+" [ 2174.357303] init_module+0x57/0xff0 [rust_panic]",
+" [ 2174.362456] ? __pfx_init_module+0x10/0x10 [rust_panic]",
+" ...",
NULL
};
diff --git a/kernel.c b/kernel.c
index e4213d7a663e..e077275d7ed6 100644
--- a/kernel.c
+++ b/kernel.c
@@ -5136,7 +5136,7 @@ cmd_log(void)
msg_flags = 0;
- while ((c = getopt(argcnt, args, "Ttdmasc")) != EOF) {
+ while ((c = getopt(argcnt, args, "TtdmascR")) != EOF) {
switch(c)
{
case 'T':
@@ -5160,6 +5160,9 @@ cmd_log(void)
case 'c':
msg_flags |= SHOW_LOG_CALLER;
break;
+ case 'R':
+ msg_flags |= SHOW_LOG_RUST;
+ break;
default:
argerrs++;
break;
diff --git a/printk.c b/printk.c
index 51b618e2a434..f7346f4c1c1d 100644
--- a/printk.c
+++ b/printk.c
@@ -116,7 +116,7 @@ dump_record(struct prb_map *m, unsigned long id, int msg_flags)
uint64_t ts_nsec;
ulonglong nanos;
ulonglong seq;
- int ilen = 0, i;
+ int ilen = 0, i, nlines;
char *desc, *info, *text, *p;
ulong rem;
@@ -202,44 +202,59 @@ dump_record(struct prb_map *m, unsigned long id, int msg_flags)
text = m->text_data + begin;
- if (text_len > BUFSIZE) {
+ if ((msg_flags & SHOW_LOG_RUST) && (text_len > BUFSIZE)) {
error(WARNING, "\nThe messages could be truncated!\n");
text_len = BUFSIZE;
}
- for (i = 0, p = text; i < text_len; i++, p++) {
- if (*p == '\n')
+ for (i = 0, nlines = 0, p = text; i < text_len; i++, p++) {
+ if (*p == '\n') {
+ if ((msg_flags & SHOW_LOG_RUST) && (i != text_len - 1)) {
+ nlines++;
+ if (strlen(buf)) {
+ fprintf(fp, "%s", buf);
+ memset(buf, 0, strlen(buf));
+ }
+ }
fprintf(fp, "\n%s", space(ilen));
- else if (isprint(*p) || isspace(*p))
- sprintf(&buf[i], "%c", *p);
+ } else if ((msg_flags & SHOW_LOG_RUST) && (isprint(*p) || isspace(*p))) {
+ if (nlines >= 1)
+ fputc(*p, fp);
+ else
+ sprintf(&buf[i], "%c", *p);
+ } else if (isprint(*p) || isspace(*p))
+ fputc(*p, fp);
else
fputc('.', fp);
}
/*
* Try to demangle a mangled Rust symbol(calltrace) from log buffer
*/
- char *p1 = strstr(buf, "_R");
- if (!p1)
- p1 = strstr(buf, "_ZN");
- char *p2 = strrchr(buf, '+');
- if (p1 && p2) {
- char mangled[BUFSIZE] = {0};
- char demangled[BUFSIZE] = {0};
- char *res;
- size_t slen = p1 - buf;
-
- if (slen)
- memcpy(demangled, buf, slen);
-
- memcpy(mangled, p1, p2-p1);
- res = rust_demangle(mangled, DMGL_RUST);
- if (res) {
- snprintf(demangled+slen, BUFSIZE-slen, "%s%s", res, p2);
- fprintf(fp, "%s",demangled);
- free(res);
- }
- } else
- fprintf(fp, "%s", buf);
+ if (msg_flags & SHOW_LOG_RUST) {
+ char *p1 = strstr(buf, "_R");
+ if (!p1)
+ p1 = strstr(buf, "_ZN");
+ char *p2 = strrchr(buf, '+');
+ if (p1 && p2) {
+ char mangled[BUFSIZE] = {0};
+ char demangled[BUFSIZE] = {0};
+ char *res;
+ size_t slen = p1 - buf;
+
+ if (slen)
+ memcpy(demangled, buf, slen);
+
+ memcpy(mangled, p1, p2-p1);
+ res = rust_demangle(mangled, DMGL_RUST);
+ if (res) {
+ snprintf(demangled+slen, BUFSIZE-slen, "%s%s", res, p2);
+ fprintf(fp, "%s",demangled);
+ free(res);
+ } else
+ fprintf(fp, "%s", buf);
+ } else
+ fprintf(fp, "%s", buf);
+ }
if (msg_flags & SHOW_LOG_DICT) {
text = info + OFFSET(printk_info_dev_info) +
--
2.50.1
1 month, 2 weeks
[PATCH v2] Add "log -R" to display human readable Rust symbol name
by Lianbo Jiang
Currently, the log command will display human readable Rust
symbol name by default if any, but, sometimes still want to
print the original messages from the log buffer(do not demangle).
In addition, if the log buffer has lines like "_R ... +" which
are not Rust symbols unexpectedly, probably the output will be
missed, that is unexpected.
To fix above cases, add "log -R" to display human readable Rust
symbol name, otherwise still print the original messages.
With the patch:
crash> log -R
...
[ 2174.289360] Tainted: [S]=CPU_OUT_OF_SPEC, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
[ 2174.297322] Hardware name: Intel Corporation S2600CWR/S2600CWR, BIOS SE5C610.86B.01.01.0018.072020161249 07/20/2016
[ 2174.308966] Call Trace:
[ 2174.311693] <TASK>
[ 2174.314033] dump_stack_lvl+0x5d/0x80
[ 2174.318125] panic+0x156/0x32a
[ 2174.321539] rust_panic::area_in_hp+0xf7/0x120 [rust_panic]
[ 2174.329700] ? console_unlock+0x9c/0x140
[ 2174.334080] ? irq_work_queue+0x2d/0x50
[ 2174.338352] ? __pfx_init_module+0x10/0x10 [rust_panic]
[ 2174.344183] <rust_panic::HelloPanic>::step_two+0x20/0xe0 [rust_panic]
[ 2174.353698] ? _printk+0x6b/0x90
[ 2174.357303] init_module+0x57/0xff0 [rust_panic]
[ 2174.362456] ? __pfx_init_module+0x10/0x10 [rust_panic]
...
Suggested-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
defs.h | 1 +
help.c | 24 +++++++++++++++++++++++-
kernel.c | 5 ++++-
printk.c | 53 +++++++++++++++++++++++++++++------------------------
4 files changed, 57 insertions(+), 26 deletions(-)
diff --git a/defs.h b/defs.h
index 156ac0232906..997145cba9d2 100644
--- a/defs.h
+++ b/defs.h
@@ -6227,6 +6227,7 @@ void parse_kernel_version(char *);
#define SHOW_LOG_CTIME (0x10)
#define SHOW_LOG_SAFE (0x20)
#define SHOW_LOG_CALLER (0x40)
+#define SHOW_LOG_RUST (0x80)
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 4f071e0bd0a0..78d7a5c70e30 100644
--- a/help.c
+++ b/help.c
@@ -4026,7 +4026,7 @@ NULL
char *help_log[] = {
"log",
"dump system message buffer",
-"[-Ttdmasc]",
+"[-TtdmascR]",
" 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",
@@ -4053,6 +4053,8 @@ char *help_log[] = {
" the CPU id (if in CPU context) that called printk(), if available.",
" Generally available on Linux 5.1 to 5.9 kernels configured with",
" CONFIG_PRINTK_CALLER or Linux 5.10 and later kernels.",
+" -R Display the message text with human readable Rust symbol name if any,",
+" otherwise still print the original message text.",
" ",
"\nEXAMPLES",
" Dump the kernel message buffer:\n",
@@ -4231,6 +4233,26 @@ char *help_log[] = {
" [ 0.014179] [ T29] RAMDISK: [mem 0x3cf4f000-0x437bbfff]",
" [ 0.198789] [ C0] DMAR: DRHD: handling fault status reg 3",
" ...",
+" ",
+" Display the message text with human readable Rust symbol name if any,",
+" otherwise still print the original message text.\n",
+" %s> log -R",
+" ...",
+" [ 2174.289360] Tainted: [S]=CPU_OUT_OF_SPEC, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE",
+" [ 2174.297322] Hardware name: Intel Corporation S2600CWR/S2600CWR, BIOS SE5C610.86B.01.01.0018.072020161249 07/20/2016",
+" [ 2174.308966] Call Trace:",
+" [ 2174.311693] <TASK>",
+" [ 2174.314033] dump_stack_lvl+0x5d/0x80",
+" [ 2174.318125] panic+0x156/0x32a",
+" [ 2174.321539] rust_panic::area_in_hp+0xf7/0x120 [rust_panic]",
+" [ 2174.329700] ? console_unlock+0x9c/0x140",
+" [ 2174.334080] ? irq_work_queue+0x2d/0x50",
+" [ 2174.338352] ? __pfx_init_module+0x10/0x10 [rust_panic]",
+" [ 2174.344183] <rust_panic::HelloPanic>::step_two+0x20/0xe0 [rust_panic]",
+" [ 2174.353698] ? _printk+0x6b/0x90",
+" [ 2174.357303] init_module+0x57/0xff0 [rust_panic]",
+" [ 2174.362456] ? __pfx_init_module+0x10/0x10 [rust_panic]",
+" ...",
NULL
};
diff --git a/kernel.c b/kernel.c
index e4213d7a663e..e077275d7ed6 100644
--- a/kernel.c
+++ b/kernel.c
@@ -5136,7 +5136,7 @@ cmd_log(void)
msg_flags = 0;
- while ((c = getopt(argcnt, args, "Ttdmasc")) != EOF) {
+ while ((c = getopt(argcnt, args, "TtdmascR")) != EOF) {
switch(c)
{
case 'T':
@@ -5160,6 +5160,9 @@ cmd_log(void)
case 'c':
msg_flags |= SHOW_LOG_CALLER;
break;
+ case 'R':
+ msg_flags |= SHOW_LOG_RUST;
+ break;
default:
argerrs++;
break;
diff --git a/printk.c b/printk.c
index 51b618e2a434..b8fcc8e58160 100644
--- a/printk.c
+++ b/printk.c
@@ -202,7 +202,7 @@ dump_record(struct prb_map *m, unsigned long id, int msg_flags)
text = m->text_data + begin;
- if (text_len > BUFSIZE) {
+ if ((msg_flags & SHOW_LOG_RUST) && (text_len > BUFSIZE)) {
error(WARNING, "\nThe messages could be truncated!\n");
text_len = BUFSIZE;
}
@@ -210,36 +210,41 @@ dump_record(struct prb_map *m, unsigned long id, int msg_flags)
for (i = 0, p = text; i < text_len; i++, p++) {
if (*p == '\n')
fprintf(fp, "\n%s", space(ilen));
- else if (isprint(*p) || isspace(*p))
+ else if ((msg_flags & SHOW_LOG_RUST) && (isprint(*p) || isspace(*p)))
sprintf(&buf[i], "%c", *p);
+ else if (isprint(*p) || isspace(*p))
+ fputc(*p, fp);
else
fputc('.', fp);
}
/*
* Try to demangle a mangled Rust symbol(calltrace) from log buffer
*/
- char *p1 = strstr(buf, "_R");
- if (!p1)
- p1 = strstr(buf, "_ZN");
- char *p2 = strrchr(buf, '+');
- if (p1 && p2) {
- char mangled[BUFSIZE] = {0};
- char demangled[BUFSIZE] = {0};
- char *res;
- size_t slen = p1 - buf;
-
- if (slen)
- memcpy(demangled, buf, slen);
-
- memcpy(mangled, p1, p2-p1);
- res = rust_demangle(mangled, DMGL_RUST);
- if (res) {
- snprintf(demangled+slen, BUFSIZE-slen, "%s%s", res, p2);
- fprintf(fp, "%s",demangled);
- free(res);
- }
- } else
- fprintf(fp, "%s", buf);
+ if (msg_flags & SHOW_LOG_RUST) {
+ char *p1 = strstr(buf, "_R");
+ if (!p1)
+ p1 = strstr(buf, "_ZN");
+ char *p2 = strrchr(buf, '+');
+ if (p1 && p2) {
+ char mangled[BUFSIZE] = {0};
+ char demangled[BUFSIZE] = {0};
+ char *res;
+ size_t slen = p1 - buf;
+
+ if (slen)
+ memcpy(demangled, buf, slen);
+
+ memcpy(mangled, p1, p2-p1);
+ res = rust_demangle(mangled, DMGL_RUST);
+ if (res) {
+ snprintf(demangled+slen, BUFSIZE-slen, "%s%s", res, p2);
+ fprintf(fp, "%s",demangled);
+ free(res);
+ } else
+ fprintf(fp, "%s", buf);
+ } else
+ fprintf(fp, "%s", buf);
+ }
if (msg_flags & SHOW_LOG_DICT) {
text = info + OFFSET(printk_info_dev_info) +
--
2.50.1
1 month, 2 weeks
Re: [PATCH] Optimize extensions's compiler from gcc to $(CC)
by lijiang
Hi, Jianyun
Thank you for the patch.
On Fri, Sep 26, 2025 at 7:27 AM <devel-request(a)lists.crash-utility.osci.io>
wrote:
> Date: Tue, 23 Sep 2025 21:43:38 +0800
> From: 高建云 <jianyungao89(a)gmail.com>
> Subject: [Crash-utility] [PATCH] Optimize extensions's compiler from
> gcc to $(CC)
> To: devel(a)lists.crash-utility.osci.io
> Message-ID:
> <
> CAHP3+4CZqDNh5LV5DgY0HLfB_MQPqAU0PzoZZTfk9Kfvz+BHJA(a)mail.gmail.com>
> Content-Type: multipart/alternative;
> boundary="00000000000043dcaa063f782098"
>
> --00000000000043dcaa063f782098
> Content-Type: text/plain; charset="UTF-8"
>
> Change the default compiler of the extensions from the fixed gcc
> to $(CC) passed in by the upper layer Makefile,
> to facilitate cross_compile.
>
> Signed-off-by: jianyun.gao <jianyungao89(a)gmail.com>
> ---
> Makefile | 2 +-
> extensions/Makefile | 10 +++++-----
> 2 files changed, 6 insertions(+), 6 deletions(-)
>
>
I tried the patch, and this caused the following failure, can you help
double check?
$ make CROSS_COMPILE=aarch64-linux-gnu- extensions
aarch64-linux-gnu-gcc -Wall -g -shared -rdynamic -o dminfo.so dminfo.c
-fPIC -DARM64 -DGDB_16_2
aarch64-linux-gnu-gcc -Wall -g -shared -rdynamic -o echo.so echo.c -fPIC
-DARM64 -DGDB_16_2
Cloning into 'eppic'...
remote: Enumerating objects: 691, done.
remote: Counting objects: 100% (210/210), done.
remote: Compressing objects: 100% (84/84), done.
remote: Total 691 (delta 150), reused 165 (delta 124), pack-reused 481
(from 1)
Receiving objects: 100% (691/691), 318.81 KiB | 312.00 KiB/s, done.
Resolving deltas: 100% (372/372), done.
cd eppic/libeppic && make
bison -peppic -v -t -d eppic.y
eppic.y: warning: 135 shift/reduce conflicts [-Wconflicts-sr]
eppic.y: warning: 22 reduce/reduce conflicts [-Wconflicts-rr]
eppic.y: note: rerun with option '-Wcounterexamples' to generate conflict
counterexamples
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_util.o eppic_util.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_node.o eppic_node.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_var.o eppic_var.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_func.o eppic_func.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_str.o eppic_str.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_op.o eppic_op.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_num.o eppic_num.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_stat.o eppic_stat.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_builtin.o eppic_builtin.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_type.o eppic_type.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_case.o eppic_case.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_api.o eppic_api.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_member.o eppic_member.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_alloc.o eppic_alloc.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_define.o eppic_define.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_input.o eppic_input.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c -o
eppic_print.o eppic_print.c
bison -peppicpp -v -t -d eppicpp.y
eppicpp.y: warning: 23 shift/reduce conflicts [-Wconflicts-sr]
eppicpp.y: note: rerun with option '-Wcounterexamples' to generate conflict
counterexamples
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c eppicpp.tab.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c eppic.tab.c
flex -L -Peppic -t eppic.l > lex.eppic.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c lex.eppic.c
flex -Peppicpp -t eppicpp.l > lex.eppicpp.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c lex.eppicpp.c
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -o mkbaseop
mkbaseop.c
./mkbaseop > baseops.c
/bin/sh: 1: ./mkbaseop: Exec format error
make[5]: [Makefile:71: baseops.o] Error 126 (ignored)
aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -fPIC -c baseops.c
ar cur libeppic.a eppic_util.o eppic_node.o eppic_var.o eppic_func.o
eppic_str.o eppic_op.o eppic_num.o eppic_stat.o eppic_builtin.o
eppic_type.o eppic_case.o eppic_api.o eppic_member.o eppic_alloc.o
eppic_define.o eppic_input.o eppic_print.o eppicpp.tab.o eppic.tab.o
lex.eppic.o lex.eppicpp.o baseops.o
ar: `u' modifier ignored since `D' is the default (see `U')
gcc -g -O0 -Ieppic/libeppic -I.. -nostartfiles -shared -rdynamic -o
eppic.so eppic/applications/crash/eppic.c -fPIC -DARM64 -DGDB_16_2
-Leppic/libeppic -leppic
/usr/bin/ld: skipping incompatible eppic/libeppic/libeppic.a when searching
for -leppic
/usr/bin/ld: cannot find -leppic: No such file or directory
collect2: error: ld returned 1 exit status
make[4]: [eppic.mk:71: eppic.so] Error 1 (ignored)
gcc -Wall -g -I. -shared -rdynamic -o snap.so snap.c -fPIC -DARM64
-DGDB_16_2
But for the trace and gcore, etc. It can work.
Thanks
Lianbo
> diff --git a/Makefile b/Makefile
> index b277129..58b1326 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -727,7 +727,7 @@ extensions: make_configure
> @$(MAKE) do_extensions
>
> do_extensions:
> - @$(MAKE) -C extensions -i TARGET=$(TARGET) TARGET_CFLAGS="$(CFLAGS)
> $(TARGET_CFLAGS)" GDB=$(GDB) GDB_FLAGS=$(GDB_FLAGS)
> + @$(MAKE) -C extensions -i CC=$(CC) TARGET=$(TARGET)
> TARGET_CFLAGS="$(CFLAGS) $(TARGET_CFLAGS)" GDB=$(GDB)
> GDB_FLAGS=$(GDB_FLAGS)
>
> memory_driver: make_configure
> @$(MAKE) -C memory_driver -i
> diff --git a/extensions/Makefile b/extensions/Makefile
> index e4c68c3..67d3839 100644
> --- a/extensions/Makefile
> +++ b/extensions/Makefile
> @@ -23,7 +23,7 @@
> # suffice, create a .mk file with the same prefix as the .c file,
> # and that makefile will be invoked.
> #
> -
> +CC ?= gcc
> CONTRIB_SO := $(patsubst %.c,%.so,$(wildcard *.c))
>
> all: link_defs $(CONTRIB_SO)
> @@ -37,11 +37,11 @@ $(CONTRIB_SO): %.so: %.c defs.h
> $(MAKE) -f $*.mk; \
> else \
> grep -q '((constructor))' $*.c && { \
> - echo "gcc -Wall -g -shared -rdynamic -o $@ $*.c -fPIC
> -D$(TARGET) $(TARGET_CFLAGS) $(GDB_FLAGS)"; \
> - gcc -Wall -g -shared -rdynamic -o $@ $*.c -fPIC -D$(TARGET)
> $(TARGET_CFLAGS) $(GDB_FLAGS); \
> + echo "$(CC) -Wall -g -shared -rdynamic -o $@ $*.c -fPIC
> -D$(TARGET) $(TARGET_CFLAGS) $(GDB_FLAGS)"; \
> + $(CC) -Wall -g -shared -rdynamic -o $@ $*.c -fPIC -D$(TARGET)
> $(TARGET_CFLAGS) $(GDB_FLAGS); \
> } || { \
> - echo "gcc -Wall -g -nostartfiles -shared -rdynamic -o $@ $*.c
> -fPIC -D$(TARGET) $(TARGET_CFLAGS) $(GDB_FLAGS)"; \
> - gcc -Wall -g -nostartfiles -shared -rdynamic -o $@ $*.c -fPIC
> -D$(TARGET) $(TARGET_CFLAGS) $(GDB_FLAGS); \
> + echo "$(CC) -Wall -g -nostartfiles -shared -rdynamic -o $@ $*.c
> -fPIC -D$(TARGET) $(TARGET_CFLAGS) $(GDB_FLAGS)"; \
> + $(CC) -Wall -g -nostartfiles -shared -rdynamic -o $@ $*.c -fPIC
> -D$(TARGET) $(TARGET_CFLAGS) $(GDB_FLAGS); \
> }; \
> fi
>
> --
> 2.34.1
>
>
1 month, 2 weeks
[PATCH v2 1/2] s390x: Add non-zero vmalloc_start check to s390x_vr_IS_VMALLOC_ADDR()
by Mikhail Zaslonko
- Update s390x_vr_IS_VMALLOC_ADDR() to include a non-zero vmalloc_start
check, making it consistent with s390x_generic_IS_VMALLOC_ADDR().
- Remove redundant vmalloc_start check from s390x_kvtop().
Signed-off-by: Mikhail Zaslonko <zaslonko(a)linux.ibm.com>
---
s390x.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/s390x.c b/s390x.c
index 0e8e2b3..25dca5e 100644
--- a/s390x.c
+++ b/s390x.c
@@ -724,13 +724,13 @@ static ulong s390x_vr_PTOV(ulong paddr)
{
return paddr + machdep->identity_map_base;
}
static int s390x_vr_IS_VMALLOC_ADDR(ulong vaddr)
{
- return (vaddr >= vt->vmalloc_start && vaddr < machdep->kvbase);
+ return (vt->vmalloc_start && vaddr >= vt->vmalloc_start && vaddr < machdep->kvbase);
}
ulong s390x_VTOP(ulong vaddr)
{
return machdep->machspec->virt_to_phys(vaddr);
}
@@ -943,17 +943,12 @@ s390x_kvtop(struct task_context *tc, ulong vaddr, physaddr_t *paddr, int verbose
if (!IS_KVADDR(vaddr)){
*paddr = 0;
return FALSE;
}
- if (!vt->vmalloc_start) {
- *paddr = VTOP(vaddr);
- return TRUE;
- }
-
if (!IS_VMALLOC_ADDR(vaddr)) {
*paddr = VTOP(vaddr);
return TRUE;
}
pgd_base = (unsigned long)vt->kernel_pgd[0];
--
2.49.0
1 month, 2 weeks