/* * Parses kernel module specified in @path and updates * @m argument like: * * @comp - true if @path contains supported compression suffix, * false otherwise * @kmod - true if @path contains '.ko' suffix in right position, * false otherwise * @name - if (@alloc_name && @kmod) is true, it contains strdup-ed base name * of the kernel module without suffixes, otherwise strudup-ed * base name of @path * @ext - if (@alloc_ext && @comp) is true, it contains strdup-ed string * the compression suffix * * Returns 0 if there's no strdup error, -ENOMEM otherwise. */ int __kmod_path__parse(struct kmod_path *m, const char *path, bool alloc_name, bool alloc_ext) { const char *name = strrchr(path, '/'); const char *ext = strrchr(path, '.'); bool is_simple_name = false; memset(m, 0x0, sizeof(*m)); name = name ? name + 1 : path; /* * '.' is also a valid character for module name. For example: * [aaa.bbb] is a valid module name. '[' should have higher * priority than '.ko' suffix. * * The kernel names are from machine__mmap_name. Such * name should belong to kernel itself, not kernel module. */ if (name[0] == '[') { is_simple_name = true; if ((strncmp(name, "[kernel.kallsyms]", 17) == 0) || (strncmp(name, "[guest.kernel.kallsyms", 22) == 0) || (strncmp(name, "[vdso]", 6) == 0) || (strncmp(name, "[vsyscall]", 10) == 0)) { m->kmod = false; } else m->kmod = true; } /* No extension, just return name. */ if ((ext == NULL) || is_simple_name) { if (alloc_name) { m->name = strdup(name); return m->name ? 0 : -ENOMEM; } return 0; } if (is_supported_compression(ext + 1)) { m->comp = true; ext -= 3; } /* Check .ko extension only if there's enough name left. */ if (ext > name) m->kmod = !strncmp(ext, ".ko", 3); if (alloc_name) { if (m->kmod) { if (asprintf(&m->name, "[%.*s]", (int) (ext - name), name) == -1) return -ENOMEM; } else { if (asprintf(&m->name, "%s", name) == -1) return -ENOMEM; } strxfrchar(m->name, '-', '_'); } if (alloc_ext && m->comp) { m->ext = strdup(ext + 4); if (!m->ext) { free((void *) m->name); return -ENOMEM; } } return 0; }
int event__process_mmap(event_t *self, struct perf_session *session) { struct thread *thread; struct map *map; dump_printf(" %d/%d: [%#Lx(%#Lx) @ %#Lx]: %s\n", self->mmap.pid, self->mmap.tid, self->mmap.start, self->mmap.len, self->mmap.pgoff, self->mmap.filename); if (self->mmap.pid == 0) { static const char kmmap_prefix[] = "[kernel.kallsyms."; if (self->mmap.filename[0] == '/') { char short_module_name[1024]; char *name = strrchr(self->mmap.filename, '/'), *dot; if (name == NULL) goto out_problem; ++name; /* skip / */ dot = strrchr(name, '.'); if (dot == NULL) goto out_problem; snprintf(short_module_name, sizeof(short_module_name), "[%.*s]", (int)(dot - name), name); strxfrchar(short_module_name, '-', '_'); map = perf_session__new_module_map(session, self->mmap.start, self->mmap.filename); if (map == NULL) goto out_problem; name = strdup(short_module_name); if (name == NULL) goto out_problem; map->dso->short_name = name; map->end = map->start + self->mmap.len; } else if (memcmp(self->mmap.filename, kmmap_prefix, sizeof(kmmap_prefix) - 1) == 0) { const char *symbol_name = (self->mmap.filename + sizeof(kmmap_prefix) - 1); /* * Should be there already, from the build-id table in * the header. */ struct dso *kernel = __dsos__findnew(&dsos__kernel, "[kernel.kallsyms]"); if (kernel == NULL) goto out_problem; kernel->kernel = 1; if (__perf_session__create_kernel_maps(session, kernel) < 0) goto out_problem; session->vmlinux_maps[MAP__FUNCTION]->start = self->mmap.start; session->vmlinux_maps[MAP__FUNCTION]->end = self->mmap.start + self->mmap.len; /* * Be a bit paranoid here, some perf.data file came with * a zero sized synthesized MMAP event for the kernel. */ if (session->vmlinux_maps[MAP__FUNCTION]->end == 0) session->vmlinux_maps[MAP__FUNCTION]->end = ~0UL; perf_session__set_kallsyms_ref_reloc_sym(session, symbol_name, self->mmap.pgoff); } return 0; } thread = perf_session__findnew(session, self->mmap.pid); map = map__new(&self->mmap, MAP__FUNCTION, session->cwd, session->cwdlen); if (thread == NULL || map == NULL) goto out_problem; thread__insert_map(thread, map); return 0; out_problem: dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n"); return 0; }
HRESULT CaPerfDataWriter::setModulesAbsolutePath(const std::string& dirName) { struct dirent* dent; const char* dirPath = dirName.c_str(); DIR* dir = opendir(dirPath); HRESULT ret = S_OK; if (!dir) { OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_ERROR, L"cannot open %hs dir", dirPath); return E_FAIL; } while ((dent = readdir(dir)) != NULL) { char path[OS_MAX_PATH]; struct stat st; /*sshfs might return bad dent->d_type, so we have to stat*/ sprintf(path, "%s/%s", dirPath, dent->d_name); if (stat(path, &st)) { continue; } if (S_ISDIR(st.st_mode)) { if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) { continue; } snprintf(path, sizeof(path), "%s/%s", dirPath, dent->d_name); ret = setModulesAbsolutePath(path); if (ret < 0) { break; } } else { char* dot = strrchr(dent->d_name, '.'); char dso_name[OS_MAX_PATH]; if (dot == NULL || strcmp(dot, ".ko")) { continue; } snprintf(dso_name, sizeof(dso_name), "[%.*s]", (int)(dot - dent->d_name), dent->d_name); strxfrchar(dso_name, '-', '_'); // map = map_groups__find_by_name(self, MAP__FUNCTION, dso_name); // if (map == NULL) // continue; kModuleNameMap::iterator it = m_kModuleNameMap.find(dso_name); if (it == m_kModuleNameMap.end()) { continue; } snprintf(path, sizeof(path), "%s/%s", dirPath, dent->d_name); it->second.addAbsPath(path); #if 0 long_name = strdup(path); if (long_name == NULL) { ret = -1; } else { dso__set_long_name(map->dso, long_name); map->dso->lname_alloc = 1; dso__kernel_module_get_build_id(map->dso, ""); } #endif // 0 } } // we are done dir closedir(dir); return ret; }
static int event__process_kernel_mmap(event_t *self, struct perf_session *session) { struct map *map; char kmmap_prefix[PATH_MAX]; struct machine *machine; enum dso_kernel_type kernel_type; bool is_kernel_mmap; machine = perf_session__findnew_machine(session, self->mmap.pid); if (!machine) { pr_err("Can't find id %d's machine\n", self->mmap.pid); goto out_problem; } machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix)); if (machine__is_host(machine)) kernel_type = DSO_TYPE_KERNEL; else kernel_type = DSO_TYPE_GUEST_KERNEL; is_kernel_mmap = memcmp(self->mmap.filename, kmmap_prefix, strlen(kmmap_prefix)) == 0; if (self->mmap.filename[0] == '/' || (!is_kernel_mmap && self->mmap.filename[0] == '[')) { char short_module_name[1024]; char *name, *dot; if (self->mmap.filename[0] == '/') { name = strrchr(self->mmap.filename, '/'); if (name == NULL) goto out_problem; ++name; /* skip / */ dot = strrchr(name, '.'); if (dot == NULL) goto out_problem; snprintf(short_module_name, sizeof(short_module_name), "[%.*s]", (int)(dot - name), name); strxfrchar(short_module_name, '-', '_'); } else strcpy(short_module_name, self->mmap.filename); map = machine__new_module(machine, self->mmap.start, self->mmap.filename); if (map == NULL) goto out_problem; name = strdup(short_module_name); if (name == NULL) goto out_problem; map->dso->short_name = name; map->end = map->start + self->mmap.len; } else if (is_kernel_mmap) { const char *symbol_name = (self->mmap.filename + strlen(kmmap_prefix)); /* * Should be there already, from the build-id table in * the header. */ struct dso *kernel = __dsos__findnew(&machine->kernel_dsos, kmmap_prefix); if (kernel == NULL) goto out_problem; kernel->kernel = kernel_type; if (__machine__create_kernel_maps(machine, kernel) < 0) goto out_problem; event_set_kernel_mmap_len(machine->vmlinux_maps, self); perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, symbol_name, self->mmap.pgoff); if (machine__is_default_guest(machine)) { /* * preload dso of guest kernel and modules */ dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION], NULL); } } return 0; out_problem: return -1; }