Linux kbuild/kconfig development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "David Laight" <david.laight.linux@gmail.com>,
	"Petr Mladek" <pmladek@suse.com>, "Kees Cook" <kees@kernel.org>,
	linux-kbuild@vger.kernel.org, bpf@vger.kernel.org,
	"Jim Cromie" <jim.cromie@gmail.com>,
	"Lorenzo Stoakes" <ljs@kernel.org>
Cc: "Luis Chamberlain" <mcgrof@kernel.org>,
	"Andrey Grodzovsky" <andrey.grodzovsky@crowdstrike.com>,
	"Steven Rostedt" <rostedt@goodmis.org>,
	"Andrii Nakryiko" <andrii@kernel.org>,
	"Samuel Wu" <wusamuel@google.com>,
	nathan@kernel.org, nsc@kernel.org
Subject: Re: [PATCH v3 next 13/13] scripts/kallsyms: Reuse little-used compression tokens
Date: Wed, 11 Nov 2026 13:37:49 +0000	[thread overview]
Message-ID: <sashiko-outbox-209079@kernel.org> (raw)
In-Reply-To: <20261111115911.1142000-14-david.laight.linux@gmail.com>

Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [Medium] scripts/kallsyms: missing syms update on split in
  uncompress_symbols()
- [Low] scripts/kallsyms: premature 3-char token disqualification in
  split_token()
- [Low] scripts/kallsyms: unreset syms.cnt and splits in
  sym_arr_free_all()
--

commit f874410df5dfe77ff678c52a66379728c6ebf5ba
Author: David Laight <david.laight.linux@gmail.com>

scripts/kallsyms: Reuse little-used compression tokens

This commit reuses compression tokens that have few remaining references by
expanding their occurrences in the symbol table back into their component
tokens when a more common token pair is available.

> diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
> index 95ccde80359f2..dc69b802478ad 100644
> --- a/scripts/kallsyms.c
> +++ b/scripts/kallsyms.c
[ ... ]
> @@ -850,6 +894,123 @@ compress_symbols(unsigned int token_idx, int compressed_chr)
>  	return subs;
>  }
>  
> +/* Change every occurance of idx back to token_pair/triple.
> + * This extends all the symbol table entries but frees up a token. */
> +static __attribute__((noinline)) void
> +uncompress_symbols(unsigned int token_pair, int idx)
> +{
> +	struct best_table *bt = best_table + idx;
> +	unsigned int sym_idx, len;
> +	unsigned char *sym, *p, *end;
> +	unsigned int substitutions;
> +	unsigned int third_char;
> +
> +	third_char = token_pair >> 16;
> +	token_pair &= 0xffff;
> +
> +	for (int j = 0; j < bt->syms.cnt; j++) {
> +		sym_idx = bt->syms.sym_indexes[j];
> +
> +		sym = table[sym_idx]->sym;
> +		len = table[sym_idx]->len;
> +		end = sym + len;
> +
> +		for (p = sym; (p = memchr(p, idx, len)); p += 2) {
> +			len = end - p - 1;
> +			if (len) {
> +				if (third_char) {
> +					/* Adding three characters */
> +					adjust_profit(sym_idx, idx, third_char, p[1], p[1]);
> +					memmove(p + 3, p + 1, len);
> +				} else {
> +					adjust_profit(sym_idx, idx, token_second(token_pair), p[1], p[1]);
> +					memmove(p + 2, p + 1, len);
> +				}
> +			}
> +			if (p != sym)
> +				adjust_profit(sym_idx, p[-1], p[-1], idx, token_first(token_pair));
> +			token_add_symbol(token_pair, sym_idx);
> +			p[0] = token_first(token_pair);
> +			p[1] = token_second(token_pair);
> +			end++;

[Severity: Medium]
Does uncompress_symbols() need to add sym_idx back to the .syms arrays of
multi-character component tokens when expanding idx into token_pair?

If a multi-character component token was previously split (clearing its
.syms.cnt) and later re-compressed so that first->str and second->str
again concatenate to bt->str across a different subset of symbols,
restoring token_first(token_pair) or token_second(token_pair) into
table[sym_idx]->sym without adding sym_idx to its best_table[].syms array
leaves that symbol untracked.  A subsequent split of that component token
will then miss table[sym_idx]->sym and leave stale token bytes behind when
the slot is reassigned.

> +			if (third_char) {
> +				token_add_symbol(token_index(p[1], third_char), sym_idx);
> +				p[2] = third_char;
> +				end++;
> +				p++;
> +			}
> +		}
> +		table[sym_idx]->len = end - sym;
> +	}
> +
> +	substitutions = bt->refs;
> +
> +	bt->refs = 0;
> +	bt->syms.cnt = 0;
> +	sym_arr_free_all(idx);

[Severity: Low]
Should sym_arr_free_all() reset best_table[ch].syms.cnt and
best_table[ch].splits instead of only clearing bt->syms.cnt here?

When optimize_result() frees a zero-reference token via sym_arr_free_all():

scripts/kallsyms.c:optimize_result() {
    ...
		if (!(first->refs -= refs) && first->len > 1)
			/* There are no references left, reuse the token. */
			to_process[idx++] = sym_arr_free_all(token_first(best));
		if (!(second->refs -= refs) && second->len > 1)
			to_process[idx++] = sym_arr_free_all(token_second(best));
    ...
}

best_table[ch].syms.cnt and best_table[ch].splits retain their values from
the old token.  When that slot is reused by compress_symbols(), new symbol
indices are merged into the stale .syms list (causing uncompress_symbols()
to scan unrelated symbols if the new token is later split), and the new
token inherits the prior token's split count (which may already be
max_splits).

> +
> +	token_profit[token_pair] += substitutions;
> +	best_table[token_first(token_pair)].refs += substitutions;
> +	best_table[token_second(token_pair)].refs += substitutions;
> +
> +	if (third_char) {
> +		best_table[third_char].refs += substitutions;
> +		token_profit[token_index(token_second(token_pair), third_char)] += substitutions;
> +	}
> +}
> +
> +static int split_token(unsigned int profit)
> +{
> +	struct best_table *bt, *first, *second;
> +	const unsigned int max_splits = 10;
> +	unsigned int i, best_token;
> +	int best_ch = -1;
> +
> +	for (i = 0; i < 256; i++) {
> +		bt = best_table + i;
> +
> +		if (bt->len == 1 || bt->refs >= profit || bt->splits >= max_splits)
> +			continue;
> +
> +		/* Ignore tokens where the original parts have been reused ... */
> +		first = &best_table[token_first(bt->token)];
> +		second = &best_table[token_second(bt->token)];
> +		if (bt->len != first->len + second->len ||
> +		    memcmp(bt->str, first->str, first->len) ||
> +		    memcmp(bt->str + first->len, second->str, second->len)) {
> +			/* ... unless they are three characters. */
> +			if (bt->len != 3 || bt->refs * 2 >= profit) {
> +				/* Don't consider again */
> +				bt->splits = max_splits;
> +				continue;
> +			}

[Severity: Low]
Does setting bt->splits = max_splits when bt->len == 3 and
bt->refs * 2 >= profit permanently disqualify 3-character tokens that only
lost to a better candidate in the current scan?

As the loop iterates, profit is lowered to the best candidate's cost
(bt->refs or bt->refs * 2).  Any later 3-character token whose original
components were reused and whose bt->refs * 2 is not strictly less than
that running minimum gets bt->splits set to max_splits, preventing it from
being split on subsequent calls to split_token().

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261111115911.1142000-1-david.laight.linux@gmail.com?part=13

      reply	other threads:[~2026-11-11 13:37 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-11 11:58 [PATCH v3 next 00/13] kallsyms: optimise symbol search by name David Laight
2026-11-11 11:58 ` [PATCH v3 next 01/13] scripts/kallsyms: Avoid overrunning on-stack buffer David Laight
2026-11-11 11:59 ` [PATCH v3 next 02/13] scripts/kallsyms: Improve error reporting David Laight
2026-11-11 12:14   ` sashiko-bot
2026-11-11 23:33   ` bot+bpf-ci
2026-11-11 11:59 ` [PATCH v3 next 03/13] scripts/elf-parse: add elf_map_big_endian() helper David Laight
2026-11-11 11:59 ` [PATCH v3 next 04/13] scripts/kallsyms: make use of binary data output optional David Laight
2026-11-11 12:32   ` sashiko-bot
2026-11-11 23:34   ` bot+bpf-ci
2026-11-11 11:59 ` [PATCH v3 next 05/13] kallsyms: Fix selftest startup delay David Laight
2026-11-11 12:36   ` sashiko-bot
2026-11-11 11:59 ` [PATCH v3 next 06/13] kallsyms: Improve selftest test_perf_kallsyms_lookup_name() output David Laight
2026-11-11 23:17   ` bot+bpf-ci
2026-11-11 11:59 ` [PATCH v3 next 07/13] kallsyms: Match compressed tokens on the fly during binary search David Laight
2026-11-11 12:46   ` sashiko-bot
2026-11-11 11:59 ` [PATCH v3 next 08/13] kallsyms: Optimise symbol name search David Laight
2026-11-11 12:59   ` sashiko-bot
2026-11-11 11:59 ` [PATCH v3 next 09/13] kallsyms: Add a kernel parameter to change the kallsyms_markers[] density David Laight
2026-11-11 13:07   ` sashiko-bot
2026-11-11 23:33   ` bot+bpf-ci
2026-11-11 11:59 ` [PATCH v3 next 10/13] scripts/kallsyms: Keep full expansion of tokens David Laight
2026-11-11 11:59 ` [PATCH v3 next 11/13] scripts/kallsyms: Optimise compress_symbols() David Laight
2026-11-11 11:59 ` [PATCH v3 next 12/13] scripts/kallsyms: Reuse tokens that have no references David Laight
2026-11-11 23:34   ` bot+bpf-ci
2026-11-11 11:59 ` [PATCH v3 next 13/13] scripts/kallsyms: Reuse little-used compression tokens David Laight
2026-11-11 13:37   ` sashiko-bot [this message]

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=sashiko-outbox-209079@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=andrey.grodzovsky@crowdstrike.com \
    --cc=andrii@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=david.laight.linux@gmail.com \
    --cc=jim.cromie@gmail.com \
    --cc=kees@kernel.org \
    --cc=linux-kbuild@vger.kernel.org \
    --cc=ljs@kernel.org \
    --cc=mcgrof@kernel.org \
    --cc=nathan@kernel.org \
    --cc=nsc@kernel.org \
    --cc=pmladek@suse.com \
    --cc=rostedt@goodmis.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=wusamuel@google.com \
    /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