blob: e7ba024f4eea099cf10262d419d7324c4f9e6adc [file] [log] [blame]
/*
* @file pe_profiling/operf_kernel.cpp
* This file is based on daemon/opd_kernel and is used for
* dealing with the kernel and kernel module samples.
*
* @remark Copyright 2011 OProfile authors
* @remark Read the file COPYING
*
* Created on: Dec 12, 2011
* @author Maynard Johnson
* (C) Copyright IBM Corp. 2011
*/
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <unistd.h>
#include <stdlib.h>
#include "operf_kernel.h"
#include "operf_sfile.h"
#include "op_list.h"
#include "op_libiberty.h"
#include "cverb.h"
#include "op_fileio.h"
extern verbose vmisc;
extern bool no_vmlinux;
static LIST_HEAD(modules);
static struct operf_kernel_image vmlinux_image;
using namespace std;
void operf_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 = xstrdup("no-vmlinux");
return;
}
vmlinux_image.name = xstrdup(name);
sscanf(arg, "%llx,%llx", &vmlinux_image.start, &vmlinux_image.end);
ostringstream message;
message << "kernel_start = " << hex << vmlinux_image.start
<< "; kernel_end = " << vmlinux_image.end << endl;
cverb << vmisc << message.str();
if (!vmlinux_image.start && !vmlinux_image.end) {
ostringstream message;
message << "error: mis-parsed kernel range: " << hex << vmlinux_image.start
<< "; kernel_end = " << vmlinux_image.end << endl;
cerr << message.str();
exit(EXIT_FAILURE);
}
}
/**
* Allocate and initialise a kernel module image description.
* @param name image name
* @param start start address
* @param end end address
*/
void operf_create_module(char const * name, vma_t start, vma_t end)
{
struct operf_kernel_image * image =(struct operf_kernel_image *) xmalloc(sizeof(struct operf_kernel_image));
image->name = xstrdup(name);
image->start = start;
image->end = end;
list_add(&image->list, &modules);
}
void operf_free_modules_list(void)
{
struct list_head * pos;
struct list_head * pos2;
struct operf_kernel_image * image;
list_for_each_safe(pos, pos2, &modules) {
image = list_entry(pos, struct operf_kernel_image, list);
free(image->name);
list_del(&image->list);
free(image);
}
}
/**
* 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 operf_kernel_image * operf_find_kernel_image(vma_t pc)
{
struct list_head * pos;
struct operf_kernel_image * image = &vmlinux_image;
if (no_vmlinux)
return image;
if (image->start <= pc && image->end > pc)
return image;
list_for_each(pos, &modules) {
image = list_entry(pos, struct operf_kernel_image, list);
if (image->start <= pc && image->end > pc)
return image;
}
return NULL;
}
const char * operf_get_vmlinux_name(void)
{
return vmlinux_image.name;
}