Re: Make note information human readable when help -D

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

 



On 12/16/2014 05:50 AM, Dave Anderson wrote:


----- Original Message -----
Hello Dave,

Thank you for suggestions.
I think I have further understanding of "keep it simple".

This time, there are five functions in the patch.
They are:
	display_ELF_note()
	display_prstatus_x86_64()
	display_prstatus_x86()
	display_qemu_x86_64()
	display_qemu_x86()

It looks much better.
Previously, I tried to avoid duplicate code though it can bring
more complexity. Now, I think simple in logic is more important.
I do appreciate your teaching me so much.

Hello Zhou,

Thank you for tightening this up -- it is looking much better.  But I still
have a few more questions, suggestions, and further simplifications.

In diskdump.c, you have this declaration:

   +void display_ELF_note(int, int, void *, char *);
   +

Please move this declaration in defs.h with the other function
prototypes under "netdump.c".  You can also put the new PRSTATUS
and QEMU #define's right underneath the function declaration
instead of putting them at the bottom of defs.h.

Also in diskdump.c:

   @@ -1736,10 +1738,18 @@ __diskdump_memory_dump(FILE *fp)
                                   dd->num_prstatus_notes);
                           fprintf(fp, "           notes_buf: %lx\n",
                                   (ulong)dd->notes_buf);
   +
   +                       char *l_buf = (char *)malloc(2 * BUFSIZE);
                           for (i = 0; i<  dd->num_prstatus_notes; i++) {
                                   fprintf(fp, "            notes[%d]: %lx\n",
                                           i, (ulong)dd->nt_prstatus_percpu[i]);
   +
   +                               display_ELF_note(dd->machine_type, PRSTATUS,
   +                                                dd->nt_prstatus_percpu[i],l_buf);
   +                               fprintf(fp, "%s", l_buf);
   +                               memset(l_buf, 0, 2 * BUFSIZE);
                           }
   +                       free(l_buf);
                           dump_nt_prstatus_offset(fp);
                   }
                   if (dh->header_version>= 5) {

First, what's the reason for the memset() call after the data has
been displayed?  Aren't they always going to be the exact same,
NULL-terminated, size?

Secondly, the use of malloc() is discouraged during the runtime of
a crash session, such as when "help -D" is entered.  The reason
for that is because:

  (1) a crash command may fail and call the error(FATAL) function
      for any number of reasons, or
  (2) CTRL-c may be entered in the middle of the command.

In both cases, RESTART() is called, which does a longjmp() back to main().
So if malloc() had been called prior to either of those two occurances,
the buffer would be leaked.  That's the reason behind using the
GETBUF()/FREEBUF facility, because buffers that GETBUF() returns are
guaranteed to be freed prior to the next "crash>" prompt, regardless
whether FREEBUF() had been called.

However, since "crash -d1" will also call __diskdump_memory_dump() very
early on before main() calls buf_init() -- which sets up the GETBUF()/FREEBUF()
facility -- GETBUF()/FREEBUF() aren't available for use at that time.

So to avoid having to choose between malloc() or GETBUF(), I would
just use a char[BUFSIZE*2] buffer automatically declared on the stack
in __diskdump_memory_dump().

In netdump.c, in the 3 places you call display_ELF_note() you qualify
it by checking "if (nd->ofp)".  I'm not sure why you do that?  You
should be able to just print the whole buffer by entering:

   netdump_print("%s", l_buf);

Correct?

All have been addressed except this. Originally, I used the function
netdump_print(), but BUFSIZE in netdump_print() is not enough. So I
changed it to fprintf().

And like diskdump.c, the ELF dumping functions can be called
immediately during initialization if "crash -d1" is invoked,
so GETBUF() cannot be used, and using malloc() during runtime
via "help -D" could cause a memory leak.  SO again, please
just declare a char[] buffer on the function stack.

And lastly, you'll note that none of the crash command output
ever use tabs as you have done.  Can you replace them with spaces,
or alternatively, use the space(count) function to return a pointer
to a string with "count" number of spaces?

Thanks,
   Dave




--
Thanks
Zhou Wenjian
From 53dc39f8271c2a0489a4a7de689b7c4f59f2dfdf Mon Sep 17 00:00:00 2001
From: Zhou Wenjian <zhouwj-fnst@xxxxxxxxxxxxxx>
Date: Tue, 16 Dec 2014 09:37:29 +0800
Subject: [PATCH] Make note info human readable when help -D

---
 defs.h     |    7 ++
 diskdump.c |    7 ++
 netdump.c  |  312 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 326 insertions(+), 0 deletions(-)

diff --git a/defs.h b/defs.h
index 2e52bc4..76b113a 100755
--- a/defs.h
+++ b/defs.h
@@ -5547,6 +5547,13 @@ int write_proc_kcore(int, void *, int, ulong, physaddr_t);
 int kcore_memory_dump(FILE *);
 void dump_registers_for_qemu_mem_dump(void);
 void kdump_backup_region_init(void);
+void display_ELF_note(int, int, void *, char *);
+
+/*
+ *  for display_ELF_note() type
+ */
+#define PRSTATUS	0x1
+#define QEMU		0X2
 
 /*
  * ramdump.c
diff --git a/diskdump.c b/diskdump.c
index 3d33fdc..b6fbfd9 100644
--- a/diskdump.c
+++ b/diskdump.c
@@ -1736,9 +1736,16 @@ __diskdump_memory_dump(FILE *fp)
 				dd->num_prstatus_notes);
 			fprintf(fp, "           notes_buf: %lx\n",
 				(ulong)dd->notes_buf);
+
+			char l_buf[BUFSIZE * 2];
+			BZERO(l_buf, BUFSIZE *2);
 			for (i = 0; i < dd->num_prstatus_notes; i++) {
 				fprintf(fp, "            notes[%d]: %lx\n",
 					i, (ulong)dd->nt_prstatus_percpu[i]);
+
+				display_ELF_note(dd->machine_type, PRSTATUS,
+						 dd->nt_prstatus_percpu[i],l_buf);
+				fprintf(fp, "%s", l_buf);
 			}
 			dump_nt_prstatus_offset(fp);
 		}
diff --git a/netdump.c b/netdump.c
index 903faa0..02f1bba 100644
--- a/netdump.c
+++ b/netdump.c
@@ -1976,6 +1976,12 @@ dump_Elf32_Nhdr(Elf32_Off offset, int store)
                 }
                 lf = 0;
 	} else {
+		if (nd->ofp) {
+			char l_buf[BUFSIZE * 2];
+			BZERO(l_buf, BUFSIZE *2);
+			display_ELF_note(EM_386, qemuinfo ? QEMU : PRSTATUS, note,l_buf);
+			fprintf(fp, "%s", l_buf);
+		}
 		for (i = lf = 0; i < note->n_descsz/sizeof(ulong); i++) {
 			if (((i%4)==0)) {
 				netdump_print("%s                         ", 
@@ -2255,6 +2261,13 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
 	}
 
 	if (BITS32() && (xen_core || (note->n_type == NT_PRSTATUS))) {
+		if (!xen_core && nd->ofp) {
+			char l_buf[BUFSIZE * 2];
+			BZERO(l_buf, BUFSIZE *2);
+			display_ELF_note(EM_386, PRSTATUS, note, l_buf);
+			fprintf(fp, "%s", l_buf);
+		}
+
 		iptr = (int *)uptr;
 		for (i = lf = 0; i < note->n_descsz/sizeof(ulong); i++) {
 			if (((i%4)==0)) {
@@ -2279,6 +2292,12 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
 		iptr = (int *)uptr;
 		netdump_print("                         %08lx\n", *iptr); 
 	} else {
+		if (nd->ofp) {
+			char l_buf[BUFSIZE * 2];
+			BZERO(l_buf, BUFSIZE *2);
+			display_ELF_note(EM_X86_64, qemuinfo ? QEMU : PRSTATUS, note, l_buf);
+			fprintf(fp, "%s", l_buf);
+		}
 		for (i = lf = 0; i < note->n_descsz/sizeof(ulonglong); i++) {
 			if (((i%2)==0)) {
 				netdump_print("%s                         ", 
@@ -2543,6 +2562,299 @@ struct x86_64_user_regs_struct {
         unsigned long ds,es,fs,gs;
 };
 
+struct x86_64_prstatus {
+	int si_signo;
+	int si_code;
+	int si_errno;
+	short cursig;
+	unsigned long sigpend;
+	unsigned long sighold;
+	int pid;
+	int ppid;
+	int pgrp;
+	int sid;
+	struct timeval utime;
+	struct timeval stime;
+	struct timeval cutime;
+	struct timeval cstime;
+	struct x86_64_user_regs_struct regs;
+	int fpvalid;
+};
+
+static void
+display_prstatus_x86_64(void *note_ptr, char *buf)
+{
+	struct x86_64_prstatus *pr;
+	Elf64_Nhdr *note;
+
+	note = (Elf64_Nhdr *)note_ptr;
+	pr = (struct x86_64_prstatus *)(
+		(char *)note + sizeof(Elf64_Nhdr) + note->n_namesz);
+	pr = (struct x86_64_prstatus *)roundup((ulong)pr, 4);
+	sprintf(buf,
+		"        si.signo: %d, si.code: %d, si.errno: %d, cursig:%d\n"
+		"        sigpend: %lu\n"
+		"        sighold: %lu\n"
+		"        pid: %d, ppid: %d, pgrp: %d, sid:%d\n"
+		"        utime: %01lld.%06d, stime: %01lld.%06d, cutime: %01lld.%06d, "
+		"cstime: %01lld.%06d\n"
+		"        ORIG_RAX: %ld, fpvalid: %d\n"
+		"        R15    : 0x%016lx    R14     : 0x%016lx\n"
+		"        R13    : 0x%016lx    R12     : 0x%016lx\n"
+		"        RBP    : 0x%016lx    RBX     : 0x%016lx\n"
+		"        R11    : 0x%016lx    R10     : 0x%016lx\n"
+		"        R9     : 0x%016lx    R8      : 0x%016lx\n"
+		"        RAX    : 0x%016lx    RCX     : 0x%016lx\n"
+		"        RDX    : 0x%016lx    RSI     : 0x%016lx\n"
+		"        RDI    : 0x%016lx    RIP     : 0x%016lx\n"
+		"        RFLAGS : 0x%016lx    RSP     : 0x%016lx\n"
+		"        FS_BASE: 0x%016lx    GS_BASE : 0x%016lx\n"
+		"        CS: 0x%04lx SS: 0x%04lx DS: 0x%04lx ES: 0x%04lx "
+		"FS: 0x%04lx GS: 0x%04lx\n",
+		pr->si_signo, pr->si_code, pr->si_errno, pr->cursig,
+		pr->sigpend, pr->sighold,
+		pr->pid, pr->ppid, pr->pgrp, pr->sid,
+		(long long)pr->utime.tv_sec, (int)pr->utime.tv_usec,
+		(long long)pr->stime.tv_sec, (int)pr->stime.tv_usec,
+		(long long)pr->cutime.tv_sec, (int)pr->cutime.tv_usec,
+		(long long)pr->cstime.tv_sec, (int)pr->cstime.tv_usec,
+		pr->regs.orig_rax, pr->fpvalid,
+		pr->regs.r15, pr->regs.r14,
+		pr->regs.r13, pr->regs.r12,
+		pr->regs.rbp, pr->regs.rbx,
+		pr->regs.r11, pr->regs.r10,
+		pr->regs.r9, pr->regs.r8,
+		pr->regs.rax, pr->regs.rcx,
+		pr->regs.rdx, pr->regs.rsi,
+		pr->regs.rdi, pr->regs.rip,
+		pr->regs.eflags, pr->regs.rsp,
+		pr->regs.fs_base, pr->regs.gs_base,
+		pr->regs.cs, pr->regs.ss,
+		pr->regs.ds, pr->regs.es,
+		pr->regs.fs, pr->regs.gs
+		);
+}
+
+struct x86_user_regs_struct {
+	unsigned long ebx,ecx,edx,esi,edi,ebp,eax;
+	unsigned long ds,es,fs,gs,orig_eax;
+	unsigned long eip,cs,eflags;
+	unsigned long esp,ss;
+};
+
+struct x86_prstatus {
+	int si_signo;
+	int si_code;
+	int si_errno;
+	short cursig;
+	unsigned long sigpend;
+	unsigned long sighold;
+	int pid;
+	int ppid;
+	int pgrp;
+	int sid;
+	struct timeval utime;
+	struct timeval stime;
+	struct timeval cutime;
+	struct timeval cstime;
+	struct x86_user_regs_struct regs;
+	int fpvalid;
+};
+
+static void
+display_prstatus_x86(void *note_ptr, char *buf)
+{
+	struct x86_prstatus *pr;
+	Elf32_Nhdr *note;
+
+	note = (Elf32_Nhdr *)note_ptr;
+	pr = (struct x86_prstatus *)(
+		(char *)note + sizeof(Elf32_Nhdr) + note->n_namesz);
+	pr = (struct x86_prstatus *)roundup((ulong)pr, 4);
+
+	sprintf(buf,
+		"        si.signo: %d si.code: %d si.errno: %d cursig: %d\n"
+		"        sigpend : %lu\n"
+		"        sighold : %lu\n"
+		"        pid: %d ppid: %d pgrp: %d sid: %d\n"
+		"        utime: %01lld.%06d, stime: %01lld.%06d, cutime: %01lld.%06d, "
+		"cstime: %01lld.%06d\n"
+		"        orig_eax: %ld, fpvalid: %d\n"
+		"        EBX    : 0x%08lx    ECX     : 0x%08lx\n"
+		"        EDX    : 0x%08lx    ESI     : 0x%08lx\n"
+		"        EDI    : 0x%08lx    EBP     : 0x%08lx\n"
+		"        EAX    : 0x%08lx    EIP     : 0x%08lx\n"
+		"        EFLAGS : 0x%08lx    ESP     : 0x%08lx\n"
+		"        DS: 0x%04lx ES: 0x%04lx FS: 0x%04lx GS: 0x%04lx "
+		"CS: 0x%04lx SS: 0x%04lx\n",
+		pr->si_signo, pr->si_code, pr->si_errno, pr->cursig,
+		pr->sigpend, pr->sighold,
+		pr->pid, pr->ppid, pr->pgrp, pr->sid,
+		(long long)pr->utime.tv_sec, (int)pr->utime.tv_usec,
+		(long long)pr->stime.tv_sec, (int)pr->stime.tv_usec,
+		(long long)pr->cutime.tv_sec, (int)pr->cutime.tv_usec,
+		(long long)pr->cstime.tv_sec, (int)pr->cstime.tv_usec,
+		pr->regs.orig_eax, pr->fpvalid,
+		pr->regs.ebx, pr->regs.ecx,
+		pr->regs.edx, pr->regs.esi,
+		pr->regs.edi, pr->regs.ebp,
+		pr->regs.eax, pr->regs.eip,
+		pr->regs.eflags, pr->regs.esp,
+		pr->regs.ds, pr->regs.es, pr->regs.fs,
+		pr->regs.gs, pr->regs.cs, pr->regs.ss
+		);
+}
+
+static void
+display_qemu_x86_64(void *note_ptr, char *buf)
+{
+	int i, size;
+	Elf64_Nhdr *note;
+	QEMUCPUState *ptr;
+	QEMUCPUSegment *seg;
+	char *seg_names[] = {"CS", "DS", "ES", "FS", "GS", "SS", "LDT", "TR",
+			     "GDT", "IDT"};
+
+	note = (Elf64_Nhdr *)note_ptr;
+	ptr = (QEMUCPUState *)(
+		(char *)note + sizeof(Elf64_Nhdr) + note->n_namesz);
+
+	ptr = (QEMUCPUState *)roundup((ulong)ptr, 4);
+	seg = &(ptr->cs);
+
+	size = sprintf(buf,
+			"        version: 0x%08x    size: 0x%08x\n"
+			"        RAX   : 0x%016llx    RBX   : 0x%016llx\n"
+			"        RCX   : 0x%016llx    RDX   : 0x%016llx\n"
+			"        RSI   : 0x%016llx    RDI   : 0x%016llx\n"
+			"        RSP   : 0x%016llx    RBP   : 0x%016llx\n"
+			"        RIP   : 0x%016llx    RFLAGS: 0x%016llx\n"
+			"        R8    : 0x%016llx    R9    : 0x%016llx\n"
+			"        R10   : 0x%016llx    R11   : 0x%016llx\n"
+			"        R12   : 0x%016llx    R13   : 0x%016llx\n"
+			"        R14   : 0x%016llx    R15   : 0x%016llx\n",
+			ptr->version, ptr->size,
+			(ulonglong)ptr->rax, (ulonglong)ptr->rbx,
+			(ulonglong)ptr->rcx, (ulonglong)ptr->rdx,
+			(ulonglong)ptr->rsi, (ulonglong)ptr->rdi,
+			(ulonglong)ptr->rsp, (ulonglong)ptr->rbp,
+			(ulonglong)ptr->rip, (ulonglong)ptr->rflags,
+			(ulonglong)ptr->r8, (ulonglong)ptr->r9,
+			(ulonglong)ptr->r10, (ulonglong)ptr->r11,
+			(ulonglong)ptr->r12, (ulonglong)ptr->r13,
+			(ulonglong)ptr->r14, (ulonglong)ptr->r15
+			);
+		buf += size;
+
+	for(i = 0; i < sizeof(seg_names)/sizeof(seg_names[0]); i++) {
+		size = sprintf(buf,
+				"        %s:\n"
+				"        selector: 0x%08x    limit: 0x%08x    flags: 0x%08x\n"
+				"        pad     : 0x%08x    base : 0x%016llx\n",
+				seg_names[i],
+				seg->selector, seg->limit, seg->flags,
+				seg->pad, (ulonglong)seg->base
+				);
+		buf += size;
+		seg++;
+	}
+
+	sprintf(buf,
+		"        cr[0]: %016llx    cr[1]: %016llx    cr[2]: %016llx\n"
+		"        cr[3]: %016llx    cr[4]: %016llx\n",
+		(ulonglong)ptr->cr[0], (ulonglong)ptr->cr[1], (ulonglong)ptr->cr[2],
+		(ulonglong)ptr->cr[3], (ulonglong)ptr->cr[4]
+		);
+}
+
+static void
+display_qemu_x86(void *note_ptr, char *buf)
+{
+	int i, size, t=0;
+	Elf32_Nhdr *note;
+	QEMUCPUState *ptr;
+	QEMUCPUSegment *seg;
+	char *seg_names[] = {"CS", "DS", "ES", "FS", "GS", "SS", "LDT", "TR",
+			     "GDT", "IDT"};
+
+
+	note = (Elf32_Nhdr *)note_ptr;
+	ptr = (QEMUCPUState *)(
+		(char *)note + sizeof(Elf32_Nhdr) + note->n_namesz);
+	ptr = (QEMUCPUState *)roundup((ulong)ptr, 4);
+	seg = &(ptr->cs);
+
+	size = sprintf(buf,
+			"        version: 0x%08x\tsize: 0x%08x\n"
+			"        EAX   : 0x%016llx\tEBX   : 0x%016llx\n"
+			"        ECX   : 0x%016llx\tEDX   : 0x%016llx\n"
+			"        ESI   : 0x%016llx\tEDI   : 0x%016llx\n"
+			"        ESP   : 0x%016llx\tEBP   : 0x%016llx\n"
+			"        EIP   : 0x%016llx\tEFLAGS: 0x%016llx\n",
+			ptr->version, ptr->size,
+			(ulonglong)ptr->rax, (ulonglong)ptr->rbx, (ulonglong)ptr->rcx,
+			(ulonglong)ptr->rdx, (ulonglong)ptr->rsi, (ulonglong)ptr->rdi,
+			(ulonglong)ptr->rsp, (ulonglong)ptr->rbp,
+			(ulonglong)ptr->rip, (ulonglong)ptr->rflags
+			);
+	buf += size;
+	t+=size;
+
+	for(i = 0; i < sizeof(seg_names)/sizeof(seg_names[0]); i++) {
+		size = sprintf(buf,
+				"        %s:\n"
+				"        selector: 0x%08x    limit: 0x%08x    flags: 0x%08x\n"
+				"        pad     : 0x%08x    base : 0x%016llx\n",
+				seg_names[i],
+				seg->selector, seg->limit, seg->flags,
+				seg->pad, (ulonglong)seg->base
+				);
+		buf += size;
+		seg++;
+	}
+
+	sprintf(buf,
+		"        cr[0]: %016llx    cr[1]: %016llx    cr[2]: %016llx\n"
+		"        cr[3]: %016llx    cr[4]: %016llx\n",
+		(ulonglong)ptr->cr[0], (ulonglong)ptr->cr[1], (ulonglong)ptr->cr[2],
+		(ulonglong)ptr->cr[3], (ulonglong)ptr->cr[4]
+		);
+}
+
+void
+display_ELF_note(int machine, int type, void *note, char *buf)
+{
+	switch (machine)
+	{
+	case EM_386:
+		switch (type)
+		{
+		case PRSTATUS:
+			display_prstatus_x86(note, buf);
+			break;
+		case QEMU:
+			display_qemu_x86(note, buf);
+			break;
+		}
+		break;
+
+	case EM_X86_64:
+		switch (type)
+		{
+		case PRSTATUS:
+			display_prstatus_x86_64(note, buf);
+			break;
+		case QEMU:
+			display_qemu_x86_64(note, buf);
+			break;
+		}
+		break;
+
+	default:
+		return;
+	}
+}
+
 void 
 get_netdump_regs_x86_64(struct bt_info *bt, ulong *ripp, ulong *rspp)
 {
-- 
1.7.1

--
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