diff options
Diffstat (limited to 'scripts/kallsyms.c')
| -rw-r--r-- | scripts/kallsyms.c | 78 | 
1 files changed, 75 insertions, 3 deletions
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 03fa07ad45d9..04e04fbd9625 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -49,6 +49,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[]; @@ -77,6 +78,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]; @@ -88,7 +90,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);  } @@ -410,6 +412,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; @@ -495,6 +556,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) { @@ -535,6 +597,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++) { @@ -573,7 +644,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; @@ -698,7 +769,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(); @@ -818,6 +889,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, <o_clang,       1},  			{},  		};  |