public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Masahiro Yamada <masahiroy@kernel.org>
To: linux-kbuild@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Greg Ungerer <gerg@kernel.org>,
	Jack Brennen <jbrennen@google.com>,
	Masahiro Yamada <masahiroy@kernel.org>,
	Nathan Chancellor <nathan@kernel.org>,
	Nick Desaulniers <ndesaulniers@google.com>,
	Nicolas Schier <nicolas@fjasle.eu>
Subject: [PATCH 5/7] modpost: prefer global symbols in symsearch_find_nearest()
Date: Thu,  2 Nov 2023 00:04:02 +0900	[thread overview]
Message-ID: <20231101150404.754108-6-masahiroy@kernel.org> (raw)
In-Reply-To: <20231101150404.754108-1-masahiroy@kernel.org>

When there are multiple symbols that share the same section index and
address, symsearch_find_nearest() returns the first occurrence in the
original .symtab section. We can add more rules to break a tie based
on symbol attributes.

Kallsyms does this; compare_symbols() in scripts/kallsyms.c first sorts
symbols by address, then by weakness and by underscore-prefixing in
order to provide users with the most desirable symbol.

This commit gives the following preference, in this order:

  1. lower address
  2. global symbol
  3. no underscore prefix

If two symbols still tie, the first one encounterd in the linear search
is selected. This does not match the order in the original .symtab
section, but it is not a significant issue.

Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
---

 scripts/mod/symsearch.c | 57 +++++++++++++++++------------------------
 1 file changed, 24 insertions(+), 33 deletions(-)

diff --git a/scripts/mod/symsearch.c b/scripts/mod/symsearch.c
index 4549c5b0bb81..13464e4f4d72 100644
--- a/scripts/mod/symsearch.c
+++ b/scripts/mod/symsearch.c
@@ -20,9 +20,7 @@ struct syminfo {
  * Entries in table are ascending, sorted first by section_index,
  * then by addr, and last by symbol_index.  The sorting by
  * symbol_index is used to ensure predictable behavior when
- * multiple symbols are present with the same address; all
- * symbols past the first are effectively ignored, by eliding
- * them in symsearch_fixup().
+ * multiple symbols are present with the same address.
  */
 struct symsearch {
 	unsigned int table_size;
@@ -97,32 +95,6 @@ static void symsearch_populate(struct elf_info *elf,
 		fatal("%s: size mismatch\n", __func__);
 }
 
-/*
- * Do any fixups on the table after sorting.
- * For now, this just finds adjacent entries which have
- * the same section_index and addr, and it propagates
- * the first symbol_index over the subsequent entries,
- * so that only one symbol_index is seen for any given
- * section_index and addr.  This ensures that whether
- * we're looking at an address from "above" or "below"
- * that we see the same symbol_index.
- * This does leave some duplicate entries in the table;
- * in practice, these are a small fraction of the
- * total number of entries, and they are harmless to
- * the binary search algorithm other than a few occasional
- * unnecessary comparisons.
- */
-static void symsearch_fixup(struct syminfo *table, unsigned int table_size)
-{
-	/* Don't look at index 0, it will never change. */
-	for (unsigned int i = 1; i < table_size; i++) {
-		if (table[i].addr == table[i - 1].addr &&
-		    table[i].section_index == table[i - 1].section_index) {
-			table[i].symbol_index = table[i - 1].symbol_index;
-		}
-	}
-}
-
 void symsearch_init(struct elf_info *elf)
 {
 	unsigned int table_size = symbol_count(elf);
@@ -134,8 +106,6 @@ void symsearch_init(struct elf_info *elf)
 	symsearch_populate(elf, elf->symsearch->table, table_size);
 	qsort(elf->symsearch->table, table_size,
 	      sizeof(struct syminfo), syminfo_compare);
-
-	symsearch_fixup(elf->symsearch->table, table_size);
 }
 
 void symsearch_finish(struct elf_info *elf)
@@ -226,12 +196,33 @@ static Elf_Sym *symsearch_find(struct elf_info *elf, Elf_Addr addr,
 static bool symsearch_nearest_filter(const Elf_Sym *sym1, const Elf_Sym *sym2,
 				     void *data)
 {
+	struct elf_info *elf = data;
+	unsigned int bind1, bind2, unscores1, unscores2;
+
 	/* If sym2 is NULL, this is the first occurrence, always take it. */
 	if (sym2 == NULL)
 		return true;
 
 	/* Prefer lower address. */
-	return sym1->st_value < sym2->st_value;
+	if (sym1->st_value < sym2->st_value)
+		return true;
+	if (sym1->st_value > sym2->st_value)
+		return false;
+
+	bind1 = ELF_ST_BIND(sym1->st_info);
+	bind2 = ELF_ST_BIND(sym2->st_info);
+
+	/* Prefer global symbol. */
+	if (bind1 == STB_GLOBAL && bind2 != STB_GLOBAL)
+		return true;
+	if (bind1 != STB_GLOBAL && bind2 == STB_GLOBAL)
+		return false;
+
+	/* Prefer less underscores. */
+	unscores1 = strspn(sym_name(elf, sym1), "_");
+	unscores2 = strspn(sym_name(elf, sym2), "_");
+
+	return unscores1 < unscores2;
 }
 
 /*
@@ -247,5 +238,5 @@ Elf_Sym *symsearch_find_nearest(struct elf_info *elf, Elf_Addr addr,
 				Elf_Addr min_distance)
 {
 	return symsearch_find(elf, addr, secndx, allow_negative, min_distance,
-			      symsearch_nearest_filter, NULL);
+			      symsearch_nearest_filter, elf);
 }
-- 
2.40.1


  parent reply	other threads:[~2023-11-01 15:05 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-01 15:03 [PATCH 0/7] modpost: fix modpost errors for m68k-uclinux-gcc Masahiro Yamada
2023-11-01 15:03 ` [PATCH 1/7] modpost: move sym_name() to modpost.h Masahiro Yamada
2023-11-01 15:03 ` [PATCH 2/7] modpost: add const qualifier to syminfo table Masahiro Yamada
2023-11-01 15:04 ` [PATCH 3/7] modpost: add table_size local variable to symsearch_find_nearest() Masahiro Yamada
2023-11-01 15:04 ` [PATCH 4/7] modpost: introduce a filtering feature to symsearch Masahiro Yamada
2023-11-01 15:04 ` Masahiro Yamada [this message]
2023-11-01 15:04 ` [PATCH 6/7] modpost: add symsearch_find_with_name() helper function Masahiro Yamada
2023-11-01 15:04 ` [PATCH 7/7] modpost: look up the correct symbol in check_export_symbol() Masahiro Yamada
2023-11-02 15:00 ` [PATCH 0/7] modpost: fix modpost errors for m68k-uclinux-gcc Greg Ungerer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231101150404.754108-6-masahiroy@kernel.org \
    --to=masahiroy@kernel.org \
    --cc=gerg@kernel.org \
    --cc=jbrennen@google.com \
    --cc=linux-kbuild@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nathan@kernel.org \
    --cc=ndesaulniers@google.com \
    --cc=nicolas@fjasle.eu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox