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 189481094A for ; Mon, 3 Jul 2023 18:57:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6EF9DC433C8; Mon, 3 Jul 2023 18:57:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1688410634; bh=1ePM7I9C8nVCelAovbcB1ZKDq5SSbvg42UchnAwvqew=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=t7pa4GXwnKOFStGnoTxVL3jB7iWE/VbCDYmKljz7a+/Rz2iyabyqRhjTWgNk65H+T cYA5n0br/NEUtjpedkOXc1t7H6gHhEFRdJZEutDQ3iL7UJUQIUSURdhVaMOjBHQnkG J8dNqKjOMLG9b6oW3GmmoqfwS8VBrKY+s6aT84Ig= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Adrian Hunter , Krister Johansen , Alexander Shishkin , David Reaver , Ian Rogers , Jiri Olsa , Mark Rutland , Michael Petlan , Namhyung Kim , Peter Zijlstra , Arnaldo Carvalho de Melo Subject: [PATCH 5.15 13/15] perf symbols: Symbol lookup with kcore can fail if multiple segments match stext Date: Mon, 3 Jul 2023 20:54:58 +0200 Message-ID: <20230703184519.254046765@linuxfoundation.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230703184518.896751186@linuxfoundation.org> References: <20230703184518.896751186@linuxfoundation.org> User-Agent: quilt/0.67 Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Krister Johansen commit 1c249565426e3a9940102c0ba9f63914f7cda73d upstream. This problem was encountered on an arm64 system with a lot of memory. Without kernel debug symbols installed, and with both kcore and kallsyms available, perf managed to get confused and returned "unknown" for all of the kernel symbols that it tried to look up. On this system, stext fell within the vmalloc segment. The kcore symbol matching code tries to find the first segment that contains stext and uses that to replace the segment generated from just the kallsyms information. In this case, however, there were two: a very large vmalloc segment, and the text segment. This caused perf to get confused because multiple overlapping segments were inserted into the RB tree that holds the discovered segments. However, that alone wasn't sufficient to cause the problem. Even when we could find the segment, the offsets were adjusted in such a way that the newly generated symbols didn't line up with the instruction addresses in the trace. The most obvious solution would be to consult which segment type is text from kcore, but this information is not exposed to users. Instead, select the smallest matching segment that contains stext instead of the first matching segment. This allows us to match the text segment instead of vmalloc, if one is contained within the other. Reviewed-by: Adrian Hunter Signed-off-by: Krister Johansen Cc: Alexander Shishkin Cc: David Reaver Cc: Ian Rogers Cc: Jiri Olsa Cc: Mark Rutland Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lore.kernel.org/lkml/20230125183418.GD1963@templeofstupid.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Krister Johansen Signed-off-by: Greg Kroah-Hartman --- tools/perf/util/symbol.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1357,10 +1357,23 @@ static int dso__load_kcore(struct dso *d /* Find the kernel map using the '_stext' symbol */ if (!kallsyms__get_function_start(kallsyms_filename, "_stext", &stext)) { + u64 replacement_size = 0; + list_for_each_entry(new_map, &md.maps, node) { - if (stext >= new_map->start && stext < new_map->end) { + u64 new_size = new_map->end - new_map->start; + + if (!(stext >= new_map->start && stext < new_map->end)) + continue; + + /* + * On some architectures, ARM64 for example, the kernel + * text can get allocated inside of the vmalloc segment. + * Select the smallest matching segment, in case stext + * falls within more than one in the list. + */ + if (!replacement_map || new_size < replacement_size) { replacement_map = new_map; - break; + replacement_size = new_size; } } }