[RFC][PATCH v3] Use register value in elf note NT_PRSTATUS to do backtrace

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

 



Hi Dave and all,

Thanks a lot for your suggestion.

According to the feedbacks, I made the following main changes since v2:
1) Add a new option --no_elf_notes. If specified, it'll skip processing
   elf notes in kdump-compressed dump files.
2) Dump notes related information including total number of notes, their
   buffers' pointer value and finally offset in the dump file.
3) Move nt_prstatus_percpu and nt_prstatus_percpu to diskdump_data struct.
   However, bt command may need sp/ip from the notes later, so I guess
   the buffer should not be freed after diskdump_read_header().

So the v3 patch is attached and we're looking forward to your opinions.

Thanks,
Wang Chao

Sent on 2011-4-26 23:15, Dave Anderson wrote:
> 
> 
> ----- Original Message -----
>> Hi Dave and list,
>>
>> I guess you still remember that a few weeks ago Wen has sent a patch which intends
>> to use register values in NT_PRSTATUS notes for backtracing if no panic task was
>> found. Thanks for your review and the suggestions are very useful.
>>
>> However, Wen was busy with other work for these days, so I'll continue with this
>> work and now the 2rd version patch is attached.
>>
>> v2: Address review feedbacks.
>> 1) Set up a flag in pc->flags2 and it's determined during the diskdump file init procedure.
>> 2) Seperate code according to the that flag.
>> 3) Also, we've done some tests on dumpfile of xen kernel and the trouble described
>> in the previous mail was gone.
>>
>> So we're looking forward to your feedback and if you still have any problems with
>> it, please tell us.
>>
>> Thanks,
>> Wang Chao
> 
> Hello Wang,
> 
> I haven't had a chance to run a complete test of this latest patch,
> but I do have several suggestions.
> 
> diskdump.c:
> 
> Put the nt_prstatus_percpu array pointer and the num_prstatus_notes
> into the diskdump_data structure -- like you did with the notes_buf.
> Make nt_prstatus_percpu a pointer that gets allocated and initialized
> only if necessary -- because if it's not used, it's a waste of space.
> 
> In read_dump_header(), when dd->notes_buf is malloc()'d, malloc() the
> dd->nt_prstatus_percpu array. 
> 
> And at the bottom of read_dump_header(), free both the dd->notes_buf
> and the dd->nt_prstatus_percpu array if they exist, under the "err:"
> label:
> 
> err:
>    ...
>    if (dd->notes_buf)
> 	free(dd->notes_buf);
>    if (dd->nt_prstatus_percpu)
>         free(dd->nt_prstatus_percpu;
> 
> In order to be able to debug/understand why things may fail, especially
> due to the exclusion of prstatus notes of offline cpus, it would be 
> very helpful to be able to see the dd->nt_prstatus pointers for 
> each cpu.  Similar to what is done with the vmcoreinfo data, can 
> you add a section to __diskdump_dump_header():
> 
>                 if (dh->header_version >= 3) {
>                         fprintf(fp, "   offset_vmcoreinfo: %lx\n",
>                                 (ulong)dd->sub_header_kdump->offset_vmcoreinfo);
>                         fprintf(fp, "     size_vmcoreinfo: %lu\n",
>                                 dd->sub_header_kdump->size_vmcoreinfo);
>                         if (dd->sub_header_kdump->offset_vmcoreinfo &&
>                                 dd->sub_header_kdump->size_vmcoreinfo) {
>                                 dump_vmcoreinfo(fp);
>                         }
>                 }
>                 if (dh->header_version >= 4) {
>                         fprintf(fp, "         offset_note: %lx\n",
>                                 (ulong)dd->sub_header_kdump->offset_note);
>                         fprintf(fp, "           size_note: %lu\n",
>                                 dd->sub_header_kdump->size_note);
> here ==================> 
>                 }
> 
> Call a function that dumps the file offset of each cpu's nt_prstatus data.  
> Then, if necessary, any cpu's register set can be read with "rd -f".
> 
> 
> netdump.c:
> 
> In get_netdump_regs_x86(), both of these settings are incorrect:
> 
>                 user_regs = get_regs_from_note((char *)note, &ip, &sp);
>      =====>     bt->flags |= BT_KDUMP_ELF_REGS;
>                 if (is_kernel_text(ip) &&
>                     (((sp >= GET_STACKBASE(bt->task)) &&
>                       (sp < GET_STACKTOP(bt->task))) ||
>                     in_alternate_stack(bt->tc->processor, sp))) {
>                         *eip = ip;
>                         *esp = sp;
>      =====>             bt->flags |= BT_KERNEL_SPACE;
>                         return;
>                 }
> 
> Neither of these flags should be set there.  BT_KDUMP_ELF_REGS
> is only applicable to x86_64, and BT_KERNEL_SPACE is only
> appicable to kvmdump dumpfiles.
> 
> Finally, in the interest of paranoia, give the user the capability
> of *not* using this facility.  In main.c, create a "--no_elf_notes"
> option (similar to "--zero_excluded"), and have it set a NO_ELF_NOTES
> bit in the globally-accessible "*diskdump_flags".  As an example, see
> how ZERO_EXCLUDED is set, used, and accessed.  Then in read_dump_header()
> skip the new ELF setup if that flag is set.  It will not be necessary
> to go as creating a new environment variable like "zero_excluded", but
> it would be nice to be able to restrict its use on the crash invocation
> command line.
>  
> Thanks,
>   Dave
> 
> 
>From 92fc495b4cd67837e22eec5f4a4bf309d580f2d4 Mon Sep 17 00:00:00 2001
From: Wang Chao <wang.chao@xxxxxxxxxxxxxx>
Date: Mon, 18 Apr 2011 09:51:21 +0800
Subject: [PATCH] Use register value in elf note NT_PRSTATUS to do backtrace

We have a new hardware to do dump, and use makedumpfile to generate
vmcore. Our hardware can work when the OS is out of controll(for
example: dead loop). When we use crash to analyze the vmcore, bt can
not work, because there is no panic task.

We have provide the value of register in the vmcore(the format is
elf_prstatus, it is same with normal kdump's vmcore). So we can use
it when we do not find panic task.

Based on previous patch from wency@xxxxxxxxxxxxxx
---
 defs.h     |    7 +++
 diskdump.c |  177 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 main.c     |    4 ++
 netdump.c  |   79 +++++++++++++++++++++++++++
 task.c     |    2 +
 x86.c      |   11 ++++
 x86_64.c   |    9 +++
 7 files changed, 289 insertions(+), 0 deletions(-)

diff --git a/defs.h b/defs.h
index d01ace7..744a5a9 100755
--- a/defs.h
+++ b/defs.h
@@ -242,6 +242,7 @@ struct number_option {
 #define ERROR_EXCLUDED      (0x4)
 #define ZERO_EXCLUDED       (0x8)
 #define DUMPFILE_SPLIT      (0x10)
+#define NO_ELF_NOTES        (0x20)
 #define DISKDUMP_VALID()    (dd->flags & DISKDUMP_LOCAL)
 #define KDUMP_CMPRS_VALID() (dd->flags & KDUMP_CMPRS_LOCAL)
 #define KDUMP_SPLIT()       (dd->flags & DUMPFILE_SPLIT)
@@ -428,7 +429,9 @@ struct program_context {
 	char *kvmdump_mapfile;          /* storage of physical to file offsets */
 	ulonglong flags2;               /* flags overrun */  
 #define FLAT          (0x1ULL)
+#define ELF_NOTES     (0x2ULL)
 #define FLAT_FORMAT() (pc->flags2 & FLAT)
+#define ELF_NOTES_VALID() (pc->flags2 & ELF_NOTES)
 	char *cleanup;
 	char *namelist_orig;
 	char *namelist_debug_orig;
@@ -1433,6 +1436,7 @@ struct offset_table {                    /* stash of commonly-used offsets */
 	long prio_array_queue;
 	long user_regs_struct_ebp;
 	long user_regs_struct_esp;
+	long user_regs_struct_eip;
 	long user_regs_struct_rip;
 	long user_regs_struct_cs;
 	long user_regs_struct_eflags;
@@ -4604,6 +4608,9 @@ ulong *diskdump_flags;
 int is_partial_diskdump(void);
 int dumpfile_is_split(void);
 void show_split_dumpfiles(void);
+void x86_process_elf_notes(void *, unsigned long);
+void *diskdump_get_prstatus_percpu(int);
+void map_cpus_to_prstatus_kdump_cmprs(void);
 
 /*
  * makedumpfile.c
diff --git a/diskdump.c b/diskdump.c
index 9a2f37f..70a7275 100644
--- a/diskdump.c
+++ b/diskdump.c
@@ -49,6 +49,8 @@ struct diskdump_data {
 	int	byte, bit;
 	char	*compressed_page;	/* copy of compressed page data */
 	char	*curbufptr;		/* ptr to uncompressed page buffer */
+	void	**nt_prstatus_percpu;
+	uint	num_prstatus_notes;
 
 	/* page cache */
 	struct page_cache_hdr {		/* header for each cached page */
@@ -84,6 +86,40 @@ int dumpfile_is_split(void)
 	return KDUMP_SPLIT();
 }
 
+void
+map_cpus_to_prstatus_kdump_cmprs(void)
+{
+	void **nt_ptr;
+	int online, i, j, nrcpus;
+	size_t size;
+
+	if (!(online = get_cpus_online()) || (online == kt->cpus))
+		return;
+
+	if (CRASHDEBUG(1))
+		error(INFO,
+		    "cpus: %d online: %d NT_PRSTATUS notes: %d (remapping)\n",
+			kt->cpus, online, dd->num_prstatus_notes);
+
+	size = NR_CPUS * sizeof(void *);
+
+	nt_ptr = (void **)GETBUF(size);
+	BCOPY(dd->nt_prstatus_percpu, nt_ptr, size);
+	BZERO(dd->nt_prstatus_percpu, size);
+
+	/*
+	 *  Re-populate the array with the notes mapping to online cpus
+	 */
+	nrcpus = (kt->kernel_NR_CPUS ? kt->kernel_NR_CPUS : NR_CPUS);
+
+	for (i = 0, j = 0; i < nrcpus; i++) {
+		if (in_cpu_map(ONLINE, i))
+			dd->nt_prstatus_percpu[i] = nt_ptr[j++];
+	}
+
+	FREEBUF(nt_ptr);
+}
+
 static void add_diskdump_data(char* name)
 {
 #define DDL_SIZE 16
@@ -185,6 +221,58 @@ static int open_dump_file(char *file)
 	return TRUE;
 }
 
+void x86_process_elf_notes(void *note_ptr, unsigned long size_note)
+{
+	Elf32_Nhdr *note32 = NULL;
+	Elf64_Nhdr *note64 = NULL;
+	size_t tot, len = 0;
+	int num = 0;
+
+	/* --no_elf_notes is specified at invocation command line, so skip process elf notes data. */
+	if (dd->flags & NO_ELF_NOTES)
+		return;
+
+	for (tot = 0; tot < size_note; tot += len) {
+		if (machine_type("X86_64")) {
+			note64 = note_ptr + tot;
+
+			len = sizeof(Elf64_Nhdr);
+			len = roundup(len + note64->n_namesz, 4);
+			len = roundup(len + note64->n_descsz, 4);
+
+			if (note64->n_type == NT_PRSTATUS) {
+				if ((dd->nt_prstatus_percpu[num] = malloc(len)) == NULL) {
+					error(FATAL, "compressed kdump: cannot malloc buffer"
+						" for NR_PRSTATUS notes\n");
+				}
+				BCOPY((void *)note64, dd->nt_prstatus_percpu[num], len);
+				num++;
+			}
+
+		} else if (machine_type("X86")) {
+			note32 = note_ptr + tot;
+
+			len = sizeof(Elf32_Nhdr);
+			len = roundup(len + note32->n_namesz, 4);
+			len = roundup(len + note32->n_descsz, 4);
+
+			if (note32->n_type == NT_PRSTATUS) {
+				if ((dd->nt_prstatus_percpu[num] = malloc(len)) == NULL) {
+					error(FATAL, "compressed kdump: cannot malloc buffer"
+						" for NR_PRSTATUS notes\n");
+				}
+				BCOPY((void *)note32, dd->nt_prstatus_percpu[num], len);
+				num++;
+			}
+		}
+	}
+
+	if (num > 0) {
+		pc->flags2 |= ELF_NOTES;
+		dd->num_prstatus_notes = num;
+	}
+}
+
 static int read_dump_header(char *file)
 {
 	struct disk_dump_header *header = NULL;
@@ -402,6 +490,10 @@ restart:
 			error(FATAL, "compressed kdump: cannot malloc notes"
 				" buffer\n");
 
+		if ((dd->nt_prstatus_percpu = malloc(NR_CPUS * sizeof(void*))) == NULL)
+			error(FATAL, "compressed kdump: cannot malloc pointer"
+				" to NT_PRSTATUS notes\n");
+
 		if (FLAT_FORMAT()) {
 			if (!read_flattened_format(dd->dfd, offset, notes_buf, size)) {
 				error(INFO, "compressed kdump: cannot read notes data"
@@ -913,6 +1005,77 @@ err:
 	return;
 }
 
+static void dump_nt_prstatus_offset(FILE *fp)
+{
+	unsigned char *notes_buf;
+	struct kdump_sub_header *sub_header_kdump = dd->sub_header_kdump;
+	size_t size;
+	off_t offset;
+	Elf32_Nhdr *note32 = NULL;
+	Elf64_Nhdr *note64 = NULL;
+	size_t tot, len = 0;
+
+	if (KDUMP_CMPRS_VALID() && (dd->header->header_version >= 4) &&
+	    (sub_header_kdump->offset_note) &&
+	    (sub_header_kdump->size_note) && (machdep->process_elf_notes)) {
+		size = sub_header_kdump->size_note;
+		offset = sub_header_kdump->offset_note;
+
+		if ((notes_buf = malloc(size)) == NULL)
+			error(FATAL, "compressed kdump: cannot malloc notes"
+				" buffer\n");
+
+		if (FLAT_FORMAT()) {
+			if (!read_flattened_format(dd->dfd, offset, notes_buf, size)) {
+				error(INFO, "compressed kdump: cannot read notes data"
+					"\n");
+				goto err;
+			}
+		} else {
+			if (lseek(dd->dfd, offset, SEEK_SET) == (off_t)-1) {
+				error(INFO, "compressed kdump: cannot lseek notes data\n");
+				goto err;
+			}
+			if (read(dd->dfd, notes_buf, size) < size) {
+				error(INFO, "compressed kdump: cannot read notes data"
+					"\n");
+				goto err;
+			}
+		}
+
+		fprintf(fp, "  NT_PRSTATUS_offset: ");
+		for (tot = 0; tot < size; tot += len) {
+			if (machine_type("X86_64")) {
+				note64 = (void *)notes_buf + tot;
+				len = sizeof(Elf64_Nhdr);
+				len = roundup(len + note64->n_namesz, 4);
+				len = roundup(len + note64->n_descsz, 4);
+
+				if (note64->n_type == NT_PRSTATUS)
+					fprintf(fp, "%s%lx\n",
+						(tot == 0) ? "" : "                      ",
+						offset + tot);
+
+			} else if (machine_type("X86")) {
+				note32 = (void *)notes_buf + tot;
+				len = sizeof(Elf32_Nhdr);
+				len = roundup(len + note32->n_namesz, 4);
+				len = roundup(len + note32->n_descsz, 4);
+
+				if (note32->n_type == NT_PRSTATUS)
+					fprintf(fp, "%s%lx\n",
+						(tot == 0) ? "" : "                      ",
+						offset + tot);
+			}
+		}
+	}
+
+err:
+	if (notes_buf)
+		free(notes_buf);
+	return;
+}
+
 /*
  *  This function is dump-type independent, and could be used
  *  to dump the diskdump_data structure contents and perhaps
@@ -942,6 +1105,8 @@ __diskdump_memory_dump(FILE *fp)
                 fprintf(fp, "%sERROR_EXCLUDED", others++ ? "|" : "");
         if (dd->flags & ZERO_EXCLUDED)
                 fprintf(fp, "%sZERO_EXCLUDED", others++ ? "|" : "");
+	if (dd->flags & NO_ELF_NOTES)
+		fprintf(fp, "%sNO_ELF_NOTES", others++ ? "|" : "");
         fprintf(fp, ") %s\n", FLAT_FORMAT() ? "[FLAT]" : "");
         fprintf(fp, "               dfd: %d\n", dd->dfd);
         fprintf(fp, "               ofp: %lx\n", (ulong)dd->ofp);
@@ -1101,6 +1266,13 @@ __diskdump_memory_dump(FILE *fp)
 				(ulong)dd->sub_header_kdump->offset_note);
 			fprintf(fp, "           size_note: %lu\n",
 				dd->sub_header_kdump->size_note);
+			fprintf(fp, "     number_of_notes: %d\n",
+				dd->num_prstatus_notes);
+			for (i = 0; i < dd->num_prstatus_notes; i++) {
+				fprintf(fp, "            notes[%d]: %lx\n",
+					i, (ulong)dd->nt_prstatus_percpu[i]);
+			}
+			dump_nt_prstatus_offset(fp);
 		}
 		fprintf(fp, "\n");
 	} else
@@ -1226,3 +1398,8 @@ show_split_dumpfiles(void)
 			fprintf(fp, "\n");
 	}
 }
+
+void *diskdump_get_prstatus_percpu(int cpu)
+{
+	return dd->nt_prstatus_percpu[cpu];
+}
diff --git a/main.c b/main.c
index 8c30fed..85a1531 100755
--- a/main.c
+++ b/main.c
@@ -62,6 +62,7 @@ static struct option long_options[] = {
 	{"mod", required_argument, 0, 0},
 	{"kvmhost", required_argument, 0, 0},
 	{"kvmio", required_argument, 0, 0},
+	{"no_elf_notes", 0, 0, 0},
         {0, 0, 0, 0}
 };
 
@@ -177,6 +178,9 @@ main(int argc, char **argv)
 		        else if (STREQ(long_options[option_index].name, "zero_excluded")) 
 				*diskdump_flags |= ZERO_EXCLUDED;
 
+			else if (STREQ(long_options[option_index].name, "no_elf_notes"))
+				*diskdump_flags |= NO_ELF_NOTES;
+
 		        else if (STREQ(long_options[option_index].name, "no_panic")) 
 				tt->flags |= PANIC_TASK_NOT_FOUND;
 
diff --git a/netdump.c b/netdump.c
index 7916df1..918de0f 100644
--- a/netdump.c
+++ b/netdump.c
@@ -39,6 +39,7 @@ static physaddr_t xen_kdump_p2m(physaddr_t);
 static void check_dumpfile_size(char *);
 static int proc_kcore_init_32(FILE *fp);
 static int proc_kcore_init_64(FILE *fp);
+static char * get_regs_from_note(char *, ulong *, ulong *);
 
 #define ELFSTORE 1
 #define ELFREAD  0
@@ -2170,6 +2171,39 @@ get_netdump_regs(struct bt_info *bt, ulong *eip, ulong *esp)
 	}
 }
 
+/* get regs from elf note, and return the address of user_regs. */
+static char * get_regs_from_note(char *note, ulong *ip, ulong *sp)
+{
+	Elf32_Nhdr *note32;
+	Elf64_Nhdr *note64;
+	size_t len;
+	char *user_regs;
+	long offset_sp, offset_ip;
+
+	if (machine_type("X86_64")) {
+		note64 = (Elf64_Nhdr *)note;
+		len = sizeof(Elf64_Nhdr);
+		len = roundup(len + note64->n_namesz, 4);
+		len = roundup(len + note64->n_descsz, 4);
+		offset_sp = OFFSET(user_regs_struct_rsp);
+		offset_ip = OFFSET(user_regs_struct_rip);
+	} else if (machine_type("X86")) {
+		note32 = (Elf32_Nhdr *)note;
+		len = sizeof(Elf32_Nhdr);
+		len = roundup(len + note32->n_namesz, 4);
+		len = roundup(len + note32->n_descsz, 4);
+		offset_sp = OFFSET(user_regs_struct_esp);
+		offset_ip = OFFSET(user_regs_struct_eip);
+	} else
+		return NULL;
+
+	user_regs = note + len - SIZE(user_regs_struct) - sizeof(long);
+	*sp = ULONG(user_regs + offset_sp);
+	*ip = ULONG(user_regs + offset_ip);
+
+	return user_regs;
+}
+
 struct x86_64_user_regs_struct {
         unsigned long r15,r14,r13,r12,rbp,rbx,r11,r10;
         unsigned long r9,r8,rax,rcx,rdx,rsi,rdi,orig_rax;
@@ -2186,6 +2220,7 @@ get_netdump_regs_x86_64(struct bt_info *bt, ulong *ripp, ulong *rspp)
         size_t len;
         char *user_regs;
 	ulong regs_size, rsp_offset, rip_offset;
+	ulong rip, rsp;
 
         if (is_task_active(bt->task)) 
                 bt->flags |= BT_DUMPFILE_SEARCH;
@@ -2232,6 +2267,28 @@ get_netdump_regs_x86_64(struct bt_info *bt, ulong *ripp, ulong *rspp)
 		bt->machdep = (void *)user_regs;
 	}
 
+	if (ELF_NOTES_VALID() && (bt->flags & BT_DUMPFILE_SEARCH) && DISKDUMP_DUMPFILE()) {
+		note = (Elf64_Nhdr *)
+			diskdump_get_prstatus_percpu(bt->tc->processor);
+		if (note == NULL)
+			goto skip_notes;
+
+		user_regs = get_regs_from_note((char *)note, &rip, &rsp);
+
+		if (CRASHDEBUG(1))
+			netdump_print("ELF prstatus rsp: %lx rip: %lx\n",
+				rsp, rip);
+
+		*rspp = rsp;
+		*ripp = rip;
+
+		if (*ripp && *rspp)
+			bt->flags |= BT_KDUMP_ELF_REGS;
+
+		bt->machdep = (void *)user_regs;
+	}
+
+skip_notes:
         machdep->get_stack_frame(bt, ripp, rspp);
 }
 
@@ -2423,6 +2480,28 @@ next_sysrq:
                 goto retry;
         }
 
+	if (ELF_NOTES_VALID() && DISKDUMP_DUMPFILE()) {
+		Elf32_Nhdr *note;
+		char *user_regs;
+		ulong ip, sp;
+
+		note = (Elf32_Nhdr *)
+			diskdump_get_prstatus_percpu(bt->tc->processor);
+		if (note == NULL)
+			goto skip_notes;
+
+		user_regs = get_regs_from_note((char *)note, &ip, &sp);
+		if (is_kernel_text(ip) &&
+		    (((sp >= GET_STACKBASE(bt->task)) &&
+		      (sp < GET_STACKTOP(bt->task))) ||
+		    in_alternate_stack(bt->tc->processor, sp))) {
+			*eip = ip;
+			*esp = sp;
+			return;
+		}
+	}
+
+skip_notes:
 	if (CRASHDEBUG(1))
 		error(INFO, 
     "get_netdump_regs_x86: cannot find anything useful (task: %lx)\n", bt->task);
diff --git a/task.c b/task.c
index 266b8de..8d4d02b 100755
--- a/task.c
+++ b/task.c
@@ -458,6 +458,8 @@ task_init(void)
 	else {
 		if (KDUMP_DUMPFILE())
 			map_cpus_to_prstatus();
+		else if (ELF_NOTES_VALID() && DISKDUMP_DUMPFILE())
+			map_cpus_to_prstatus_kdump_cmprs();
 		please_wait("determining panic task");
 		set_context(get_panic_context(), NO_PID);
 		please_wait_done();
diff --git a/x86.c b/x86.c
index c5cf010..4425ee1 100755
--- a/x86.c
+++ b/x86.c
@@ -1704,6 +1704,9 @@ x86_init(int when)
 
 	switch (when)
 	{
+	case SETUP_ENV:
+		machdep->process_elf_notes = x86_process_elf_notes;
+		break;
 	case PRE_SYMTAB:
 		machdep->verify_symbol = x86_verify_symbol;
                 if (pc->flags & KERNEL_DEBUG_QUERY)
@@ -1797,6 +1800,12 @@ x86_init(int when)
 		else
 			MEMBER_OFFSET_INIT(user_regs_struct_esp,
 				"user_regs_struct", "sp");
+		if (MEMBER_EXISTS("user_regs_struct", "eip"))
+			MEMBER_OFFSET_INIT(user_regs_struct_eip,
+				"user_regs_struct", "eip");
+		else
+			MEMBER_OFFSET_INIT(user_regs_struct_eip,
+				"user_regs_struct", "ip");
 		if (!VALID_STRUCT(user_regs_struct)) {
 			/*  Use this hardwired version -- sometimes the 
 			 *  debuginfo doesn't pick this up even though
@@ -1817,6 +1826,8 @@ x86_init(int when)
 				offsetof(struct x86_user_regs_struct, ebp);
 			ASSIGN_OFFSET(user_regs_struct_esp) =
 				offsetof(struct x86_user_regs_struct, esp);
+			ASSIGN_OFFSET(user_regs_struct_eip) =
+				offsetof(struct x86_user_regs_struct, eip);
 		}
 		MEMBER_OFFSET_INIT(thread_struct_cr3, "thread_struct", "cr3");
 		STRUCT_SIZE_INIT(cpuinfo_x86, "cpuinfo_x86");
diff --git a/x86_64.c b/x86_64.c
index eaf6373..6639cf2 100755
--- a/x86_64.c
+++ b/x86_64.c
@@ -124,6 +124,9 @@ x86_64_init(int when)
 
 	switch (when)
 	{
+	case SETUP_ENV:
+		machdep->process_elf_notes = x86_process_elf_notes;
+		break;
 	case PRE_SYMTAB:
 		machdep->verify_symbol = x86_64_verify_symbol;
                 machdep->machspec = &x86_64_machine_specific;
@@ -4043,6 +4046,12 @@ x86_64_get_dumpfile_stack_frame(struct bt_info *bt_in, ulong *rip, ulong *rsp)
 				goto skip_stage;
 			}
 		}
+	} else if (ELF_NOTES_VALID()) {
+		user_regs = bt->machdep;
+		ur_rip = ULONG(user_regs +
+			OFFSET(user_regs_struct_rip));
+		ur_rsp = ULONG(user_regs +
+			OFFSET(user_regs_struct_rsp));
 	}
 
 	panic = FALSE;
-- 
1.7.3

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