• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * @file daemon/liblegacy/opd_kernel.c
3  * Dealing with the kernel and kernel module samples
4  *
5  * @remark Copyright 2002 OProfile authors
6  * @remark Read the file COPYING
7  *
8  * @author John Levon
9  * @author Philippe Elie
10  */
11 
12 #include "opd_kernel.h"
13 #include "opd_proc.h"
14 #include "opd_image.h"
15 #include "opd_mapping.h"
16 #include "opd_printf.h"
17 #include "opd_24_stats.h"
18 #include "oprofiled.h"
19 
20 #include "op_fileio.h"
21 #include "op_config_24.h"
22 #include "op_libiberty.h"
23 
24 #include "p_module.h"
25 #include <string.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 
29 /* kernel module */
30 struct opd_module {
31 	char * name;
32 	struct opd_image * image;
33 	unsigned long start;
34 	unsigned long end;
35 	struct list_head module_list;
36 };
37 
38 static struct opd_image * kernel_image;
39 
40 /* kernel and module support */
41 static unsigned long kernel_start;
42 static unsigned long kernel_end;
43 static struct list_head opd_modules = { &opd_modules, &opd_modules };
44 static unsigned int nr_modules=0;
45 
opd_init_kernel_image(void)46 void opd_init_kernel_image(void)
47 {
48 	/* for no vmlinux */
49 	if (!vmlinux)
50 		vmlinux = "no-vmlinux";
51 	kernel_image = opd_get_kernel_image(vmlinux, NULL, 0, 0);
52 	kernel_image->ref_count++;
53 }
54 
55 
opd_parse_kernel_range(char const * arg)56 void opd_parse_kernel_range(char const * arg)
57 {
58 	sscanf(arg, "%lx,%lx", &kernel_start, &kernel_end);
59 
60 	verbprintf(vmisc, "OPD_PARSE_KERNEL_RANGE: kernel_start = %lx, kernel_end = %lx\n",
61 		   kernel_start, kernel_end);
62 
63 	if (!kernel_start && !kernel_end) {
64 		fprintf(stderr,
65 			"Warning: mis-parsed kernel range: %lx-%lx\n",
66 			kernel_start, kernel_end);
67 		fprintf(stderr, "kernel profiles will be wrong.\n");
68 	}
69 }
70 
71 
72 /**
73  * opd_create_module - allocate and initialise a module description
74  * @param name module name
75  * @param start start address
76  * @param end end address
77  */
78 static struct opd_module *
opd_create_module(char * name,unsigned long start,unsigned long end)79 opd_create_module(char * name, unsigned long start, unsigned long end)
80 {
81 	struct opd_module * module = xmalloc(sizeof(struct opd_module));
82 
83 	module->name = xstrdup(name);
84 	module->image = NULL;
85 	module->start = start;
86 	module->end = end;
87 	list_add(&module->module_list, &opd_modules);
88 
89 	return module;
90 }
91 
92 
93 /**
94  * opd_find_module_by_name - find a module by name, ccreating a new once if
95  * search fail
96  * @param name module name
97  */
opd_find_module_by_name(char * name)98 static struct opd_module * opd_find_module_by_name(char * name)
99 {
100 	struct list_head * pos;
101 	struct opd_module * module;
102 
103 	list_for_each(pos, &opd_modules) {
104 		module = list_entry(pos, struct opd_module, module_list);
105 		if (!strcmp(name, module->name))
106 			return module;
107 	}
108 
109 	return opd_create_module(name, 0, 0);
110 }
111 
112 
opd_clear_module_info(void)113 void opd_clear_module_info(void)
114 {
115 	struct list_head * pos;
116 	struct list_head * pos2;
117 	struct opd_module * module;
118 
119 	verbprintf(vmodule, "Removing module list\n");
120 	list_for_each_safe(pos, pos2, &opd_modules) {
121 		module = list_entry(pos, struct opd_module, module_list);
122 		free(module->name);
123 		free(module);
124 	}
125 
126 	list_init(&opd_modules);
127 
128 	opd_clear_kernel_mapping();
129 }
130 
131 
132 /**
133  * opd_get_module_info - parse mapping information for kernel modules
134  *
135  * Parse the file /proc/ksyms to read in mapping information for
136  * all kernel modules. The modutils package adds special symbols
137  * to this file which allows determination of the module image
138  * and mapping addresses of the form :
139  *
140  * __insmod_modulename_Oobjectfile_Mmtime_Vversion
141  * __insmod_modulename_Ssectionname_Llength
142  *
143  * Currently the image file "objectfile" is stored, and details of
144  * ".text" sections.
145  *
146  * There is no query_module API that allow to get directly the pathname
147  * of a module so we need to parse all the /proc/ksyms.
148  */
opd_get_module_info(void)149 static void opd_get_module_info(void)
150 {
151 	char * line;
152 	char * cp, * cp2, * cp3;
153 	FILE * fp;
154 	struct opd_module * mod;
155 	char * modname;
156 	char * filename;
157 
158 	nr_modules=0;
159 
160 	fp = op_try_open_file("/proc/ksyms", "r");
161 
162 	if (!fp) {
163 		printf("oprofiled: /proc/ksyms not readable, can't process module samples.\n");
164 		return;
165 	}
166 
167 	verbprintf(vmodule, "Read module info.\n");
168 
169 	while (1) {
170 		line = op_get_line(fp);
171 
172 		if (!line)
173 			break;
174 
175 		if (!strcmp("", line)) {
176 			free(line);
177 			continue;
178 		}
179 
180 		if (strlen(line) < 9) {
181 			printf("oprofiled: corrupt /proc/ksyms line \"%s\"\n", line);
182 			break;
183 		}
184 
185 		if (strncmp("__insmod_", line + 9, 9)) {
186 			free(line);
187 			continue;
188 		}
189 
190 		cp = line + 18;
191 		cp2 = cp;
192 		while ((*cp2) && !!strncmp("_S", cp2+1, 2) && !!strncmp("_O", cp2+1, 2))
193 			cp2++;
194 
195 		if (!*cp2) {
196 			printf("oprofiled: corrupt /proc/ksyms line \"%s\"\n", line);
197 			break;
198 		}
199 
200 		cp2++;
201 
202 		modname = xmalloc((size_t)((cp2-cp) + 1));
203 		strncpy(modname, cp, (size_t)((cp2-cp)));
204 		modname[cp2-cp] = '\0';
205 
206 		mod = opd_find_module_by_name(modname);
207 
208 		free(modname);
209 
210 		switch (*(++cp2)) {
211 			case 'O':
212 				/* get filename */
213 				cp2++;
214 				cp3 = cp2;
215 
216 				while ((*cp3) && !!strncmp("_M", cp3+1, 2))
217 					cp3++;
218 
219 				if (!*cp3) {
220 					free(line);
221 					continue;
222 				}
223 
224 				cp3++;
225 				filename = xmalloc((size_t)(cp3 - cp2 + 1));
226 				strncpy(filename, cp2, (size_t)(cp3 - cp2));
227 				filename[cp3-cp2] = '\0';
228 
229 				mod->image = opd_get_kernel_image(filename, NULL, 0, 0);
230 				mod->image->ref_count++;
231 				free(filename);
232 				break;
233 
234 			case 'S':
235 				/* get extent of .text section */
236 				cp2++;
237 				if (strncmp(".text_L", cp2, 7)) {
238 					free(line);
239 					continue;
240 				}
241 
242 				cp2 += 7;
243 				sscanf(line, "%lx", &mod->start);
244 				sscanf(cp2, "%lu", &mod->end);
245 				mod->end += mod->start;
246 				break;
247 		}
248 
249 		free(line);
250 	}
251 
252 	if (line)
253 		free(line);
254 	op_close_file(fp);
255 }
256 
257 
258 /**
259  * opd_drop_module_sample - drop a module sample efficiently
260  * @param eip  eip of sample
261  *
262  * This function is called to recover from failing to put a samples even
263  * after re-reading /proc/ksyms. It's either a rogue sample, or from a module
264  * that didn't create symbols (like in some initrd setups). So we check with
265  * query_module() if we can place it in a symbol-less module, and if so create
266  * a negative entry for it, to quickly ignore future samples.
267  *
268  * Problem uncovered by Bob Montgomery <bobm@fc.hp.com>
269  *
270  */
opd_drop_module_sample(unsigned long eip)271 static void opd_drop_module_sample(unsigned long eip)
272 {
273 	char * module_names;
274 	char * name;
275 	size_t size = 1024;
276 	size_t ret;
277 	uint nr_mods;
278 	uint mod = 0;
279 
280 	opd_24_stats[OPD_LOST_MODULE]++;
281 
282 	module_names = xmalloc(size);
283 	while (query_module(NULL, QM_MODULES, module_names, size, &ret)) {
284 		if (errno != ENOSPC) {
285 			verbprintf(vmodule, "query_module failed: %s\n", strerror(errno));
286 			return;
287 		}
288 		size = ret;
289 		module_names = xrealloc(module_names, size);
290 	}
291 
292 	nr_mods = ret;
293 	name = module_names;
294 
295 	while (mod < nr_mods) {
296 		struct module_info info;
297 		if (!query_module(name, QM_INFO, &info, sizeof(info), &ret)) {
298 			if (eip >= info.addr && eip < info.addr + info.size) {
299 				verbprintf(vmodule, "Sample from unprofilable module %s\n", name);
300 				opd_create_module(name, info.addr, info.addr + info.size);
301 				break;
302 			}
303 		}
304 		mod++;
305 		name += strlen(name) + 1;
306 	}
307 
308 	if (module_names)
309 		free(module_names);
310 }
311 
312 
313 /**
314  * opd_find_module_by_eip - find a module by its eip
315  * @param eip  EIP value
316  *
317  * find in the modules container the module which
318  * contain this eip return %NULL if not found.
319  * caller must check than the module image is valid
320  */
opd_find_module_by_eip(unsigned long eip)321 static struct opd_module * opd_find_module_by_eip(unsigned long eip)
322 {
323 	struct list_head * pos;
324 	struct opd_module * module;
325 
326 	list_for_each(pos, &opd_modules) {
327 		module = list_entry(pos, struct opd_module, module_list);
328 		if (module->start <= eip && module->end > eip)
329 			return module;
330 	}
331 
332 	return NULL;
333 }
334 
335 
336 /**
337  * opd_handle_module_sample - process a module sample
338  * @param eip  EIP value
339  * @param counter  counter number
340  *
341  * Process a sample in module address space. The sample eip
342  * is matched against module information. If the search was
343  * successful, the sample is output to the relevant file.
344  *
345  * Note that for modules and the kernel, the offset will be
346  * wrong in the file, as it is not a file offset, but the offset
347  * from the text section. This is fixed up in pp.
348  *
349  * If the sample could not be located in a module, it is treated
350  * as a kernel sample.
351  */
opd_handle_module_sample(unsigned long eip,u32 counter)352 static void opd_handle_module_sample(unsigned long eip, u32 counter)
353 {
354 	struct opd_module * module;
355 
356 	module = opd_find_module_by_eip(eip);
357 	if (!module) {
358 		/* not found in known modules, re-read our info and retry */
359 		opd_clear_module_info();
360 		opd_get_module_info();
361 
362 		module = opd_find_module_by_eip(eip);
363 	}
364 
365 	if (module) {
366 		if (module->image != NULL) {
367 			opd_24_stats[OPD_MODULE]++;
368 			opd_put_image_sample(module->image,
369 					     eip - module->start, counter);
370 		} else {
371 			opd_24_stats[OPD_LOST_MODULE]++;
372 			verbprintf(vmodule, "No image for sampled module %s\n",
373 				   module->name);
374 		}
375 	} else {
376 		opd_drop_module_sample(eip);
377 	}
378 }
379 
380 
opd_handle_kernel_sample(unsigned long eip,u32 counter)381 void opd_handle_kernel_sample(unsigned long eip, u32 counter)
382 {
383 	if (no_vmlinux || eip < kernel_end) {
384 		opd_24_stats[OPD_KERNEL]++;
385 		opd_put_image_sample(kernel_image, eip - kernel_start, counter);
386 		return;
387 	}
388 
389 	/* in a module */
390 	opd_handle_module_sample(eip, counter);
391 }
392 
393 
opd_eip_is_kernel(unsigned long eip)394 int opd_eip_is_kernel(unsigned long eip)
395 {
396 #ifdef __i386
397 #define KERNEL_OFFSET 0xC0000000
398 	/*
399 	 * kernel_start == 0 when using --no-vmlinux.
400 	 * This is wrong, wrong, wrong, wrong, but we don't have much
401 	 * choice. It obviously breaks for IA64.
402 	 */
403 	if (!kernel_start)
404 		return eip >= KERNEL_OFFSET;
405 #endif
406 
407 	return eip >= kernel_start;
408 }
409 
410 
opd_add_kernel_map(struct opd_proc * proc,unsigned long eip)411 void opd_add_kernel_map(struct opd_proc * proc, unsigned long eip)
412 {
413 	struct opd_module * module;
414 	struct opd_image * image;
415 	char const * app_name;
416 
417 	app_name = proc->name;
418 	if (!app_name) {
419 		verbprintf(vmisc, "un-named proc for tid %d\n", proc->tid);
420 		return;
421 	}
422 
423 
424 	if (eip < kernel_end) {
425 		image = opd_get_kernel_image(vmlinux, app_name, proc->tid, proc->tgid);
426 		if (!image) {
427 			verbprintf(vmisc, "Can't create image for %s %s\n", vmlinux, app_name);
428 			return;
429 		}
430 
431 		opd_add_mapping(proc, image, kernel_start, 0, kernel_end);
432 		return;
433 	}
434 
435 	module = opd_find_module_by_eip(eip);
436 	if (!module) {
437 		/* not found in known modules, re-read our info and retry */
438 		opd_clear_module_info();
439 		opd_get_module_info();
440 
441 		module = opd_find_module_by_eip(eip);
442 	}
443 
444 	if (module) {
445 		/* module->name is only the module name not the full path */
446 		char const * module_name = 0;
447 		if (module->image)
448 			module_name = module->image->name;
449 		if (!module_name) {
450 			verbprintf(vmodule, "unable to get path name for module %s\n",
451 			       module->name);
452 			module_name = module->name;
453 		}
454 		image = opd_get_kernel_image(module_name, app_name, proc->tid, proc->tgid);
455 		if (!image) {
456 			verbprintf(vmodule, "Can't create image for %s %s\n",
457 			       module->name, app_name);
458 			return;
459 		}
460 		opd_add_mapping(proc, image, module->start, 0, module->end);
461 	} else {
462 		opd_drop_module_sample(eip);
463 	}
464 }
465