Linux kbuild/kconfig development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "David Laight" <david.laight.linux@gmail.com>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"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>,
	nathan@kernel.org, nsc@kernel.org
Subject: Re: [PATCH 15/15] kallsyms: scripts/kallsyms: Improve compression by about 2%
Date: Sun, 18 Oct 2026 16:05:10 +0000	[thread overview]
Message-ID: <sashiko-outbox-176259@kernel.org> (raw)
In-Reply-To: <20261018155206.132411-16-david.laight.linux@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] kallsyms: infinite loop in optimize_result() on self-overlapping token pairs
--

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

kallsyms: scripts/kallsyms: Improve compression by about 2%

This commit improves kallsyms compression by expanding infrequently used
merged tokens back into their original constituent pairs when no unused
tokens remain, freeing slots for more profitable token pairs.

> diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
> index 8576fe6ad90b7..9dbd7c85eec1e 100644
> --- a/scripts/kallsyms.c
> +++ b/scripts/kallsyms.c
[ ... ]
> @@ -561,6 +593,47 @@ static __attribute__((noinline)) unsigned int compress_symbols(unsigned int toke
>  	return substitutions;
>  }
>  
> +/* Change every occurance of idx back to token_pair.
> + * This extends all the symbol table entries but frees up a token. */
> +static __attribute__((noinline)) void uncompress_symbols(unsigned int token_pair, int idx)
> +{
> +	unsigned int i, len;
> +	unsigned char *sym, *p, *end;
> +	unsigned int substitutions;
> +
> +	for (i = 0; i < symbol_cnt; i++) {
> +		sym = symbol[i]->sym;
> +		len = symbol[i]->len;
> +		p = memchr(sym, idx, len);
> +		if (!p)
> +			continue;
> +		end = sym + len;
> +
> +		do {
> +			len = end - p - 1;
> +			end++;
> +			if (len) {
> +				adjust_profit(idx, RIGHT(token_pair), p[1], p[1]);
> +				memmove(p + 2, p + 1, len);
> +			}
> +			p[0] = LEFT(token_pair);
> +			p[1] = RIGHT(token_pair);
> +			if (p != sym)
> +				adjust_profit(p[-1], p[-1], idx, LEFT(token_pair));
> +			p = memchr(p + 2, idx, len);
> +		} while (p);
> +		symbol[i]->len = end - sym;
> +	}
> +
> +	substitutions = token_table[idx].refs;
> +
> +	token_profit[token_pair] += substitutions;
> +
> +	token_table[idx].refs = 0;
> +	token_table[LEFT(token_pair)].refs += substitutions;
> +	token_table[RIGHT(token_pair)].refs += substitutions;
> +}
> +
>  /* search the token with the maximum profit */
>  static int find_best_token(void)
>  {
> @@ -578,14 +651,47 @@ static int find_best_token(void)
>  	return best;
>  }
>  
> +static int split_token(unsigned int profit)
> +{
> +	struct token_table *tt, *left, *right;
> +	unsigned int i;
> +	int best = -1;
> +
> +	for (i = 0; i < 256; i++) {
> +		tt = token_table + i;
> +
> +		if (tt->len == 1 || tt->refs >= profit)
> +			continue;
> +
> +		/* Ignore tokens where the original parts have be reused */
> +		left = &token_table[LEFT(tt->pair)];
> +		right = &token_table[RIGHT(tt->pair)];
> +		if (tt->len != left->len + right->len ||
> +		    memcmp(tt->str, left->str, left->len) ||
> +		    memcmp(tt->str + left->len, right->str, right->len))
> +			continue;
> +
> +		best = i;
> +		if (tt->refs == 2)
> +			break;
> +		profit = tt->refs;
> +	}
> +	if (best < 0)
> +		return -1;
> +
> +	uncompress_symbols(token_table[best].pair, best);
> +
> +	return best;
> +}
> +
>  /* this is the core of the algorithm: calculate the "best" table */
>  static void optimize_result(void)
>  {
> -	unsigned int i, idx, len, refs;
> -	struct token_table *left, *right;
> +	struct token_table *t, *left, *right;
>  	unsigned char to_process[256];
> +	unsigned int idx, len, refs;
> +	int i, best;
>  	char *str;
> -	int best;
>  
>  	/* Generate a list of the unused tokens. */
>  	for (i = 0, idx = 0; i < 256; i++) {
> @@ -593,20 +699,28 @@ static void optimize_result(void)
>  			to_process[idx++] = i;
>  	}
>  
> -	do {
> +	for (;;) {
>  		/* find the token pair with the best profit value */
>  		best = find_best_token();
>  		if (best < 0)
>  			break;
> -		i = to_process[--idx];
> +		if (idx) {
> +			i = to_process[--idx];
> +		} else {
> +			/* Try to free up a little-used token. */
> +			i = split_token(token_profit[best]);
> +			if (i < 0)
> +				break;
> +		}
>  
>  		/* replace this token pair in all the valid symbols */
>  		refs = compress_symbols(best, i);
> +		t = &token_table[i];
>  
>  		/* Update the number of times each token is used */
> -		token_table[i].refs += refs;
> +		t->refs += refs;
> +		t->pair = best;

[Severity: Medium]
Can optimize_result() enter an infinite loop when find_best_token() selects a
homogeneous token pair best = PAIR(x, x) that overlaps with itself in runs of
3 or more identical tokens?

For a homogeneous pair PAIR(x, x) where LEFT(best) == RIGHT(best),
learn_symbol() and uncompress_symbols() count every adjacent pair, so a run
of [x, x, x] increments token_profit[PAIR(x, x)] by 2. However, when
compress_symbols(PAIR(x, x), i) replaces the first pair to form [i, x], it
calls:

    adjust_profit(RIGHT(token_pair), idx, p[2], p[2]);

which is adjust_profit(x, i, x, x), decrementing token_profit[PAIR(x, x)] by
1 for each triple. As a result, compress_symbols() performs fewer
substitutions (refs) than the initial token_profit[best] passed to
split_token().

If idx == 0 and a splittable token s representing PAIR(y, z) has
refs < token_table[s].refs < token_profit[PAIR(x, x)] (for example, two
occurrences of [x, x, x] giving token_profit[PAIR(x, x)] = 4 and actual
refs = 2, while token s has token_table[s].refs = 3):

1. optimize_result() calls split_token(4), which selects token s (since
3 < 4) and calls uncompress_symbols(PAIR(y, z), s), setting
token_profit[PAIR(y, z)] = 3. Then compress_symbols(PAIR(x, x), s) performs
only refs = 2 substitutions, setting token_table[s].refs = 2 and
token_table[s].pair = PAIR(x, x).

2. On the next iteration, find_best_token() selects PAIR(y, z) with profit 3.
split_token(3) selects token s again because token_table[s].refs (2) < 3 and
token_table[x] is still valid. uncompress_symbols(PAIR(x, x), s) restores the
two [x, x, x] runs and sets token_profit[PAIR(x, x)] back to 4 (2 from
adjust_profit(s, x, x, x) in the loop plus 2 from substitutions). Then
compress_symbols(PAIR(y, z), s) sets token_table[s].refs = 3.

Would this cause optimize_result() to alternate between splitting and
compressing PAIR(x, x) and PAIR(y, z) indefinitely?

>  
> -		/* Generate the full name for this symbol */
>  		left = &token_table[LEFT(best)];
>  		right = &token_table[RIGHT(best)];
[ ... ]

ওয়াট

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

  reply	other threads:[~2026-10-18 16:05 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-18 15:51 [PATCH v2 next 00/15] kallsyms: optimise symbol search by name David Laight
2026-10-18 15:51 ` [PATCH v2 next 01/15] kallsyms: scripts/kallsyms.c: Avoid overrunning on-stack buffer David Laight
2026-10-18 15:51 ` [PATCH v2 next 02/15] kallsyms: Fix selftest startup delay David Laight
2026-10-18 15:51 ` [PATCH v2 next 03/15] kallsyms: Improve selftest test_perf_kallsyms_lookup_name() output David Laight
2026-10-18 16:03   ` sashiko-bot
2026-10-19 16:07   ` kernel test robot
2026-10-19 17:08     ` David Laight
2026-10-18 15:51 ` [PATCH v2 next 04/15] kallsyms: scripts/kallsyms: Check for output file write errors David Laight
2026-10-18 15:51 ` [PATCH v2 next 05/15] kallsyms: Match compressed tokens on the fly during binary search David Laight
2026-10-18 15:51 ` [PATCH v2 next 06/15] kallsyms: Optimise symbol name search David Laight
2026-10-18 16:15   ` sashiko-bot
2026-10-18 17:04     ` David Laight
2026-10-18 15:51 ` [PATCH v2 next 07/15] kallsyms: Optimise detection of duplicate symbol names David Laight
2026-10-18 15:51 ` [PATCH v2 next 08/15] kallsyms: Support changing the density of the kallsyms_markers[] array David Laight
2026-10-18 15:52 ` [PATCH v2 next 09/15] kallsyms: Add a kernel parameter for the marker shift David Laight
2026-10-18 15:52 ` [PATCH v2 next 10/15] kallsyms: scripts/kallsyms: Rename some variables for clarity David Laight
2026-10-18 15:52 ` [PATCH v2 next 11/15] kallsyms: scripts/kallsyms: Keep full expansion of tokens David Laight
2026-10-18 16:00   ` sashiko-bot
2026-10-18 16:37     ` David Laight
2026-10-18 15:52 ` [PATCH v2 next 12/15] kallsyms: scripts/kallsyms: Optimise compress_symbols() David Laight
2026-10-18 15:52 ` [PATCH v2 next 13/15] kallsyms: scripts/kallsyms: Reuse tokens that have no references David Laight
2026-10-18 15:52 ` [PATCH 14/15] kallsyms: scripts/kallsyms: Reduce the output file size David Laight
2026-10-18 16:05   ` sashiko-bot
2026-10-18 16:47     ` David Laight
2026-10-18 15:52 ` [PATCH 15/15] kallsyms: scripts/kallsyms: Improve compression by about 2% David Laight
2026-10-18 16:05   ` sashiko-bot [this message]
2026-10-18 17:28     ` David Laight

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-176259@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=andrey.grodzovsky@crowdstrike.com \
    --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 \
    /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