On Wed, 2010-02-24 at 18:39 +0100, Moritz Muehlenhoff wrote:
> On Tue, Oct 06, 2009 at 01:43:03AM +0100, Ben Hutchings wrote:
> > On Mon, 2009-10-05 at 11:57 +0200, Michal Suchanek wrote:
> > > 2009/10/5 Ben Hutchings <b...@decadent.org.uk>:
> > > > While we still aren't providing an uncompressed vmlinux image, it is now
> > > > possible to extract one from vmlinuz.  The following Python script does
> > > > the job; give it the filename of the compressed image followed by the
> > > > filename for the uncompressed image.
> > > >
> > > > Ben.
> > > >
> > > 
> > > Yes, I thought this should be possible but did not find a tool for
> > > decompressing the kernel.
> > > 
> > > Does the script also work for non-x86 architectures (or are there any
> > > that do compress the kernel besides x86 and have usable precompiled
> > > kernels)?
> > 
> > Don't know; I've never tried it.
> > 
> > > I guess if this is packaged with oprofile and pointers to the
> > > decompression tool are added to its documentation this would resolve
> > > the issue. Perhaps even oprofile upstream might be interested in
> > > including the script.
> > 
> > Perhaps, though I expect they would prefer a C program.  It shouldn't
> > take long to translate to C though.  Maybe I'll do that.
> 
> Maybe we should reassign this to the orofile package for now so that
> they can include your Python script for Squeeze?

I've reassigned it to oprofile.

I've attached the C version which should be easier to integrate into the
oprofile package (and may be suitable for upstream).

Ben.

-- 
Ben Hutchings
I say we take off; nuke the site from orbit.  It's the only way to be sure.
/*
 * gunzip-vmlinux
 * Copyright 2010 Ben Hutchings.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License, version 2 or later,
 * as published by the Free Software Foundation.
 */

#define _GNU_SOURCE
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/fcntl.h>
#include <unistd.h>
#include <zlib.h>

#define BUF_SIZE		(1 << 16)
#define GZIP_SIGNATURE		"\x1f\x8b\x08"

static void usage(void)
{
	fprintf(stderr, "Usage: gunzip-vmlinux [-c] vmlinuz\n");
	exit(2);
}

int main(int argc, char **argv)
{
	static unsigned char in_buf[BUF_SIZE], out_buf[BUF_SIZE];
	const char *in_name, *out_name;
	int to_stdout = 0, in_eof = 0, opt, z_ret;
	int in_file = -1, out_file = -1;
	z_stream zstream;
	ssize_t io_size;

	for (;;) {
		opt = getopt(argc, argv, "c");
		if (opt == -1)
			break;
		else if (opt == 'c')
			to_stdout = 1;
		else
			usage();
	}
	if (optind != argc - 1)
		usage();

	/* Open input */
	in_name = argv[optind];
	in_file = open(in_name, O_RDONLY);
	if (in_file < 0) {
		perror(in_name);
		exit(1);
	}

	/* Fill input buffer, find gzip signature and set up gzip stream */
	io_size = read(in_file, in_buf, BUF_SIZE);
	if (io_size < 0) {
		perror(in_name);
		exit(1);
	}
	memset(&zstream, 0, sizeof(zstream));
	zstream.next_in = memmem(in_buf, io_size,
				 GZIP_SIGNATURE, sizeof(GZIP_SIGNATURE) - 1);
	if (!zstream.next_in) {
		fprintf(stderr, "%s: no valid gzip header found\n", in_name);
		exit(1);
	}
	zstream.avail_in = in_buf + io_size - zstream.next_in;
	zstream.next_out = out_buf;
	zstream.avail_out = BUF_SIZE;
	z_ret = inflateInit2(&zstream, 16 + 15 /* gzip window=2^15 */);
	if (z_ret != Z_OK) {
		fprintf(stderr, "inflate: %s\n", zstream.msg);
		exit(1);
	}

	/* Open output */
	if (to_stdout) {
		out_name = "-";
		out_file = 1;
	} else {
		out_name = "vmlinux";
		out_file = open(out_name, O_WRONLY | O_CREAT | O_EXCL, 0666);
		if (out_file < 0) {
			perror(out_name);
			exit(1);
		}
	}

	do {
		z_ret = inflate(&zstream, in_eof ? Z_FINISH : Z_NO_FLUSH);

		/* Read more input if necessary */
		if (z_ret == Z_BUF_ERROR) {
			memmove(in_buf, zstream.next_in, zstream.avail_in);
			io_size = read(in_file, in_buf + zstream.avail_in,
				       BUF_SIZE - zstream.avail_in);
			if (io_size < 0) {
				perror(in_name);
				exit(1);
			}
			if (io_size == 0)
				in_eof = 1;
			zstream.next_in = in_buf;
			zstream.avail_in += io_size;
		}

		/* Flush output at stream end or if more than half full */
		if (zstream.avail_out < BUF_SIZE / 2 ||
		    z_ret == Z_STREAM_END) {
			ssize_t off = 0;
			do {
				io_size = write(out_file, out_buf + off,
						BUF_SIZE -
						zstream.avail_out - off);
				if (io_size < 0) {
					perror(out_name);
					exit(1);
				}
				off += io_size;
			} while (off != BUF_SIZE - zstream.avail_out);
			zstream.next_out = out_buf;
			zstream.avail_out = BUF_SIZE;
		}
	} while (z_ret == Z_OK || z_ret == Z_BUF_ERROR);

	if (z_ret != Z_STREAM_END) {
		fprintf(stderr, "%s: %s\n", in_name, zstream.msg);
		exit(1);
	}

	return 0;
}

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to