makedumpfile: backport security filter feature fixes.

From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>

This patch backports the makedumpfile security filter fixes from upstream
makedumpfile-1.4.0 to kexec-tools on RHEL6.3. This patch cleanly applies on
kexec-tools--2.0.0-214.el6

This patch is generated by backporting following upstream patches:

- [PATCH] Use the same format as erase commands for eraseinfo data.    894680e
- [PATCH] Fix array traversal for array of structure and char type.    6a78de7
- [PATCH] Cleanup: Revert unnecessary change about writing sub header. 4edcbc5
- [PATCH] Identify eraseinfo without NT_ERASE_INFO.                    389e1c8
- [PATCH] Bugfix: Avoid a SIGSEGV at the memset() of                   40c5772
          write_cache_zero().
- [PATCH] Bugfix: Avoid writting offset_eraseinfo in kdump_sub_header  de50b06
          if not containing eraseinfo.
- [PATCH] Bugfix: set kdump_sub_header data with --reassemble option.  bb646d8
- [PATCH] Add free() and use CONFIG_SKIP_SECTION.                      706ab0b
- [PATCH] Move debuginfo search to set_dwarf_debuginfo() routine.      af54031
- [PATCH] Cleanup: Get a pointer size by sizeof(void  -).              d07bc64
- [PATCH] Cleanup: Add __load_module_symbol() for shrinking function   91f3696
          size.
- [PATCH] Cleanup: Output error message if mod_st.num_modules is 0.    e80c858
- [PATCH] Cleanup: Make the call of dwfl_report_offline() clear.       2536dd9
- [PATCH] Cleanup: Fix return values of get_symbol_addr, etc.          c20e415
- [PATCH] Bugfix: Write both vmcoreinfo and pt_note when reassembling. 3a93bbb
- [PATCH] Bugfix: Skip writing PT_LOAD segment not having real data.   e3ac177

Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
---
 makedumpfile-1.3.5/IMPLEMENTATION |    4 
 makedumpfile-1.3.5/makedumpfile.c |  940 ++++++++++++++++++++++---------------
 makedumpfile-1.3.5/makedumpfile.h |   18 -
 makedumpfile-1.3.5/s390x.c        |    4 
 4 files changed, 562 insertions(+), 404 deletions(-)

diff --git a/makedumpfile-1.3.5/IMPLEMENTATION b/makedumpfile-1.3.5/IMPLEMENTATION
index cafc596..94390e4 100644
--- a/makedumpfile-1.3.5/IMPLEMENTATION
+++ b/makedumpfile-1.3.5/IMPLEMENTATION
@@ -26,9 +26,9 @@
     |                        :                 |
     |         page data (pfn Z)                |
     +------------------------------------------+ offset_eraseinfo
-    | erase mystruct2.mystruct1.var 4          |
+    | erase mystruct2.mystruct1.var size 4     |
     | erase mystruct2.mystruct1.ptr nullify    |
-    | erase mystruct2.mystruct.array 100       |
+    | erase mystruct2.mystruct.array size 100  |
     +------------------------------------------+
 
 
diff --git a/makedumpfile-1.3.5/makedumpfile.c b/makedumpfile-1.3.5/makedumpfile.c
index fac95e8..e0c6ed8 100644
--- a/makedumpfile-1.3.5/makedumpfile.c
+++ b/makedumpfile-1.3.5/makedumpfile.c
@@ -34,7 +34,6 @@ unsigned long		num_erase_info = 1; /* Node 0 is unused. */
 char filename_stdout[] = FILENAME_STDOUT;
 int message_level;
 int flag_ignore_r_char; /* 0: '\r' is effective. 1: not effective. */
-long pointer_size;
 char config_buf[BUFSIZE_FGETS];
 
 /*
@@ -1407,12 +1406,61 @@ clean_dwfl_info(void)
 }
 
 /*
- * Intitialize the dwarf info.
- * Linux kernel module debuginfo are of ET_REL (relocatable) type. The old
- * implementation of get_debug_info() function that reads the debuginfo was
- * not relocation-aware and hence could not read the dwarf info properly
- * from module debuginfo.
+ * Search module debuginfo.
+ * This function searches for module debuginfo in default debuginfo path for
+ * a given module in dwarf_info.module_name.
  *
+ * On success, dwarf_info.name_debuginfo is set to absolute path of
+ * module debuginfo.
+ */
+static int
+search_module_debuginfo(void)
+{
+	Dwfl *dwfl = NULL;
+	static char *debuginfo_path = DEFAULT_DEBUGINFO_PATH;
+	static const Dwfl_Callbacks callbacks = {
+		.section_address = dwfl_offline_section_address,
+		.find_debuginfo = dwfl_standard_find_debuginfo,
+		.debuginfo_path = &debuginfo_path,
+	};
+
+	/*
+	 * Check if We already have debuginfo file name with us. If yes,
+	 * then we don't need to proceed with search method.
+	 */
+	if (dwarf_info.name_debuginfo)
+		return TRUE;
+
+	if ((dwfl = dwfl_begin(&callbacks)) == NULL) {
+		ERRMSG("Can't create a handle for a new dwfl session.\n");
+		return FALSE;
+	}
+
+	/* Search for module debuginfo file. */
+	if (dwfl_linux_kernel_report_offline(dwfl,
+						info->system_utsname.release,
+						&dwfl_report_module_p)) {
+		ERRMSG("Can't get Module debuginfo for module '%s'\n",
+					dwarf_info.module_name);
+		dwfl_end(dwfl);
+		return FALSE;
+	}
+	dwfl_report_end(dwfl, NULL, NULL);
+	dwfl_getmodules(dwfl, &process_module, NULL, 0);
+
+	dwfl_end(dwfl);
+	clean_dwfl_info();
+
+	/* Return success if module debuginfo is found. */
+	if (dwarf_info.name_debuginfo)
+		return TRUE;
+
+	return FALSE;
+}
+
+/*
+ * Initialize the dwarf info.
+ * Linux kernel module debuginfo are of ET_REL (relocatable) type.
  * This function uses dwfl API's to apply relocation before reading the
  * dwarf information from module debuginfo.
  * On success, this function sets the dwarf_info.elfd and dwarf_info.dwarfd
@@ -1423,54 +1471,45 @@ init_dwarf_info(void)
 {
 	Dwfl *dwfl = NULL;
 	int dwfl_fd = -1;
-	static char *debuginfo_path = DEFAULT_DEBUGINFO_PATH;
 	static const Dwfl_Callbacks callbacks = {
 		.section_address = dwfl_offline_section_address,
-		.find_debuginfo = dwfl_standard_find_debuginfo,
-		.debuginfo_path = &debuginfo_path,
 	};
 
 	dwarf_info.elfd = NULL;
 	dwarf_info.dwarfd = NULL;
 
+	 /*
+	  * We already know the absolute path of debuginfo file. Fail if we
+	  * still don't have one. Ideally we should never be in this situation.
+	  */
+	if (!dwarf_info.name_debuginfo) {
+		ERRMSG("Can't find absolute path to debuginfo file.\n");
+		return FALSE;
+	}
+
 	if ((dwfl = dwfl_begin(&callbacks)) == NULL) {
 		ERRMSG("Can't create a handle for a new dwfl session.\n");
 		return FALSE;
 	}
 
-	if (dwarf_info.name_debuginfo) {
-		/* We have absolute path for debuginfo file, use it directly
-		 * instead of searching it through
-		 * dwfl_linux_kernel_report_offline() call.
-		 *
-		 * Open the debuginfo file if it is not already open.
-		 */
-		if (dwarf_info.fd_debuginfo < 0)
-			dwarf_info.fd_debuginfo =
-				open(dwarf_info.name_debuginfo, O_RDONLY);
-
-		dwfl_fd = dup(dwarf_info.fd_debuginfo);
-		if (dwfl_fd < 0) {
-			ERRMSG("Failed to get a duplicate handle for"
-				" debuginfo.\n");
-			goto err_out;
-		}
-	}
-	if (dwarf_info.fd_debuginfo > 0) {
-		if (dwfl_report_offline(dwfl, dwarf_info.module_name,
-				dwarf_info.name_debuginfo, dwfl_fd) == NULL) {
-			ERRMSG("Failed reading %s: %s\n",
-				dwarf_info.name_debuginfo, dwfl_errmsg (-1));
-			/* dwfl_fd is consumed on success, not on failure */
-			close(dwfl_fd);
-			goto err_out;
-		}
+	/* Open the debuginfo file if it is not already open.  */
+	if (dwarf_info.fd_debuginfo < 0)
+		dwarf_info.fd_debuginfo =
+			open(dwarf_info.name_debuginfo, O_RDONLY);
+
+	dwfl_fd = dup(dwarf_info.fd_debuginfo);
+	if (dwfl_fd < 0) {
+		ERRMSG("Failed to get a duplicate handle for"
+			" debuginfo.\n");
+		goto err_out;
 	}
-	else if (dwfl_linux_kernel_report_offline(dwfl,
-						info->system_utsname.release,
-						&dwfl_report_module_p)) {
-		ERRMSG("Can't get Module debuginfo for module '%s'\n",
-					dwarf_info.module_name);
+	/* Apply relocations. */
+	if (dwfl_report_offline(dwfl, dwarf_info.module_name,
+			dwarf_info.name_debuginfo, dwfl_fd) == NULL) {
+		ERRMSG("Failed reading %s: %s\n",
+			dwarf_info.name_debuginfo, dwfl_errmsg (-1));
+		/* dwfl_fd is consumed on success, not on failure */
+		close(dwfl_fd);
 		goto err_out;
 	}
 	dwfl_report_end(dwfl, NULL, NULL);
@@ -1565,7 +1604,7 @@ get_symbol_addr(char *symname)
 		return symbol;
 
 	if (!init_dwarf_info())
-		return 0;
+		return NOT_FOUND_SYMBOL;
 
 	elfd = dwarf_info.elfd;
 
@@ -1624,7 +1663,7 @@ get_next_symbol_addr(char *symname)
 	char *sym_name = NULL;
 
 	if (!init_dwarf_info())
-		return 0;
+		return NOT_FOUND_SYMBOL;
 
 	elfd = dwarf_info.elfd;
 
@@ -1755,6 +1794,14 @@ get_data_array_length(Dwarf *dwarfd, Dwarf_Die *die)
 		return FALSE;
 	}
 	tag = dwarf_tag(&die_type);
+	if (tag == DW_TAG_const_type) {
+		/* This array is of const type. Get the die type again */
+		if (!get_die_type(dwarfd, &die_type, &die_type)) {
+			ERRMSG("Can't get CU die of DW_AT_type.\n");
+			return FALSE;
+		}
+		tag = dwarf_tag(&die_type);
+	}
 	if (tag != DW_TAG_array_type) {
 		/*
 		 * This kernel doesn't have the member of array.
@@ -2283,10 +2330,6 @@ get_debug_info(void)
 	 */
 	while (dwarf_nextcu(dwarfd, off, &next_off, &header_size,
 	    &abbrev_offset, &address_size, &offset_size) == 0) {
-		if (dwarf_info.cmd == DWARF_INFO_GET_PTR_SIZE) {
-			dwarf_info.struct_size = address_size;
-			break;
-		}
 		off += header_size;
 		if (dwarf_offdie(dwarfd, off, &cu_die) == NULL) {
 			ERRMSG("Can't get CU die.\n");
@@ -2330,14 +2373,7 @@ get_structure_size(char *structname, int flag_typedef)
 long
 get_pointer_size()
 {
-	dwarf_info.cmd = DWARF_INFO_GET_PTR_SIZE;
-	/* reuse struct_size member to report pointer size */
-	dwarf_info.struct_size = NOT_FOUND_STRUCTURE;
-
-	if (!get_debug_info())
-		return FAILED_DWARFINFO;
-
-	return dwarf_info.struct_size;
+	return sizeof(void *);
 }
 
 /*
@@ -2510,8 +2546,6 @@ get_symbol_info(void)
 	if (SYMBOL(node_memblk) != NOT_FOUND_SYMBOL)
 		SYMBOL_ARRAY_LENGTH_INIT(node_memblk, "node_memblk");
 
-	pointer_size = get_pointer_size();
-
 	return TRUE;
 }
 
@@ -2772,20 +2806,19 @@ set_dwarf_debuginfo(char *mod_name, char *name_debuginfo, int fd_debuginfo)
 		if (dwarf_info.name_debuginfo)
 			free(dwarf_info.name_debuginfo);
 	}
+	if (dwarf_info.module_name)
+		free(dwarf_info.module_name);
+
 	dwarf_info.fd_debuginfo = fd_debuginfo;
 	dwarf_info.name_debuginfo = name_debuginfo;
-	dwarf_info.module_name = mod_name;
+	dwarf_info.module_name = strdup(mod_name);
 
 	if (!strcmp(dwarf_info.module_name, "vmlinux") ||
 		!strcmp(dwarf_info.module_name, "xen-syms"))
 		return TRUE;
 
 	/* check to see whether module debuginfo is available */
-	if (!init_dwarf_info())
-		return FALSE;
-	else
-		clean_dwfl_info();
-	return TRUE;
+	return search_module_debuginfo();
 }
 
 int
@@ -3325,7 +3358,15 @@ get_pt_note_info(off_t off_note, unsigned long sz_note)
 				return FALSE;
 			}
 			info->p2m_mfn = p2m_mfn;
-		} else if (n_type == NT_ERASE_INFO) {
+
+		/*
+		 * Check whether a source dumpfile contains eraseinfo.
+		 *   /proc/vmcore does not contain eraseinfo, because eraseinfo
+		 *   is added only by makedumpfile and makedumpfile does not
+		 *   create /proc/vmcore.
+		 */
+		} else if (!strncmp(ERASEINFO_NOTE_NAME, buf,
+		    ERASEINFO_NOTE_NAME_BYTES)) {
 			info->offset_eraseinfo = offset_desc;
 			info->size_eraseinfo = size_desc;
 		}
@@ -4625,6 +4666,9 @@ write_cache_bufsz(struct cache_data *cd)
 int
 write_cache_zero(struct cache_data *cd, size_t size)
 {
+	if (!write_cache_bufsz(cd))
+		return FALSE;
+
 	memset(cd->buf + cd->buf_size, 0, size);
 	cd->buf_size += size;
 
@@ -5833,7 +5877,7 @@ write_elf_header(struct cache_data *cd_header)
 		if (fl_info->nullify)
 			sprintf(size_str, "nullify\n");
 		else
-			sprintf(size_str, "%ld\n", fl_info->size);
+			sprintf(size_str, "size %ld\n", fl_info->size);
 
 		size_eraseinfo += strlen("erase ") +
 				strlen(ei->symbol_expr) + 1 +
@@ -6019,15 +6063,9 @@ write_kdump_header(void)
 			kh.size_vmcoreinfo = info->size_vmcoreinfo;
 		}
 	}
-	/*
-	 * While writing dump data to STDOUT, delay the writing of sub header
-	 * untill we gather erase info offset and size.
-	 */
-	if (!info->flag_flatten) {
-		if (!write_buffer(info->fd_dumpfile, dh->block_size, &kh,
-		    size, info->name_dumpfile))
-			goto out;
-	}
+	if (!write_buffer(info->fd_dumpfile, dh->block_size, &kh,
+	    size, info->name_dumpfile))
+		goto out;
 
 	info->sub_header = kh;
 	info->offset_bitmap1
@@ -6328,7 +6366,15 @@ write_elf_pages(struct cache_data *cd_header, struct cache_data *cd_page)
 			 */
 			load.p_memsz  = memsz;
 			load.p_filesz = filesz;
-			load.p_offset = off_seg_load;
+			if (load.p_filesz)
+				load.p_offset = off_seg_load;
+			else
+				/*
+				 * If PT_LOAD segment does not have real data
+				 * due to the all excluded pages, the file
+				 * offset is not effective and it should be 0.
+				 */
+				load.p_offset = 0;
 
 			/*
 			 * Write a PT_LOAD header.
@@ -6339,9 +6385,10 @@ write_elf_pages(struct cache_data *cd_header, struct cache_data *cd_page)
 			/*
 			 * Write a PT_LOAD segment.
 			 */
-			if (!write_elf_load_segment(cd_page, paddr, off_memory,
-			    load.p_filesz))
-				return FALSE;
+			if (load.p_filesz)
+				if (!write_elf_load_segment(cd_page, paddr,
+				    off_memory, load.p_filesz))
+					return FALSE;
 
 			load.p_paddr += load.p_memsz;
 #ifdef __x86__
@@ -6378,8 +6425,10 @@ write_elf_pages(struct cache_data *cd_header, struct cache_data *cd_page)
 		/*
 		 * Write a PT_LOAD segment.
 		 */
-		if (!write_elf_load_segment(cd_page, paddr, off_memory, load.p_filesz))
-			return FALSE;
+		if (load.p_filesz)
+			if (!write_elf_load_segment(cd_page, paddr,
+						    off_memory, load.p_filesz))
+				return FALSE;
 
 		off_seg_load += load.p_filesz;
 	}
@@ -6690,7 +6739,7 @@ write_eraseinfo(struct cache_data *cd_page, unsigned long *size_out)
 			continue;
 		for (j = 0; j < erase_info[i].num_sizes; j++) {
 			if (erase_info[i].sizes[j] > 0)
-				sprintf(size_str, "%ld\n",
+				sprintf(size_str, "size %ld\n",
 						erase_info[i].sizes[j]);
 			else if (erase_info[i].sizes[j] == -1)
 				sprintf(size_str, "nullify\n");
@@ -6761,14 +6810,14 @@ write_elf_eraseinfo(struct cache_data *cd_header)
 		note_header_size = sizeof(Elf64_Nhdr);
 		nh->n_namesz = ERASEINFO_NOTE_NAME_BYTES;
 		nh->n_descsz = info->size_eraseinfo;
-		nh->n_type = NT_ERASE_INFO;
+		nh->n_type = 0;
 	} else {
 		Elf32_Nhdr *nh = (Elf32_Nhdr *)note;
 
 		note_header_size = sizeof(Elf32_Nhdr);
 		nh->n_namesz = ERASEINFO_NOTE_NAME_BYTES;
 		nh->n_descsz = info->size_eraseinfo;
-		nh->n_type = NT_ERASE_INFO;
+		nh->n_type = 0;
 	}
 	if (!write_cache(cd_header, note, note_header_size))
 		return FALSE;
@@ -6826,9 +6875,10 @@ write_kdump_eraseinfo(struct cache_data *cd_page)
 	DEBUG_MSG("offset_eraseinfo: %lx, size_eraseinfo: %ld\n",
 			info->offset_eraseinfo, info->size_eraseinfo);
 
-	/* Update the erase info offset and size in kdump sub header */
-	if (!update_sub_header())
-		return FALSE;
+	if (info->size_eraseinfo)
+		/* Update the erase info offset and size in kdump sub header */
+		if (!update_sub_header())
+			return FALSE;
 
 	return TRUE;
 }
@@ -7851,27 +7901,165 @@ clean_module_symbols(void)
 }
 
 static int
-load_module_symbols(void)
+__load_module_symbol(struct module_info *modules, unsigned long addr_module)
 {
-	unsigned long head, cur, cur_module;
+	int ret = FALSE;
+	unsigned int nsym;
 	unsigned long symtab, strtab;
 	unsigned long mod_base, mod_init;
 	unsigned int mod_size, mod_init_size;
-	unsigned char *module_struct_mem, *module_core_mem;
+	unsigned char *module_struct_mem = NULL;
+	unsigned char *module_core_mem = NULL;
 	unsigned char *module_init_mem = NULL;
 	unsigned char *symtab_mem;
 	char *module_name, *strtab_mem, *nameptr;
-	struct module_info *modules = NULL;
-	struct symbol_info *sym_info;
 	unsigned int num_symtab;
-	unsigned int i = 0, nsym;
 
-	head = SYMBOL(modules);
-	if (!get_num_modules(head, &mod_st.num_modules)) {
-		ERRMSG("Can't get module count\n");
+	/* Allocate buffer to read struct module data from vmcore. */
+	if ((module_struct_mem = calloc(1, SIZE(module))) == NULL) {
+		ERRMSG("Failed to allocate buffer for module\n");
 		return FALSE;
 	}
-	if (!mod_st.num_modules) {
+	if (!readmem(VADDR, addr_module, module_struct_mem,
+						SIZE(module))) {
+		ERRMSG("Can't get module info.\n");
+		goto out;
+	}
+
+	module_name = (char *)(module_struct_mem + OFFSET(module.name));
+	if (strlen(module_name) < MOD_NAME_LEN)
+		strcpy(modules->name, module_name);
+	else
+		strncpy(modules->name, module_name, MOD_NAME_LEN-1);
+
+	mod_init = ULONG(module_struct_mem +
+					OFFSET(module.module_init));
+	mod_init_size = UINT(module_struct_mem +
+					OFFSET(module.init_size));
+	mod_base = ULONG(module_struct_mem +
+					OFFSET(module.module_core));
+	mod_size = UINT(module_struct_mem +
+					OFFSET(module.core_size));
+
+	DEBUG_MSG("Module: %s, Base: 0x%lx, Size: %u\n",
+			module_name, mod_base, mod_size);
+	if (mod_init_size > 0) {
+		module_init_mem = calloc(1, mod_init_size);
+		if (module_init_mem == NULL) {
+			ERRMSG("Can't allocate memory for module "
+							"init\n");
+			goto out;
+		}
+		if (!readmem(VADDR, mod_init, module_init_mem,
+						mod_init_size)) {
+			ERRMSG("Can't access module init in memory.\n");
+			goto out;
+		}
+	}
+
+	if ((module_core_mem = calloc(1, mod_size)) == NULL) {
+		ERRMSG("Can't allocate memory for module\n");
+		goto out;
+	}
+	if (!readmem(VADDR, mod_base, module_core_mem, mod_size)) {
+		ERRMSG("Can't access module in memory.\n");
+		goto out;
+	}
+
+	num_symtab = UINT(module_struct_mem +
+					OFFSET(module.num_symtab));
+	if (!num_symtab) {
+		ERRMSG("%s: Symbol info not available\n", module_name);
+		goto out;
+	}
+	modules->num_syms = num_symtab;
+	DEBUG_MSG("num_sym: %d\n", num_symtab);
+
+	symtab = ULONG(module_struct_mem + OFFSET(module.symtab));
+	strtab = ULONG(module_struct_mem + OFFSET(module.strtab));
+
+	/* check if symtab and strtab are inside the module space. */
+	if (!IN_RANGE(symtab, mod_base, mod_size) &&
+		!IN_RANGE(symtab, mod_init, mod_init_size)) {
+		ERRMSG("%s: module symtab is outseide of module "
+			"address space\n", module_name);
+		goto out;
+	}
+	if (IN_RANGE(symtab, mod_base, mod_size))
+		symtab_mem = module_core_mem + (symtab - mod_base);
+	else
+		symtab_mem = module_init_mem + (symtab - mod_init);
+
+	if (!IN_RANGE(strtab, mod_base, mod_size) &&
+		!IN_RANGE(strtab, mod_init, mod_init_size)) {
+		ERRMSG("%s: module strtab is outseide of module "
+			"address space\n", module_name);
+		goto out;
+	}
+	if (IN_RANGE(strtab, mod_base, mod_size))
+		strtab_mem = (char *)(module_core_mem
+					+ (strtab - mod_base));
+	else
+		strtab_mem = (char *)(module_init_mem
+					+ (strtab - mod_init));
+
+	modules->sym_info = calloc(num_symtab, sizeof(struct symbol_info));
+	if (modules->sym_info == NULL) {
+		ERRMSG("Can't allocate memory to store sym info\n");
+		goto out;
+	}
+
+	/* symbols starts from 1 */
+	for (nsym = 1; nsym < num_symtab; nsym++) {
+		Elf32_Sym *sym32;
+		Elf64_Sym *sym64;
+		/* If case of ELF vmcore then the word size can be
+		 * determined using info->flag_elf64_memory flag.
+		 * But in case of kdump-compressed dump, kdump header
+		 * does not carry word size info. May be in future
+		 * this info will be available in kdump header.
+		 * Until then, in order to make this logic work on both
+		 * situation we depend on pointer_size that is
+		 * extracted from vmlinux dwarf information.
+		 */
+		if ((get_pointer_size() * 8) == 64) {
+			sym64 = (Elf64_Sym *) (symtab_mem
+					+ (nsym * sizeof(Elf64_Sym)));
+			modules->sym_info[nsym].value =
+				(unsigned long long) sym64->st_value;
+			nameptr = strtab_mem + sym64->st_name;
+		} else {
+			sym32 = (Elf32_Sym *) (symtab_mem
+					+ (nsym * sizeof(Elf32_Sym)));
+			modules->sym_info[nsym].value =
+				(unsigned long long) sym32->st_value;
+			nameptr = strtab_mem + sym32->st_name;
+		}
+		if (strlen(nameptr))
+			modules->sym_info[nsym].name = strdup(nameptr);
+		DEBUG_MSG("\t[%d] %llx %s\n", nsym,
+					modules->sym_info[nsym].value, nameptr);
+	}
+	ret = TRUE;
+out:
+	free(module_struct_mem);
+	free(module_core_mem);
+	free(module_init_mem);
+
+	return ret;
+}
+
+static int
+load_module_symbols(void)
+{
+	unsigned long head, cur, cur_module;
+	struct module_info *modules = NULL;
+	unsigned int i = 0;
+
+	head = SYMBOL(modules);
+	if (!get_num_modules(head, &mod_st.num_modules) ||
+	    !mod_st.num_modules) {
+		ERRMSG("Can't get module count\n");
 		return FALSE;
 	}
 	mod_st.modules = calloc(mod_st.num_modules,
@@ -7882,12 +8070,6 @@ load_module_symbols(void)
 	}
 	modules = mod_st.modules;
 
-	/* Allocate buffer to read struct module data from vmcore. */
-	if ((module_struct_mem = calloc(1, SIZE(module))) == NULL) {
-		ERRMSG("Failed to allocate buffer for module\n");
-		return FALSE;
-	}
-
 	if (!readmem(VADDR, head + OFFSET(list_head.next), &cur, sizeof cur)) {
 		ERRMSG("Can't get next list_head.\n");
 		return FALSE;
@@ -7896,129 +8078,9 @@ load_module_symbols(void)
 	/* Travese the list and read module symbols */
 	while (cur != head) {
 		cur_module = cur - OFFSET(module.list);
-		if (!readmem(VADDR, cur_module, module_struct_mem,
-							SIZE(module))) {
-			ERRMSG("Can't get module info.\n");
-			return FALSE;
-		}
-
-		module_name = (char *)(module_struct_mem + OFFSET(module.name));
-		if (strlen(module_name) < MOD_NAME_LEN)
-			strcpy(modules[i].name, module_name);
-		else
-			strncpy(modules[i].name, module_name, MOD_NAME_LEN-1);
-
-		mod_init = ULONG(module_struct_mem +
-						OFFSET(module.module_init));
-		mod_init_size = UINT(module_struct_mem +
-						OFFSET(module.init_size));
-		mod_base = ULONG(module_struct_mem +
-						OFFSET(module.module_core));
-		mod_size = UINT(module_struct_mem +
-						OFFSET(module.core_size));
-
-		DEBUG_MSG("Module: %s, Base: 0x%lx, Size: %u\n",
-				module_name, mod_base, mod_size);
-		if (mod_init_size > 0) {
-			module_init_mem = calloc(1, mod_init_size);
-			if (module_init_mem == NULL) {
-				ERRMSG("Can't allocate memory for module "
-								"init\n");
-				return FALSE;
-			}
-			if (!readmem(VADDR, mod_init, module_init_mem,
-							mod_init_size)) {
-				ERRMSG("Can't access module init in memory.\n");
-				return FALSE;
-			}
-		}
-
-		if ((module_core_mem = calloc(1, mod_size)) == NULL) {
-			ERRMSG("Can't allocate memory for module\n");
-			return FALSE;
-		}
-		if (!readmem(VADDR, mod_base, module_core_mem, mod_size)) {
-			ERRMSG("Can't access module in memory.\n");
-			return FALSE;
-		}
-
-		num_symtab = UINT(module_struct_mem +
-						OFFSET(module.num_symtab));
-		if (!num_symtab) {
-			ERRMSG("%s: Symbol info not available\n", module_name);
-			return FALSE;
-		}
-		modules[i].num_syms = num_symtab;
-		DEBUG_MSG("num_sym: %d\n", num_symtab);
-
-		symtab = ULONG(module_struct_mem + OFFSET(module.symtab));
-		strtab = ULONG(module_struct_mem + OFFSET(module.strtab));
-
-		/* check if symtab and strtab are inside the module space. */
-		if (!IN_RANGE(symtab, mod_base, mod_size) &&
-			!IN_RANGE(symtab, mod_init, mod_init_size)) {
-			ERRMSG("%s: module symtab is outseide of module "
-				"address space\n", module_name);
-			return FALSE;
-		}
-		if (IN_RANGE(symtab, mod_base, mod_size))
-			symtab_mem = module_core_mem + (symtab - mod_base);
-		else
-			symtab_mem = module_init_mem + (symtab - mod_init);
-
-		if (!IN_RANGE(strtab, mod_base, mod_size) &&
-			!IN_RANGE(strtab, mod_init, mod_init_size)) {
-			ERRMSG("%s: module strtab is outseide of module "
-				"address space\n", module_name);
-			return FALSE;
-		}
-		if (IN_RANGE(strtab, mod_base, mod_size))
-			strtab_mem = (char *)(module_core_mem
-						+ (strtab - mod_base));
-		else
-			strtab_mem = (char *)(module_init_mem
-						+ (strtab - mod_init));
 
-		modules[i].sym_info = calloc(num_symtab,
-						sizeof(struct symbol_info));
-		if (modules[i].sym_info == NULL) {
-			ERRMSG("Can't allocate memory to store sym info\n");
+		if (!__load_module_symbol(&modules[i], cur_module))
 			return FALSE;
-		}
-		sym_info = modules[i].sym_info;
-
-		/* symbols starts from 1 */
-		for (nsym = 1; nsym < num_symtab; nsym++) {
-			Elf32_Sym *sym32;
-			Elf64_Sym *sym64;
-			/* If case of ELF vmcore then the word size can be
-			 * determined using info->flag_elf64_memory flag.
-			 * But in case of kdump-compressed dump, kdump header
-			 * does not carry word size info. May be in future
-			 * this info will be available in kdump header.
-			 * Until then, in order to make this logic work on both
-			 * situation we depend on pointer_size that is
-			 * extracted from vmlinux dwarf information.
-			 */
-			if ((pointer_size * 8) == 64) {
-				sym64 = (Elf64_Sym *) (symtab_mem
-						+ (nsym * sizeof(Elf64_Sym)));
-				sym_info[nsym].value =
-					(unsigned long long) sym64->st_value;
-				nameptr = strtab_mem + sym64->st_name;
-			}
-			else {
-				sym32 = (Elf32_Sym *) (symtab_mem
-						+ (nsym * sizeof(Elf32_Sym)));
-				sym_info[nsym].value =
-					(unsigned long long) sym32->st_value;
-				nameptr = strtab_mem + sym32->st_name;
-			}
-			if (strlen(nameptr))
-				sym_info[nsym].name = strdup(nameptr);
-			DEBUG_MSG("\t[%d] %llx %s\n", nsym,
-						sym_info[nsym].value, nameptr);
-		}
 
 		if (!readmem(VADDR, cur + OFFSET(list_head.next),
 					&cur, sizeof cur)) {
@@ -8026,11 +8088,7 @@ load_module_symbols(void)
 			return FALSE;
 		}
 		i++;
-		free(module_core_mem);
-		if (mod_init_size > 0)
-			free(module_init_mem);
 	} while (cur != head);
-	free(module_struct_mem);
 	return TRUE;
 }
 
@@ -8082,7 +8140,7 @@ print_config_entry(struct config_entry *ce)
 		DEBUG_MSG("flag: %x, ", ce->flag);
 		DEBUG_MSG("Type flag: %lx, ", ce->type_flag);
 		DEBUG_MSG("sym_addr: %llx, ", ce->sym_addr);
-		DEBUG_MSG("addr: %llx, ", ce->addr);
+		DEBUG_MSG("addr: %lx, ", ce->addr);
 		DEBUG_MSG("offset: %lx, ", ce->offset);
 		DEBUG_MSG("size: %zd\n", ce->size);
 
@@ -8188,6 +8246,7 @@ err_out:
 		free_config_entry(ce);
 	if (ptr)
 		free_config_entry(ptr);
+	free(str);
 	return NULL;
 }
 
@@ -8582,7 +8641,10 @@ get_config(int skip)
 	static int line_count = 0;
 	char *cur_module = NULL;
 	int eof = 0;
-	unsigned char flag = CONFIG_NEW_CMD | skip;
+	unsigned char flag = CONFIG_NEW_CMD;
+
+	if (skip)
+		flag |= CONFIG_SKIP_SECTION;
 
 	if ((config = calloc(1, sizeof(struct config))) == NULL)
 		return NULL;
@@ -8617,36 +8679,39 @@ err_out:
 	return NULL;
 }
 
-static unsigned long long
+static unsigned long
 read_pointer_value(unsigned long long addr)
 {
-	uint32_t val_32;
-	uint64_t val_64;
+	unsigned long val;
 
-	switch (pointer_size) {
-	case 4:
-		if (!readmem(VADDR, addr, &val_32, sizeof(val_32))) {
-			ERRMSG("Can't read pointer value\n");
-			return 0;
-		}
-		return (unsigned long long)val_32;
-		break;
-	case 8:
-		if (!readmem(VADDR, addr, &val_64, sizeof(val_64))) {
-			ERRMSG("Can't read pointer value\n");
-			return 0;
-		}
-		return (unsigned long long)val_64;
-		break;
+	if (!readmem(VADDR, addr, &val, sizeof(val))) {
+		ERRMSG("Can't read pointer value\n");
+		return 0;
 	}
-	return 0;
+	return val;
+}
+
+static long
+get_strlen(unsigned long long vaddr)
+{
+	char buf[BUFSIZE + 1];
+	long len = 0;
+
+	/*
+	 * Determine the string length for 'char' pointer.
+	 * BUFSIZE(1024) is the upper limit for string length.
+	 */
+	if (readmem(VADDR, vaddr, buf, BUFSIZE)) {
+		buf[BUFSIZE] = '\0';
+		len = strlen(buf);
+	}
+	return len;
 }
 
 int
 resolve_config_entry(struct config_entry *ce, unsigned long long base_addr,
 						char *base_struct_name)
 {
-	char buf[BUFSIZE + 1];
 
 	if (ce->flag & SYMBOL_ENTRY) {
 		/* find the symbol info */
@@ -8737,7 +8802,7 @@ resolve_config_entry(struct config_entry *ce, unsigned long long base_addr,
 		 * If this is a struct or list_head data type then
 		 * create a leaf node entry with 'next' member.
 		 */
-		if ((ce->type_flag & TYPE_BASE)
+		if (((ce->type_flag & (TYPE_BASE | TYPE_ARRAY)) == TYPE_BASE)
 					&& (strcmp(ce->type_name, "void")))
 			return FALSE;
 
@@ -8776,17 +8841,14 @@ resolve_config_entry(struct config_entry *ce, unsigned long long base_addr,
 			ce->size = 0;
 
 	}
-	if ((ce->type_flag & TYPE_BASE) && (ce->type_flag & TYPE_PTR)) {
+	if ((ce->type_flag & TYPE_BASE) && (ce->type_flag & TYPE_PTR)
+					&& !(ce->type_flag & TYPE_ARRAY)) {
 		/*
 		 * Determine the string length for 'char' pointer.
 		 * BUFSIZE(1024) is the upper limit for string length.
 		 */
-		if (!strcmp(ce->type_name, "char")) {
-			if (readmem(VADDR, ce->addr, buf, BUFSIZE)) {
-				buf[BUFSIZE] = '\0';
-				ce->size = strlen(buf);
-			}
-		}
+		if (!strcmp(ce->type_name, "char"))
+			ce->size = get_strlen(ce->addr);
 	}
 	if (!ce->next && (ce->flag & SIZE_ENTRY)) {
 		void *val;
@@ -8839,80 +8901,11 @@ get_config_symbol_addr(struct config_entry *ce,
 			unsigned long long base_addr,
 			char *base_struct_name)
 {
-	unsigned long long addr = 0;
-
 	if (!(ce->flag & ENTRY_RESOLVED)) {
 		if (!resolve_config_entry(ce, base_addr, base_struct_name))
 			return 0;
 	}
 
-	if ((ce->flag & LIST_ENTRY)) {
-		/* handle List entry differently */
-		if (!ce->next) {
-			/* leaf node. */
-			if (ce->type_flag & TYPE_ARRAY) {
-				if (ce->index == ce->array_length)
-					return 0;
-				if (!(ce->type_flag & TYPE_PTR))
-					return (ce->addr +
-							(ce->index * ce->size));
-				/* Array of pointers.
-				 *
-				 * Array may contain NULL pointers at some
-				 * indexes. Hence return the next non-null
-				 * address value.
-				 */
-				while (ce->index < ce->array_length) {
-					addr = read_pointer_value(ce->addr +
-						(ce->index * pointer_size));
-					ce->index++;
-					if (addr)
-						break;
-				}
-				return addr;
-			}
-			else {
-				if (ce->addr == ce->cmp_addr)
-					return 0;
-
-				/* Set the leaf node as unresolved, so that
-				 * it will be resolved every time when
-				 * get_config_symbol_addr is called untill
-				 * it hits the exit condiftion.
-				 */
-				ce->flag &= ~ENTRY_RESOLVED;
-			}
-		}
-		else if ((ce->next->next == NULL) &&
-					!(ce->next->type_flag & TYPE_ARRAY)) {
-			/* the next node is leaf node. for non-array element
-			 * Set the sym_addr and addr of this node with that of
-			 * leaf node.
-			 */
-			addr = ce->addr;
-			ce->addr = ce->next->addr;
-
-			if (!(ce->type_flag & TYPE_LIST_HEAD)) {
-				if (addr == ce->next->cmp_addr)
-					return 0;
-
-				if (!ce->next->cmp_addr) {
-					/* safeguard against circular
-					 * link-list
-					 */
-					ce->next->cmp_addr = addr;
-				}
-
-				/* Force resolution of traversal node */
-				if (ce->addr && !resolve_config_entry(ce->next,
-						ce->addr, ce->type_name))
-					return 0;
-
-				return addr;
-			}
-		}
-	}
-
 	if (ce->next && ce->addr) {
 		/* Populate nullify flag down the list */
 		ce->next->nullify = ce->nullify;
@@ -8946,7 +8939,7 @@ get_config_symbol_size(struct config_entry *ce,
 	else {
 		if (ce->type_flag & TYPE_ARRAY) {
 			if (ce->type_flag & TYPE_PTR)
-				return ce->array_length * pointer_size;
+				return ce->array_length * get_pointer_size();
 			else
 				return ce->array_length * ce->size;
 		}
@@ -8954,6 +8947,116 @@ get_config_symbol_size(struct config_entry *ce,
 	}
 }
 
+int
+get_next_list_entry(struct config_entry *ce, unsigned long long base_addr,
+			char *base_struct_name, struct config_entry *out_ce)
+{
+	unsigned long addr = 0;
+
+	/* This function only deals with LIST_ENTRY config entry. */
+	if (!(ce->flag & LIST_ENTRY))
+		return FALSE;
+
+	if (!(ce->flag & ENTRY_RESOLVED)) {
+		if (!resolve_config_entry(ce, base_addr, base_struct_name))
+			return FALSE;
+	}
+
+	if (!ce->next) {
+		/* leaf node. */
+		if (ce->type_flag & TYPE_ARRAY) {
+			if (ce->index == ce->array_length)
+				return FALSE;
+
+			if (ce->type_flag & TYPE_PTR) {
+				/* Array of pointers.
+				 *
+				 * Array may contain NULL pointers at some
+				 * indexes. Hence jump to the next non-null
+				 * address value.
+				 */
+				while (ce->index < ce->array_length) {
+					addr = read_pointer_value(ce->addr +
+						(ce->index * get_pointer_size()));
+					if (addr)
+						break;
+					ce->index++;
+				}
+				if (ce->index == ce->array_length)
+					return FALSE;
+				out_ce->sym_addr = ce->addr + (ce->index *
+							get_pointer_size());
+				out_ce->addr = addr;
+				if (!strcmp(ce->type_name, "char"))
+					out_ce->size = get_strlen(addr);
+				else
+					out_ce->size = ce->size;
+			}
+			else {
+				out_ce->sym_addr = ce->addr +
+							(ce->index * ce->size);
+				out_ce->addr = out_ce->sym_addr;
+				out_ce->size = ce->size;
+			}
+			ce->index++;
+		}
+		else {
+			if (ce->addr == ce->cmp_addr)
+				return FALSE;
+
+			out_ce->addr = ce->addr;
+			/* Set the leaf node as unresolved, so that
+			 * it will be resolved every time when
+			 * get_next_list_entry is called untill
+			 * it hits the exit condiftion.
+			 */
+			ce->flag &= ~ENTRY_RESOLVED;
+		}
+		return TRUE;
+	}
+	else if ((ce->next->next == NULL) &&
+				!(ce->next->type_flag & TYPE_ARRAY)) {
+		/* the next node is leaf node. for non-array element
+		 * Set the sym_addr and addr of this node with that of
+		 * leaf node.
+		 */
+		if (!(ce->type_flag & TYPE_LIST_HEAD)) {
+			if (!ce->addr || ce->addr == ce->next->cmp_addr)
+				return FALSE;
+
+			if (!ce->next->cmp_addr) {
+				/* safeguard against circular
+				 * link-list
+				 */
+				ce->next->cmp_addr = ce->addr;
+			}
+
+			out_ce->addr = ce->addr;
+			out_ce->sym_addr = ce->sym_addr;
+			out_ce->size = ce->size;
+
+			ce->sym_addr = ce->next->sym_addr;
+			ce->addr = ce->next->addr;
+
+			/* Force resolution of traversal node */
+			if (ce->addr && !resolve_config_entry(ce->next,
+					ce->addr, ce->type_name))
+				return FALSE;
+
+			return TRUE;
+		}
+		else {
+			ce->sym_addr = ce->next->sym_addr;
+			ce->addr = ce->next->addr;
+		}
+	}
+
+	if (ce->next && ce->addr)
+		return get_next_list_entry(ce->next, ce->addr,
+						ce->type_name, out_ce);
+	return FALSE;
+}
+
 static int
 resolve_list_entry(struct config_entry *ce, unsigned long long base_addr,
 			char *base_struct_name, char **out_type_name,
@@ -9127,7 +9230,7 @@ update_filter_info(struct config_entry *filter_symbol,
 		return FALSE;
 
 	if (filter_symbol->nullify)
-		size = pointer_size;
+		size = get_pointer_size();
 	else if (size_symbol) {
 		size = get_config_symbol_size(size_symbol, 0, NULL);
 		if (message_level & ML_PRINT_DEBUG_MSG)
@@ -9179,31 +9282,14 @@ initialize_iteration_entry(struct config_entry *ie,
 								ie->line);
 			ie->next->flag &= ~SYMBOL_ENTRY;
 		}
-	}
-	else {
-		if (ie->type_name) {
-			/* looks like user has used 'within' keyword for
-			 * non-list_head VAR. Print the warning and continue.
-			 */
-			ERRMSG("Warning: line %d: 'within' keyword not "
-				"required for ArrayVar/StructVar.\n", ie->line);
-			free(ie->type_name);
 
-			/* remove the next list_head member from iteration
-			 * entry that would have added as part of 'within'
-			 * keyword processing.
-			 */
-			if (ie->next) {
-				free_config_entry(ie->next);
-				ie->next = NULL;
-			}
-		}
-		ie->type_name = strdup(type_name);
-	}
-
-	if (!ie->size) {
-		ie->size = get_structure_size(ie->type_name,
-						DWARF_INFO_GET_STRUCT_SIZE);
+		/*
+		 * For list_head find out the size of the StructName and
+		 * populate ie->size now. For array and link list we get the
+		 * size info from config entry returned by
+		 * get_next_list_entry().
+		 */
+		ie->size = get_structure_size(ie->type_name, 0);
 		if (ie->size == FAILED_DWARFINFO) {
 			ERRMSG("Config error at %d: "
 				"Can't get size for type: %s.\n",
@@ -9216,8 +9302,7 @@ initialize_iteration_entry(struct config_entry *ie,
 				ie->line, ie->type_name);
 			return FALSE;
 		}
-	}
-	if (type_flag & TYPE_LIST_HEAD) {
+
 		if (!resolve_config_entry(ie->next, 0, ie->type_name))
 			return FALSE;
 
@@ -9227,6 +9312,34 @@ initialize_iteration_entry(struct config_entry *ie,
 				ie->next->line, ie->next->name);
 			return FALSE;
 		}
+		ie->type_flag = TYPE_STRUCT;
+	}
+	else {
+		if (ie->type_name) {
+			/* looks like user has used 'within' keyword for
+			 * non-list_head VAR. Print the warning and continue.
+			 */
+			ERRMSG("Warning: line %d: 'within' keyword not "
+				"required for ArrayVar/StructVar.\n", ie->line);
+			free(ie->type_name);
+
+			/* remove the next list_head member from iteration
+			 * entry that would have added as part of 'within'
+			 * keyword processing.
+			 */
+			if (ie->next) {
+				free_config_entry(ie->next);
+				ie->next = NULL;
+			}
+		}
+		/*
+		 * Set type flag for iteration entry. The iteration entry holds
+		 * individual element from array/list, hence strip off the
+		 * array type flag bit.
+		 */
+		ie->type_name = strdup(type_name);
+		ie->type_flag = type_flag;
+		ie->type_flag &= ~TYPE_ARRAY;
 	}
 	return TRUE;
 }
@@ -9234,25 +9347,29 @@ initialize_iteration_entry(struct config_entry *ie,
 int
 list_entry_empty(struct config_entry *le, struct config_entry *ie)
 {
-	unsigned long long addr;
+	struct config_entry ce;
 
 	/* Error out if arguments are not correct */
 	if (!(le->flag & LIST_ENTRY) || !(ie->flag & ITERATION_ENTRY)) {
 		ERRMSG("Invalid arguments\n");
 		return TRUE;
 	}
-	addr = get_config_symbol_addr(le, 0, NULL);
-	if (!addr)
+
+	memset(&ce, 0, sizeof(struct config_entry));
+	/* get next available entry from LIST entry. */
+	if (!get_next_list_entry(le, 0, NULL, &ce))
 		return TRUE;
 
 	if (ie->next) {
 		/* we are dealing with list_head */
-		ie->next->addr = addr;
-		ie->addr = addr - ie->next->offset;
-		//resolve_iteration_entry(ie, addr);
+		ie->next->addr = ce.addr;
+		ie->addr = ce.addr - ie->next->offset;
+	}
+	else {
+		ie->addr = ce.addr;
+		ie->sym_addr = ce.sym_addr;
+		ie->size = ce.size;
 	}
-	else
-		ie->addr = addr;
 	return FALSE;
 }
 
@@ -9692,17 +9809,53 @@ get_splitting_info(void)
 	if (!check_splitting_info())
 		return FALSE;
 
+	if (!get_kdump_compressed_header_info(SPLITTING_DUMPFILE(0)))
+		return FALSE;
+
 	return TRUE;
 }
 
 int
+copy_same_data(int src_fd, int dst_fd, off_t offset, unsigned long size)
+{
+	int ret = FALSE;
+	char *buf = NULL;
+
+	if ((buf = malloc(size)) == NULL) {
+		ERRMSG("Can't allcate memory.\n");
+		return FALSE;
+	}
+	if (lseek(src_fd, offset, SEEK_SET) < 0) {
+		ERRMSG("Can't seek a source file. %s\n", strerror(errno));
+		goto out;
+	}
+	if (read(src_fd, buf, size) != size) {
+		ERRMSG("Can't read a source file. %s\n", strerror(errno));
+		goto out;
+	}
+	if (lseek(dst_fd, offset, SEEK_SET) < 0) {
+		ERRMSG("Can't seek a destination file. %s\n", strerror(errno));
+		goto out;
+	}
+	if (write(dst_fd, buf, size) != size) {
+		ERRMSG("Can't write a destination file. %s\n", strerror(errno));
+		goto out;
+	}
+	ret = TRUE;
+out:
+	free(buf);
+	return ret;
+}
+
+int
 reassemble_kdump_header(void)
 {
-	int fd, ret = FALSE;
-	off_t offset_bitmap;
+	int fd = -1, ret = FALSE;
+	off_t offset;
+	unsigned long size;
 	struct disk_dump_header dh;
 	struct kdump_sub_header kh;
-	char *buf_bitmap;
+	char *buf_bitmap = NULL;
 
 	/*
 	 * Write common header.
@@ -9741,25 +9894,42 @@ reassemble_kdump_header(void)
 		    info->name_dumpfile, strerror(errno));
 		return FALSE;
 	}
+	memcpy(&info->sub_header, &kh, sizeof(kh));
+
+	if ((fd = open(SPLITTING_DUMPFILE(0), O_RDONLY)) < 0) {
+		ERRMSG("Can't open a file(%s). %s\n",
+		    SPLITTING_DUMPFILE(0), strerror(errno));
+		return FALSE;
+	}
+	if (info->offset_note && info->size_note) {
+		offset = info->offset_note;
+		size = info->size_note;
+		if (!copy_same_data(fd, info->fd_dumpfile, offset, size)) {
+			ERRMSG("Can't copy pt_note data to %s.\n",
+			    info->name_dumpfile);
+			goto out;
+		}
+	}
+	if (info->offset_vmcoreinfo && info->size_vmcoreinfo) {
+		offset = info->offset_vmcoreinfo;
+		size = info->size_vmcoreinfo;
+		if (!copy_same_data(fd, info->fd_dumpfile, offset, size)) {
+			ERRMSG("Can't copy vmcoreinfo data to %s.\n",
+			    info->name_dumpfile);
+			goto out;
+		}
+	}
 
 	/*
 	 * Write dump bitmap to both a dumpfile and a bitmap file.
 	 */
-	offset_bitmap
-	    = (DISKDUMP_HEADER_BLOCKS + dh.sub_hdr_size) * dh.block_size;
+	offset = (DISKDUMP_HEADER_BLOCKS + dh.sub_hdr_size) * dh.block_size;
 	info->len_bitmap = dh.bitmap_blocks * dh.block_size;
 	if ((buf_bitmap = malloc(info->len_bitmap)) == NULL) {
 		ERRMSG("Can't allcate memory for bitmap.\n");
-		return FALSE;
-	}
-
-	if ((fd = open(SPLITTING_DUMPFILE(0), O_RDONLY)) < 0) {
-		ERRMSG("Can't open a file(%s). %s\n",
-		    SPLITTING_DUMPFILE(0), strerror(errno));
-		free(buf_bitmap);
-		return FALSE;
+		goto out;
 	}
-	if (lseek(fd, offset_bitmap, SEEK_SET) < 0) {
+	if (lseek(fd, offset, SEEK_SET) < 0) {
 		ERRMSG("Can't seek a file(%s). %s\n",
 		    SPLITTING_DUMPFILE(0), strerror(errno));
 		goto out;
@@ -9770,7 +9940,7 @@ reassemble_kdump_header(void)
 		goto out;
 	}
 
-	if (lseek(info->fd_dumpfile, offset_bitmap, SEEK_SET) < 0) {
+	if (lseek(info->fd_dumpfile, offset, SEEK_SET) < 0) {
 		ERRMSG("Can't seek a file(%s). %s\n",
 		    info->name_dumpfile, strerror(errno));
 		goto out;
@@ -9796,7 +9966,9 @@ reassemble_kdump_header(void)
 
 	ret = TRUE;
 out:
-	close(fd);
+	if (fd > 0)
+		close(fd);
+	free(buf_bitmap);
 
 	return ret;
 }
@@ -9932,6 +10104,7 @@ reassemble_kdump_pages(void)
 		goto out;
 
 	info->offset_eraseinfo = cd_data.offset;
+	info->size_eraseinfo = 0;
 	/* Copy eraseinfo from split dumpfiles to o/p dumpfile */
 	for (i = 0; i < info->num_dumpfile; i++) {
 		if (!SPLITTING_SIZE_EI(i))
@@ -9968,12 +10141,13 @@ reassemble_kdump_pages(void)
 		close(fd);
 		fd = 0;
 	}
-	if (!write_cache_bufsz(&cd_data))
-		goto out;
-
-	if (!update_sub_header())
-		goto out;
+	if (info->size_eraseinfo) {
+		if (!write_cache_bufsz(&cd_data))
+			goto out;
 
+		if (!update_sub_header())
+			goto out;
+	}
 	print_progress(PROGRESS_COPY, num_dumpable, num_dumpable);
 	ret = TRUE;
 out:
diff --git a/makedumpfile-1.3.5/makedumpfile.h b/makedumpfile-1.3.5/makedumpfile.h
index 312a0c3..6cc36c4 100644
--- a/makedumpfile-1.3.5/makedumpfile.h
+++ b/makedumpfile-1.3.5/makedumpfile.h
@@ -504,21 +504,8 @@ do { \
 #define XEN_ELFNOTE_CRASH_INFO	(0x1000001)
 #define SIZE_XEN_CRASH_INFO_V2	(sizeof(unsigned long) * 10)
 
-#define MAX_SIZE_STR_LEN (21)
+#define MAX_SIZE_STR_LEN (26)
 
-/*
- * ELF note section for erase information
- *
- * According to elf.h the unused values are 0x15(21) through 0xff. The value
- * range 0x1XX, 0x2XX and 0x3XX is been used for PPC, i386 and s390
- * respectively.
- *
- * Using 0xff to be on safer side so that any new Elf Note addition in elf.h
- * after 0x15 value would not clash.
- */
-#ifndef NT_ERASE_INFO
-#define NT_ERASE_INFO (0xff)	/* Contains erased information. */
-#endif
 #define ERASEINFO_NOTE_NAME		"ERASEINFO"
 #define ERASEINFO_NOTE_NAME_BYTES	(sizeof(ERASEINFO_NOTE_NAME))
 
@@ -1244,7 +1231,6 @@ enum {
 	DWARF_INFO_CHECK_SYMBOL_ARRAY_TYPE,
 	DWARF_INFO_GET_SYMBOL_TYPE,
 	DWARF_INFO_GET_MEMBER_TYPE,
-	DWARF_INFO_GET_PTR_SIZE,
 };
 
 struct dwarf_info {
@@ -1310,7 +1296,7 @@ struct config_entry {
 	unsigned short		flag;
 	unsigned short		nullify;
 	unsigned long long	sym_addr;	/* Symbol address */
-	unsigned long long	addr;		/* Symbol address or
+	unsigned long		addr;		/* Symbol address or
 						   value pointed by sym_addr */
 	unsigned long long	cmp_addr;	/* for LIST_ENTRY */
 	unsigned long		offset;
diff --git a/makedumpfile-1.3.5/s390x.c b/makedumpfile-1.3.5/s390x.c
index 3ee1e7a..5e136de 100644
--- a/makedumpfile-1.3.5/s390x.c
+++ b/makedumpfile-1.3.5/s390x.c
@@ -274,9 +274,7 @@ vaddr_to_paddr_s390x(unsigned long vaddr)
 		paddr = vtop_s390x(vaddr);
 	}
 	else {
-		ERRMSG("Can't convert a virtual address(%lx) to " \
-		    "physical address.\n", vaddr);
-		return NOT_PADDR;
+		paddr = vaddr - KVBASE;
 	}
 
 	return paddr;
