Пример #1
0
Файл: util.c Проект: idkwim/ktap
/*
 * read kernel symbol from /proc/kallsyms
 */
int kallsyms_parse(void *arg,
		   int(*process_symbol)(void *arg, const char *name,
		   char type, unsigned long start))
{
	int ret = 0;
	FILE *file;
	char *line = NULL;

	file = fopen(KALLSYMS_PATH, "r");
	if (file == NULL)
		handle_error("open " KALLSYMS_PATH " failed");

	while (!feof(file)) {
		char *symbol_name;
		char symbol_type;
		int line_len, len;
		unsigned long start;
		size_t n;

		line_len = getline(&line, &n, file);
		if (line_len < 0 || !line)
			break;

		line[--line_len] = '\0'; /* \n */

		len = hex2u64(line, &start);
		len++;
		if (len + 2 >= line_len)
			continue;

		symbol_type = line[len];
		len += 2;
		symbol_name = line + len;
		len = line_len - len;

		if (len >= KSYM_NAME_LEN) {
			ret = -1;
			break;
		}

		ret = process_symbol(arg, symbol_name, symbol_type, start);
		if (ret)
			break;
	}

	free(line);
	fclose(file);

	return ret;
}
Пример #2
0
static int perf_event__synthesize_mmap_events(union perf_event *event,
        pid_t pid, pid_t tgid,
        perf_event__handler_t process,
        struct perf_session *session)
{
    char filename[PATH_MAX];
    FILE *fp;

    snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);

    fp = fopen(filename, "r");
    if (fp == NULL) {
        /*
         * We raced with a task exiting - just return:
         */
        pr_debug("couldn't open %s\n", filename);
        return -1;
    }

    event->header.type = PERF_RECORD_MMAP;
    /*
     * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
     */
    event->header.misc = PERF_RECORD_MISC_USER;

    while (1) {
        char bf[BUFSIZ], *pbf = bf;
        int n;
        size_t size;
        if (fgets(bf, sizeof(bf), fp) == NULL)
            break;

        /* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
        n = hex2u64(pbf, &event->mmap.start);
        if (n < 0)
            continue;
        pbf += n + 1;
        n = hex2u64(pbf, &event->mmap.len);
        if (n < 0)
            continue;
        pbf += n + 3;
        if (*pbf == 'x') { /* vm_exec */
            char *execname = strchr(bf, '/');

            /* Catch VDSO */
            if (execname == NULL)
                execname = strstr(bf, "[vdso]");

            if (execname == NULL)
                continue;

            pbf += 3;
            n = hex2u64(pbf, &event->mmap.pgoff);

            size = strlen(execname);
            execname[size - 1] = '\0'; /* Remove \n */
            memcpy(event->mmap.filename, execname, size);
            size = ALIGN(size, sizeof(u64));
            event->mmap.len -= event->mmap.start;
            event->mmap.header.size = (sizeof(event->mmap) -
                                       (sizeof(event->mmap.filename) - size));
            memset(event->mmap.filename + size, 0, session->id_hdr_size);
            event->mmap.header.size += session->id_hdr_size;
            event->mmap.pid = tgid;
            event->mmap.tid = pid;

            process(event, &synth_sample, session);
        }
    }

    fclose(fp);
    return 0;
}
Пример #3
0
static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
					 int (*process)(event_t *event))
{
	char filename[PATH_MAX];
	FILE *fp;

	snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);

	fp = fopen(filename, "r");
	if (fp == NULL) {
		/*
		 * We raced with a task exiting - just return:
		 */
		pr_debug("couldn't open %s\n", filename);
		return -1;
	}

	while (1) {
		char bf[BUFSIZ], *pbf = bf;
		event_t ev = {
			.header = { .type = PERF_RECORD_MMAP },
		};
		int n;
		size_t size;
		if (fgets(bf, sizeof(bf), fp) == NULL)
			break;

		/* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
		n = hex2u64(pbf, &ev.mmap.start);
		if (n < 0)
			continue;
		pbf += n + 1;
		n = hex2u64(pbf, &ev.mmap.len);
		if (n < 0)
			continue;
		pbf += n + 3;
		if (*pbf == 'x') { /* vm_exec */
			char *execname = strchr(bf, '/');

			/* Catch VDSO */
			if (execname == NULL)
				execname = strstr(bf, "[vdso]");

			if (execname == NULL)
				continue;

			size = strlen(execname);
			execname[size - 1] = '\0'; /* Remove \n */
			memcpy(ev.mmap.filename, execname, size);
			size = ALIGN(size, sizeof(u64));
			ev.mmap.len -= ev.mmap.start;
			ev.mmap.header.size = (sizeof(ev.mmap) -
					       (sizeof(ev.mmap.filename) - size));
			ev.mmap.pid = tgid;
			ev.mmap.tid = pid;

			process(&ev);
		}
	}

	fclose(fp);
	return 0;
}
HRESULT CaPerfDataWriter::writePidMmaps(pid_t pid, pid_t tgid, gtUInt16  sampleRecSize)
{
    char filename[OS_MAX_PATH];
    FILE* fp;

    if (! m_pMmapEvent)
    {
        m_pMmapEvent = (ca_event_t*)calloc(1, sizeof(m_pMmapEvent->mmap) + sampleRecSize);

        if (m_pMmapEvent == NULL)
        {
            return E_FAIL;
        }
    }

    snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);

    fp = fopen(filename, "r");

    if (fp == NULL)
    {
        /*
         * We raced with a task exiting - just return:
         */
        OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_ERROR, L"couldn't open %hs", filename);
        return -1;
    }

    m_pMmapEvent->header.type = PERF_RECORD_MMAP;
    /*
     * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
     */
    m_pMmapEvent->header.misc = PERF_RECORD_MISC_USER;

    while (1)
    {
        char bf[BUFSIZ], *pbf = bf;
        int n;
        size_t size;

        if (fgets(bf, sizeof(bf), fp) == NULL)
        {
            break;
        }

        /* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
        n = hex2u64(pbf, &m_pMmapEvent->mmap.start);

        if (n < 0)
        {
            continue;
        }

        pbf += n + 1;
        n = hex2u64(pbf, &m_pMmapEvent->mmap.len);

        if (n < 0)
        {
            continue;
        }

        pbf += n + 3;

        if (*pbf == 'x')   /* vm_exec */
        {
            char* execname = strchr(bf, '/');

            /* Catch VDSO */
            if (execname == NULL)
            {
                execname = strstr(bf, "[vdso]");
            }

            if (execname == NULL)
            {
                continue;
            }

            pbf += 3;
            n = hex2u64(pbf, &m_pMmapEvent->mmap.pgoff);

            size = strlen(execname);
            execname[size - 1] = '\0'; /* Remove \n */
            memcpy(m_pMmapEvent->mmap.filename, execname, size);
            size = ALIGN_FOR_SIZE_T(size, sizeof(gtUInt64));
            m_pMmapEvent->mmap.len -= m_pMmapEvent->mmap.start;
            m_pMmapEvent->mmap.header.size = (sizeof(m_pMmapEvent->mmap) -
                                              (sizeof(m_pMmapEvent->mmap.filename) - size));
            memset(m_pMmapEvent->mmap.filename + size, 0, sampleRecSize);
            m_pMmapEvent->mmap.header.size += sampleRecSize;
            m_pMmapEvent->mmap.pid = tgid;
            m_pMmapEvent->mmap.tid = pid;

            writePMUSampleData(m_pMmapEvent, m_pMmapEvent->header.size);
        }
    }

    fclose(fp);
    return 0;
}
HRESULT CaPerfDataWriter::readKernelModules()
{
    char* line = NULL;
    size_t n;
    FILE* file;
    const char* modules = NULL;
    char path[OS_MAX_PATH];

    if (! m_guestOs)
    {
        // sprintf(path, "%s/proc/modules", self->root_dir);
        sprintf(path, "/proc/modules");
        modules = path;
    }
    else
    {
#if 0
        // TODO:
        // modules = symbol_conf.default_guest_modules;
#else
        return E_FAIL;
#endif
    }

    file = fopen(modules, "r");

    if (file == NULL)
    {
        return E_FAIL;
    }

    while (!feof(file))
    {
        // char      name[OS_MAX_PATH];
        // gtUInt64  start;
        char*      sep;
        int       line_len;
        struct kModule module;

        line_len = getline(&line, &n, file);

        if (line_len < 0)
        {
            break;
        }

        if (!line)
        {
            return E_FAIL;
        }

        line[--line_len] = '\0'; /* \n */

        sep = strrchr(line, 'x');

        if (sep == NULL)
        {
            continue;
        }

        hex2u64(sep + 1, &module.m_startAddress);

        sep = strchr(line, ' ');

        if (sep == NULL)
        {
            continue;
        }

        *sep = '\0';

        snprintf(module.m_modName, sizeof(module.m_modName), "[%s]", line);
        m_kModuleNameMap.insert(kModuleNameMap::value_type(module.m_modName, module));

        // TODO: build id stuff ??
        // dso__kernel_module_get_build_id(map->dso, self->root_dir);
    }

    free(line);
    fclose(file);

    // set the modules path
    setModulesPath();

    return S_OK;
}
HRESULT CaPerfDataWriter::findKernelSymbol(const char* symbol, gtUByte type, gtUInt64* startAddress)
{
    (void)(symbol); // unused
    const char* filename = m_kernelSymbolFile.c_str();
    FILE*    file;
    char*    line = NULL;
    size_t  n;

    if (!filename || !startAddress)
    {
        return E_INVALIDARG;
    }

    if ((file = fopen(filename, "r")) == NULL)
    {
        return E_FAIL;
    }

    HRESULT ret = S_OK;

    // read the kernel symbol file /proc/kallsyms
    while (!feof(file))
    {
        gtUInt64  start;
        int   lineLen, len;
        char      symbolType;

        lineLen = getline(&line, &n, file);

        if (lineLen < 0 || !line)
        {
            break;
        }

        line[--lineLen] = '\0'; /* \n */

        len = hex2u64(line, &start);

        len++;

        if (len + 2 >= lineLen)
        {
            continue;
        }

        symbolType = toupper(line[len]);
        len += 2;
        len = lineLen - len;

        if (len >= CA_KERNEL_SYMBOL_LEN)
        {
            ret = E_FAIL;
            break;
        }

        // check for the symbol type
        if (KERNEL_FUNCTION == type)
        {
            if (symbolType == 'T' || symbolType == 'W')
            {
                *startAddress = start;
                break;
            }
        }
        else if (KERNEL_VARIABLE == type)
        {
            if (symbolType == 'D' || symbolType == 'd')
            {
                *startAddress = start;
                break;
            }
        }
        else
        {
            ret = E_FAIL;
            break;
        }

    }

    free(line);
    fclose(file);
    return ret;
}
Пример #7
0
static void pid_synthesize_mmap_samples(pid_t pid, pid_t tgid)
{
	char filename[PATH_MAX];
	FILE *fp;

	snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);

	fp = fopen(filename, "r");
	if (fp == NULL) {
		/*
		 * We raced with a task exiting - just return:
		 */
		if (verbose)
			fprintf(stderr, "couldn't open %s\n", filename);
		return;
	}
	while (1) {
		char bf[BUFSIZ], *pbf = bf;
		struct mmap_event mmap_ev = {
			.header = { .type = PERF_RECORD_MMAP },
		};
		int n;
		size_t size;
		if (fgets(bf, sizeof(bf), fp) == NULL)
			break;

		/* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
		n = hex2u64(pbf, &mmap_ev.start);
		if (n < 0)
			continue;
		pbf += n + 1;
		n = hex2u64(pbf, &mmap_ev.len);
		if (n < 0)
			continue;
		pbf += n + 3;
		if (*pbf == 'x') { /* vm_exec */
			char *execname = strchr(bf, '/');

			/* Catch VDSO */
			if (execname == NULL)
				execname = strstr(bf, "[vdso]");

			if (execname == NULL)
				continue;

			size = strlen(execname);
			execname[size - 1] = '\0'; /* Remove \n */
			memcpy(mmap_ev.filename, execname, size);
			size = ALIGN(size, sizeof(u64));
			mmap_ev.len -= mmap_ev.start;
			mmap_ev.header.size = (sizeof(mmap_ev) -
					       (sizeof(mmap_ev.filename) - size));
			mmap_ev.pid = tgid;
			mmap_ev.tid = pid;

			write_output(&mmap_ev, mmap_ev.header.size);
		}
	}

	fclose(fp);
}
Пример #8
0
static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
					 event__handler_t process,
					 struct perf_session *session)
{
	char filename[PATH_MAX];
	FILE *fp;

	snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);

	fp = fopen(filename, "r");
	if (fp == NULL) {
		/*
		 * We raced with a task exiting - just return:
		 */
		pr_debug("couldn't open %s\n", filename);
		return -1;
	}

	while (1) {
		char bf[BUFSIZ], *pbf = bf;
		event_t ev = {
			.header = {
				.type = PERF_RECORD_MMAP,
				/*
				 * Just like the kernel, see __perf_event_mmap
				 * in kernel/perf_event.c
				 */
				.misc = PERF_RECORD_MISC_USER,
			 },
		};
		int n;
		size_t size;
		if (fgets(bf, sizeof(bf), fp) == NULL)
			break;

		/* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
		n = hex2u64(pbf, &ev.mmap.start);
		if (n < 0)
			continue;
		pbf += n + 1;
		n = hex2u64(pbf, &ev.mmap.len);
		if (n < 0)
			continue;
		pbf += n + 3;
		if (*pbf == 'x') { /* vm_exec */
			u64 vm_pgoff;
			char *execname = strchr(bf, '/');

			/* Catch VDSO */
			if (execname == NULL)
				execname = strstr(bf, "[vdso]");

			if (execname == NULL)
				continue;

			pbf += 3;
			n = hex2u64(pbf, &vm_pgoff);
			/* pgoff is in bytes, not pages */
			if (n >= 0)
				ev.mmap.pgoff = vm_pgoff << getpagesize();
			else
				ev.mmap.pgoff = 0;

			size = strlen(execname);
			execname[size - 1] = '\0'; /* Remove \n */
			memcpy(ev.mmap.filename, execname, size);
			size = ALIGN(size, sizeof(u64));
			ev.mmap.len -= ev.mmap.start;
			ev.mmap.header.size = (sizeof(ev.mmap) -
					       (sizeof(ev.mmap.filename) - size));
			ev.mmap.pid = tgid;
			ev.mmap.tid = pid;

			process(&ev, session);
		}
	}

	fclose(fp);
	return 0;
}
Пример #9
0
static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int verbose)
{
	char *line = NULL;
	size_t n;
	FILE *file;
	int nr_syms = 0;

	file = fopen(self->name, "r");
	if (file == NULL)
		goto out_failure;

	while (!feof(file)) {
		u64 start, size;
		struct symbol *sym;
		int line_len, len;

		line_len = getline(&line, &n, file);
		if (line_len < 0)
			break;

		if (!line)
			goto out_failure;

		line[--line_len] = '\0'; /* \n */

		len = hex2u64(line, &start);

		len++;
		if (len + 2 >= line_len)
			continue;

		len += hex2u64(line + len, &size);

		len++;
		if (len + 2 >= line_len)
			continue;

		sym = symbol__new(start, size, line + len,
				  self->sym_priv_size, start, verbose);

		if (sym == NULL)
			goto out_delete_line;

		if (filter && filter(self, sym))
			symbol__delete(sym, self->sym_priv_size);
		else {
			dso__insert_symbol(self, sym);
			nr_syms++;
		}
	}

	free(line);
	fclose(file);

	return nr_syms;

out_delete_line:
	free(line);
out_failure:
	return -1;
}
Пример #10
0
static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verbose)
{
	struct rb_node *nd, *prevnd;
	char *line = NULL;
	size_t n;
	FILE *file = fopen("/proc/kallsyms", "r");
	int count = 0;

	if (file == NULL)
		goto out_failure;

	while (!feof(file)) {
		u64 start;
		struct symbol *sym;
		int line_len, len;
		char symbol_type;

		line_len = getline(&line, &n, file);
		if (line_len < 0)
			break;

		if (!line)
			goto out_failure;

		line[--line_len] = '\0'; /* \n */

		len = hex2u64(line, &start);

		len++;
		if (len + 2 >= line_len)
			continue;

		symbol_type = toupper(line[len]);
		/*
		 * We're interested only in code ('T'ext)
		 */
		if (symbol_type != 'T' && symbol_type != 'W')
			continue;
		/*
		 * Well fix up the end later, when we have all sorted.
		 */
		sym = symbol__new(start, 0xdead, line + len + 2,
				  self->sym_priv_size, 0, verbose);

		if (sym == NULL)
			goto out_delete_line;

		if (filter && filter(self, sym))
			symbol__delete(sym, self->sym_priv_size);
		else {
			dso__insert_symbol(self, sym);
			count++;
		}
	}

	/*
	 * Now that we have all sorted out, just set the ->end of all
	 * symbols
	 */
	prevnd = rb_first(&self->syms);

	if (prevnd == NULL)
		goto out_delete_line;

	for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
		struct symbol *prev = rb_entry(prevnd, struct symbol, rb_node),
			      *curr = rb_entry(nd, struct symbol, rb_node);

		prev->end = curr->start - 1;
		prevnd = nd;
	}

	free(line);
	fclose(file);

	return count;

out_delete_line:
	free(line);
out_failure:
	return -1;
}