Commit d9f2ecbc authored by Ian Rogers's avatar Ian Rogers Committed by Namhyung Kim
Browse files

perf dso: Move build_id to dso_id



The dso_id previously contained the major, minor, inode and inode
generation information from a mmap2 event - the inode generation would
be zero when reading from /proc/pid/maps. The build_id was in the
dso. With build ID mmap2 events these fields wouldn't be initialized
which would largely mean the special empty case where any dso would
match for equality. This isn't desirable as if a dso is replaced we
want the comparison to yield a difference.

To support detecting the difference between DSOs based on build_id,
move the build_id out of the DSO and into the dso_id. The dso_id is
also stored in the DSO so nothing is lost. Capture in the dso_id what
parts have been initialized and rename dso_id__inject to
dso_id__improve_id so that it is clear the dso_id is being improved
upon with additional information. With the build_id in the dso_id, use
memcmp to compare for equality.

Signed-off-by: default avatarIan Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20250724163302.596743-7-irogers@google.com


Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
parent eee4b661
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ static int buildid__map_cb(struct map *map, void *arg __maybe_unused)

	memset(bid_buf, 0, sizeof(bid_buf));
	if (dso__has_build_id(dso))
		build_id__snprintf(dso__bid_const(dso), bid_buf, sizeof(bid_buf));
		build_id__snprintf(dso__bid(dso), bid_buf, sizeof(bid_buf));
	printf("%s %16" PRIx64 " %16" PRIx64, bid_buf, map__start(map), map__end(map));
	if (dso_long_name != NULL)
		printf(" %s", dso_long_name);
+21 −15
Original line number Diff line number Diff line
@@ -587,15 +587,17 @@ static int perf_event__repipe_mmap2(const struct perf_tool *tool,
				struct perf_sample *sample,
				struct machine *machine)
{
	struct dso_id id;
	struct dso_id *dso_id = NULL;
	struct dso_id id = dso_id_empty;

	if (!(event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)) {
	if (event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) {
		build_id__init(&id.build_id, event->mmap2.build_id, event->mmap2.build_id_size);
	} else {
		id.maj = event->mmap2.maj;
		id.min = event->mmap2.min;
		id.ino = event->mmap2.ino;
		id.ino_generation = event->mmap2.ino_generation;
		dso_id = &id;
		id.mmap2_valid = true;
		id.mmap2_ino_generation_valid = true;
	}

	return perf_event__repipe_common_mmap(
@@ -603,7 +605,7 @@ static int perf_event__repipe_mmap2(const struct perf_tool *tool,
		event->mmap2.pid, event->mmap2.tid,
		event->mmap2.start, event->mmap2.len, event->mmap2.pgoff,
		event->mmap2.flags, event->mmap2.prot,
		event->mmap2.filename, dso_id,
		event->mmap2.filename, &id,
		perf_event__process_mmap2);
}

@@ -671,19 +673,20 @@ static int perf_event__repipe_tracing_data(struct perf_session *session,
static int dso__read_build_id(struct dso *dso)
{
	struct nscookie nsc;
	struct build_id bid = { .size = 0, };

	if (dso__has_build_id(dso))
		return 0;

	mutex_lock(dso__lock(dso));
	nsinfo__mountns_enter(dso__nsinfo(dso), &nsc);
	if (filename__read_build_id(dso__long_name(dso), dso__bid(dso)) > 0)
		dso__set_has_build_id(dso);
	if (filename__read_build_id(dso__long_name(dso), &bid) > 0)
		dso__set_build_id(dso, &bid);
	else if (dso__nsinfo(dso)) {
		char *new_name = dso__filename_with_chroot(dso, dso__long_name(dso));

		if (new_name && filename__read_build_id(new_name, dso__bid(dso)) > 0)
			dso__set_has_build_id(dso);
		if (new_name && filename__read_build_id(new_name, &bid) > 0)
			dso__set_build_id(dso, &bid);
		free(new_name);
	}
	nsinfo__mountns_exit(&nsc);
@@ -732,23 +735,26 @@ static bool perf_inject__lookup_known_build_id(struct perf_inject *inject,
					       struct dso *dso)
{
	struct str_node *pos;
	int bid_len;

	strlist__for_each_entry(pos, inject->known_build_ids) {
		struct build_id bid;
		const char *build_id, *dso_name;
		size_t bid_len;

		build_id = skip_spaces(pos->s);
		dso_name = strchr(build_id, ' ');
		bid_len = dso_name - pos->s;
		if (bid_len > sizeof(bid.data))
			bid_len = sizeof(bid.data);
		dso_name = skip_spaces(dso_name);
		if (strcmp(dso__long_name(dso), dso_name))
			continue;
		for (int ix = 0; 2 * ix + 1 < bid_len; ++ix) {
			dso__bid(dso)->data[ix] = (hex(build_id[2 * ix]) << 4 |
		for (size_t ix = 0; 2 * ix + 1 < bid_len; ++ix) {
			bid.data[ix] = (hex(build_id[2 * ix]) << 4 |
					hex(build_id[2 * ix + 1]));
		}
		dso__bid(dso)->size = bid_len / 2;
		dso__set_has_build_id(dso);
		bid.size = bid_len / 2;
		dso__set_build_id(dso, &bid);
		return true;
	}
	return false;
+9 −2
Original line number Diff line number Diff line
@@ -861,17 +861,24 @@ static int maps__fprintf_task_cb(struct map *map, void *data)
	struct maps__fprintf_task_args *args = data;
	const struct dso *dso = map__dso(map);
	u32 prot = map__prot(map);
	const struct dso_id *dso_id = dso__id_const(dso);
	int ret;
	char buf[SBUILD_ID_SIZE];

	if (dso_id->mmap2_valid)
		snprintf(buf, sizeof(buf), "%" PRIu64, dso_id->ino);
	else
		build_id__snprintf(&dso_id->build_id, buf, sizeof(buf));

	ret = fprintf(args->fp,
		"%*s  %" PRIx64 "-%" PRIx64 " %c%c%c%c %08" PRIx64 " %" PRIu64 " %s\n",
		"%*s  %" PRIx64 "-%" PRIx64 " %c%c%c%c %08" PRIx64 " %s %s\n",
		args->indent, "", map__start(map), map__end(map),
		prot & PROT_READ ? 'r' : '-',
		prot & PROT_WRITE ? 'w' : '-',
		prot & PROT_EXEC ? 'x' : '-',
		map__flags(map) ? 's' : 'p',
		map__pgoff(map),
		dso__id_const(dso)->ino, dso__name(dso));
		buf, dso__name(dso));

	if (ret < 0)
		return ret;
+1 −1
Original line number Diff line number Diff line
@@ -87,7 +87,7 @@ struct perf_dlfilter_al {
	__u8  is_64_bit; /* Only valid if dso is not NULL */
	__u8  is_kernel_ip; /* True if in kernel space */
	__u32 buildid_size;
	__u8 *buildid;
	const __u8 *buildid;
	/* Below members are only populated by resolve_ip() */
	__u8 filtered; /* True if this sample event will be filtered out */
	const char *comm;
+2 −2
Original line number Diff line number Diff line
@@ -96,8 +96,8 @@ static int create_map(struct test_info *ti, char *filename, struct map **map_p)
	dso__put(dso);

	/* Create a dummy map at 0x100000 */
	*map_p = map__new(ti->machine, 0x100000, 0xffffffff, 0, NULL,
			  PROT_EXEC, 0, NULL, filename, ti->thread);
	*map_p = map__new(ti->machine, 0x100000, 0xffffffff, 0, &dso_id_empty,
			  PROT_EXEC, /*flags=*/0, filename, ti->thread);
	if (!*map_p) {
		pr_debug("Failed to create map!");
		return TEST_FAIL;
Loading