[PATCH] [makedumpfile] Fix ELF output with overlapping sections

Ken'ichi Ohmichi oomichi at mxs.nes.nec.co.jp
Wed May 30 22:26:08 EDT 2007


Hi Bernhard,

2007/05/18 12:47:15 +0200, Bernhard Walle <bwalle at suse.de> wrote:
>I have a core dump with following program headers on IA64:
>
>  LOAD           0x0000000000001f4c 0xa000000100000000 0x0000000004000000
>                 0x000000000055c4a0 0x000000000055c4a0  RWE    0
>...
>  LOAD           0x00000000044fc3ec 0xe000000004000000 0x0000000004000000
>                 0x0000000000c92000 0x0000000000c92000  RWE    0
>
>The interesting thing is the overlap in the physical address space.
>write_elf_pages() assumes that there's no overlap because it looks only
>for the file offset according to the physical start address and silently
>assumes that the length matches.

Thank you for the patch.
I'm worry that the overlapping spaces may have the same p_filesz.
I think it is certain to check it by p_offset, and created the
attached patch. Please let me know your opinion.


BTW, I don't know the reason why your system's /proc/vmcore has the
overlapping physical address. If you know it, please let me know.


Thanks
Ken'ichi Ohmichi

------------------------------------------------------------


Signed-off-by: Bernhard Walle <bwalle at suse.de>
Signed-off-by: Ken'ichi Ohmichi <oomichi at mxs.nes.nec.co.jp>
---

diff -puN backup/v1.1.3/makedumpfile.c a/makedumpfile.c
--- backup/v1.1.3/makedumpfile.c	2007-04-13 15:44:55.000000000 +0900
+++ a/makedumpfile.c	2007-05-31 11:18:04.000000000 +0900
@@ -2561,6 +2561,33 @@ out:
 	return ret;
 }
 
+/*
+ * Sames as paddr_to_offset() but makes sure that the specified offset (hint)
+ * in the segment.
+ */
+off_t
+paddr_to_offset2(struct DumpInfo *info, unsigned long long paddr, off_t hint)
+{
+	int i;
+	off_t offset;
+	unsigned long long len;
+	struct pt_load_segment *pls;
+
+	for (i = offset = 0; i < info->num_load_memory; i++) {
+		pls = &info->pt_load_segments[i];
+		len = pls->phys_end - pls->phys_start;
+		if ((paddr >= pls->phys_start)
+		    && (paddr < pls->phys_end)
+		    && (hint >= pls->file_offset)
+		    && (hint < pls->file_offset + len)) {
+			offset = (off_t)(paddr - pls->phys_start) +
+				pls->file_offset;
+				break;
+		}
+	}
+	return offset;
+}
+
 unsigned long long
 page_to_pfn(struct DumpInfo *info, unsigned long page)
 {
@@ -3462,7 +3489,6 @@ write_elf_pages(struct DumpInfo *info)
 
 	off_seg_load  = info->offset_load_dumpfile;
 	cd_seg.offset = info->offset_load_dumpfile;
-	off_memory = 0;
 
 	if (info->flag_elf64) { /* ELF64 */
 		cd_hdr.offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr);
@@ -3488,7 +3514,7 @@ write_elf_pages(struct DumpInfo *info)
 			}
 			if (load64.p_type != PT_LOAD)
 				continue;
-
+			off_memory= load64.p_offset;
 			paddr     = load64.p_paddr;
 			pfn_start = load64.p_paddr / page_size;
 			pfn_end   = (load64.p_paddr+ load64.p_memsz)/page_size;
@@ -3501,6 +3527,7 @@ write_elf_pages(struct DumpInfo *info)
 			}
 			if (load32.p_type != PT_LOAD)
 				continue;
+			off_memory= load32.p_offset;
 			paddr     = load32.p_paddr;
 			pfn_start = load32.p_paddr / page_size;
 			pfn_end   = (load32.p_paddr+ load32.p_memsz)/page_size;
@@ -3588,7 +3615,7 @@ write_elf_pages(struct DumpInfo *info)
 			/*
 			 * Write a PT_LOAD segment.
 			 */
-			off_memory = paddr_to_offset(info, paddr);
+			off_memory = paddr_to_offset2(info, paddr, off_memory);
 			if (!off_memory) {
 				ERRMSG("Can't convert physaddr(%llx) to a offset.\n",
 				    paddr);
@@ -3680,7 +3707,7 @@ write_elf_pages(struct DumpInfo *info)
 		/*
 		 * Write a PT_LOAD segment.
 		 */
-		off_memory = paddr_to_offset(info, paddr);
+		off_memory = paddr_to_offset2(info, paddr, off_memory);
 		if (!off_memory) {
 			ERRMSG("Can't convert physaddr(%llx) to a offset.\n",
 			    paddr);
_



More information about the kexec mailing list