opd_kernel.c

Go to the documentation of this file.
00001 
00015 #include "opd_kernel.h"
00016 #include "opd_sfile.h"
00017 #include "opd_trans.h"
00018 #include "opd_printf.h"
00019 #include "opd_stats.h"
00020 #include "oprofiled.h"
00021 
00022 #include "op_fileio.h"
00023 #include "op_config.h"
00024 #include "op_libiberty.h"
00025 
00026 #include <string.h>
00027 #include <stdlib.h>
00028 #include <errno.h>
00029 #include <assert.h>
00030 
00031 static LIST_HEAD(modules);
00032 
00033 static struct kernel_image vmlinux_image;
00034 
00035 static struct kernel_image xen_image;
00036 
00037 void opd_create_vmlinux(char const * name, char const * arg)
00038 {
00039     /* vmlinux is *not* on the list of modules */
00040     list_init(&vmlinux_image.list);
00041 
00042     /* for no vmlinux */
00043     if (no_vmlinux) {
00044         vmlinux_image.name = "no-vmlinux";
00045         return;
00046     }
00047     
00048     vmlinux_image.name = xstrdup(name);
00049 
00050     sscanf(arg, "%llx,%llx", &vmlinux_image.start, &vmlinux_image.end);
00051 
00052     verbprintf(vmisc, "kernel_start = %llx, kernel_end = %llx\n",
00053                vmlinux_image.start, vmlinux_image.end);
00054 
00055     if (!vmlinux_image.start && !vmlinux_image.end) {
00056         fprintf(stderr, "error: mis-parsed kernel range: %llx-%llx\n",
00057                 vmlinux_image.start, vmlinux_image.end);
00058         exit(EXIT_FAILURE);
00059     }
00060 }
00061 
00062 void opd_create_xen(char const * name, char const * arg)
00063 {
00064     /* xen is *not* on the list of modules */
00065     list_init(&xen_image.list);
00066 
00067     /* for no xen */
00068     if (no_xen) {
00069         xen_image.name = "no-xen";
00070         return;
00071     }
00072 
00073     xen_image.name = xstrdup(name);
00074 
00075     sscanf(arg, "%llx,%llx", &xen_image.start, &xen_image.end);
00076 
00077     verbprintf(vmisc, "xen_start = %llx, xen_end = %llx\n",
00078                xen_image.start, xen_image.end);
00079 
00080     if (!xen_image.start && !xen_image.end) {
00081         fprintf(stderr, "error: mis-parsed xen range: %llx-%llx\n",
00082                 xen_image.start, xen_image.end);
00083         exit(EXIT_FAILURE);
00084     }
00085 }
00086 
00087 
00094 static struct kernel_image *
00095 opd_create_module(char const * name, vma_t start, vma_t end)
00096 {
00097     struct kernel_image * image = xmalloc(sizeof(struct kernel_image));
00098 
00099     image->name = xstrdup(name);
00100     image->start = start;
00101     image->end = end;
00102     list_add(&image->list, &modules);
00103 
00104     return image;
00105 }
00106 
00107 
00112 static void opd_clear_modules(void)
00113 {
00114     struct list_head * pos;
00115     struct list_head * pos2;
00116     struct kernel_image * image;
00117 
00118     list_for_each_safe(pos, pos2, &modules) {
00119         image = list_entry(pos, struct kernel_image, list);
00120         if (image->name)
00121             free(image->name);
00122         free(image);
00123     }
00124 
00125     list_init(&modules);
00126 
00127     /* clear out lingering references */
00128     sfile_clear_kernel();
00129 }
00130 
00131 
00132 /*
00133  * each line is in the format:
00134  *
00135  * module_name 16480 1 dependencies Live 0xe091e000
00136  *
00137  * without any blank space in each field
00138  */
00139 void opd_reread_module_info(void)
00140 {
00141     FILE * fp;
00142     char * line;
00143     struct kernel_image * image;
00144     int module_size;
00145     char ref_count[32+1];
00146     int ret;
00147     char module_name[256+1];
00148     char live_info[32+1];
00149     char dependencies[4096+1];
00150     unsigned long long start_address;
00151 
00152     if (no_vmlinux)
00153         return;
00154 
00155     opd_clear_modules();
00156 
00157     printf("Reading module info.\n");
00158 
00159     fp = op_try_open_file("/proc/modules", "r");
00160 
00161     if (!fp) {
00162         printf("oprofiled: /proc/modules not readable, "
00163             "can't process module samples.\n");
00164         return;
00165     }
00166 
00167     while (1) {
00168         line = op_get_line(fp);
00169 
00170         if (!line)
00171             break;
00172 
00173         if (line[0] == '\0') {
00174             free(line);
00175             continue;
00176         }
00177 
00178         ret = sscanf(line, "%256s %u %32s %4096s %32s %llx",
00179                  module_name, &module_size, ref_count,
00180                  dependencies, live_info, &start_address);
00181         if (ret != 6) {
00182             printf("bad /proc/modules entry: %s\n", line);
00183             free(line);
00184             continue;
00185         }
00186 
00187         image = opd_create_module(module_name, start_address,
00188                                   start_address + module_size);
00189 
00190         verbprintf(vmodule, "module %s start %llx end %llx\n",
00191                image->name, image->start, image->end);
00192 
00193         free(line);
00194     }
00195 
00196     op_close_file(fp);
00197 }
00198 
00199 
00208 struct kernel_image * find_kernel_image(struct transient const * trans)
00209 {
00210     struct list_head * pos;
00211     struct kernel_image * image = &vmlinux_image;
00212 
00213     if (no_vmlinux)
00214         return image;
00215 
00216     if (image->start <= trans->pc && image->end > trans->pc)
00217         return image;
00218 
00219     list_for_each(pos, &modules) {
00220         image = list_entry(pos, struct kernel_image, list);
00221         if (image->start <= trans->pc && image->end > trans->pc)
00222             return image;
00223     }
00224 
00225     if (xen_image.start <= trans->pc && xen_image.end > trans->pc)
00226         return &xen_image;
00227 
00228     return NULL;
00229 }

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1