18cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/**
28cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @file daemon/liblegacy/opd_kernel.c
38cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Dealing with the kernel and kernel module samples
48cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
58cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Copyright 2002 OProfile authors
68cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Read the file COPYING
78cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
88cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author John Levon
98cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Philippe Elie
108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opd_kernel.h"
138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opd_proc.h"
148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opd_image.h"
158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opd_mapping.h"
168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opd_printf.h"
178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opd_24_stats.h"
188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "oprofiled.h"
198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_fileio.h"
218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_config_24.h"
228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_libiberty.h"
238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "p_module.h"
258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <string.h>
268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <stdlib.h>
278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <errno.h>
288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* kernel module */
308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct opd_module {
318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char * name;
328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct opd_image * image;
338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned long start;
348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	unsigned long end;
358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct list_head module_list;
368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd};
378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic struct opd_image * kernel_image;
398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* kernel and module support */
418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic unsigned long kernel_start;
428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic unsigned long kernel_end;
438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic struct list_head opd_modules = { &opd_modules, &opd_modules };
448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic unsigned int nr_modules=0;
458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid opd_init_kernel_image(void)
478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* for no vmlinux */
498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!vmlinux)
508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		vmlinux = "no-vmlinux";
518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	kernel_image = opd_get_kernel_image(vmlinux, NULL, 0, 0);
528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	kernel_image->ref_count++;
538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid opd_parse_kernel_range(char const * arg)
578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	sscanf(arg, "%lx,%lx", &kernel_start, &kernel_end);
598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	verbprintf(vmisc, "OPD_PARSE_KERNEL_RANGE: kernel_start = %lx, kernel_end = %lx\n",
618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		   kernel_start, kernel_end);
628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!kernel_start && !kernel_end) {
648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		fprintf(stderr,
658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			"Warning: mis-parsed kernel range: %lx-%lx\n",
668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			kernel_start, kernel_end);
678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		fprintf(stderr, "kernel profiles will be wrong.\n");
688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/**
738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * opd_create_module - allocate and initialise a module description
748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param name module name
758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param start start address
768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param end end address
778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic struct opd_module *
798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddopd_create_module(char * name, unsigned long start, unsigned long end)
808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct opd_module * module = xmalloc(sizeof(struct opd_module));
828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	module->name = xstrdup(name);
848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	module->image = NULL;
858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	module->start = start;
868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	module->end = end;
878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	list_add(&module->module_list, &opd_modules);
888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return module;
908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/**
948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * opd_find_module_by_name - find a module by name, ccreating a new once if
958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * search fail
968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param name module name
978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic struct opd_module * opd_find_module_by_name(char * name)
998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct list_head * pos;
1018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct opd_module * module;
1028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	list_for_each(pos, &opd_modules) {
1048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		module = list_entry(pos, struct opd_module, module_list);
1058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!strcmp(name, module->name))
1068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return module;
1078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return opd_create_module(name, 0, 0);
1108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid opd_clear_module_info(void)
1148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct list_head * pos;
1168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct list_head * pos2;
1178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct opd_module * module;
1188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	verbprintf(vmodule, "Removing module list\n");
1208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	list_for_each_safe(pos, pos2, &opd_modules) {
1218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		module = list_entry(pos, struct opd_module, module_list);
1228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		free(module->name);
1238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		free(module);
1248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	list_init(&opd_modules);
1278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	opd_clear_kernel_mapping();
1298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/**
1338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * opd_get_module_info - parse mapping information for kernel modules
1348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
1358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Parse the file /proc/ksyms to read in mapping information for
1368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * all kernel modules. The modutils package adds special symbols
1378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * to this file which allows determination of the module image
1388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * and mapping addresses of the form :
1398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
1408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * __insmod_modulename_Oobjectfile_Mmtime_Vversion
1418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * __insmod_modulename_Ssectionname_Llength
1428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
1438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Currently the image file "objectfile" is stored, and details of
1448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * ".text" sections.
1458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
1468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * There is no query_module API that allow to get directly the pathname
1478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * of a module so we need to parse all the /proc/ksyms.
1488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
1498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_get_module_info(void)
1508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char * line;
1528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char * cp, * cp2, * cp3;
1538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	FILE * fp;
1548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct opd_module * mod;
1558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char * modname;
1568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char * filename;
1578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	nr_modules=0;
1598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	fp = op_try_open_file("/proc/ksyms", "r");
1618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!fp) {
1638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		printf("oprofiled: /proc/ksyms not readable, can't process module samples.\n");
1648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return;
1658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	verbprintf(vmodule, "Read module info.\n");
1688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	while (1) {
1708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		line = op_get_line(fp);
1718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!line)
1738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			break;
1748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!strcmp("", line)) {
1768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			free(line);
1778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			continue;
1788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
1798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (strlen(line) < 9) {
1818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			printf("oprofiled: corrupt /proc/ksyms line \"%s\"\n", line);
1828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			break;
1838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
1848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (strncmp("__insmod_", line + 9, 9)) {
1868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			free(line);
1878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			continue;
1888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
1898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		cp = line + 18;
1918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		cp2 = cp;
1928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		while ((*cp2) && !!strncmp("_S", cp2+1, 2) && !!strncmp("_O", cp2+1, 2))
1938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			cp2++;
1948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!*cp2) {
1968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			printf("oprofiled: corrupt /proc/ksyms line \"%s\"\n", line);
1978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			break;
1988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
1998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		cp2++;
2018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		modname = xmalloc((size_t)((cp2-cp) + 1));
2038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		strncpy(modname, cp, (size_t)((cp2-cp)));
2048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		modname[cp2-cp] = '\0';
2058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		mod = opd_find_module_by_name(modname);
2078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		free(modname);
2098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		switch (*(++cp2)) {
2118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			case 'O':
2128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				/* get filename */
2138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				cp2++;
2148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				cp3 = cp2;
2158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				while ((*cp3) && !!strncmp("_M", cp3+1, 2))
2178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					cp3++;
2188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				if (!*cp3) {
2208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					free(line);
2218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					continue;
2228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				}
2238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				cp3++;
2258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				filename = xmalloc((size_t)(cp3 - cp2 + 1));
2268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				strncpy(filename, cp2, (size_t)(cp3 - cp2));
2278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				filename[cp3-cp2] = '\0';
2288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				mod->image = opd_get_kernel_image(filename, NULL, 0, 0);
2308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				mod->image->ref_count++;
2318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				free(filename);
2328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				break;
2338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			case 'S':
2358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				/* get extent of .text section */
2368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				cp2++;
2378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				if (strncmp(".text_L", cp2, 7)) {
2388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					free(line);
2398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					continue;
2408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				}
2418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				cp2 += 7;
2438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				sscanf(line, "%lx", &mod->start);
2448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				sscanf(cp2, "%lu", &mod->end);
2458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				mod->end += mod->start;
2468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				break;
2478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
2488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		free(line);
2508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
2518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (line)
2538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		free(line);
2548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	op_close_file(fp);
2558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
2568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/**
2598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * opd_drop_module_sample - drop a module sample efficiently
2608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param eip  eip of sample
2618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
2628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * This function is called to recover from failing to put a samples even
2638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * after re-reading /proc/ksyms. It's either a rogue sample, or from a module
2648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * that didn't create symbols (like in some initrd setups). So we check with
2658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * query_module() if we can place it in a symbol-less module, and if so create
2668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * a negative entry for it, to quickly ignore future samples.
2678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
2688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Problem uncovered by Bob Montgomery <bobm@fc.hp.com>
2698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
2708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
2718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_drop_module_sample(unsigned long eip)
2728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
2738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char * module_names;
2748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char * name;
2758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	size_t size = 1024;
2768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	size_t ret;
2778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	uint nr_mods;
2788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	uint mod = 0;
2798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	opd_24_stats[OPD_LOST_MODULE]++;
2818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	module_names = xmalloc(size);
2838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	while (query_module(NULL, QM_MODULES, module_names, size, &ret)) {
2848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (errno != ENOSPC) {
2858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			verbprintf(vmodule, "query_module failed: %s\n", strerror(errno));
2868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return;
2878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
2888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		size = ret;
2898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		module_names = xrealloc(module_names, size);
2908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
2918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	nr_mods = ret;
2938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	name = module_names;
2948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
2958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	while (mod < nr_mods) {
2968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		struct module_info info;
2978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!query_module(name, QM_INFO, &info, sizeof(info), &ret)) {
2988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			if (eip >= info.addr && eip < info.addr + info.size) {
2998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				verbprintf(vmodule, "Sample from unprofilable module %s\n", name);
3008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				opd_create_module(name, info.addr, info.addr + info.size);
3018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				break;
3028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			}
3038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
3048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		mod++;
3058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		name += strlen(name) + 1;
3068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
3078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (module_names)
3098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		free(module_names);
3108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
3118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/**
3148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * opd_find_module_by_eip - find a module by its eip
3158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param eip  EIP value
3168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
3178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * find in the modules container the module which
3188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * contain this eip return %NULL if not found.
3198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * caller must check than the module image is valid
3208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
3218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic struct opd_module * opd_find_module_by_eip(unsigned long eip)
3228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
3238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct list_head * pos;
3248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct opd_module * module;
3258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	list_for_each(pos, &opd_modules) {
3278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		module = list_entry(pos, struct opd_module, module_list);
3288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (module->start <= eip && module->end > eip)
3298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return module;
3308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
3318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return NULL;
3338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
3348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/**
3378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * opd_handle_module_sample - process a module sample
3388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param eip  EIP value
3398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @param counter  counter number
3408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
3418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Process a sample in module address space. The sample eip
3428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * is matched against module information. If the search was
3438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * successful, the sample is output to the relevant file.
3448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
3458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Note that for modules and the kernel, the offset will be
3468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * wrong in the file, as it is not a file offset, but the offset
3478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * from the text section. This is fixed up in pp.
3488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
3498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * If the sample could not be located in a module, it is treated
3508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * as a kernel sample.
3518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
3528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void opd_handle_module_sample(unsigned long eip, u32 counter)
3538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
3548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct opd_module * module;
3558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	module = opd_find_module_by_eip(eip);
3578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!module) {
3588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* not found in known modules, re-read our info and retry */
3598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		opd_clear_module_info();
3608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		opd_get_module_info();
3618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		module = opd_find_module_by_eip(eip);
3638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
3648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (module) {
3668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (module->image != NULL) {
3678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			opd_24_stats[OPD_MODULE]++;
3688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			opd_put_image_sample(module->image,
3698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd					     eip - module->start, counter);
3708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		} else {
3718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			opd_24_stats[OPD_LOST_MODULE]++;
3728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			verbprintf(vmodule, "No image for sampled module %s\n",
3738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				   module->name);
3748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
3758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	} else {
3768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		opd_drop_module_sample(eip);
3778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
3788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
3798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid opd_handle_kernel_sample(unsigned long eip, u32 counter)
3828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
3838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (no_vmlinux || eip < kernel_end) {
3848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		opd_24_stats[OPD_KERNEL]++;
3858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		opd_put_image_sample(kernel_image, eip - kernel_start, counter);
3868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return;
3878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
3888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/* in a module */
3908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	opd_handle_module_sample(eip, counter);
3918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
3928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
3948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddint opd_eip_is_kernel(unsigned long eip)
3958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
39673f45fe6aeb2ac4c67c405c6cd4cfe97f0b07b72Paul Lind#ifdef __i386__
3978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#define KERNEL_OFFSET 0xC0000000
3988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	/*
3998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * kernel_start == 0 when using --no-vmlinux.
4008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * This is wrong, wrong, wrong, wrong, but we don't have much
4018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 * choice. It obviously breaks for IA64.
4028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	 */
4038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!kernel_start)
4048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return eip >= KERNEL_OFFSET;
4058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif
4068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return eip >= kernel_start;
4088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
4098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid opd_add_kernel_map(struct opd_proc * proc, unsigned long eip)
4128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
4138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct opd_module * module;
4148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	struct opd_image * image;
4158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	char const * app_name;
4168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	app_name = proc->name;
4188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!app_name) {
4198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		verbprintf(vmisc, "un-named proc for tid %d\n", proc->tid);
4208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return;
4218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (eip < kernel_end) {
4258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		image = opd_get_kernel_image(vmlinux, app_name, proc->tid, proc->tgid);
4268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!image) {
4278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			verbprintf(vmisc, "Can't create image for %s %s\n", vmlinux, app_name);
4288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return;
4298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
4308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		opd_add_mapping(proc, image, kernel_start, 0, kernel_end);
4328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return;
4338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	module = opd_find_module_by_eip(eip);
4368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (!module) {
4378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* not found in known modules, re-read our info and retry */
4388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		opd_clear_module_info();
4398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		opd_get_module_info();
4408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		module = opd_find_module_by_eip(eip);
4428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
4448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (module) {
4458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		/* module->name is only the module name not the full path */
4468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		char const * module_name = 0;
4478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (module->image)
4488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			module_name = module->image->name;
4498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!module_name) {
4508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			verbprintf(vmodule, "unable to get path name for module %s\n",
4518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			       module->name);
4528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			module_name = module->name;
4538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
4548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		image = opd_get_kernel_image(module_name, app_name, proc->tid, proc->tgid);
4558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (!image) {
4568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			verbprintf(vmodule, "Can't create image for %s %s\n",
4578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			       module->name, app_name);
4588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return;
4598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
4608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		opd_add_mapping(proc, image, module->start, 0, module->end);
4618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	} else {
4628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		opd_drop_module_sample(eip);
4638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
4648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
465