auto import from //depot/cupcake/@135843
diff --git a/daemon/opd_kernel.c b/daemon/opd_kernel.c
new file mode 100644
index 0000000..5ebc210
--- /dev/null
+++ b/daemon/opd_kernel.c
@@ -0,0 +1,229 @@
+/**
+ * @file daemon/opd_kernel.c
+ * Dealing with the kernel and kernel module samples
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ * @author Philippe Elie
+ * Modified by Aravind Menon for Xen
+ * These modifications are:
+ * Copyright (C) 2005 Hewlett-Packard Co.
+ */
+
+#include "opd_kernel.h"
+#include "opd_sfile.h"
+#include "opd_trans.h"
+#include "opd_printf.h"
+#include "opd_stats.h"
+#include "oprofiled.h"
+
+#include "op_fileio.h"
+#include "op_config.h"
+#include "op_libiberty.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+
+static LIST_HEAD(modules);
+
+static struct kernel_image vmlinux_image;
+
+static struct kernel_image xen_image;
+
+void opd_create_vmlinux(char const * name, char const * arg)
+{
+	/* vmlinux is *not* on the list of modules */
+	list_init(&vmlinux_image.list);
+
+	/* for no vmlinux */
+	if (no_vmlinux) {
+		vmlinux_image.name = "no-vmlinux";
+		return;
+	}
+	
+	vmlinux_image.name = xstrdup(name);
+
+	sscanf(arg, "%llx,%llx", &vmlinux_image.start, &vmlinux_image.end);
+
+	verbprintf(vmisc, "kernel_start = %llx, kernel_end = %llx\n",
+	           vmlinux_image.start, vmlinux_image.end);
+
+	if (!vmlinux_image.start && !vmlinux_image.end) {
+		fprintf(stderr, "error: mis-parsed kernel range: %llx-%llx\n",
+		        vmlinux_image.start, vmlinux_image.end);
+		exit(EXIT_FAILURE);
+	}
+}
+
+void opd_create_xen(char const * name, char const * arg)
+{
+	/* xen is *not* on the list of modules */
+	list_init(&xen_image.list);
+
+	/* for no xen */
+	if (no_xen) {
+		xen_image.name = "no-xen";
+		return;
+	}
+
+	xen_image.name = xstrdup(name);
+
+	sscanf(arg, "%llx,%llx", &xen_image.start, &xen_image.end);
+
+	verbprintf(vmisc, "xen_start = %llx, xen_end = %llx\n",
+	           xen_image.start, xen_image.end);
+
+	if (!xen_image.start && !xen_image.end) {
+		fprintf(stderr, "error: mis-parsed xen range: %llx-%llx\n",
+		        xen_image.start, xen_image.end);
+		exit(EXIT_FAILURE);
+	}
+}
+
+
+/**
+ * Allocate and initialise a kernel image description
+ * @param name image name
+ * @param start start address
+ * @param end end address
+ */
+static struct kernel_image *
+opd_create_module(char const * name, vma_t start, vma_t end)
+{
+	struct kernel_image * image = xmalloc(sizeof(struct kernel_image));
+
+	image->name = xstrdup(name);
+	image->start = start;
+	image->end = end;
+	list_add(&image->list, &modules);
+
+	return image;
+}
+
+
+/**
+ * Clear and free all kernel image information and reset
+ * values.
+ */
+static void opd_clear_modules(void)
+{
+	struct list_head * pos;
+	struct list_head * pos2;
+	struct kernel_image * image;
+
+	list_for_each_safe(pos, pos2, &modules) {
+		image = list_entry(pos, struct kernel_image, list);
+		if (image->name)
+			free(image->name);
+		free(image);
+	}
+
+	list_init(&modules);
+
+	/* clear out lingering references */
+	sfile_clear_kernel();
+}
+
+
+/*
+ * each line is in the format:
+ *
+ * module_name 16480 1 dependencies Live 0xe091e000
+ *
+ * without any blank space in each field
+ */
+void opd_reread_module_info(void)
+{
+	FILE * fp;
+	char * line;
+	struct kernel_image * image;
+	int module_size;
+	char ref_count[32+1];
+	int ret;
+	char module_name[256+1];
+	char live_info[32+1];
+	char dependencies[4096+1];
+	unsigned long long start_address;
+
+	if (no_vmlinux)
+		return;
+
+	opd_clear_modules();
+
+	printf("Reading module info.\n");
+
+	fp = op_try_open_file("/proc/modules", "r");
+
+	if (!fp) {
+		printf("oprofiled: /proc/modules not readable, "
+			"can't process module samples.\n");
+		return;
+	}
+
+	while (1) {
+		line = op_get_line(fp);
+
+		if (!line)
+			break;
+
+		if (line[0] == '\0') {
+			free(line);
+			continue;
+		}
+
+		ret = sscanf(line, "%256s %u %32s %4096s %32s %llx",
+			     module_name, &module_size, ref_count,
+			     dependencies, live_info, &start_address);
+		if (ret != 6) {
+			printf("bad /proc/modules entry: %s\n", line);
+			free(line);
+			continue;
+		}
+
+		image = opd_create_module(module_name, start_address,
+		                          start_address + module_size);
+
+		verbprintf(vmodule, "module %s start %llx end %llx\n",
+			   image->name, image->start, image->end);
+
+		free(line);
+	}
+
+	op_close_file(fp);
+}
+
+
+/**
+ * find a kernel image by PC value
+ * @param trans holds PC value to look up
+ *
+ * find the kernel image which contains this PC.
+ *
+ * Return %NULL if not found.
+ */
+struct kernel_image * find_kernel_image(struct transient const * trans)
+{
+	struct list_head * pos;
+	struct kernel_image * image = &vmlinux_image;
+
+	if (no_vmlinux)
+		return image;
+
+	if (image->start <= trans->pc && image->end > trans->pc)
+		return image;
+
+	list_for_each(pos, &modules) {
+		image = list_entry(pos, struct kernel_image, list);
+		if (image->start <= trans->pc && image->end > trans->pc)
+			return image;
+	}
+
+	if (xen_image.start <= trans->pc && xen_image.end > trans->pc)
+		return &xen_image;
+
+	return NULL;
+}