--- /dev/null
+From 73bbb94466fd3f8b313eeb0b0467314a262dddb3 Mon Sep 17 00:00:00 2001
+From: Miguel Ojeda <ojeda@kernel.org>
+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 <keescook@chromium.org>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
+Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
+Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
+Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
+Co-developed-by: Gary Guo <gary@garyguo.net>
+Signed-off-by: Gary Guo <gary@garyguo.net>
+Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
+Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
+Co-developed-by: Matthew Wilcox <willy@infradead.org>
+Signed-off-by: Matthew Wilcox <willy@infradead.org>
+Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
+---
+ 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");
+