瀏覽代碼

generic: 5.15: backport patch supporting "big" kernel symbols

Backport patch supporting "big" kernel symbols. This is needed for
powerpc arch that seems to suffer from this problem when
CONFIG_ALL_KMODS is selected and fail to compile with the error:
Inconsistent kallsyms data
Try make KALLSYMS_EXTRA_PASS=1 as a workaround

Backport this patch to handle these corner case.

Signed-off-by: Christian Marangi <[email protected]>
Christian Marangi 2 年之前
父節點
當前提交
9dfade39f5
共有 1 個文件被更改,包括 128 次插入0 次删除
  1. 128 0
      target/linux/generic/backport-5.15/202-v6.1-kallsyms-support-big-kernel-symbols.patch

+ 128 - 0
target/linux/generic/backport-5.15/202-v6.1-kallsyms-support-big-kernel-symbols.patch

@@ -0,0 +1,128 @@
+From 73bbb94466fd3f8b313eeb0b0467314a262dddb3 Mon Sep 17 00:00:00 2001
+From: Miguel Ojeda <[email protected]>
+Date: Mon, 5 Apr 2021 04:58:39 +0200
+Subject: [PATCH] kallsyms: support "big" kernel symbols
+
+Rust symbols can become quite long due to namespacing introduced
+by modules, types, traits, generics, etc.
+
+Increasing to 255 is not enough in some cases, therefore
+introduce longer lengths to the symbol table.
+
+In order to avoid increasing all lengths to 2 bytes (since most
+of them are small, including many Rust ones), use ULEB128 to
+keep smaller symbols in 1 byte, with the rest in 2 bytes.
+
+Reviewed-by: Kees Cook <[email protected]>
+Reviewed-by: Greg Kroah-Hartman <[email protected]>
+Co-developed-by: Alex Gaynor <[email protected]>
+Signed-off-by: Alex Gaynor <[email protected]>
+Co-developed-by: Wedson Almeida Filho <[email protected]>
+Signed-off-by: Wedson Almeida Filho <[email protected]>
+Co-developed-by: Gary Guo <[email protected]>
+Signed-off-by: Gary Guo <[email protected]>
+Co-developed-by: Boqun Feng <[email protected]>
+Signed-off-by: Boqun Feng <[email protected]>
+Co-developed-by: Matthew Wilcox <[email protected]>
+Signed-off-by: Matthew Wilcox <[email protected]>
+Signed-off-by: Miguel Ojeda <[email protected]>
+---
+ kernel/kallsyms.c  | 26 ++++++++++++++++++++++----
+ scripts/kallsyms.c | 29 ++++++++++++++++++++++++++---
+ 2 files changed, 48 insertions(+), 7 deletions(-)
+
+--- a/kernel/kallsyms.c
++++ b/kernel/kallsyms.c
+@@ -69,12 +69,20 @@ static unsigned int kallsyms_expand_symb
+ 	data = &kallsyms_names[off];
+ 	len = *data;
+ 	data++;
++	off++;
++
++	/* If MSB is 1, it is a "big" symbol, so needs an additional byte. */
++	if ((len & 0x80) != 0) {
++		len = (len & 0x7F) | (*data << 7);
++		data++;
++		off++;
++	}
+ 
+ 	/*
+ 	 * Update the offset to return the offset for the next symbol on
+ 	 * the compressed stream.
+ 	 */
+-	off += len + 1;
++	off += len;
+ 
+ 	/*
+ 	 * For every byte on the compressed symbol data, copy the table
+@@ -127,7 +135,7 @@ static char kallsyms_get_symbol_type(uns
+ static unsigned int get_symbol_offset(unsigned long pos)
+ {
+ 	const u8 *name;
+-	int i;
++	int i, len;
+ 
+ 	/*
+ 	 * Use the closest marker we have. We have markers every 256 positions,
+@@ -141,8 +149,18 @@ static unsigned int get_symbol_offset(un
+ 	 * so we just need to add the len to the current pointer for every
+ 	 * symbol we wish to skip.
+ 	 */
+-	for (i = 0; i < (pos & 0xFF); i++)
+-		name = name + (*name) + 1;
++	for (i = 0; i < (pos & 0xFF); i++) {
++		len = *name;
++
++		/*
++		 * If MSB is 1, it is a "big" symbol, so we need to look into
++		 * the next byte (and skip it, too).
++		 */
++		if ((len & 0x80) != 0)
++			len = ((len & 0x7F) | (name[1] << 7)) + 1;
++
++		name = name + len + 1;
++	}
+ 
+ 	return name - kallsyms_names;
+ }
+--- a/scripts/kallsyms.c
++++ b/scripts/kallsyms.c
+@@ -470,12 +470,35 @@ static void write_src(void)
+ 		if ((i & 0xFF) == 0)
+ 			markers[i >> 8] = off;
+ 
+-		printf("\t.byte 0x%02x", table[i]->len);
++		/* There cannot be any symbol of length zero. */
++		if (table[i]->len == 0) {
++			fprintf(stderr, "kallsyms failure: "
++				"unexpected zero symbol length\n");
++			exit(EXIT_FAILURE);
++		}
++
++		/* Only lengths that fit in up-to-two-byte ULEB128 are supported. */
++		if (table[i]->len > 0x3FFF) {
++			fprintf(stderr, "kallsyms failure: "
++				"unexpected huge symbol length\n");
++			exit(EXIT_FAILURE);
++		}
++
++		/* Encode length with ULEB128. */
++		if (table[i]->len <= 0x7F) {
++			/* Most symbols use a single byte for the length. */
++			printf("\t.byte 0x%02x", table[i]->len);
++			off += table[i]->len + 1;
++		} else {
++			/* "Big" symbols use two bytes. */
++			printf("\t.byte 0x%02x, 0x%02x",
++				(table[i]->len & 0x7F) | 0x80,
++				(table[i]->len >> 7) & 0x7F);
++			off += table[i]->len + 2;
++		}
+ 		for (k = 0; k < table[i]->len; k++)
+ 			printf(", 0x%02x", table[i]->sym[k]);
+ 		printf("\n");
+-
+-		off += table[i]->len + 1;
+ 	}
+ 	printf("\n");
+