Re: [Crash-utility] [PATCH 1/1] Handle task_struct cpu member changes in linux-next
by lijiang
On Thu, Oct 14, 2021 at 12:03 AM <crash-utility-request(a)redhat.com> wrote:
> Date: Wed, 13 Oct 2021 10:56:39 +0200
> From: Alexander Egorenkov <egorenar(a)linux.ibm.com>
> To: crash-utility(a)redhat.com
> Subject: [Crash-utility] [PATCH 1/1] Handle task_struct cpu member
> changes in linux-next
> Message-ID: <20211013085639.192233-1-egorenar(a)linux.ibm.com>
> Content-Type: text/plain; charset="US-ASCII"
>
> Kernel commit bcf9033e5449bdcaa9bed46467a7141a8049dadb
> ("sched: move CPU field back into thread_info if THREAD_INFO_IN_TASK=y")
> moved the member cpu of task_struct back into thread_info.
>
> https://lkml.org/lkml/2021/9/30/517
>
> This fixes the following problem:
>
> please wait... (gathering task table data)
> crash: invalid structure member offset: task_struct_cpu
> FILE: task.c LINE: 2904 FUNCTION: add_context()
>
> [/usr/bin/crash] error trace: 114840a => 115560a => 114e360 => 11d6394
>
> 11d6394: (undetermined)
> 114e360: (undetermined)
> 115560a: (undetermined)
> 114840a: task_init+4634
>
> Signed-off-by: Alexander Egorenkov <egorenar(a)linux.ibm.com>
> ---
> task.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/task.c b/task.c
> index 672b41697e75..bb6a5da8ad33 100644
> --- a/task.c
> +++ b/task.c
> @@ -278,8 +278,10 @@ task_init(void)
> } else if (VALID_MEMBER(task_struct_stack))
> MEMBER_OFFSET_INIT(task_struct_thread_info, "task_struct", "stack");
>
> + MEMBER_OFFSET_INIT(task_struct_cpu, "task_struct", "cpu");
> +
> if (VALID_MEMBER(task_struct_thread_info)) {
> - if (tt->flags & THREAD_INFO_IN_TASK) {
> + if (tt->flags & THREAD_INFO_IN_TASK && VALID_MEMBER(task_struct_cpu)) {
> MEMBER_OFFSET_INIT(thread_info_flags, "thread_info", "flags");
> /* (unnecessary) reminders */
> ASSIGN_OFFSET(thread_info_task) = INVALID_OFFSET;
> @@ -315,7 +317,6 @@ task_init(void)
> MEMBER_OFFSET_INIT(task_struct_has_cpu, "task_struct", "has_cpu");
> MEMBER_OFFSET_INIT(task_struct_cpus_runnable,
> "task_struct", "cpus_runnable");
> - MEMBER_OFFSET_INIT(task_struct_cpu, "task_struct", "cpu");
> MEMBER_OFFSET_INIT(task_struct_active_mm, "task_struct", "active_mm");
> MEMBER_OFFSET_INIT(task_struct_next_run, "task_struct", "next_run");
> MEMBER_OFFSET_INIT(task_struct_flags, "task_struct", "flags");
> @@ -2900,7 +2901,7 @@ add_context(ulong task, char *tp)
> else
> tc->thread_info = ULONG(tp + OFFSET(task_struct_thread_info));
> fill_thread_info(tc->thread_info);
> - if (tt->flags & THREAD_INFO_IN_TASK)
> + if (tt->flags & THREAD_INFO_IN_TASK && VALID_MEMBER(task_struct_cpu))
> processor_addr = (int *) (tp + OFFSET(task_struct_cpu));
> else
> processor_addr = (int *) (tt->thread_info +
> --
> 2.31.1
Thank you for the fix, Alexander.
Acked-by: Lianbo Jiang <lijiang(a)redhat.com>
3 years
[PATCH] arm64: Use VA_BITS for page_offset calculation
by HAGIO KAZUHITO(萩尾 一仁)
Hi,
Here is a patch for the issue reported by Ankur.
Could you help test this with your ramdumps and arm64 machines?
--
>From 028ddf655c847c16cce23198017d2ff0169bb4de Mon Sep 17 00:00:00 2001
From: Kazuhito Hagio <k-hagio-ab(a)nec.com>
Date: Mon, 25 Oct 2021 16:53:26 +0900
Subject: [PATCH] arm64: Use VA_BITS for page_offset calculation
Commit 167d37e347fe ("arm64: assign page_offset with VA_BITS kernel
configuration value") changed the page_offset calculation from
using VA_BITS_ACTUAL to CONFIG_ARM64_VA_BITS. This caused an error
for ramdumps without vmcoreinfo like this:
crash: vmlinux and /var/tmp/ramdump_elf_XUtCMT do not match!
Set the vmcoreinfo value to VA_BITS if available, and use VA_BITS
for page_offset calculation instead.
Also remove ARM64_FLIP_PAGE_OFFSET_ACTUAL because it's not used
actually.
Reported-by: Ankur Bansal <er.ankurbansal(a)gmail.com>
Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
arm64.c | 5 ++++-
defs.h | 4 +---
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/arm64.c b/arm64.c
index 7069312671cf..3dcbcc642fda 100644
--- a/arm64.c
+++ b/arm64.c
@@ -404,7 +404,7 @@ arm64_init(int when)
fprintf(fp, "CONFIG_ARM64_VA_BITS: %ld\n", ms->CONFIG_ARM64_VA_BITS);
fprintf(fp, " VA_BITS_ACTUAL: %ld\n", ms->VA_BITS_ACTUAL);
fprintf(fp, "(calculated) VA_BITS: %ld\n", ms->VA_BITS);
- fprintf(fp, " PAGE_OFFSET: %lx\n", ARM64_FLIP_PAGE_OFFSET_ACTUAL);
+ fprintf(fp, " PAGE_OFFSET: %lx\n", ARM64_FLIP_PAGE_OFFSET);
fprintf(fp, " VA_START: %lx\n", ms->VA_START);
fprintf(fp, " modules: %lx - %lx\n", ms->modules_vaddr, ms->modules_end);
fprintf(fp, " vmalloc: %lx - %lx\n", ms->vmalloc_start_addr, ms->vmalloc_end);
@@ -4031,6 +4031,9 @@ arm64_calc_VA_BITS(void)
error(FATAL, "cannot determine VA_BITS_ACTUAL\n");
}
+ if (machdep->machspec->CONFIG_ARM64_VA_BITS)
+ machdep->machspec->VA_BITS = machdep->machspec->CONFIG_ARM64_VA_BITS;
+
/*
* The mm flip commit is introduced before 52-bits VA, which is before the
* commit to export NUMBER(TCR_EL1_T1SZ)
diff --git a/defs.h b/defs.h
index 8b356d5e8959..971005596506 100644
--- a/defs.h
+++ b/defs.h
@@ -3238,9 +3238,7 @@ typedef signed int s32;
#define ARM64_PAGE_OFFSET ((0xffffffffffffffffUL) \
<< (machdep->machspec->VA_BITS - 1))
/* kernels >= v5.4 the kernel VA space is flipped */
-#define ARM64_FLIP_PAGE_OFFSET (-(1UL) << machdep->machspec->CONFIG_ARM64_VA_BITS)
-#define ARM64_FLIP_PAGE_OFFSET_ACTUAL ((0xffffffffffffffffUL) \
- - ((1UL) << machdep->machspec->VA_BITS_ACTUAL) + 1)
+#define ARM64_FLIP_PAGE_OFFSET (-(1UL) << machdep->machspec->VA_BITS)
#define ARM64_USERSPACE_TOP ((1UL) << machdep->machspec->VA_BITS)
#define ARM64_USERSPACE_TOP_ACTUAL ((1UL) << machdep->machspec->VA_BITS_ACTUAL)
--
2.27.0
3 years
Re: [Crash-utility] [PATCH] arm64: Use VA_BITS for page_offset calculation
by lijiang
This change looks good to me.
Acked-by: Lianbo Jiang <lijiang(a)redhat.com>
On Mon, Oct 25, 2021 at 4:58 PM <crash-utility-request(a)redhat.com> wrote:
> From: Kazuhito Hagio <k-hagio-ab(a)nec.com>
> Date: Mon, 25 Oct 2021 16:53:26 +0900
> Subject: [PATCH] arm64: Use VA_BITS for page_offset calculation
>
> Commit 167d37e347fe ("arm64: assign page_offset with VA_BITS kernel
> configuration value") changed the page_offset calculation from
> using VA_BITS_ACTUAL to CONFIG_ARM64_VA_BITS. This caused an error
> for ramdumps without vmcoreinfo like this:
>
> crash: vmlinux and /var/tmp/ramdump_elf_XUtCMT do not match!
>
> Set the vmcoreinfo value to VA_BITS if available, and use VA_BITS
> for page_offset calculation instead.
>
> Also remove ARM64_FLIP_PAGE_OFFSET_ACTUAL because it's not used
> actually.
>
> Reported-by: Ankur Bansal <er.ankurbansal(a)gmail.com>
> Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
> ---
> arm64.c | 5 ++++-
> defs.h | 4 +---
> 2 files changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/arm64.c b/arm64.c
> index 7069312671cf..3dcbcc642fda 100644
> --- a/arm64.c
> +++ b/arm64.c
> @@ -404,7 +404,7 @@ arm64_init(int when)
> fprintf(fp, "CONFIG_ARM64_VA_BITS: %ld\n",
> ms->CONFIG_ARM64_VA_BITS);
> fprintf(fp, " VA_BITS_ACTUAL: %ld\n",
> ms->VA_BITS_ACTUAL);
> fprintf(fp, "(calculated) VA_BITS: %ld\n",
> ms->VA_BITS);
> - fprintf(fp, " PAGE_OFFSET: %lx\n",
> ARM64_FLIP_PAGE_OFFSET_ACTUAL);
> + fprintf(fp, " PAGE_OFFSET: %lx\n",
> ARM64_FLIP_PAGE_OFFSET);
> fprintf(fp, " VA_START: %lx\n",
> ms->VA_START);
> fprintf(fp, " modules: %lx - %lx\n",
> ms->modules_vaddr, ms->modules_end);
> fprintf(fp, " vmalloc: %lx - %lx\n",
> ms->vmalloc_start_addr, ms->vmalloc_end);
> @@ -4031,6 +4031,9 @@ arm64_calc_VA_BITS(void)
> error(FATAL, "cannot determine
> VA_BITS_ACTUAL\n");
> }
>
> + if (machdep->machspec->CONFIG_ARM64_VA_BITS)
> + machdep->machspec->VA_BITS =
> machdep->machspec->CONFIG_ARM64_VA_BITS;
> +
> /*
> * The mm flip commit is introduced before 52-bits VA,
> which is before the
> * commit to export NUMBER(TCR_EL1_T1SZ)
> diff --git a/defs.h b/defs.h
> index 8b356d5e8959..971005596506 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -3238,9 +3238,7 @@ typedef signed int s32;
> #define ARM64_PAGE_OFFSET ((0xffffffffffffffffUL) \
> << (machdep->machspec->VA_BITS -
> 1))
> /* kernels >= v5.4 the kernel VA space is flipped */
> -#define ARM64_FLIP_PAGE_OFFSET (-(1UL) <<
> machdep->machspec->CONFIG_ARM64_VA_BITS)
> -#define ARM64_FLIP_PAGE_OFFSET_ACTUAL ((0xffffffffffffffffUL) \
> - - ((1UL) <<
> machdep->machspec->VA_BITS_ACTUAL) + 1)
> +#define ARM64_FLIP_PAGE_OFFSET (-(1UL) << machdep->machspec->VA_BITS)
>
> #define ARM64_USERSPACE_TOP ((1UL) << machdep->machspec->VA_BITS)
> #define ARM64_USERSPACE_TOP_ACTUAL ((1UL) <<
> machdep->machspec->VA_BITS_ACTUAL)
> --
> 2.27.0
>
3 years, 1 month
Re: [Crash-utility] [PATCH] arm64 : assign page_offset and kvbase based on VA_BITS passed
by ankur bansal
>
> Date: Mon, 27 Sep 2021 14:29:25 +0800
> From: lijiang <lijiang(a)redhat.com>
> To: "Discussion list for crash utility usage, maintenance and
> development" <crash-utility(a)redhat.com>
> Subject: Re: [Crash-utility] [PATCH] arm64 : assign page_offset and
> kvbase based on VA_BITS passed
> Message-ID:
> <
> CANU+ZyffmHocjiXy1F1v7YPdRtQ+eeukXXT-PXsW2H5Q2cHEfA(a)mail.gmail.com>
> Content-Type: text/plain; charset="UTF-8"
>
> >> Date: Thu, 23 Sep 2021 01:46:31 +0530
> >> From: Ankur Bansal <er.ankurbansal(a)gmail.com>
> >> To: crash-utility(a)redhat.com
> >> Cc: Ankur Bansal <er.ankurbansal(a)gmail.com>
> >> Subject: [Crash-utility] [PATCH] arm64 : assign page_offset and kvbase
> >> based on VA_BITS passed
> >> Message-ID:
> >> <1632341791-10205-1-git-send-email-er.ankurbansal(a)gmail.com>
> >> Content-Type: text/plain; charset="US-ASCII"
> >>
> >> assign page_offset and kvbase based on VA_BITS passed
> >>
>
> >Thank you for the patch, Ankur.
> >Can you help to describe the reason in detail? And what happened?
>
Hi Lianbo, Raw ramdump without vmcoreinfo doesn't work here.
read_vmcoreinfo("NUMBER(BA_BITS)") will not work on raw ramdump.
getting below error
crash_64: vmlinux and /var/tmp/ramdump_elf_XUtCMT do not match!
Usage:
crash [OPTION]... NAMELIST MEMORY-IMAGE[@address
<https://github.com/address>] (dumpfile form)
crash [OPTION]... [NAMELIST] (live system form)
Enter "crash_64 -h" for details.
Recent change
https://github.com/crash-utility/crash/commit/167d37e347fe35c6f7db826e853...
is causing this issue, before this change VA_BITS_ACTUAL was used which is
passed from cmd line.
3987 static void
3988 arm64_calc_VA_BITS(void)
3989 {
3990 int bitval;
3991 struct syment *sp;
3992 ulong vabits_actual, value;
3993 char *string;
3994
3995 if ((string = pc->read_vmcoreinfo("NUMBER(VA_BITS)"))) {
3996 value = atol(string);
3997 free(string);
3998 machdep->machspec->CONFIG_ARM64_VA_BITS = value;
3999 }
> >Thanks.
> >Lianbo
>
> >> Change-Id: I525f3c7fd91e1f06e909c2f4c1749c44c068baea
> >> Signed-off-by: Ankur Bansal <er.ankurbansal(a)gmail.com>
> >> ---
> >> arm64.c | 15 +++++++++++----
> >> 1 file changed, 11 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/arm64.c b/arm64.c
> >> index 7069312..2dc77f7 100644
> >> --- a/arm64.c
> >> +++ b/arm64.c
> >> @@ -220,10 +220,17 @@ arm64_init(int when)
> >>
> >> /* vabits_actual introduced after mm flip, so it should
> be flipped layout */
> >> if (ms->VA_BITS_ACTUAL) {
> >> - ms->page_offset = ARM64_FLIP_PAGE_OFFSET;
> >> - /* useless on arm64 */
> >> - machdep->identity_map_base =
> ARM64_FLIP_PAGE_OFFSET;
> >> - machdep->kvbase = ARM64_FLIP_PAGE_OFFSET;
> >> + if ((pc->flags2 & SNAP)) {
> >> + ms->page_offset =
> ARM64_FLIP_PAGE_OFFSET;
> >> + /* useless on arm64 */
> >> + machdep->identity_map_base =
> ARM64_FLIP_PAGE_OFFSET;
> >> + machdep->kvbase =
> ARM64_FLIP_PAGE_OFFSET;
> >> + }
> >> + else{
> >> + ms->page_offset =
> ARM64_FLIP_PAGE_OFFSET_ACTUAL;
> >> + machdep->identity_map_base =
> ARM64_FLIP_PAGE_OFFSET_ACTUAL;
> >> + machdep->kvbase =
> ARM64_FLIP_PAGE_OFFSET_ACTUAL;
> >> + }
> >> ms->userspace_top = ARM64_USERSPACE_TOP_ACTUAL;
> >> } else {
> >> ms->page_offset = ARM64_PAGE_OFFSET;
> >> --
> >> 2.7.4
>
>
>
> ------------------------------
>
> --
> Crash-utility mailing list
> Crash-utility(a)redhat.com
> https://listman.redhat.com/mailman/listinfo/crash-utility
>
> End of Crash-utility Digest, Vol 192, Issue 28
> **********************************************
>
>
3 years, 1 month
Re: [Crash-utility] [PATCH] New sbitmap command
by lijiang
On Tue, Oct 5, 2021 at 4:51 PM <crash-utility-request(a)redhat.com> wrote:
> Date: Mon, 4 Oct 2021 20:15:36 +0300
> From: Sergey Samoylenko <s.samoylenko(a)yadro.com>
> To: <crash-utility(a)redhat.com>
> Cc: Sergey Samoylenko <s.samoylenko(a)yadro.com>, linux(a)yadro.com
> Subject: [Crash-utility] [PATCH] New sbitmap command
> Message-ID: <20211004171536.30971-1-s.samoylenko(a)yadro.com>
> Content-Type: text/plain
>
> Patch adds new 'sbitmap' command. This command dumps
> the contents of the sbitmap_queue structure and the used
> bits in the bitmap. Also, it shows the dump of a structure
> array associated with the sbitmap_queue.
>
> Signed-off-by: Sergey Samoylenko <s.samoylenko(a)yadro.com>
> ---
> Makefile | 7 +-
> defs.h | 2 +
> global_data.c | 1 +
> help.c | 89 ++++++++
> sbitmap.c | 591 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 688 insertions(+), 2 deletions(-)
> create mode 100644 sbitmap.c
>
Thank you for the patch,Sergey. It is very helpful for parsing
sbitmap. But I need some time to understand this patch, please be
patient.
Thanks.
Lianbo
> diff --git a/Makefile b/Makefile
> index ece1306..c116177 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -72,7 +72,7 @@ CFILES=main.c tools.c global_data.c memory.c filesys.c help.c task.c \
> xen_hyper.c xen_hyper_command.c xen_hyper_global_data.c \
> xen_hyper_dump_tables.c kvmdump.c qemu.c qemu-load.c sadump.c ipcs.c \
> ramdump.c vmware_vmss.c vmware_guestdump.c \
> - xen_dom0.c kaslr_helper.c
> + xen_dom0.c kaslr_helper.c sbitmap.c
>
> SOURCE_FILES=${CFILES} ${GENERIC_HFILES} ${MCORE_HFILES} \
> ${REDHAT_CFILES} ${REDHAT_HFILES} ${UNWIND_HFILES} \
> @@ -92,7 +92,7 @@ OBJECT_FILES=main.o tools.o global_data.o memory.o filesys.o help.o task.o \
> xen_hyper.o xen_hyper_command.o xen_hyper_global_data.o \
> xen_hyper_dump_tables.o kvmdump.o qemu.o qemu-load.o sadump.o ipcs.o \
> ramdump.o vmware_vmss.o vmware_guestdump.o \
> - xen_dom0.o kaslr_helper.o
> + xen_dom0.o kaslr_helper.o sbitmap.o
>
> MEMORY_DRIVER_FILES=memory_driver/Makefile memory_driver/crash.c memory_driver/README
>
> @@ -346,6 +346,9 @@ cmdline.o: ${GENERIC_HFILES} cmdline.c
> tools.o: ${GENERIC_HFILES} tools.c
> ${CC} -c ${CRASH_CFLAGS} tools.c ${WARNING_OPTIONS} ${WARNING_ERROR}
>
> +sbitmap.o: ${GENERIC_HFILES} sbitmap.c
> + ${CC} -c ${CRASH_CFLAGS} sbitmap.c ${WARNING_OPTIONS} ${WARNING_ERROR}
> +
> global_data.o: ${GENERIC_HFILES} global_data.c
> ${CC} -c ${CRASH_CFLAGS} global_data.c ${WARNING_OPTIONS} ${WARNING_ERROR}
>
> diff --git a/defs.h b/defs.h
> index eb1c71b..1fa5c21 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -4956,6 +4956,7 @@ void cmd_mach(void); /* main.c */
> void cmd_help(void); /* help.c */
> void cmd_test(void); /* test.c */
> void cmd_ascii(void); /* tools.c */
> +void cmd_sbitmap(void); /* sbitmap.c */
> void cmd_bpf(void); /* bfp.c */
> void cmd_set(void); /* tools.c */
> void cmd_eval(void); /* tools.c */
> @@ -5543,6 +5544,7 @@ void display_help_screen(char *);
> extern char *help_pointer[];
> extern char *help_alias[];
> extern char *help_ascii[];
> +extern char *help_sbitmap[];
> extern char *help_bpf[];
> extern char *help_bt[];
> extern char *help_btop[];
> diff --git a/global_data.c b/global_data.c
> index a316d1c..55524e3 100644
> --- a/global_data.c
> +++ b/global_data.c
> @@ -105,6 +105,7 @@ struct command_table_entry linux_command_table[] = {
> {"rd", cmd_rd, help_rd, MINIMAL},
> {"repeat", cmd_repeat, help_repeat, 0},
> {"runq", cmd_runq, help_runq, REFRESH_TASK_TABLE},
> + {"sbitmap", cmd_sbitmap, help_sbitmap, 0},
> {"search", cmd_search, help_search, 0},
> {"set", cmd_set, help_set, REFRESH_TASK_TABLE | MINIMAL},
> {"sig", cmd_sig, help_sig, REFRESH_TASK_TABLE},
> diff --git a/help.c b/help.c
> index 6c262a3..b946745 100644
> --- a/help.c
> +++ b/help.c
> @@ -967,6 +967,95 @@ char *help_ascii[] = {
> NULL
> };
>
> +char *help_sbitmap[] = {
> +"sbitmap",
> +"sbitmap_queue struct contents",
> +"[-s struct[.member[,member]] -p address [-v]] address",
> +" This command dumps the contents of the sbitmap_queue structure and",
> +" the used bits in the bitmap. Also, it shows the dump of a structure",
> +" array associated with the sbitmap_queue.",
> +"",
> +" The arguments are as follows:",
> +"",
> +" -s struct - name of a C-code structure, that is stored in an array",
> +" sssociated with sbitmap_queue structure. Use the",
> +" \"struct.member\" format in order to display a particular",
> +" member of the structure. -s option requires -p option",
> +"",
> +" -p address - address of a structure array associated with sbitmap_queue",
> +" structure. The set bits in sbitmap are used for the index",
> +" in an associated array.",
> +"",
> +" -x - override default output format with hexadecimal format.",
> +"",
> +" -d - override default output format with decimal format.",
> +"",
> +" -v - By default, the sbitmap command shows only a used sbitmap",
> +" index and a structure address in the associated array.",
> +" This flag says to print of a formatted display of the",
> +" contents of a structure in an associated array. -v option",
> +" requires of -s.",
> +"",
> +"EXAMPLES",
> +"",
> +" Display the common sbitmap information:",
> +"",
> +" %s> sbitmap ffffffffc06b9420",
> +" depth = 256",
> +" busy = 15",
> +" cleared = 1",
> +" bits_per_word = 64",
> +" map_nr = 4",
> +" alloc_hint = {193, 78}",
> +" wake_batch = 8",
> +" wake_index = 0",
> +" ws_active = 0",
> +" ws = {",
> +" { .wait_cnt = 8, .wait = inactive },",
> +" { .wait_cnt = 8, .wait = inactive },",
> +" { .wait_cnt = 8, .wait = inactive },",
> +" { .wait_cnt = 8, .wait = inactive },",
> +" { .wait_cnt = 8, .wait = inactive },",
> +" { .wait_cnt = 8, .wait = inactive },",
> +" { .wait_cnt = 8, .wait = inactive },",
> +" { .wait_cnt = 8, .wait = inactive },",
> +" }",
> +" round_robin = 0",
> +" min_shallow_depth = 4294967295",
> +"",
> +" 00000000: 0000 0000 0000 0000 ffbf 0000 0000 0000",
> +" 00000010: 0000 0000 0000 0000 0000 0000 0000 0000",
> +"",
> +" Display the structure address is associated with sbitmap_queue:",
> +"",
> +" %s> sbitmap -s test_data -p ffff973422dac000 ffffffffc06b9420",
> +" 64: 0xffff973422dac200",
> +" 65: 0xffff973422dac208",
> +" 66: 0xffff973422dac210",
> +" ...",
> +"",
> +" Display a formatted content of a structures:",
> +"",
> +" %s> sbitmap -s test_data -p ffff973422dac000 -v ffffffffc06b9420",
> +" 64 (0xffff973422dac200):",
> +" struct test_data {",
> +" tag = 64,",
> +" cpu = 1",
> +" }",
> +" 65 (0xffff973422dac208):",
> +" struct test_data {",
> +" tag = 65,",
> +" cpu = 1",
> +" }",
> +" 66 (0xffff973422dac210):",
> +" struct test_data {",
> +" tag = 66,",
> +" cpu = 1",
> +" }",
> +" ...",
> +NULL
> +};
> +
> char *help_quit[] = {
> "quit",
> "exit this session",
> diff --git a/sbitmap.c b/sbitmap.c
> new file mode 100644
> index 0000000..71522f8
> --- /dev/null
> +++ b/sbitmap.c
> @@ -0,0 +1,591 @@
> +/* sbitmap.c - core analysis suite
> + *
> + * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
> + * Copyright (C) 2002-2020 David Anderson
> + * Copyright (C) 2002-2020 Red Hat, Inc. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include "defs.h"
> +#include <stdbool.h>
> +
> +#define SBQ_WAIT_QUEUES 8
> +
> +static inline unsigned int __const_hweight8(unsigned long w)
> +{
> + return
> + (!!((w) & (1ULL << 0))) +
> + (!!((w) & (1ULL << 1))) +
> + (!!((w) & (1ULL << 2))) +
> + (!!((w) & (1ULL << 3))) +
> + (!!((w) & (1ULL << 4))) +
> + (!!((w) & (1ULL << 5))) +
> + (!!((w) & (1ULL << 6))) +
> + (!!((w) & (1ULL << 7)));
> +}
> +
> +#define __const_hweight16(w) (__const_hweight8(w) + __const_hweight8((w) >> 8))
> +#define __const_hweight32(w) (__const_hweight16(w) + __const_hweight16((w) >> 16))
> +#define __const_hweight64(w) (__const_hweight32(w) + __const_hweight32((w) >> 32))
> +
> +#define hweight32(w) __const_hweight32(w)
> +#define hweight64(w) __const_hweight64(w)
> +
> +#define BIT(nr) (1UL << (nr))
> +
> +/* sbitmap and sbitmap_word structs context */
> +struct sbitmap_context {
> + unsigned sb_depth;
> + unsigned sb_shift;
> + unsigned sb_map_nr;
> + ulong sb_map_addr;
> + unsigned sb_map_size;
> +
> + int w_depth_off;
> + int w_word_off;
> + int w_cleared_off;
> +};
> +
> +/* sbitmap_queue struct context */
> +struct sbitmap_queue_context {
> + ulong sb_addr;
> + ulong alloc_hint;
> + unsigned int wake_batch;
> + int wake_index;
> + ulong ws_addr;
> + int ws_active;
> + bool round_robin;
> + unsigned int min_shallow_depth;
> +
> +};
> +
> +struct sbitmap_data {
> +#define SD_FLAG_STRUCT_NAME (VERBOSE << 1)
> +#define SD_FLAG_STRUCT_ADDR (VERBOSE << 2)
> +#define SD_FLAG_STRUCT_MEMBER (VERBOSE << 3)
> + ulong flags;
> + int radix;
> + /* sbitmap_queue info */
> + ulong addr;
> + /* data array info */
> + char *data_name;
> + ulong data_addr;
> +
> + struct sbitmap_queue_context sqc;
> + struct sbitmap_context sc;
> +};
> +
> +static inline unsigned long min(unsigned long a, unsigned long b)
> +{
> + return (a < b) ? a : b;
> +}
> +
> +static void __readmem(ulong addr, void *buffer, size_t size)
> +{
> + ulong flag = FAULT_ON_ERROR;
> +
> + if (!readmem(addr, KVADDR, buffer, size, "__readmem", flag))
> + error(FATAL, "failed read memory: 0x%x\n", addr);
> +}
> +
> +static ulong __read_ulong(ulong addr)
> +{
> + ulong value;
> +
> + __readmem(addr, &value, sizeof(value));
> + return value;
> +}
> +
> +static long __struct_size(char *name)
> +{
> + long size;
> +
> + size = STRUCT_SIZE(name);
> + if (size < 0)
> + error(FATAL, "Invalid struct size: %s\n", name);
> +
> + return size;
> +}
> +
> +static long __member_offset(char *name, char *member)
> +{
> + long offset;
> +
> + offset = MEMBER_OFFSET(name, member);
> + if (offset == INVALID_OFFSET)
> + offset = ANON_MEMBER_OFFSET(name, member);
> + if (offset == INVALID_OFFSET)
> + error(FATAL, "Can't get offset of '%s.%s'\n", name, member);
> +
> + return offset;
> +}
> +
> +static unsigned long __last_word_mask(unsigned long nbits)
> +{
> + return ~0UL >> (-(nbits) & (BITS_PER_LONG - 1));
> +}
> +
> +static unsigned long bitmap_hweight_long(unsigned long w)
> +{
> + return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
> +}
> +
> +static unsigned long bitmap_weight(unsigned long bitmap, unsigned int bits)
> +{
> + unsigned long w = 0;
> +
> + w += bitmap_hweight_long(bitmap);
> + if (bits % BITS_PER_LONG)
> + w += bitmap_hweight_long(bitmap & __last_word_mask(bits));
> +
> + return w;
> +}
> +
> +static unsigned int __sbitmap_weight(const struct sbitmap_context *sc, bool set)
> +{
> + unsigned int weight = 0;
> + ulong addr = sc->sb_map_addr;
> + unsigned long depth, word, cleared;
> + int i;
> +
> + for (i = 0; i < sc->sb_map_nr; i++) {
> + depth = __read_ulong(addr + sc->w_depth_off);
> +
> + if (set) {
> + word = __read_ulong(addr + sc->w_word_off);
> + weight += bitmap_weight(word, depth);
> + } else {
> + cleared = __read_ulong(addr + sc->w_cleared_off);
> + weight += bitmap_weight(cleared, depth);
> + }
> +
> + addr += sc->sb_map_size;
> + }
> +
> + return weight;
> +}
> +
> +static unsigned int sbitmap_weight(const struct sbitmap_context *sc)
> +{
> + return __sbitmap_weight(sc, true);
> +}
> +
> +static unsigned int sbitmap_cleared(const struct sbitmap_context *sc)
> +{
> + return __sbitmap_weight(sc, false);
> +}
> +
> +static void sbitmap_queue_show(const struct sbitmap_queue_context *sqc,
> + const struct sbitmap_context *sc)
> +{
> + int cpus = get_cpus_possible();
> + int sbq_wait_state_size, wait_cnt_off, wait_off, list_head_off;
> + bool first;
> + int i;
> +
> + fprintf(fp, "depth = %u\n", sc->sb_depth);
> + fprintf(fp, "busy = %u\n", sbitmap_weight(sc) - sbitmap_cleared(sc));
> + fprintf(fp, "cleared = %u\n", sbitmap_cleared(sc));
> + fprintf(fp, "bits_per_word = %u\n", 1U << sc->sb_shift);
> + fprintf(fp, "map_nr = %u\n", sc->sb_map_nr);
> +
> + fputs("alloc_hint = {", fp);
> + first = true;
> + for (i = 0; i < cpus; i++) {
> + if (!first)
> + fprintf(fp, ", ");
> + first = false;
> +
> + ulong ptr = kt->__per_cpu_offset[i] + sqc->alloc_hint;
> + fprintf(fp, "%lu", __read_ulong(ptr));
> + }
> + fputs("}\n", fp);
> +
> + fprintf(fp, "wake_batch = %u\n", sqc->wake_batch);
> + fprintf(fp, "wake_index = %d\n", sqc->wake_index);
> + fprintf(fp, "ws_active = %d\n", sqc->ws_active);
> +
> + sbq_wait_state_size = __struct_size("sbq_wait_state");
> + wait_cnt_off = __member_offset("sbq_wait_state", "wait_cnt");
> + wait_off = __member_offset("sbq_wait_state", "wait");
> + list_head_off = __member_offset("wait_queue_head", "head");
> +
> + fputs("ws = {\n", fp);
> + for (i = 0; i < SBQ_WAIT_QUEUES; i++) {
> + ulong ws_addr = sqc->ws_addr + (sbq_wait_state_size * i);
> + struct kernel_list_head lh;
> + ulong wait_cnt_addr, list_head_addr;
> + ulong wait_cnt;
> +
> + wait_cnt_addr = ws_addr + wait_cnt_off;
> + __readmem(wait_cnt_addr, &wait_cnt, sizeof(wait_cnt));
> +
> + list_head_addr = ws_addr + wait_off + list_head_off;
> + __readmem(list_head_addr, &lh, sizeof(lh));
> +
> + fprintf(fp, "\t{ .wait_cnt = %lu, .wait = %s },\n",
> + wait_cnt, (lh.next == lh.prev) ? "inactive" : "active");
> + }
> + fputs("}\n", fp);
> +
> + fprintf(fp, "round_robin = %d\n", sqc->round_robin);
> + fprintf(fp, "min_shallow_depth = %u\n", sqc->min_shallow_depth);
> +}
> +
> +static void sbitmap_emit_byte(unsigned int offset, uint8_t byte)
> +{
> + if ((offset &0xf) == 0) {
> + if (offset != 0)
> + fputc('\n', fp);
> + fprintf(fp, "%08x:", offset);
> + }
> + if ((offset & 0x1) == 0)
> + fputc(' ', fp);
> + fprintf(fp, "%02x", byte);
> +}
> +
> +static void sbitmap_bitmap_show(const struct sbitmap_context *sc)
> +{
> + uint8_t byte = 0;
> + unsigned int byte_bits = 0;
> + unsigned int offset = 0;
> + int i;
> +
> + for (i = 0; i < sc->sb_map_nr; i++) {
> + ulong addr = sc->sb_map_addr + (sc->sb_map_size * i);
> + unsigned long word = __read_ulong(addr + sc->w_word_off);
> + unsigned long cleared = __read_ulong(addr + sc->w_cleared_off);
> + unsigned long word_bits = __read_ulong(addr + sc->w_depth_off);
> +
> + word &= ~cleared;
> +
> + while (word_bits > 0) {
> + unsigned int bits = min(8 - byte_bits, word_bits);
> +
> + byte |= (word & (BIT(bits) - 1)) << byte_bits;
> + byte_bits += bits;
> + if (byte_bits == 8) {
> + sbitmap_emit_byte(offset, byte);
> + byte = 0;
> + byte_bits = 0;
> + offset++;
> + }
> + word >>= bits;
> + word_bits -= bits;
> + }
> +
> + }
> + if (byte_bits) {
> + sbitmap_emit_byte(offset, byte);
> + offset++;
> + }
> + if (offset)
> + fputc('\n', fp);
> +}
> +
> +static void sbitmap_queue_dump(const struct sbitmap_data *sd)
> +{
> + sbitmap_queue_show(&sd->sqc, &sd->sc);
> + fputc('\n', fp);
> + sbitmap_bitmap_show(&sd->sc);
> +}
> +
> +static unsigned long sbitmap_find_next_bit(unsigned long word,
> + unsigned long size, unsigned long offset)
> +{
> + if (size > BITS_PER_LONG)
> + error(FATAL, "%s: word size isn't correct\n", __func__);
> +
> + for (; offset < size; offset++)
> + if (word & (1UL << offset))
> + return offset;
> +
> + return size;
> +}
> +
> +typedef bool (*sb_for_each_fn)(unsigned int, void *);
> +
> +static void __sbitmap_for_each_set(const struct sbitmap_context *sc,
> + unsigned int start, sb_for_each_fn fn, void *data)
> +{
> + unsigned int index;
> + unsigned int nr;
> + unsigned int scanned = 0;
> +
> + if (start >= sc->sb_map_nr)
> + start = 0;
> +
> + index = start >> sc->sb_shift;
> + nr = start & ((1U << sc->sb_shift) - 1U);
> +
> + while (scanned < sc->sb_depth) {
> + unsigned long w_addr = sc->sb_map_addr + (sc->sb_map_size * index);
> +
> + unsigned long w_depth = __read_ulong(w_addr + sc->w_depth_off);
> + unsigned long w_word = __read_ulong(w_addr + sc->w_word_off);
> + unsigned long w_cleared = __read_ulong(w_addr + sc->w_cleared_off);
> +
> + unsigned long word;
> + unsigned int depth = min(w_depth - nr, sc->sb_depth - scanned);
> +
> + scanned += depth;
> + word = w_word & ~w_cleared;
> + if (!word)
> + goto next;
> +
> + /*
> + * On the first iteration of the outer loop, we need to add the
> + * bit offset back to the size of the word for find_next_bit().
> + * On all other iterations, nr is zero, so this is a noop.
> + */
> + depth += nr;
> + while (1) {
> + nr = sbitmap_find_next_bit(word, depth, nr);
> + if (nr >= depth)
> + break;
> + if (!fn((index << sc->sb_shift) + nr, data))
> + return;
> +
> + nr++;
> + }
> +next:
> + nr = 0;
> + if (++index >= sc->sb_map_nr)
> + index = 0;
> + }
> +}
> +
> +static void sbitmap_for_each_set(const struct sbitmap_context *sc,
> + sb_for_each_fn fn, void *data)
> +{
> + __sbitmap_for_each_set(sc, 0, fn, data);
> +}
> +
> +static void sbitmap_dump_struct_members(const char *s, ulong addr, unsigned radix)
> +{
> + int i, argc;
> + char *p1, *p2;
> + char *structname, *members;
> + char *arglist[MAXARGS];
> +
> + structname = GETBUF(strlen(s) + 1);
> + members = GETBUF(strlen(s) + 1);
> +
> + strcpy(structname, s);
> + p1 = strstr(structname, ".") + 1;
> +
> + p2 = strstr(s, ".") + 1;
> + strcpy(members, p2);
> + replace_string(members, ",", ' ');
> + argc = parse_line(members, arglist);
> +
> + for (i = 0; i < argc; i++) {
> + *p1 = NULLCHAR;
> + strcat(structname, arglist[i]);
> + dump_struct_member(structname, addr, radix);
> + }
> +
> + FREEBUF(structname);
> + FREEBUF(members);
> +}
> +
> +struct data_info {
> + ulong addr;
> + int size;
> + char *name;
> + unsigned radix;
> + bool verbose;
> + bool members;
> +};
> +
> +static bool sbitmap_data_print(unsigned int idx, void *data)
> +{
> + const struct data_info *d = data;
> + ulong addr = d->addr + (d->size * idx);
> +
> + if (d->verbose) {
> + fprintf(fp, "%d (0x%08lx):\n", idx, addr);
> + if (d->members)
> + sbitmap_dump_struct_members(d->name, addr, d->radix);
> + else
> + dump_struct(d->name, addr, d->radix);
> + } else
> + fprintf(fp, "%d: 0x%08lx\n", idx, addr);
> +
> + return true;
> +}
> +
> +static char *__get_struct_name(const char *s)
> +{
> + char *name, *p;
> +
> + name = GETBUF(strlen(s) + 1);
> + strcpy(name, s);
> +
> + p = strstr(name, ".");
> + *p = NULLCHAR;
> +
> + return name;
> +}
> +
> +static void sbitmap_data_dump(const struct sbitmap_data *sd)
> +{
> + struct data_info d = {0};
> +
> + d.addr = sd->data_addr;
> + d.name = sd->data_name;
> + d.radix = sd->radix;
> + d.verbose = !!(sd->flags & VERBOSE);
> + d.members = !!(sd->flags & SD_FLAG_STRUCT_MEMBER);
> +
> + if (d.members) {
> + char *name = __get_struct_name(d.name);
> + d.size = __struct_size(name);
> + FREEBUF(name);
> + } else
> + d.size = __struct_size(d.name);
> +
> + sbitmap_for_each_set(&sd->sc, sbitmap_data_print, &d);
> +}
> +
> +static void load_sbitmap_queue_context(ulong addr, struct sbitmap_queue_context *sqc)
> +{
> + char *sb_q = "sbitmap_queue";
> +
> + sqc->sb_addr = addr + __member_offset(sb_q, "sb");
> + __readmem(addr + __member_offset(sb_q, "alloc_hint"), &sqc->alloc_hint, sizeof(sqc->alloc_hint));
> + __readmem(addr + __member_offset(sb_q, "wake_batch"), &sqc->wake_batch, sizeof(sqc->wake_batch));
> + __readmem(addr + __member_offset(sb_q, "wake_index"), &sqc->wake_index, sizeof(sqc->wake_index));
> + __readmem(addr + __member_offset(sb_q, "ws"), &sqc->ws_addr, sizeof(sqc->ws_addr));
> + __readmem(addr + __member_offset(sb_q, "ws_active"), &sqc->ws_active, sizeof(sqc->ws_active));
> + __readmem(addr + __member_offset(sb_q, "round_robin"), &sqc->round_robin, sizeof(sqc->round_robin));
> + __readmem(addr + __member_offset(sb_q, "min_shallow_depth"), &sqc->min_shallow_depth, sizeof(sqc->min_shallow_depth));
> +}
> +
> +static void load_sbitmap_context(ulong addr, struct sbitmap_context *sc)
> +{
> + char *sb = "sbitmap";
> + char *map = "sbitmap_word";
> +
> + __readmem(addr + __member_offset(sb, "depth"), &sc->sb_depth, sizeof(sc->sb_depth));
> + __readmem(addr + __member_offset(sb, "shift"), &sc->sb_shift, sizeof(sc->sb_shift));
> + __readmem(addr + __member_offset(sb, "map_nr"), &sc->sb_map_nr, sizeof(sc->sb_map_nr));
> + __readmem(addr + __member_offset(sb, "map"), &sc->sb_map_addr, sizeof(sc->sb_map_addr));
> + sc->sb_map_size = __struct_size(map);
> + sc->w_depth_off = __member_offset(map, "depth");
> + sc->w_word_off = __member_offset(map, "word");
> + sc->w_cleared_off = __member_offset(map, "cleared");
> +}
> +
> +void cmd_sbitmap(void)
> +{
> + struct sbitmap_data sd = {0};
> + int c;
> +
> + while ((c = getopt(argcnt, args, "s:p:xdv")) != EOF) {
> + switch (c) {
> + case 's':
> + if (sd.flags & SD_FLAG_STRUCT_NAME)
> + error(FATAL, "-s option (%s) already entered\n", sd.data_name);
> +
> + sd.data_name = optarg;
> + sd.flags |= SD_FLAG_STRUCT_NAME;
> +
> + break;
> +
> + case 'p':
> + if (sd.flags & SD_FLAG_STRUCT_ADDR)
> + error(FATAL, "-m option (0x%lx) already entered\n", sd.data_addr);
> + else if (!IS_A_NUMBER(optarg))
> + error(FATAL, "invalid -m option: %s\n", optarg);
> +
> + sd.data_addr = htol(optarg, FAULT_ON_ERROR, NULL);
> + if (!IS_KVADDR(sd.data_addr))
> + error(FATAL, "invalid kernel virtual address: %s\n", optarg);
> + sd.flags |= SD_FLAG_STRUCT_ADDR;
> +
> + break;
> +
> + case 'v':
> + sd.flags |= VERBOSE;
> + break;
> +
> + case 'x':
> + if (sd.radix == 10)
> + error(FATAL, "-d and -x are mutually exclusive\n");
> + sd.radix = 16;
> + break;
> +
> + case 'd':
> + if (sd.radix == 16)
> + error(FATAL, "-d and -x are mutually exclusive\n");
> + sd.radix = 10;
> + break;
> +
> + default:
> + argerrs++;
> + break;
> + }
> + }
> +
> + if (argerrs)
> + cmd_usage(pc->curcmd, SYNOPSIS);
> +
> + if (!args[optind]) {
> + error(INFO, "command argument is required\n");
> + cmd_usage(pc->curcmd, SYNOPSIS);
> + } else if (args[optind] && args[optind + 1]) {
> + error(INFO, "too many arguments\n");
> + cmd_usage(pc->curcmd, SYNOPSIS);
> + } else if (!IS_A_NUMBER(args[optind])) {
> + error(FATAL, "invalid command argument: %s\n", args[optind]);
> + }
> +
> + sd.addr = htol(args[optind], FAULT_ON_ERROR, NULL);
> + if (!IS_KVADDR(sd.addr))
> + error(FATAL, "invalid kernel virtual address: %s\n", args[optind]);
> +
> + if ((sd.flags & SD_FLAG_STRUCT_NAME) && !(sd.flags & SD_FLAG_STRUCT_ADDR)) {
> + error(INFO, "-s option requires -m option");
> + cmd_usage(pc->curcmd, SYNOPSIS);
> + } else if ((sd.flags & SD_FLAG_STRUCT_ADDR) && !(sd.flags & SD_FLAG_STRUCT_NAME)) {
> + error(FATAL, "-m option is used with -s option only\n");
> + cmd_usage(pc->curcmd, SYNOPSIS);
> + }
> +
> + if (sd.flags & SD_FLAG_STRUCT_NAME) {
> + bool error_flag = false;
> +
> + if (count_chars(sd.data_name, '.') > 0)
> + sd.flags |= SD_FLAG_STRUCT_MEMBER;
> +
> + if (sd.flags & SD_FLAG_STRUCT_MEMBER) {
> + char *data_name = __get_struct_name(sd.data_name);
> + if (!STRUCT_EXISTS(data_name))
> + error_flag = true;
> + FREEBUF(data_name);
> + } else {
> + if (!STRUCT_EXISTS(sd.data_name))
> + error_flag = true;
> + }
> + if (error_flag)
> + error(FATAL, "invalid data structure reference: %s\n", sd.data_name);
> + }
> +
> + load_sbitmap_queue_context(sd.addr, &sd.sqc);
> + load_sbitmap_context(sd.sqc.sb_addr, &sd.sc);
> +
> + if (sd.flags & SD_FLAG_STRUCT_NAME)
> + sbitmap_data_dump(&sd);
> + else
> + sbitmap_queue_dump(&sd);
> +}
> --
> 2.25.1
3 years, 1 month
[PATCH v6 0/7] Improve kernel modules symbol searching performance
by Tao Liu
Currently the sequence for symbol_search to search a symbol is: 1) kernel
symname hash table, 2) iterate all kernel symbols, 3) iterate all kernel
modules and their symbols. In the worst case, if a non-exist symbol been
searched, all 3 stages will be went through. The time consuming status for
each stage is like:
stage 1 stage 2 stage 3
0.007000(ms) 0.593000(ms) 2.421000(ms)
stage 3 takes too much time when comparing to stage 1. This patch introduces
a symname hash table for kernel modules, to improve the performance of symbol
searching.
Functions symbol_search and symbol_exists are fundamental and widely used by
other crash functions, thus the benefit of performance improvement can
get accumulated. For example, "ps -m" and "irq" commands, which call
the functions many times, will become faster with the patch.
v5 -> v6:
1) Add mod_symname_hash table dump to help -s
2) Modified mod_symname_hash install/remove based on Kazu's suggestion.
Tao Liu (7):
Implement install and remove operations for mod_symname_hash
Integrate symbol_search with mod_symname_hash search
Extend symname_hash_search with hash table select
Intergrate symbol_exists with mod_symname_hash search
Sync module symbols into mod_symtable whenever module symbols change
Refactor SYMNAME_HASH_INDEX macro to be a function
Add mod_symname_hash table dump to help -s
defs.h | 3 +-
kernel.c | 1 +
symbols.c | 261 +++++++++++++++++++++++++++++++++---------------------
3 files changed, 164 insertions(+), 101 deletions(-)
--
2.29.2
3 years, 1 month
eppic extension doesn't build with recent master
by Alexander Egorenkov
Hello,
i'm trying to build the recent master branch of the crash utility and
not able to build eppic extension.
The build failure on x86_64 Fedora 34
-------------------------------------
$ make lzo
[snip]
$ make extensions
gcc -Wall -g -shared -rdynamic -o dminfo.so dminfo.c -fPIC -DX86_64 -DLZO -DGDB_10_2
gcc -Wall -g -shared -rdynamic -o echo.so echo.c -fPIC -DX86_64 -DLZO -DGDB_10_2
Cloning into 'eppic'...
remote: Enumerating objects: 268, done.
remote: Counting objects: 100% (51/51), done.
remote: Compressing objects: 100% (44/44), done.
remote: Total 268 (delta 4), reused 31 (delta 4), pack-reused 217
Receiving objects: 100% (268/268), 256.48 KiB | 2.49 MiB/s, done.
Resolving deltas: 100% (93/93), done.
cd eppic/libeppic && make
bison -peppic -v -t -d eppic.y
eppic.y: warning: 253 shift/reduce conflicts [-Wconflicts-sr]
eppic.y: warning: 20 reduce/reduce conflicts [-Wconflicts-rr]
eppic.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
cc -g -fno-omit-frame-pointer -fPIC -c -o eppic_util.o eppic_util.c
cc -g -fno-omit-frame-pointer -fPIC -c -o eppic_node.o eppic_node.c
cc -g -fno-omit-frame-pointer -fPIC -c -o eppic_var.o eppic_var.c
cc -g -fno-omit-frame-pointer -fPIC -c -o eppic_func.o eppic_func.c
cc -g -fno-omit-frame-pointer -fPIC -c -o eppic_str.o eppic_str.c
cc -g -fno-omit-frame-pointer -fPIC -c -o eppic_op.o eppic_op.c
cc -g -fno-omit-frame-pointer -fPIC -c -o eppic_num.o eppic_num.c
cc -g -fno-omit-frame-pointer -fPIC -c -o eppic_stat.o eppic_stat.c
cc -g -fno-omit-frame-pointer -fPIC -c -o eppic_builtin.o eppic_builtin.c
cc -g -fno-omit-frame-pointer -fPIC -c -o eppic_type.o eppic_type.c
cc -g -fno-omit-frame-pointer -fPIC -c -o eppic_case.o eppic_case.c
cc -g -fno-omit-frame-pointer -fPIC -c -o eppic_api.o eppic_api.c
cc -g -fno-omit-frame-pointer -fPIC -c -o eppic_member.o eppic_member.c
cc -g -fno-omit-frame-pointer -fPIC -c -o eppic_alloc.o eppic_alloc.c
cc -g -fno-omit-frame-pointer -fPIC -c -o eppic_define.o eppic_define.c
cc -g -fno-omit-frame-pointer -fPIC -c -o eppic_input.o eppic_input.c
cc -g -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
cc -g -fno-omit-frame-pointer -fPIC -c eppicpp.tab.c
cc -g -fno-omit-frame-pointer -fPIC -c eppic.tab.c
flex -L -Peppic -t eppic.l > lex.eppic.c
cc -g -fno-omit-frame-pointer -fPIC -c lex.eppic.c
flex -Peppicpp -t eppicpp.l > lex.eppicpp.c
cc -g -fno-omit-frame-pointer -fPIC -c lex.eppicpp.c
cc -g -fno-omit-frame-pointer -fPIC -o mkbaseop mkbaseop.c
./mkbaseop > baseops.c
cc -g -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
gcc -g -Ieppic/libeppic -I../gdb-10.2/gdb -I../gdb-10.2/bfd -I../gdb-10.2/include -I../gdb-10.2/gdb/config -I../gdb-10.2/gdb/common -I../gdb-10.2 -nostartfiles -shared -rdynamic -o eppic.so eppic/applications/crash/eppic.c -fPIC -DX86_64 -DGDB_10_2 -Leppic/libeppic -leppic
In file included from ../gdb-10.2/gdb/defs.h:28,
from eppic/applications/crash/eppic.c:22:
../gdb-10.2/gdbsupport/common-defs.h:90:10: fatal error: cstdlib: No such file or directory
90 | #include <cstdlib>
| ^~~~~~~~~
compilation terminated.
make[4]: [eppic.mk:67: eppic.so] Error 1 (ignored)
gcc -Wall -g -I. -shared -rdynamic -o snap.so snap.c -fPIC -DX86_64 -DLZO -DGDB_10_2
--------------------------------------------------------------------------------------------------------------
Exactly the same problem is occurring on s390 architecture.
I find it's very weird that a C library like eppic is including a C++
header from GDB.
gdb-10.2/gdbsupport/common-defs.h is a C++ header containing includes of
other C++ headers like cstdlib, array etc. Furthermore, it contains C++
templates !
Has anybody tested this ? Maybe i'm doing something wrong :/
Would appreciate any hint how to fix this. So far i haven't figured out
howto fix this and we depend on eppic extension.
Thanks
Regards
Alex
3 years, 1 month
[PATCH 1/1] Handle task_struct cpu member changes in linux-next
by Alexander Egorenkov
Kernel commit bcf9033e5449bdcaa9bed46467a7141a8049dadb
("sched: move CPU field back into thread_info if THREAD_INFO_IN_TASK=y")
moved the member cpu of task_struct back into thread_info.
https://lkml.org/lkml/2021/9/30/517
This fixes the following problem:
please wait... (gathering task table data)
crash: invalid structure member offset: task_struct_cpu
FILE: task.c LINE: 2904 FUNCTION: add_context()
[/usr/bin/crash] error trace: 114840a => 115560a => 114e360 => 11d6394
11d6394: (undetermined)
114e360: (undetermined)
115560a: (undetermined)
114840a: task_init+4634
Signed-off-by: Alexander Egorenkov <egorenar(a)linux.ibm.com>
---
task.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/task.c b/task.c
index 672b41697e75..bb6a5da8ad33 100644
--- a/task.c
+++ b/task.c
@@ -278,8 +278,10 @@ task_init(void)
} else if (VALID_MEMBER(task_struct_stack))
MEMBER_OFFSET_INIT(task_struct_thread_info, "task_struct", "stack");
+ MEMBER_OFFSET_INIT(task_struct_cpu, "task_struct", "cpu");
+
if (VALID_MEMBER(task_struct_thread_info)) {
- if (tt->flags & THREAD_INFO_IN_TASK) {
+ if (tt->flags & THREAD_INFO_IN_TASK && VALID_MEMBER(task_struct_cpu)) {
MEMBER_OFFSET_INIT(thread_info_flags, "thread_info", "flags");
/* (unnecessary) reminders */
ASSIGN_OFFSET(thread_info_task) = INVALID_OFFSET;
@@ -315,7 +317,6 @@ task_init(void)
MEMBER_OFFSET_INIT(task_struct_has_cpu, "task_struct", "has_cpu");
MEMBER_OFFSET_INIT(task_struct_cpus_runnable,
"task_struct", "cpus_runnable");
- MEMBER_OFFSET_INIT(task_struct_cpu, "task_struct", "cpu");
MEMBER_OFFSET_INIT(task_struct_active_mm, "task_struct", "active_mm");
MEMBER_OFFSET_INIT(task_struct_next_run, "task_struct", "next_run");
MEMBER_OFFSET_INIT(task_struct_flags, "task_struct", "flags");
@@ -2900,7 +2901,7 @@ add_context(ulong task, char *tp)
else
tc->thread_info = ULONG(tp + OFFSET(task_struct_thread_info));
fill_thread_info(tc->thread_info);
- if (tt->flags & THREAD_INFO_IN_TASK)
+ if (tt->flags & THREAD_INFO_IN_TASK && VALID_MEMBER(task_struct_cpu))
processor_addr = (int *) (tp + OFFSET(task_struct_cpu));
else
processor_addr = (int *) (tt->thread_info +
--
2.31.1
3 years, 1 month
[PATCH v5 0/6] Improve kernel modules symbol searching performance
by Tao Liu
Currently the sequence for symbol_search to search a symbol is: 1) kernel
symname hash table, 2) iterate all kernel symbols, 3) iterate all kernel
modules and their symbols. In the worst case, if a non-exist symbol been
searched, all 3 stages will be went through. The time consuming status for
each stage is like:
stage 1 stage 2 stage 3
0.007000(ms) 0.593000(ms) 2.421000(ms)
stage 3 takes too much time when comparing to stage 1. This patch introduces
a symname hash table for kernel modules, to improve the performance of symbol
searching.
Functions symbol_search and symbol_exists are fundamental and widely used by
other crash functions, thus the benefit of performance improvement can
get accumulated. For example, "ps -m" and "irq" commands, which call
the functions many times, will become faster with the patch.
v4 -> v5:
1) Seperated kernel modules syment install from kernel syment install,
making them 2 independent functions. Thus kernel modules syment can get sorted
when installed into mod_syment_hash. And spn->cnt stays untouched in v5.
2) Removed syment_is_installed check, it is no longer needed for the new
kernel modules syment install function.
3) Splitted the patches into smaller ones for better patch review.
4) Changed SYMNAME_HASH_INDEX macro into symname_hash_index function.
5) v5 patch can be applied to master branch, for crash-7-branch it needs
slightly modification.
Tao Liu (6):
Implement install and remove operations for mod_symname_hash
Integrate symbol_search with mod_symname_hash search
Extend symname_hash_search with hash table select
Intergrate symbol_exists with mod_symname_hash search
Sync module symbols into mod_symtable whenever module symbols change
Refactor SYMNAME_HASH_INDEX macro to be a function
defs.h | 3 +-
kernel.c | 1 +
symbols.c | 212 ++++++++++++++++++++++++++++++++++--------------------
3 files changed, 137 insertions(+), 79 deletions(-)
--
2.29.2
3 years, 1 month
Re: [Crash-utility] [PATCH v4 2/4] Get the absolute value of SYMNAME_HASH_INDEX
by lijiang
> > > Currently, the macro is used twice in the symbols.c. This change seems
> > > not complicated. Any thoughts?
> >
> > do I understand your suggestion correct, you propose to replace the
> >
> > #define SYMNAME_HASH_INDEX(name) ...
> >
> > in defs.h by something like
> >
> > static unsigned long long SYMNAME_HASH_INDEX(const unsigned char * const name) {
> > return (name[0] ^ (name[strlen(name)-1] * name[strlen(name)/2]) % SYMNAME_HASH);
> > }
> >
> > in symbols.c? If so, I think that should be fine.
> >
Yes, you are right, Philipp.
>
> Please correct me if I'm wrong. I don't think the function can work.
> Let's say name[0] ^ (name[strlen(name)-1] * name[strlen(name)/2]) ==
> -1, then we will have:
>
> static unsigned long long SYMNAME_HASH_INDEX(const unsigned char * const name) {
> return (-1) % 512;
> }
>
> The returned value is a very large number, and will overflow the array.
>
No, this is a modulo operation, and its result will never exceed '512' anyway.
(unsigned long long)(-1) % 512 = 511
Thanks.
Lianbo
3 years, 1 month