[PATCH] netdump: Add a helper function to check if registers is available for a given active task in ELF notes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add a helper function, exist_regs_in_elf_notes(tc), which checks
whether or not register values for a given active task is available in
ELF notes.

I intend to use the helper function in gcore extension module. vmcore
generated by diskdump has NT_PRSTATUS for a panic task only, and so
specifying get_regs_from_elf_notes() directly to non-panic active
tasks leads to a fatal action. So, it's necessary to check, in
advance, that an active task can get registers from ELF notes, but the
variable holding vmcore's data including ELF notes', nd, is defined as
a static global variable in netdump.c and thus the new helper function
needs to be introduced.

The change includes:

  1) Add and export exist_regs_in_elf_notes(), and
  2) Merge two kinds of fatal information printed in the case where no
  corresponding register values exist in ELF notes.

 defs.h    |    1 +
 netdump.c |  174 +++++++++++++++++++++++++++++--------------------------------
 2 files changed, 83 insertions(+), 92 deletions(-)

Signed-off-by: HATAYAMA Daisuke <d.hatayama@xxxxxxxxxxxxxx>
>From 82758e6e2614b7f2ded9b4ecb1573a6525719823 Mon Sep 17 00:00:00 2001
From: HATAYAMA Daisuke <d.hatayama@xxxxxxxxxxxxxx>
Date: Thu, 31 Mar 2011 23:40:28 +0900
Subject: [PATCH 4/4] Introduce and export exist_regs_in_elf_notes()

Unify checking presence of registers in ELF notes, introduce it as function
exist_regs_in_elf_notes() and export it.
---
 defs.h    |    1 +
 netdump.c |   14 +++++++++++---
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/defs.h b/defs.h
index d01ace7..0231707 100755
--- a/defs.h
+++ b/defs.h
@@ -4575,6 +4575,7 @@ ulong xen_phys_start(void);
 int xen_major_version(void);
 int xen_minor_version(void);
 int get_netdump_arch(void);
+int exist_regs_in_elf_notes(struct task_context *);
 void *get_regs_from_elf_notes(struct task_context *);
 void map_cpus_to_prstatus(void);
 int arm_kdump_phys_base(ulong *);
diff --git a/netdump.c b/netdump.c
index 1db003f..5deda1c 100644
--- a/netdump.c
+++ b/netdump.c
@@ -2780,6 +2780,16 @@ int get_netdump_arch(void)
 	return e_machine;
 }
 
+int exist_regs_in_elf_notes(struct task_context *tc)
+{
+	if ((tc->task == tt->panic_task) ||
+	    (is_task_active(tc->task) && (nd->num_prstatus_notes > 1) &&
+	     (tc->processor < nd->num_prstatus_notes)))
+		return TRUE;
+	else
+		return FALSE;
+}
+
 void * 
 get_regs_from_elf_notes(struct task_context *tc)
 {
@@ -2791,9 +2801,7 @@ get_regs_from_elf_notes(struct task_context *tc)
 		      "support for ELF machine type %d not available\n",
 		      e_machine);
 
-	if ((tc->task != tt->panic_task) &&
-	    (!is_task_active(tc->task) || (nd->num_prstatus_notes <= 1) ||
-	     (tc->processor >= nd->num_prstatus_notes)))
+	if (!exist_regs_in_elf_notes(tc))
 		error(FATAL, "cannot determine register set "
 		      "for %s task: %lx comm: \"%s\"\n",
 		      (tc->task == tt->panic_task) ? "panic" : "active",
-- 
1.7.4

>From 7e56a546f8a4f7230589edc6ad55ecad98eb84db Mon Sep 17 00:00:00 2001
From: HATAYAMA Daisuke <d.hatayama@xxxxxxxxxxxxxx>
Date: Thu, 31 Mar 2011 23:31:56 +0900
Subject: [PATCH 3/4] Unify error check conditions and information printed

Condition becomes strict on architectures except for PPC64 by further checking
if there's a prstatus for a corresponding processor number. Information printed
changes by merging two kinds of messages

    test: cannot determine register set for task "bash"

and

    test: cannot determine NT_PRSTATUS ELF note for panic task: ffff8800212e4080

into

    test: cannot determine register set for panic task: ffff8800212e4080 comm: "bash"

so information contained in the message is not changed.
---
 netdump.c |   16 ++++++----------
 1 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/netdump.c b/netdump.c
index 12930d2..1db003f 100644
--- a/netdump.c
+++ b/netdump.c
@@ -2792,16 +2792,12 @@ get_regs_from_elf_notes(struct task_context *tc)
 		      e_machine);
 
 	if ((tc->task != tt->panic_task) &&
-	    (!is_task_active(tc->task) || (nd->num_prstatus_notes <= 1)))
-		error(FATAL,
-		      "cannot determine register set for task \"%s\"\n",
-		      tc->comm);
-
-	if (e_machine == EM_PPC64 && nd->num_prstatus_notes > 1 &&
-	    tc->processor >= nd->num_prstatus_notes)
-		error(FATAL, "cannot determine NT_PRSTATUS ELF note "
-		      "for %s task: %lx\n", (tc->task == tt->panic_task) ?
-		      "panic" : "active", tc->task);
+	    (!is_task_active(tc->task) || (nd->num_prstatus_notes <= 1) ||
+	     (tc->processor >= nd->num_prstatus_notes)))
+		error(FATAL, "cannot determine register set "
+		      "for %s task: %lx comm: \"%s\"\n",
+		      (tc->task == tt->panic_task) ? "panic" : "active",
+		      tc->task, tc->comm);
 
 	switch(e_machine)
 	{
-- 
1.7.4

>From 9db497b4b5bbdb90f9980fc5364e8f3e4c63cffc Mon Sep 17 00:00:00 2001
From: HATAYAMA Daisuke <d.hatayama@xxxxxxxxxxxxxx>
Date: Thu, 31 Mar 2011 23:10:28 +0900
Subject: [PATCH 2/4] Move all common error processings in get_arch_regs_from_elf_notes()

Move all common error processings in get_arch_regs_from_elf_notes() to unify
them. This change keeps unique error processing on PPC64 and so doesn't bring
about any logical change.
---
 netdump.c |  157 +++++++++++++++++++++++++++----------------------------------
 1 files changed, 70 insertions(+), 87 deletions(-)

diff --git a/netdump.c b/netdump.c
index 8b64e7c..12930d2 100644
--- a/netdump.c
+++ b/netdump.c
@@ -2791,6 +2791,18 @@ get_regs_from_elf_notes(struct task_context *tc)
 		      "support for ELF machine type %d not available\n",
 		      e_machine);
 
+	if ((tc->task != tt->panic_task) &&
+	    (!is_task_active(tc->task) || (nd->num_prstatus_notes <= 1)))
+		error(FATAL,
+		      "cannot determine register set for task \"%s\"\n",
+		      tc->comm);
+
+	if (e_machine == EM_PPC64 && nd->num_prstatus_notes > 1 &&
+	    tc->processor >= nd->num_prstatus_notes)
+		error(FATAL, "cannot determine NT_PRSTATUS ELF note "
+		      "for %s task: %lx\n", (tc->task == tt->panic_task) ?
+		      "panic" : "active", tc->task);
+
 	switch(e_machine)
 	{
 	case EM_386:
@@ -2818,31 +2830,25 @@ get_x86_regs_from_elf_notes(struct task_context *tc)
 	len = 0;
 	pt_regs = NULL;
 
-	if ((tc->task == tt->panic_task) || 
-	    (is_task_active(tc->task) && (nd->num_prstatus_notes > 1))) {
-		if (nd->num_prstatus_notes > 1)
-			note = (void *)
-				nd->nt_prstatus_percpu[tc->processor];
-		else
-			note = (void *)nd->nt_prstatus;
-		if (nd->elf32) {
-			note_32 = (Elf32_Nhdr *)note;
-			len = sizeof(Elf32_Nhdr);
-			len = roundup(len + note_32->n_namesz, 4);
-		} else if (nd->elf64) {
-			note_64 = (Elf64_Nhdr *)note;
-			len = sizeof(Elf64_Nhdr);
-			len = roundup(len + note_64->n_namesz, 4);
-		}
-		
-		pt_regs = (void *)((char *)note + len + 
-			MEMBER_OFFSET("elf_prstatus", "pr_reg"));
-		/* NEED TO BE FIXED: Hack to get the proper alignment */
-		pt_regs +=4;
-	} else
-		error(FATAL, 
-		    "cannot determine register set for task \"%s\"\n",
-			tc->comm);
+	if (nd->num_prstatus_notes > 1)
+		note = (void *)nd->nt_prstatus_percpu[tc->processor];
+	else
+		note = (void *)nd->nt_prstatus;
+	if (nd->elf32) {
+		note_32 = (Elf32_Nhdr *)note;
+		len = sizeof(Elf32_Nhdr);
+		len = roundup(len + note_32->n_namesz, 4);
+	} else if (nd->elf64) {
+		note_64 = (Elf64_Nhdr *)note;
+		len = sizeof(Elf64_Nhdr);
+		len = roundup(len + note_64->n_namesz, 4);
+	}
+
+	pt_regs = (void *)((char *)note + len +
+			   MEMBER_OFFSET("elf_prstatus", "pr_reg"));
+	/* NEED TO BE FIXED: Hack to get the proper alignment */
+	pt_regs +=4;
+
 	return pt_regs;
 
 }
@@ -2856,22 +2862,16 @@ get_x86_64_regs_from_elf_notes(struct task_context *tc)
 
 	pt_regs = NULL;
 
-	if ((tc->task == tt->panic_task) || 
-	    (is_task_active(tc->task) && (nd->num_prstatus_notes > 1))) {
-		if (nd->num_prstatus_notes > 1)
-			note = (Elf64_Nhdr *)
-				nd->nt_prstatus_percpu[tc->processor];
-		else
-			note = (Elf64_Nhdr *)nd->nt_prstatus;
+	if (nd->num_prstatus_notes > 1)
+		note = (Elf64_Nhdr *)nd->nt_prstatus_percpu[tc->processor];
+	else
+		note = (Elf64_Nhdr *)nd->nt_prstatus;
+
+	len = sizeof(Elf64_Nhdr);
+	len = roundup(len + note->n_namesz, 4);
+	pt_regs = (void *)((char *)note + len +
+			   MEMBER_OFFSET("elf_prstatus", "pr_reg"));
 
-		len = sizeof(Elf64_Nhdr);
-		len = roundup(len + note->n_namesz, 4);
-		pt_regs = (void *)((char *)note + len + 
-			MEMBER_OFFSET("elf_prstatus", "pr_reg"));
-	} else
-		error(FATAL, 
-		    "cannot determine register set for task \"%s\"\n",
-			tc->comm);
 	return pt_regs;
 }
 
@@ -2885,32 +2885,21 @@ get_ppc64_regs_from_elf_notes(struct task_context *tc)
 
 	pt_regs = NULL;
 
-	if ((tc->task == tt->panic_task) ||
-	    (is_task_active(tc->task) && (nd->num_prstatus_notes > 1))) {
-		/*	
-		 * Registers are always saved during the dump process for the 
-		 * panic task.  Kdump also captures registers for all CPUs if
-		 * they responded to an IPI.
-		 */
-		if (nd->num_prstatus_notes > 1) {
-			if (tc->processor >= nd->num_prstatus_notes)
-				error(FATAL, "cannot determine NT_PRSTATUS ELF note "
-				    "for %s task: %lx\n", (tc->task == tt->panic_task) ?
-				    "panic" : "active", tc->task);	
-			note = (Elf64_Nhdr *)
-				nd->nt_prstatus_percpu[tc->processor];
-		} else
-			note = (Elf64_Nhdr *)nd->nt_prstatus;
-
-		len = sizeof(Elf64_Nhdr);
-		len = roundup(len + note->n_namesz, 4);
-		pt_regs = (void *)((char *)note + len + 
-			MEMBER_OFFSET("elf_prstatus", "pr_reg"));
+	/*
+	 * Registers are always saved during the dump process for the
+	 * panic task.  Kdump also captures registers for all CPUs if
+	 * they responded to an IPI.
+	 */
+	if (nd->num_prstatus_notes > 1) {
+		note = (Elf64_Nhdr *)nd->nt_prstatus_percpu[tc->processor];
 	} else
-		error(FATAL, 
-		    "cannot determine register set for task \"%s\"\n",
-			tc->comm);
-	
+		note = (Elf64_Nhdr *)nd->nt_prstatus;
+
+	len = sizeof(Elf64_Nhdr);
+	len = roundup(len + note->n_namesz, 4);
+	pt_regs = (void *)((char *)note + len +
+			   MEMBER_OFFSET("elf_prstatus", "pr_reg"));
+
 	return pt_regs;
 }
 
@@ -2953,29 +2942,23 @@ get_arm_regs_from_elf_notes(struct task_context *tc)
 	len = 0;
 	pt_regs = NULL;
 
-	if ((tc->task == tt->panic_task) ||
-	    (is_task_active(tc->task) && (nd->num_prstatus_notes > 1))) {
-		if (nd->num_prstatus_notes > 1)
-			note = (void *)
-				nd->nt_prstatus_percpu[tc->processor];
-		else
-			note = (void *)nd->nt_prstatus;
-		if (nd->elf32) {
-			note_32 = (Elf32_Nhdr *)note;
-			len = sizeof(Elf32_Nhdr);
-			len = roundup(len + note_32->n_namesz, 4);
-		} else if (nd->elf64) {
-			note_64 = (Elf64_Nhdr *)note;
-			len = sizeof(Elf64_Nhdr);
-			len = roundup(len + note_64->n_namesz, 4);
-		}
+	if (nd->num_prstatus_notes > 1)
+		note = (void *)nd->nt_prstatus_percpu[tc->processor];
+	else
+		note = (void *)nd->nt_prstatus;
+	if (nd->elf32) {
+		note_32 = (Elf32_Nhdr *)note;
+		len = sizeof(Elf32_Nhdr);
+		len = roundup(len + note_32->n_namesz, 4);
+	} else if (nd->elf64) {
+		note_64 = (Elf64_Nhdr *)note;
+		len = sizeof(Elf64_Nhdr);
+		len = roundup(len + note_64->n_namesz, 4);
+	}
+
+	pt_regs = (void *)((char *)note + len +
+			   MEMBER_OFFSET("elf_prstatus", "pr_reg"));
 
-		pt_regs = (void *)((char *)note + len +
-			MEMBER_OFFSET("elf_prstatus", "pr_reg"));
-	} else
-		error(FATAL,
-		    "cannot determine arm register set for task \"%s\"\n",
-			tc->comm);
 	return pt_regs;
 }
 
-- 
1.7.4

>From d69b26d99a1c416584a79ca2970b40094bd09ec5 Mon Sep 17 00:00:00 2001
From: HATAYAMA Daisuke <d.hatayama@xxxxxxxxxxxxxx>
Date: Thu, 31 Mar 2011 22:37:06 +0900
Subject: [PATCH 1/4] Check non-support machine check first

The patch that follows will move error handling processings in several
get_regs_arch_from_elf_notes() in get_regs_from_elf_notes(). As a preparation
for it, move machine check to identify non-support architecture in the
beginning.
---
 netdump.c |   14 +++++++++-----
 1 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/netdump.c b/netdump.c
index 7916df1..8b64e7c 100644
--- a/netdump.c
+++ b/netdump.c
@@ -2783,7 +2783,15 @@ int get_netdump_arch(void)
 void * 
 get_regs_from_elf_notes(struct task_context *tc)
 {
-	switch(get_netdump_arch())
+	int e_machine = get_netdump_arch();
+
+	if (e_machine != EM_386 && e_machine != EM_PPC64 &&
+	    e_machine != EM_X86_64 && e_machine != EM_ARM)
+		error(FATAL,
+		      "support for ELF machine type %d not available\n",
+		      e_machine);
+
+	switch(e_machine)
 	{
 	case EM_386:
 		return get_x86_regs_from_elf_notes(tc);
@@ -2793,10 +2801,6 @@ get_regs_from_elf_notes(struct task_context *tc)
 		return get_x86_64_regs_from_elf_notes(tc);
 	case EM_ARM:
 		return get_arm_regs_from_elf_notes(tc);
-	default:
-		error(FATAL,
-		    "support for ELF machine type %d not available\n",
-			get_netdump_arch());
 	}
 
 	return NULL;
-- 
1.7.4

--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux