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
00040 list_init(&vmlinux_image.list);
00041
00042
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
00065 list_init(&xen_image.list);
00066
00067
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
00128 sfile_clear_kernel();
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
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 }