summaryrefslogtreecommitdiff
path: root/scripts/kallsyms.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/kallsyms.c')
-rw-r--r--scripts/kallsyms.c78
1 files changed, 75 insertions, 3 deletions
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 46d1afaaf4cd..8a68179a98a3 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -50,6 +50,7 @@ _Static_assert(
struct sym_entry {
unsigned long long addr;
unsigned int len;
+ unsigned int seq;
unsigned int start_pos;
unsigned int percpu_absolute;
unsigned char sym[];
@@ -78,6 +79,7 @@ static unsigned int table_size, table_cnt;
static int all_symbols;
static int absolute_percpu;
static int base_relative;
+static int lto_clang;
static int token_profit[0x10000];
@@ -89,7 +91,7 @@ static unsigned char best_table_len[256];
static void usage(void)
{
fprintf(stderr, "Usage: kallsyms [--all-symbols] [--absolute-percpu] "
- "[--base-relative] in.map > out.S\n");
+ "[--base-relative] [--lto-clang] in.map > out.S\n");
exit(1);
}
@@ -411,6 +413,65 @@ static int symbol_absolute(const struct sym_entry *s)
return s->percpu_absolute;
}
+static char * s_name(char *buf)
+{
+ /* Skip the symbol type */
+ return buf + 1;
+}
+
+static void cleanup_symbol_name(char *s)
+{
+ char *p;
+
+ if (!lto_clang)
+ return;
+
+ /*
+ * ASCII[.] = 2e
+ * ASCII[0-9] = 30,39
+ * ASCII[A-Z] = 41,5a
+ * ASCII[_] = 5f
+ * ASCII[a-z] = 61,7a
+ *
+ * As above, replacing '.' with '\0' does not affect the main sorting,
+ * but it helps us with subsorting.
+ */
+ p = strchr(s, '.');
+ if (p)
+ *p = '\0';
+}
+
+static int compare_names(const void *a, const void *b)
+{
+ int ret;
+ char sa_namebuf[KSYM_NAME_LEN];
+ char sb_namebuf[KSYM_NAME_LEN];
+ const struct sym_entry *sa = *(const struct sym_entry **)a;
+ const struct sym_entry *sb = *(const struct sym_entry **)b;
+
+ expand_symbol(sa->sym, sa->len, sa_namebuf);
+ expand_symbol(sb->sym, sb->len, sb_namebuf);
+ cleanup_symbol_name(s_name(sa_namebuf));
+ cleanup_symbol_name(s_name(sb_namebuf));
+ ret = strcmp(s_name(sa_namebuf), s_name(sb_namebuf));
+ if (!ret) {
+ if (sa->addr > sb->addr)
+ return 1;
+ else if (sa->addr < sb->addr)
+ return -1;
+
+ /* keep old order */
+ return (int)(sa->seq - sb->seq);
+ }
+
+ return ret;
+}
+
+static void sort_symbols_by_name(void)
+{
+ qsort(table, table_cnt, sizeof(table[0]), compare_names);
+}
+
static void write_src(void)
{
unsigned int i, k, off;
@@ -496,6 +557,7 @@ static void write_src(void)
for (i = 0; i < table_cnt; i++) {
if ((i & 0xFF) == 0)
markers[i >> 8] = off;
+ table[i]->seq = i;
/* There cannot be any symbol of length zero. */
if (table[i]->len == 0) {
@@ -536,6 +598,15 @@ static void write_src(void)
free(markers);
+ sort_symbols_by_name();
+ output_label("kallsyms_seqs_of_names");
+ for (i = 0; i < table_cnt; i++)
+ printf("\t.byte 0x%02x, 0x%02x, 0x%02x\n",
+ (unsigned char)(table[i]->seq >> 16),
+ (unsigned char)(table[i]->seq >> 8),
+ (unsigned char)(table[i]->seq >> 0));
+ printf("\n");
+
output_label("kallsyms_token_table");
off = 0;
for (i = 0; i < 256; i++) {
@@ -574,7 +645,7 @@ static void forget_symbol(const unsigned char *symbol, int len)
}
/* do the initial token count */
-static void build_initial_tok_table(void)
+static void build_initial_token_table(void)
{
unsigned int i;
@@ -699,7 +770,7 @@ static void insert_real_symbols_in_table(void)
static void optimize_token_table(void)
{
- build_initial_tok_table();
+ build_initial_token_table();
insert_real_symbols_in_table();
@@ -819,6 +890,7 @@ int main(int argc, char **argv)
{"all-symbols", no_argument, &all_symbols, 1},
{"absolute-percpu", no_argument, &absolute_percpu, 1},
{"base-relative", no_argument, &base_relative, 1},
+ {"lto-clang", no_argument, &lto_clang, 1},
{},
};