예제 #1
0
파일: dso.c 프로젝트: 020gzh/linux
/*
 * 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;
}
예제 #2
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;
}
예제 #4
0
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;
}