generic: 5.15: backport patch supporting "big" kernel symbols
authorChristian Marangi <ansuelsmth@gmail.com>
Sat, 10 Jun 2023 03:33:44 +0000 (05:33 +0200)
committerChristian Marangi <ansuelsmth@gmail.com>
Sat, 10 Jun 2023 04:56:19 +0000 (06:56 +0200)
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 <ansuelsmth@gmail.com>
target/linux/generic/backport-5.15/202-v6.1-kallsyms-support-big-kernel-symbols.patch [new file with mode: 0644]

diff --git a/target/linux/generic/backport-5.15/202-v6.1-kallsyms-support-big-kernel-symbols.patch b/target/linux/generic/backport-5.15/202-v6.1-kallsyms-support-big-kernel-symbols.patch
new file mode 100644 (file)
index 0000000..786a2d9
--- /dev/null
@@ -0,0 +1,128 @@
+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");