forked from Openwrt/openwrt
9dfade39f5
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>
129 lines
3.8 KiB
Diff
129 lines
3.8 KiB
Diff
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");
|
|
|