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