提交 29aee99a 编写于 作者: M Miguel Ojeda 提交者: Zheng Zengkai

kallsyms: support "big" kernel symbols

maillist inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I5J75G
CVE: NA

Reference: https://lore.kernel.org/rust-for-linux/CANiq72nDcJLSB3pLhkdqGdLitfmqqCUVVfkY5EjP9AcwVv9B4A@mail.gmail.com/T/#t

--------------------------------

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, and therefore
we need to 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), we use ULEB128 to
keep smaller symbols in 1 byte, with the rest in 2 bytes.
Reviewed-by: NKees Cook <keescook@chromium.org>
Co-developed-by: NAlex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: NAlex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: NWedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: NWedson Almeida Filho <wedsonaf@google.com>
Co-developed-by: NGary Guo <gary@garyguo.net>
Signed-off-by: NGary Guo <gary@garyguo.net>
Co-developed-by: NBoqun Feng <boqun.feng@gmail.com>
Signed-off-by: NBoqun Feng <boqun.feng@gmail.com>
Co-developed-by: NMatthew Wilcox <willy@infradead.org>
Signed-off-by: NMatthew Wilcox <willy@infradead.org>
Signed-off-by: NMiguel Ojeda <ojeda@kernel.org>
Signed-off-by: NWeilong Chen <chenweilong@huawei.com>
上级 153f32d7
...@@ -66,12 +66,20 @@ static unsigned int kallsyms_expand_symbol(unsigned int off, ...@@ -66,12 +66,20 @@ static unsigned int kallsyms_expand_symbol(unsigned int off,
data = &kallsyms_names[off]; data = &kallsyms_names[off];
len = *data; len = *data;
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 * Update the offset to return the offset for the next symbol on
* the compressed stream. * the compressed stream.
*/ */
off += len + 1; off += len;
/* /*
* For every byte on the compressed symbol data, copy the table * For every byte on the compressed symbol data, copy the table
...@@ -124,7 +132,7 @@ static char kallsyms_get_symbol_type(unsigned int off) ...@@ -124,7 +132,7 @@ static char kallsyms_get_symbol_type(unsigned int off)
static unsigned int get_symbol_offset(unsigned long pos) static unsigned int get_symbol_offset(unsigned long pos)
{ {
const u8 *name; const u8 *name;
int i; int i, len;
/* /*
* Use the closest marker we have. We have markers every 256 positions, * Use the closest marker we have. We have markers every 256 positions,
...@@ -138,8 +146,18 @@ static unsigned int get_symbol_offset(unsigned long pos) ...@@ -138,8 +146,18 @@ static unsigned int get_symbol_offset(unsigned long pos)
* so we just need to add the len to the current pointer for every * so we just need to add the len to the current pointer for every
* symbol we wish to skip. * symbol we wish to skip.
*/ */
for (i = 0; i < (pos & 0xFF); i++) for (i = 0; i < (pos & 0xFF); i++) {
name = name + (*name) + 1; 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; return name - kallsyms_names;
} }
......
...@@ -480,12 +480,35 @@ static void write_src(void) ...@@ -480,12 +480,35 @@ static void write_src(void)
if ((i & 0xFF) == 0) if ((i & 0xFF) == 0)
markers[i >> 8] = off; markers[i >> 8] = off;
/* 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); 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++) for (k = 0; k < table[i]->len; k++)
printf(", 0x%02x", table[i]->sym[k]); printf(", 0x%02x", table[i]->sym[k]);
printf("\n"); printf("\n");
off += table[i]->len + 1;
} }
printf("\n"); printf("\n");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册