Skip to content

Commit 73bbb94

Browse files
committed
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]>
1 parent 6e8c5bb commit 73bbb94

File tree

2 files changed

+48
-7
lines changed

2 files changed

+48
-7
lines changed

kernel/kallsyms.c

+22-4
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,20 @@ static unsigned int kallsyms_expand_symbol(unsigned int off,
5050
data = &kallsyms_names[off];
5151
len = *data;
5252
data++;
53+
off++;
54+
55+
/* If MSB is 1, it is a "big" symbol, so needs an additional byte. */
56+
if ((len & 0x80) != 0) {
57+
len = (len & 0x7F) | (*data << 7);
58+
data++;
59+
off++;
60+
}
5361

5462
/*
5563
* Update the offset to return the offset for the next symbol on
5664
* the compressed stream.
5765
*/
58-
off += len + 1;
66+
off += len;
5967

6068
/*
6169
* For every byte on the compressed symbol data, copy the table
@@ -108,7 +116,7 @@ static char kallsyms_get_symbol_type(unsigned int off)
108116
static unsigned int get_symbol_offset(unsigned long pos)
109117
{
110118
const u8 *name;
111-
int i;
119+
int i, len;
112120

113121
/*
114122
* Use the closest marker we have. We have markers every 256 positions,
@@ -122,8 +130,18 @@ static unsigned int get_symbol_offset(unsigned long pos)
122130
* so we just need to add the len to the current pointer for every
123131
* symbol we wish to skip.
124132
*/
125-
for (i = 0; i < (pos & 0xFF); i++)
126-
name = name + (*name) + 1;
133+
for (i = 0; i < (pos & 0xFF); i++) {
134+
len = *name;
135+
136+
/*
137+
* If MSB is 1, it is a "big" symbol, so we need to look into
138+
* the next byte (and skip it, too).
139+
*/
140+
if ((len & 0x80) != 0)
141+
len = ((len & 0x7F) | (name[1] << 7)) + 1;
142+
143+
name = name + len + 1;
144+
}
127145

128146
return name - kallsyms_names;
129147
}

scripts/kallsyms.c

+26-3
Original file line numberDiff line numberDiff line change
@@ -487,12 +487,35 @@ static void write_src(void)
487487
if ((i & 0xFF) == 0)
488488
markers[i >> 8] = off;
489489

490-
printf("\t.byte 0x%02x", table[i]->len);
490+
/* There cannot be any symbol of length zero. */
491+
if (table[i]->len == 0) {
492+
fprintf(stderr, "kallsyms failure: "
493+
"unexpected zero symbol length\n");
494+
exit(EXIT_FAILURE);
495+
}
496+
497+
/* Only lengths that fit in up-to-two-byte ULEB128 are supported. */
498+
if (table[i]->len > 0x3FFF) {
499+
fprintf(stderr, "kallsyms failure: "
500+
"unexpected huge symbol length\n");
501+
exit(EXIT_FAILURE);
502+
}
503+
504+
/* Encode length with ULEB128. */
505+
if (table[i]->len <= 0x7F) {
506+
/* Most symbols use a single byte for the length. */
507+
printf("\t.byte 0x%02x", table[i]->len);
508+
off += table[i]->len + 1;
509+
} else {
510+
/* "Big" symbols use two bytes. */
511+
printf("\t.byte 0x%02x, 0x%02x",
512+
(table[i]->len & 0x7F) | 0x80,
513+
(table[i]->len >> 7) & 0x7F);
514+
off += table[i]->len + 2;
515+
}
491516
for (k = 0; k < table[i]->len; k++)
492517
printf(", 0x%02x", table[i]->sym[k]);
493518
printf("\n");
494-
495-
off += table[i]->len + 1;
496519
}
497520
printf("\n");
498521

0 commit comments

Comments
 (0)