diff options
Diffstat (limited to 'scripts/kallsyms.c')
| -rw-r--r-- | scripts/kallsyms.c | 92 | 
1 files changed, 70 insertions, 22 deletions
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 487ac6f37ca..dc7aa45e80c 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -36,13 +36,13 @@ struct sym_entry {  	unsigned char *sym;  }; -struct text_range { -	const char *stext, *etext; +struct addr_range { +	const char *start_sym, *end_sym;  	unsigned long long start, end;  };  static unsigned long long _text; -static struct text_range text_ranges[] = { +static struct addr_range text_ranges[] = {  	{ "_stext",     "_etext"     },  	{ "_sinittext", "_einittext" },  	{ "_stext_l1",  "_etext_l1"  },	/* Blackfin on-chip L1 inst SRAM */ @@ -51,10 +51,16 @@ static struct text_range text_ranges[] = {  #define text_range_text     (&text_ranges[0])  #define text_range_inittext (&text_ranges[1]) +static struct addr_range percpu_range = { +	"__per_cpu_start", "__per_cpu_end", -1ULL, 0 +}; +  static struct sym_entry *table;  static unsigned int table_size, table_cnt;  static int all_symbols = 0; +static int absolute_percpu = 0;  static char symbol_prefix_char = '\0'; +static unsigned long long kernel_start_addr = 0;  int token_profit[0x10000]; @@ -65,7 +71,10 @@ unsigned char best_table_len[256];  static void usage(void)  { -	fprintf(stderr, "Usage: kallsyms [--all-symbols] [--symbol-prefix=<prefix char>] < in.map > out.S\n"); +	fprintf(stderr, "Usage: kallsyms [--all-symbols] " +			"[--symbol-prefix=<prefix char>] " +			"[--page-offset=<CONFIG_PAGE_OFFSET>] " +			"< in.map > out.S\n");  	exit(1);  } @@ -79,19 +88,20 @@ static inline int is_arm_mapping_symbol(const char *str)  	       && (str[2] == '\0' || str[2] == '.');  } -static int read_symbol_tr(const char *sym, unsigned long long addr) +static int check_symbol_range(const char *sym, unsigned long long addr, +			      struct addr_range *ranges, int entries)  {  	size_t i; -	struct text_range *tr; +	struct addr_range *ar; -	for (i = 0; i < ARRAY_SIZE(text_ranges); ++i) { -		tr = &text_ranges[i]; +	for (i = 0; i < entries; ++i) { +		ar = &ranges[i]; -		if (strcmp(sym, tr->stext) == 0) { -			tr->start = addr; +		if (strcmp(sym, ar->start_sym) == 0) { +			ar->start = addr;  			return 0; -		} else if (strcmp(sym, tr->etext) == 0) { -			tr->end = addr; +		} else if (strcmp(sym, ar->end_sym) == 0) { +			ar->end = addr;  			return 0;  		}  	} @@ -111,6 +121,12 @@ static int read_symbol(FILE *in, struct sym_entry *s)  			fprintf(stderr, "Read error or end of file.\n");  		return -1;  	} +	if (strlen(str) > KSYM_NAME_LEN) { +		fprintf(stderr, "Symbol %s too long for kallsyms (%zu vs %d).\n" +				"Please increase KSYM_NAME_LEN both in kernel and kallsyms.c\n", +			str, strlen(str), KSYM_NAME_LEN); +		return -1; +	}  	sym = str;  	/* skip prefix char */ @@ -120,7 +136,8 @@ static int read_symbol(FILE *in, struct sym_entry *s)  	/* Ignore most absolute/undefined (?) symbols. */  	if (strcmp(sym, "_text") == 0)  		_text = s->addr; -	else if (read_symbol_tr(sym, s->addr) == 0) +	else if (check_symbol_range(sym, s->addr, text_ranges, +				    ARRAY_SIZE(text_ranges)) == 0)  		/* nothing to do */;  	else if (toupper(stype) == 'A')  	{ @@ -154,18 +171,22 @@ static int read_symbol(FILE *in, struct sym_entry *s)  	strcpy((char *)s->sym + 1, str);  	s->sym[0] = stype; +	/* Record if we've found __per_cpu_start/end. */ +	check_symbol_range(sym, s->addr, &percpu_range, 1); +  	return 0;  } -static int symbol_valid_tr(struct sym_entry *s) +static int symbol_in_range(struct sym_entry *s, struct addr_range *ranges, +			   int entries)  {  	size_t i; -	struct text_range *tr; +	struct addr_range *ar; -	for (i = 0; i < ARRAY_SIZE(text_ranges); ++i) { -		tr = &text_ranges[i]; +	for (i = 0; i < entries; ++i) { +		ar = &ranges[i]; -		if (s->addr >= tr->start && s->addr <= tr->end) +		if (s->addr >= ar->start && s->addr <= ar->end)  			return 1;  	} @@ -194,6 +215,9 @@ static int symbol_valid(struct sym_entry *s)  	int i;  	int offset = 1; +	if (s->addr < kernel_start_addr) +		return 0; +  	/* skip prefix char */  	if (symbol_prefix_char && *(s->sym + 1) == symbol_prefix_char)  		offset++; @@ -201,7 +225,8 @@ static int symbol_valid(struct sym_entry *s)  	/* if --all-symbols is not specified, then symbols outside the text  	 * and inittext sections are discarded */  	if (!all_symbols) { -		if (symbol_valid_tr(s) == 0) +		if (symbol_in_range(s, text_ranges, +				    ARRAY_SIZE(text_ranges)) == 0)  			return 0;  		/* Corner case.  Discard any symbols with the same value as  		 * _etext _einittext; they can move between pass 1 and 2 when @@ -210,9 +235,11 @@ static int symbol_valid(struct sym_entry *s)  		 * rules.  		 */  		if ((s->addr == text_range_text->end && -				strcmp((char *)s->sym + offset, text_range_text->etext)) || +				strcmp((char *)s->sym + offset, +				       text_range_text->end_sym)) ||  		    (s->addr == text_range_inittext->end && -				strcmp((char *)s->sym + offset, text_range_inittext->etext))) +				strcmp((char *)s->sym + offset, +				       text_range_inittext->end_sym)))  			return 0;  	} @@ -285,6 +312,11 @@ static int expand_symbol(unsigned char *data, int len, char *result)  	return total;  } +static int symbol_absolute(struct sym_entry *s) +{ +	return toupper(s->sym[0]) == 'A'; +} +  static void write_src(void)  {  	unsigned int i, k, off; @@ -312,7 +344,7 @@ static void write_src(void)  	 */  	output_label("kallsyms_addresses");  	for (i = 0; i < table_cnt; i++) { -		if (toupper(table[i].sym[0]) != 'A') { +		if (!symbol_absolute(&table[i])) {  			if (_text <= table[i].addr)  				printf("\tPTR\t_text + %#llx\n",  					table[i].addr - _text); @@ -633,6 +665,15 @@ static void sort_symbols(void)  	qsort(table, table_cnt, sizeof(struct sym_entry), compare_symbols);  } +static void make_percpus_absolute(void) +{ +	unsigned int i; + +	for (i = 0; i < table_cnt; i++) +		if (symbol_in_range(&table[i], &percpu_range, 1)) +			table[i].sym[0] = 'A'; +} +  int main(int argc, char **argv)  {  	if (argc >= 2) { @@ -640,12 +681,17 @@ int main(int argc, char **argv)  		for (i = 1; i < argc; i++) {  			if(strcmp(argv[i], "--all-symbols") == 0)  				all_symbols = 1; +			else if (strcmp(argv[i], "--absolute-percpu") == 0) +				absolute_percpu = 1;  			else if (strncmp(argv[i], "--symbol-prefix=", 16) == 0) {  				char *p = &argv[i][16];  				/* skip quote */  				if ((*p == '"' && *(p+2) == '"') || (*p == '\'' && *(p+2) == '\''))  					p++;  				symbol_prefix_char = *p; +			} else if (strncmp(argv[i], "--page-offset=", 14) == 0) { +				const char *p = &argv[i][14]; +				kernel_start_addr = strtoull(p, NULL, 16);  			} else  				usage();  		} @@ -653,6 +699,8 @@ int main(int argc, char **argv)  		usage();  	read_map(stdin); +	if (absolute_percpu) +		make_percpus_absolute();  	sort_symbols();  	optimize_token_table();  	write_src();  | 
