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 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 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 * 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 */ 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 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 */ 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 (at) fc.hp.com> 269 * 270 */ 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 */ 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 */ 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 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 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 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