From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B66AD4A35; Fri, 2 Oct 2026 18:45:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790966759; cv=none; b=iEa2eSfRBuZh2b7trv2CXEmt6AF3eWFKrhYGfisPOykNR2f2jmzS/DGKbPDyJ5UpdTJUyCJnQL5NaDdxTHMQnAfPouSikQNCYict3Ve0W8Ke5GYmjMX3jjpmjITK4yg1/zVUJC0niuI919rAG8Xo5/5797fSTg/BNkTomKXslU4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790966759; c=relaxed/simple; bh=lfy6QkoPZcrMkahaXCHW6z0VByntaV973icvPdYGzJM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=MvP4kmE41eKQAynmHlSeJFPtY1pAalItNEBn4lfH6sKsTMJCj5oC1m7j7fWobatD0T0G2qDsKk3lVnUfykVQE+40XElu5yo5ZFjXg3vP0CRy1nn9NfQmLBEXPZjvSEk7ZfT08Q/umStjMDvJQWbmjr5sgtkD2BaRa//PgvWpVZc= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bwYPXbrv; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bwYPXbrv" Received: by smtp.kernel.org (Postfix) with ESMTPS id 5B70AC4AF13; Fri, 2 Oct 2026 18:45:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1790966759; bh=lfy6QkoPZcrMkahaXCHW6z0VByntaV973icvPdYGzJM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=bwYPXbrvyZMEFhbKO92aEiFOceqLRw1f7Pg/HgloRnsCS2M/+zbORy8T3kItfNkuu GthkeNPKCPmduW9p3MmT2xS6Ey5j2o4Xkf00C5ZYTG8HS+2NuxtvYKLGqlG9ExXkts BIakBLf4//Wq2ce+sqPIKtn0gK3zOyhFXBiXSPa2c2N3pU1z7BUy6uWZHjaw9K5enM OoM373Q9zA7GRaLmNsj/q33Uo4qIT4tivBjaLcC3EmlzHNByd+IrzGk2k2RYXONhUV daNYbBCU7t5JR7xyHy4K/o18j7TFEUjYymnQIg4nglyoxsZYy2AHztahRPKtCgoUwZ j1eH16wQNg9Eg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3BBBECA5FDD; Fri, 2 Oct 2026 18:45:59 +0000 (UTC) From: Alireza Haghdoost via B4 Relay Date: Fri, 02 Oct 2026 11:45:34 -0700 Subject: [PATCH v4 2/5] perf dso: Allow reading DSO data from an explicit file Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20261002-perf-symbol-memory-send-v4-2-0a592bb2539e@uber.com> References: <20261002-perf-symbol-memory-send-v4-0-0a592bb2539e@uber.com> In-Reply-To: <20261002-perf-symbol-memory-send-v4-0-0a592bb2539e@uber.com> To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark , Alexei Starovoitov , Andrii Nakryiko Cc: linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, Alireza Haghdoost X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=6171; i=haghdoost@uber.com; h=from:subject:message-id; bh=zHOBxWbVfbd1CinZEWKES+6xUEv+Rr9ivgGHO2OKulE=; b=owEBiQJ2/ZANAwAIAVNlBDxl2ALYAcsmYgBqv/vlacBMx4u+Gc+9zCAAstqxXq5l2tRZq1QQ2 Nz/ts58mYyJAk8EAAEIADkWIQS5+sFL3gX/8PrA0S1TZQQ8ZdgC2AUCar/75RsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMiwwLDMACgkQU2UEPGXYAtg7Hg/+LIRkW2VZ2prNJzuT5t13INR4VliDyq7 Bq7+BcBKEM7Dcba0NmjKf3Qp1zXDD9OaYRv2F7kbLCi+O+G3l4+ds4rE1//zyTz/kSggy0DZTzC mH70C7nQMietV9LY9mkDSn7yZECqmg55Y1cruyT9JgGAjKwqMf6orra8e867UrQd8bu9ewYfMaG mXmB7xvE6bDwLXYQIFgv2EbuQPNVv7BK3pS9oFiGv0NnA9qWc4WsngoNf20AFLrLu7PrZy83UDf d7Um0bTH1j4JkpIpYjUzQhrki+WIBJzimjAxusGZe1XfmyVh76WCRcE37XIQjt54akUf2eZv2F5 mppetaudZp8cgxr0lhmuslii6PGPlV9vrDDNEr0ZbKMUOuFMLU06WG6lp6mRjyBLJHB1FZgHV7N giHmFjnSwVdGvBhihxFAPuZq/k+YR511AObNw8RTCySoeUQDkFX+MdqyNTkOGIMdrGRd6fKC630 Pgi+9/zEQxGUP7CL5T8RSECAcoWkHJz/Vw+/IWzSxiNE3RnbTLI8V7Opwo+ovGfU+GVIm8ayaiW vnVBUT5INNpPhZds696AgMiH9T6TNLvsKpWzaKtYrHf7dOBXWxVPAHl0DAu3aeefgbATW37fqbW J3Fjw0292zPYD8Ypcfu8/dBm6jCcVaMZ/3GN4oT1GUQlGuc8Qg0s= X-Developer-Key: i=haghdoost@uber.com; a=openpgp; fpr=B9FAC14BDE05FFF0FAC0D12D5365043C65D802D8 X-Endpoint-Received: by B4 Relay for haghdoost@uber.com/default with auth_id=764 X-Original-From: Alireza Haghdoost Reply-To: haghdoost@uber.com From: Alireza Haghdoost The DSO data cache derives the file to open from the DSO's binary type, which can resolve to the runtime image rather than the file a symbol table was read from. The lazy symbol loader added later in this series reads symbol names at string-table offsets in the file the symbol table came from. With split debuginfo, the data cache would apply those debuginfo offsets to the runtime image. This patch adds dso__data_set_path() so a DSO can be configured to read from one exact file while keeping the data cache's descriptor eviction and reopening. The path is used only when the data cache opens the file; dso__get_filename() and its debuginfo callers are unchanged. Such DSOs may be owned privately rather than being part of a dsos collection, so the patch also drops the assertion that every opened data DSO is in one. Add a DSO data test that reads through an explicit path, closes the descriptor, and reads an uncached offset to exercise reopening. Signed-off-by: Alireza Haghdoost --- tools/perf/tests/dso-data.c | 42 ++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/dso.c | 30 ++++++++++++++++++++++++++---- tools/perf/util/dso.h | 2 ++ 3 files changed, 70 insertions(+), 4 deletions(-) diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c index 46bc3f597260..fbfb2f08d3ba 100644 --- a/tools/perf/tests/dso-data.c +++ b/tools/perf/tests/dso-data.c @@ -393,11 +393,53 @@ static int test__dso_data_reopen(struct test_suite *test __maybe_unused, int sub return 0; } +static int test__dso_data_path(struct test_suite *test __maybe_unused, int subtest __maybe_unused) +{ + u8 expect[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + char *file = test_file(TEST_FILE_SIZE); + struct dso *dso; + long nr, nr_end; + u8 buf[10]; + + TEST_ASSERT_VAL("No test file", file); + nr = open_files_cnt(); + + /* + * The DSO name does not exist and the DSO is not in a dsos + * collection; reads must come from the configured path. + */ + dso = dso__new("/nonexistent/perf-test-dso-data-path"); + TEST_ASSERT_VAL("Failed to create dso", dso); + dso__set_binary_type(dso, DSO_BINARY_TYPE__SYSTEM_PATH_DSO); + TEST_ASSERT_VAL("Failed to set path", !dso__data_set_path(dso, file)); + + TEST_ASSERT_VAL("Wrong size", + dso__data_read_offset(dso, NULL, 10, buf, 10) == 10); + TEST_ASSERT_VAL("Wrong data", !memcmp(buf, expect, 10)); + + /* An uncached offset after close must reopen the configured path. */ + dso__data_close(dso); + memset(buf, 0, sizeof(buf)); + TEST_ASSERT_VAL("Wrong size after reopen", + dso__data_read_offset(dso, NULL, DSO__DATA_CACHE_SIZE * 2 + 10, + buf, 10) == 10); + TEST_ASSERT_VAL("Wrong data after reopen", + buf[0] == (DSO__DATA_CACHE_SIZE * 2 + 10) % 10); + + dso__data_close(dso); + dso__put(dso); + unlink(file); + + nr_end = open_files_cnt(); + TEST_ASSERT_VAL("failed leaking files", nr == nr_end); + return 0; +} static struct test_case tests__dso_data[] = { TEST_CASE("read", dso_data), TEST_CASE("cache", dso_data_cache), TEST_CASE("reopen", dso_data_reopen), + TEST_CASE("explicit path", dso_data_path), { .name = NULL, } }; diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index d3017c82ffb5..5c4872810ada 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -547,8 +547,6 @@ static void dso__list_add(struct dso *dso) EXCLUSIVE_LOCKS_REQUIRED(_dso__data_o #ifdef REFCNT_CHECKING dso__data(dso)->dso = dso__get(dso); #endif - /* Assume the dso is part of dsos, hence the optional reference count above. */ - assert(dso__dsos(dso)); dso__data_open_cnt++; } @@ -678,8 +676,11 @@ static int __open_dso(struct dso *dso, struct machine *machine) mutex_lock(dso__lock(dso)); - name = dso__get_filename(dso, machine ? machine->root_dir : "", &decomp, - dso__binary_type(dso)); + if (dso__data(dso)->path) + name = strdup(dso__data(dso)->path); + else + name = dso__get_filename(dso, machine ? machine->root_dir : "", + &decomp, dso__binary_type(dso)); if (name) { fd = do_open(name); } else { @@ -833,6 +834,26 @@ void dso__data_close(struct dso *dso) mutex_unlock(dso__data_open_lock()); } +/** + * dso__data_set_path - Read @dso's data from an explicit file + * @dso: dso object + * @path: file to open instead of the path derived from the binary type + * + * Used when the data must come from one specific file, such as the separate + * debuginfo file that a symbol table was read from. Must be called before any + * data is read, as already cached data is not invalidated. + */ +int dso__data_set_path(struct dso *dso, const char *path) +{ + char *new_path = strdup(path); + + if (!new_path) + return -ENOMEM; + free(dso__data(dso)->path); + dso__data(dso)->path = new_path; + return 0; +} + static void try_to_open_dso(struct dso *dso, struct machine *machine) EXCLUSIVE_LOCKS_REQUIRED(_dso__data_open_lock) { @@ -1783,6 +1804,7 @@ void dso__delete(struct dso *dso) dso__data_close(dso); auxtrace_cache__free(RC_CHK_ACCESS(dso)->auxtrace_cache); dso_cache__free(dso); + zfree(&RC_CHK_ACCESS(dso)->data.path); dso__free_a2l(dso); dso__free_a2l_libbfd(dso); dso__free_libdw(dso); diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 3f08d45e7f53..7bcd5ec0c312 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -264,6 +264,7 @@ struct dso_data { #ifdef REFCNT_CHECKING struct dso *dso; #endif + char *path; int fd; int status; u32 status_seen; @@ -921,6 +922,7 @@ bool dso__data_get_fd(struct dso *dso, struct machine *machine, int *fd) EXCLUSIVE_TRYLOCK_FUNCTION(true, _dso__data_open_lock); void dso__data_put_fd(struct dso *dso) UNLOCK_FUNCTION(_dso__data_open_lock); void dso__data_close(struct dso *dso) LOCKS_EXCLUDED(_dso__data_open_lock); +int dso__data_set_path(struct dso *dso, const char *path); int dso__data_file_size(struct dso *dso, struct machine *machine); off_t dso__data_size(struct dso *dso, struct machine *machine); -- Git-157)