All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] linux-2.6.16.51 gzipped core dump patch
@ 2007-09-04  0:49 Pallewatta Mano-FPCD67
  2007-09-04  1:38 ` Al Viro
  0 siblings, 1 reply; 6+ messages in thread
From: Pallewatta Mano-FPCD67 @ 2007-09-04  0:49 UTC (permalink / raw)
  To: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 429 bytes --]

Hi,
The attached patch is based on Jan Frey's previous patch posted in 2004
for the Linux 2.4 kernel. It has been tested on X86 and MIPS platforms.
If the core pattern doesn't end in ".gz" it will be added to the name of
the core file. It's offered under GPL v2 without any warranties. If you
have any questions, please contact me directly at Mano.Pallewatta "at"
motorola.com. 

Regards,

Methlal (Mano) Pallewatta  

[-- Attachment #2: gzipped_core_dump.patch --]
[-- Type: application/octet-stream, Size: 16713 bytes --]

--- linux-2.6.16.51/fs/binfmt_elf.c	2007-07-30 18:31:50.000000000 -0700
+++ linux-2.6.16.51/fs/binfmt_elf.c	2007-07-31 00:38:18.000000000 -0700
@@ -9,6 +9,7 @@
  * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
@@ -60,6 +61,20 @@
  */
 #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
 static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file);
+
+#ifdef CONFIG_GZIP_COREDUMPS
+
+/*
+ * Functions added to support writing core files in gzipped format, 2004
+ * Jan Frey <jan.frey@nokia.com>
+ * Mano Pallewatta <Mano.Pallewatta@motorola.com>
+ */
+#include <linux/zlib.h>
+#include <linux/vmalloc.h>
+#include <linux/crc32.h>
+#endif
+
+
 #else
 #define elf_core_dump	NULL
 #endif
@@ -1122,18 +1137,67 @@
 /*
  * ELF core dumper
  *
- * Modelled on fs/exec.c:aout_core_dump()
- * Jeremy Fitzhardinge <jeremy@sw.oz.au>
- */
-/*
- * These are the only things you should do on a core-file: use only these
- * functions to write out all the necessary info.
+ * gz writing support
+ * Jan Frey <jan.frey@nokia.com>
+ * Mano Pallewatta <Mano.Pallewatta@motorola.com>
  */
-static int dump_write(struct file *file, const void *addr, int nr)
+#ifdef CONFIG_GZIP_COREDUMPS
+
+#define  OUT_BUF_SIZE  100*1024
+
+static int gz_dump_write(struct file *file, const void *addr, int nr, u32 *crc, z_streamp zstr, void *out_buf)
 {
-	return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+       int       all_fine     = 1;
+
+       *crc = crc32_le (*crc, addr, nr);
+
+       zstr->next_in  = (void *)addr;
+       zstr->avail_in = nr;
+
+       do {
+               zstr->next_out  = out_buf;
+               zstr->avail_out = OUT_BUF_SIZE;
+
+               if (zlib_deflate (zstr, Z_NO_FLUSH) == Z_OK) {
+                       /* new output generated */
+                       all_fine = (file->f_op->write (file,
+                                                      out_buf,
+                                                      OUT_BUF_SIZE - zstr->avail_out,
+                                                      &file->f_pos)
+                                   == (OUT_BUF_SIZE - zstr->avail_out));
+               }
+       } while ((zstr->avail_out != OUT_BUF_SIZE) && all_fine);
+
+       return all_fine;
 }
 
+static int gz_finish (struct file *file, z_streamp zstr, void *out_buf)
+{
+       int       all_fine     = 1;
+       int       ret;
+
+       zstr->next_in   = 0;
+       zstr->avail_in  = 0;
+
+       do {
+               zstr->next_out  = out_buf;
+               zstr->avail_out = OUT_BUF_SIZE;
+
+               ret = zlib_deflate (zstr, Z_FINISH);
+               if ((ret == Z_OK) || (ret == Z_STREAM_END)) {
+                       /* new output generated */
+                       all_fine = (file->f_op->write (file,
+                                                     out_buf,
+                                                     OUT_BUF_SIZE - zstr->avail_out,
+                                                     &file->f_pos)
+                                   == (OUT_BUF_SIZE - zstr->avail_out));
+               }
+       } while ((zstr->avail_out != OUT_BUF_SIZE) && all_fine && (ret != Z_STREAM_END));
+
+       return all_fine;
+}
+
+#else
 static int dump_seek(struct file *file, loff_t off)
 {
 	if (file->f_op->llseek) {
@@ -1143,6 +1207,15 @@
 		file->f_pos = off;
 	return 1;
 }
+#endif
+/*
+ * These are the only things you should do on a core-file: use only these
+ * functions to write out all the necessary info.
+ */
+static int dump_write(struct file *file, const void *addr, int nr)
+{
+	return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+}
 
 /*
  * Decide whether a segment is worth dumping; default is yes to be
@@ -1189,12 +1262,55 @@
 
 	return sz;
 }
+#ifdef CONFIG_GZIP_COREDUMPS
+#define PAD_GZ(nr, buf, crc, str, out_buf) \
+        do { \
+               int cur=(nr); \
+                 while (cur>1024) { \
+                   gz_dump_write(file, (buf), 1024, (crc), (str), (out_buf)); \
+                   cur-=1024; \
+               } \
+               if (cur) { \
+                 gz_dump_write(file, (buf), cur, (crc), (str), (out_buf)); \
+               } \
+        } while(0)
 
-#define DUMP_WRITE(addr, nr)	\
-	do { if (!dump_write(file, (addr), (nr))) return 0; } while(0)
+#define DUMP_GZ(addr, nr, crc, str, out_buf)    \
+       do { if (!gz_dump_write(file, (addr), (nr), (crc), (str), (out_buf))) return 0; } while(0)
+
+#else
 #define DUMP_SEEK(off)	\
 	do { if (!dump_seek(file, (off))) return 0; } while(0)
+#endif
+
+#define DUMP_WRITE(addr, nr)	\
+	do { if (!dump_write(file, (addr), (nr))) return 0; } while(0)
+
+#ifdef CONFIG_GZIP_COREDUMPS
+static int writenote_gz(struct memelfnote *men, struct file *file, char *buf, u32 *crc, z_streamp zstr, void *out_buf)
+{
+       struct elf_note en;
+       int dummy_bytes;
+
+       en.n_namesz = strlen(men->name)+1;
+       en.n_descsz = men->datasz;
+       en.n_type = men->type;
+
+       DUMP_GZ(&en, sizeof(en), crc, zstr, out_buf);
+       DUMP_GZ(men->name, en.n_namesz, crc, zstr, out_buf);
+
+       dummy_bytes = roundup((unsigned long)zstr->total_in, 4) - zstr->total_in;
+       PAD_GZ(dummy_bytes, buf, crc, zstr, out_buf);
+
+       DUMP_GZ(men->data, men->datasz, crc, zstr, out_buf);
+
+       dummy_bytes = roundup((unsigned long)zstr->total_in, 4) - zstr->total_in;
+       PAD_GZ(dummy_bytes, buf, crc, zstr, out_buf);
 
+       return 1;
+}
+#undef DUMP_GZ
+#else
 static int writenote(struct memelfnote *men, struct file *file)
 {
 	struct elf_note en;
@@ -1214,13 +1330,20 @@
 }
 #undef DUMP_WRITE
 #undef DUMP_SEEK
+#endif
 
+#ifdef CONFIG_GZIP_COREDUMPS
+#define DUMP_GZ(addr, nr, crc, str, out_buf)    \
+       if ((size += (nr)) > limit || !gz_dump_write(file, (addr), (nr), (crc), (str), (out_buf))) \
+               goto end_coredump;
+#else
 #define DUMP_WRITE(addr, nr)	\
 	if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
 		goto end_coredump;
 #define DUMP_SEEK(off)	\
 	if (!dump_seek(file, (off))) \
 		goto end_coredump;
+#endif
 
 static void fill_elf_header(struct elfhdr *elf, int segs)
 {
@@ -1424,6 +1547,52 @@
 #endif
 	int thread_status_size = 0;
 	elf_addr_t *auxv;
+#ifdef CONFIG_GZIP_COREDUMPS
+       z_stream gz_stream;
+       void *deflate_workspace;
+       u32 crc = ~0; /* init */
+       unsigned char gz_magic[10] = { /* gzip magic header */
+         0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 0x03 };
+       void *out_buf = NULL;
+       void *empty_buf = NULL;
+
+       out_buf = vmalloc(OUT_BUF_SIZE);
+       if (!out_buf) {
+         printk(KERN_WARNING "Failed to allocate deflate buffer");
+         return -ENOMEM;
+       }
+
+       empty_buf = vmalloc(1024);
+       if (!empty_buf) {
+         vfree(out_buf);
+         printk(KERN_WARNING "Failed to allocate memory for dummy buffer\n");
+         return -ENOMEM;
+       }
+
+       deflate_workspace = vmalloc(zlib_deflate_workspacesize());
+         if (!deflate_workspace) {
+           vfree(out_buf);
+           vfree(empty_buf);
+           printk(KERN_WARNING "Failed to allocate deflate workspace\n");
+           return -ENOMEM;
+        }
+
+       gz_stream.workspace = deflate_workspace;
+       if (Z_OK != zlib_deflateInit2(&gz_stream,
+                                     7, /* compression level */
+                                     Z_DEFLATED,
+                                     -15, /* window bits */
+                                     6, /* mem level */
+                                     Z_DEFAULT_STRATEGY)) {
+               printk(KERN_WARNING "deflateInit failed\n");
+           vfree(out_buf);
+           vfree(empty_buf);
+           vfree(deflate_workspace);
+           return -ENOMEM;
+        }
+
+       memset (empty_buf, 0, 1024);
+#endif
 
 	/*
 	 * We no longer stop all VM operations.
@@ -1535,7 +1704,15 @@
 	fs = get_fs();
 	set_fs(KERNEL_DS);
 
+#ifdef CONFIG_GZIP_COREDUMPS
+        /* write gzip header */
+        DUMP_WRITE(gz_magic, 10);
+
+        /* write elf header */
+        DUMP_GZ(elf, sizeof(*elf), &crc, &gz_stream, out_buf);
+#else
 	DUMP_WRITE(elf, sizeof(*elf));
+#endif
 	offset += sizeof(*elf);				/* Elf header */
 	offset += (segs+1) * sizeof(struct elf_phdr);	/* Program headers */
 
@@ -1551,7 +1728,12 @@
 
 		fill_elf_note_phdr(&phdr, sz, offset);
 		offset += sz;
+
+#ifdef CONFIG_GZIP_COREDUMPS
+                DUMP_GZ(&phdr, sizeof(phdr), &crc, &gz_stream, out_buf);
+#else
 		DUMP_WRITE(&phdr, sizeof(phdr));
+#endif
 	}
 
 	/* Page-align dumped data */
@@ -1576,7 +1758,11 @@
 		if (vma->vm_flags & VM_EXEC) phdr.p_flags |= PF_X;
 		phdr.p_align = ELF_EXEC_PAGESIZE;
 
+#ifdef CONFIG_GZIP_COREDUMPS
+                DUMP_GZ(&phdr, sizeof(phdr), &crc, &gz_stream, out_buf);
+#else
 		DUMP_WRITE(&phdr, sizeof(phdr));
+#endif
 	}
 
 #ifdef ELF_CORE_WRITE_EXTRA_PHDRS
@@ -1585,18 +1771,30 @@
 
  	/* write out the notes section */
 	for (i = 0; i < numnote; i++)
+#ifdef CONFIG_GZIP_COREDUMPS
+               if (!writenote_gz(notes + i, file, empty_buf, &crc, &gz_stream, out_buf))
+#else
 		if (!writenote(notes + i, file))
+#endif
 			goto end_coredump;
 
 	/* write out the thread status notes section */
 	list_for_each(t, &thread_list) {
 		struct elf_thread_status *tmp = list_entry(t, struct elf_thread_status, list);
 		for (i = 0; i < tmp->num_notes; i++)
+#ifdef CONFIG_GZIP_COREDUMPS
+			if (!writenote_gz(&tmp->notes[i], file, empty_buf, &crc, &gz_stream, out_buf))
+#else
 			if (!writenote(&tmp->notes[i], file))
+#endif
 				goto end_coredump;
 	}
  
+#ifdef CONFIG_GZIP_COREDUMPS
+        PAD_GZ (dataoff-gz_stream.total_in, empty_buf, &crc, &gz_stream, out_buf);
+#else
 	DUMP_SEEK(dataoff);
+#endif
 
 	for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
 		unsigned long addr;
@@ -1612,17 +1810,30 @@
 
 			if (get_user_pages(current, current->mm, addr, 1, 0, 1,
 						&page, &vma) <= 0) {
+#ifdef CONFIG_GZIP_COREDUMPS
+                         PAD_GZ(PAGE_SIZE, empty_buf, &crc, &gz_stream, out_buf);
+#else
 				DUMP_SEEK (file->f_pos + PAGE_SIZE);
+#endif
 			} else {
 				if (page == ZERO_PAGE(addr)) {
-					DUMP_SEEK (file->f_pos + PAGE_SIZE);
+#ifdef CONFIG_GZIP_COREDUMPS
+                                 PAD_GZ(PAGE_SIZE, empty_buf, &crc, &gz_stream, out_buf);
+#else
+				 DUMP_SEEK (file->f_pos + PAGE_SIZE);
+#endif
 				} else {
 					void *kaddr;
 					flush_cache_page(vma, addr, page_to_pfn(page));
 					kaddr = kmap(page);
 					if ((size += PAGE_SIZE) > limit ||
+#ifdef CONFIG_GZIP_COREDUMPS
+					    !gz_dump_write(file, kaddr,
+					    PAGE_SIZE, &crc, &gz_stream, out_buf)) {
+#else
 					    !dump_write(file, kaddr,
 					    PAGE_SIZE)) {
+#endif
 						kunmap(page);
 						page_cache_release(page);
 						goto end_coredump;
@@ -1638,13 +1849,29 @@
 	ELF_CORE_WRITE_EXTRA_DATA;
 #endif
 
+#ifndef CONFIG_GZIP_COREDUMPS
 	if ((off_t)file->f_pos != offset) {
 		/* Sanity check */
 		printk(KERN_WARNING "elf_core_dump: file->f_pos (%ld) != offset (%ld)\n",
 		       (off_t)file->f_pos, offset);
 	}
+#endif
 
 end_coredump:
+#ifdef CONFIG_GZIP_COREDUMPS
+        gz_finish (file, &gz_stream, out_buf);
+        zlib_deflateEnd (&gz_stream);
+
+        gz_magic[0] = (~crc & 0x000000FF);
+        gz_magic[1] = (~crc & 0x0000FF00) >> 8;
+        gz_magic[2] = (~crc & 0x00FF0000) >> 16;
+        gz_magic[3] = (~crc & 0xFF000000) >> 24;
+        gz_magic[4] = (gz_stream.total_in & 0x000000FF);
+        gz_magic[5] = (gz_stream.total_in & 0x0000FF00) >> 8;
+        gz_magic[6] = (gz_stream.total_in & 0x00FF0000) >> 16;
+        gz_magic[7] = (gz_stream.total_in & 0xFF000000) >> 24;
+        dump_write (file, gz_magic, 8);
+ #endif
 	set_fs(fs);
 
 cleanup:
@@ -1662,6 +1889,12 @@
 #ifdef ELF_CORE_COPY_XFPREGS
 	kfree(xfpu);
 #endif
+
+#ifdef CONFIG_GZIP_COREDUMPS
+       vfree (deflate_workspace);
+       vfree (empty_buf);
+       vfree (out_buf);
+#endif
 	return has_dumped;
 #undef NUM_NOTES
 }
--- linux-2.6.16.51/fs/exec.c	2007-07-30 18:31:51.000000000 -0700
+++ linux-2.6.16.51/fs/exec.c	2007-07-31 00:25:05.000000000 -0700
@@ -1366,6 +1366,15 @@
 		out_ptr += rc;
 	}
       out:
+#ifdef CONFIG_GZIP_COREDUMPS
+      if (strncmp(out_ptr-3,".gz",3)) {
+        rc = snprintf(out_ptr, out_end - out_ptr,"%s",".gz");
+          if (rc > out_end - out_ptr)
+            goto out1;
+          out_ptr += rc;
+      }
+#endif
+      out1:
 	*out_ptr = 0;
 }
 
--- linux-2.6.16.51/fs/Kconfig	2007-07-30 18:31:50.000000000 -0700
+++ linux-2.6.16.51/fs/Kconfig	2007-07-31 00:25:05.000000000 -0700
@@ -802,6 +802,12 @@
         help
         Exports the dump image of crashed kernel in ELF format.
 
+config GZIP_COREDUMPS
+        bool "Write gzipped core dump files"
+        default n
+        select ZLIB_DEFLATE
+        select CRC32
+
 config SYSFS
 	bool "sysfs file system support" if EMBEDDED
 	default y
--- linux-2.6.16.51/include/asm-i386/elf.h	2007-08-15 00:59:49.000000000 -0700
+++ linux-2.6.16.51/include/asm-i386/elf.h	2007-08-15 09:39:12.000000000 -0700
@@ -149,6 +149,8 @@
  * a debugger needs to easily find how the vsyscall DSO was being used.
  */
 #define ELF_CORE_EXTRA_PHDRS		(VSYSCALL_EHDR->e_phnum)
+
+#ifdef CONFIG_GZIP_COREDUMPS
 #define ELF_CORE_WRITE_EXTRA_PHDRS					      \
 do {									      \
 	const struct elf_phdr *const vsyscall_phdrs =			      \
@@ -168,9 +170,49 @@
 		else							      \
 			phdr.p_offset += ofs;				      \
 		phdr.p_paddr = 0; /* match other core phdrs */		      \
-		DUMP_WRITE(&phdr, sizeof(phdr));			      \
+                DUMP_GZ(&phdr, sizeof(phdr), &crc, &gz_stream, out_buf);      \
 	}								      \
 } while (0)
+#else
+#define ELF_CORE_WRITE_EXTRA_PHDRS                                            \
+do {                                                                          \
+        const struct elf_phdr *const vsyscall_phdrs =                         \
+                (const struct elf_phdr *) (VSYSCALL_BASE                      \
+                                           + VSYSCALL_EHDR->e_phoff);         \
+        int i;                                                                \
+        Elf32_Off ofs = 0;                                                    \
+        for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {                        \
+                struct elf_phdr phdr = vsyscall_phdrs[i];                     \
+                if (phdr.p_type == PT_LOAD) {                                 \
+                        BUG_ON(ofs != 0);                                     \
+                        ofs = phdr.p_offset = offset;                         \
+                        phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz);              \
+                        phdr.p_filesz = phdr.p_memsz;                         \
+                        offset += phdr.p_filesz;                              \
+                }                                                             \
+                else                                                          \
+                        phdr.p_offset += ofs;                                 \
+                phdr.p_paddr = 0; /* match other core phdrs */                \
+                DUMP_WRITE(&phdr, sizeof(phdr));                              \
+        }                                                                     \
+} while (0)
+#endif
+
+#ifdef CONFIG_GZIP_COREDUMPS
+#define ELF_CORE_WRITE_EXTRA_DATA                                             \
+do {                                                                          \
+        const struct elf_phdr *const vsyscall_phdrs =                         \
+                (const struct elf_phdr *) (VSYSCALL_BASE                      \
+                                           + VSYSCALL_EHDR->e_phoff);         \
+        int i;                                                                \
+        for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {                        \
+                if (vsyscall_phdrs[i].p_type == PT_LOAD)                      \
+			DUMP_GZ((void *) vsyscall_phdrs[i].p_vaddr,	      \
+				   PAGE_ALIGN(vsyscall_phdrs[i].p_memsz),     \
+				   &crc, &gz_stream, out_buf);                \
+        }                                                                     \
+} while (0)
+#else
 #define ELF_CORE_WRITE_EXTRA_DATA					      \
 do {									      \
 	const struct elf_phdr *const vsyscall_phdrs =			      \
@@ -183,6 +225,7 @@
 				   PAGE_ALIGN(vsyscall_phdrs[i].p_memsz));    \
 	}								      \
 } while (0)
+#endif
 
 #endif
 

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2007-09-04  4:12 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-04  0:49 [PATCH] linux-2.6.16.51 gzipped core dump patch Pallewatta Mano-FPCD67
2007-09-04  1:38 ` Al Viro
2007-09-04  2:32   ` Pallewatta Mano-FPCD67
2007-09-04  3:26     ` Al Viro
2007-09-04  4:04       ` Pallewatta Mano-FPCD67
2007-09-04  4:12         ` Al Viro

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.