diff options
Diffstat (limited to 'scripts/kallsyms.c')
-rw-r--r-- | scripts/kallsyms.c | 94 |
1 files changed, 68 insertions, 26 deletions
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 090ffda4adbc..d3d2e5341051 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c | |||
@@ -67,8 +67,9 @@ struct sym_entry { | |||
67 | 67 | ||
68 | static struct sym_entry *table; | 68 | static struct sym_entry *table; |
69 | static int size, cnt; | 69 | static int size, cnt; |
70 | static unsigned long long _stext, _etext, _sinittext, _einittext; | 70 | static unsigned long long _stext, _etext, _sinittext, _einittext, _sextratext, _eextratext; |
71 | static int all_symbols = 0; | 71 | static int all_symbols = 0; |
72 | static char symbol_prefix_char = '\0'; | ||
72 | 73 | ||
73 | struct token { | 74 | struct token { |
74 | unsigned char data[MAX_TOK_SIZE]; | 75 | unsigned char data[MAX_TOK_SIZE]; |
@@ -93,7 +94,7 @@ unsigned char best_table_len[256]; | |||
93 | static void | 94 | static void |
94 | usage(void) | 95 | usage(void) |
95 | { | 96 | { |
96 | fprintf(stderr, "Usage: kallsyms [--all-symbols] < in.map > out.S\n"); | 97 | fprintf(stderr, "Usage: kallsyms [--all-symbols] [--symbol-prefix=<prefix char>] < in.map > out.S\n"); |
97 | exit(1); | 98 | exit(1); |
98 | } | 99 | } |
99 | 100 | ||
@@ -112,6 +113,7 @@ static int | |||
112 | read_symbol(FILE *in, struct sym_entry *s) | 113 | read_symbol(FILE *in, struct sym_entry *s) |
113 | { | 114 | { |
114 | char str[500]; | 115 | char str[500]; |
116 | char *sym; | ||
115 | int rc; | 117 | int rc; |
116 | 118 | ||
117 | rc = fscanf(in, "%llx %c %499s\n", &s->addr, &s->type, str); | 119 | rc = fscanf(in, "%llx %c %499s\n", &s->addr, &s->type, str); |
@@ -123,27 +125,36 @@ read_symbol(FILE *in, struct sym_entry *s) | |||
123 | return -1; | 125 | return -1; |
124 | } | 126 | } |
125 | 127 | ||
128 | sym = str; | ||
129 | /* skip prefix char */ | ||
130 | if (symbol_prefix_char && str[0] == symbol_prefix_char) | ||
131 | sym++; | ||
132 | |||
126 | /* Ignore most absolute/undefined (?) symbols. */ | 133 | /* Ignore most absolute/undefined (?) symbols. */ |
127 | if (strcmp(str, "_stext") == 0) | 134 | if (strcmp(sym, "_stext") == 0) |
128 | _stext = s->addr; | 135 | _stext = s->addr; |
129 | else if (strcmp(str, "_etext") == 0) | 136 | else if (strcmp(sym, "_etext") == 0) |
130 | _etext = s->addr; | 137 | _etext = s->addr; |
131 | else if (strcmp(str, "_sinittext") == 0) | 138 | else if (strcmp(sym, "_sinittext") == 0) |
132 | _sinittext = s->addr; | 139 | _sinittext = s->addr; |
133 | else if (strcmp(str, "_einittext") == 0) | 140 | else if (strcmp(sym, "_einittext") == 0) |
134 | _einittext = s->addr; | 141 | _einittext = s->addr; |
142 | else if (strcmp(sym, "_sextratext") == 0) | ||
143 | _sextratext = s->addr; | ||
144 | else if (strcmp(sym, "_eextratext") == 0) | ||
145 | _eextratext = s->addr; | ||
135 | else if (toupper(s->type) == 'A') | 146 | else if (toupper(s->type) == 'A') |
136 | { | 147 | { |
137 | /* Keep these useful absolute symbols */ | 148 | /* Keep these useful absolute symbols */ |
138 | if (strcmp(str, "__kernel_syscall_via_break") && | 149 | if (strcmp(sym, "__kernel_syscall_via_break") && |
139 | strcmp(str, "__kernel_syscall_via_epc") && | 150 | strcmp(sym, "__kernel_syscall_via_epc") && |
140 | strcmp(str, "__kernel_sigtramp") && | 151 | strcmp(sym, "__kernel_sigtramp") && |
141 | strcmp(str, "__gp")) | 152 | strcmp(sym, "__gp")) |
142 | return -1; | 153 | return -1; |
143 | 154 | ||
144 | } | 155 | } |
145 | else if (toupper(s->type) == 'U' || | 156 | else if (toupper(s->type) == 'U' || |
146 | is_arm_mapping_symbol(str)) | 157 | is_arm_mapping_symbol(sym)) |
147 | return -1; | 158 | return -1; |
148 | 159 | ||
149 | /* include the type field in the symbol name, so that it gets | 160 | /* include the type field in the symbol name, so that it gets |
@@ -177,30 +188,37 @@ symbol_valid(struct sym_entry *s) | |||
177 | "_SDA2_BASE_", /* ppc */ | 188 | "_SDA2_BASE_", /* ppc */ |
178 | NULL }; | 189 | NULL }; |
179 | int i; | 190 | int i; |
191 | int offset = 1; | ||
192 | |||
193 | /* skip prefix char */ | ||
194 | if (symbol_prefix_char && *(s->sym + 1) == symbol_prefix_char) | ||
195 | offset++; | ||
180 | 196 | ||
181 | /* if --all-symbols is not specified, then symbols outside the text | 197 | /* if --all-symbols is not specified, then symbols outside the text |
182 | * and inittext sections are discarded */ | 198 | * and inittext sections are discarded */ |
183 | if (!all_symbols) { | 199 | if (!all_symbols) { |
184 | if ((s->addr < _stext || s->addr > _etext) | 200 | if ((s->addr < _stext || s->addr > _etext) |
185 | && (s->addr < _sinittext || s->addr > _einittext)) | 201 | && (s->addr < _sinittext || s->addr > _einittext) |
202 | && (s->addr < _sextratext || s->addr > _eextratext)) | ||
186 | return 0; | 203 | return 0; |
187 | /* Corner case. Discard any symbols with the same value as | 204 | /* Corner case. Discard any symbols with the same value as |
188 | * _etext or _einittext, they can move between pass 1 and 2 | 205 | * _etext _einittext or _eextratext; they can move between pass |
189 | * when the kallsyms data is added. If these symbols move then | 206 | * 1 and 2 when the kallsyms data are added. If these symbols |
190 | * they may get dropped in pass 2, which breaks the kallsyms | 207 | * move then they may get dropped in pass 2, which breaks the |
191 | * rules. | 208 | * kallsyms rules. |
192 | */ | 209 | */ |
193 | if ((s->addr == _etext && strcmp(s->sym + 1, "_etext")) || | 210 | if ((s->addr == _etext && strcmp(s->sym + offset, "_etext")) || |
194 | (s->addr == _einittext && strcmp(s->sym + 1, "_einittext"))) | 211 | (s->addr == _einittext && strcmp(s->sym + offset, "_einittext")) || |
212 | (s->addr == _eextratext && strcmp(s->sym + offset, "_eextratext"))) | ||
195 | return 0; | 213 | return 0; |
196 | } | 214 | } |
197 | 215 | ||
198 | /* Exclude symbols which vary between passes. */ | 216 | /* Exclude symbols which vary between passes. */ |
199 | if (strstr(s->sym + 1, "_compiled.")) | 217 | if (strstr(s->sym + offset, "_compiled.")) |
200 | return 0; | 218 | return 0; |
201 | 219 | ||
202 | for (i = 0; special_symbols[i]; i++) | 220 | for (i = 0; special_symbols[i]; i++) |
203 | if( strcmp(s->sym + 1, special_symbols[i]) == 0 ) | 221 | if( strcmp(s->sym + offset, special_symbols[i]) == 0 ) |
204 | return 0; | 222 | return 0; |
205 | 223 | ||
206 | return 1; | 224 | return 1; |
@@ -225,9 +243,15 @@ read_map(FILE *in) | |||
225 | 243 | ||
226 | static void output_label(char *label) | 244 | static void output_label(char *label) |
227 | { | 245 | { |
228 | printf(".globl %s\n",label); | 246 | if (symbol_prefix_char) |
247 | printf(".globl %c%s\n", symbol_prefix_char, label); | ||
248 | else | ||
249 | printf(".globl %s\n", label); | ||
229 | printf("\tALGN\n"); | 250 | printf("\tALGN\n"); |
230 | printf("%s:\n",label); | 251 | if (symbol_prefix_char) |
252 | printf("%c%s:\n", symbol_prefix_char, label); | ||
253 | else | ||
254 | printf("%s:\n", label); | ||
231 | } | 255 | } |
232 | 256 | ||
233 | /* uncompress a compressed symbol. When this function is called, the best table | 257 | /* uncompress a compressed symbol. When this function is called, the best table |
@@ -665,6 +689,13 @@ static void optimize_token_table(void) | |||
665 | 689 | ||
666 | insert_real_symbols_in_table(); | 690 | insert_real_symbols_in_table(); |
667 | 691 | ||
692 | /* When valid symbol is not registered, exit to error */ | ||
693 | if (good_head.left == good_head.right && | ||
694 | bad_head.left == bad_head.right) { | ||
695 | fprintf(stderr, "No valid symbol.\n"); | ||
696 | exit(1); | ||
697 | } | ||
698 | |||
668 | optimize_result(); | 699 | optimize_result(); |
669 | } | 700 | } |
670 | 701 | ||
@@ -672,9 +703,21 @@ static void optimize_token_table(void) | |||
672 | int | 703 | int |
673 | main(int argc, char **argv) | 704 | main(int argc, char **argv) |
674 | { | 705 | { |
675 | if (argc == 2 && strcmp(argv[1], "--all-symbols") == 0) | 706 | if (argc >= 2) { |
676 | all_symbols = 1; | 707 | int i; |
677 | else if (argc != 1) | 708 | for (i = 1; i < argc; i++) { |
709 | if(strcmp(argv[i], "--all-symbols") == 0) | ||
710 | all_symbols = 1; | ||
711 | else if (strncmp(argv[i], "--symbol-prefix=", 16) == 0) { | ||
712 | char *p = &argv[i][16]; | ||
713 | /* skip quote */ | ||
714 | if ((*p == '"' && *(p+2) == '"') || (*p == '\'' && *(p+2) == '\'')) | ||
715 | p++; | ||
716 | symbol_prefix_char = *p; | ||
717 | } else | ||
718 | usage(); | ||
719 | } | ||
720 | } else if (argc != 1) | ||
678 | usage(); | 721 | usage(); |
679 | 722 | ||
680 | read_map(stdin); | 723 | read_map(stdin); |
@@ -683,4 +726,3 @@ main(int argc, char **argv) | |||
683 | 726 | ||
684 | return 0; | 727 | return 0; |
685 | } | 728 | } |
686 | |||