aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulo Marques <pmarques@grupopie.com>2005-09-06 18:16:31 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-07 19:57:18 -0400
commitb3dbb4ecd46767b621df3dedd28788da93ee0cac (patch)
treeae0187791a1b1997efadd56461d2e2191af8cf22
parente82894f84dbba130ab46c97748c03647f8204f92 (diff)
[PATCH] kallsyms: change compression algorithm
This patch changes the way the compression algorithm works. The base algorithm is similiar to the previous but we force the compressed token size to 2. Having a fixed size compressed token allows for a lot of optimizations, and that in turn allows this code to run over *all* the symbols faster than it did before over just a subset. Having it work over all the symbols will make it behave better when symbols change positions between passes, and the "inconsistent kallsyms" messages should become less frequent. In my tests the compression ratio was degraded by about 0.5%, but the results will depend greatly on the number of symbols to compress. Signed-off-by: Paulo Marques <pmarques@grupopie.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--scripts/kallsyms.c424
1 files changed, 95 insertions, 329 deletions
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 9be41a9f5aff..1f53d4fc4c1d 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -24,75 +24,37 @@
24 * 24 *
25 */ 25 */
26 26
27#define _GNU_SOURCE
28
27#include <stdio.h> 29#include <stdio.h>
28#include <stdlib.h> 30#include <stdlib.h>
29#include <string.h> 31#include <string.h>
30#include <ctype.h> 32#include <ctype.h>
31 33
32/* maximum token length used. It doesn't pay to increase it a lot, because
33 * very long substrings probably don't repeat themselves too often. */
34#define MAX_TOK_SIZE 11
35#define KSYM_NAME_LEN 127 34#define KSYM_NAME_LEN 127
36 35
37/* we use only a subset of the complete symbol table to gather the token count,
38 * to speed up compression, at the expense of a little compression ratio */
39#define WORKING_SET 1024
40
41/* first find the best token only on the list of tokens that would profit more
42 * than GOOD_BAD_THRESHOLD. Only if this list is empty go to the "bad" list.
43 * Increasing this value will put less tokens on the "good" list, so the search
44 * is faster. However, if the good list runs out of tokens, we must painfully
45 * search the bad list. */
46#define GOOD_BAD_THRESHOLD 10
47
48/* token hash parameters */
49#define HASH_BITS 18
50#define HASH_TABLE_SIZE (1 << HASH_BITS)
51#define HASH_MASK (HASH_TABLE_SIZE - 1)
52#define HASH_BASE_OFFSET 2166136261U
53#define HASH_FOLD(a) ((a)&(HASH_MASK))
54
55/* flags to mark symbols */
56#define SYM_FLAG_VALID 1
57#define SYM_FLAG_SAMPLED 2
58 36
59struct sym_entry { 37struct sym_entry {
60 unsigned long long addr; 38 unsigned long long addr;
61 char type; 39 unsigned int len;
62 unsigned char flags;
63 unsigned char len;
64 unsigned char *sym; 40 unsigned char *sym;
65}; 41};
66 42
67 43
68static struct sym_entry *table; 44static struct sym_entry *table;
69static int size, cnt; 45static unsigned int table_size, table_cnt;
70static unsigned long long _stext, _etext, _sinittext, _einittext, _sextratext, _eextratext; 46static unsigned long long _stext, _etext, _sinittext, _einittext, _sextratext, _eextratext;
71static int all_symbols = 0; 47static int all_symbols = 0;
72static char symbol_prefix_char = '\0'; 48static char symbol_prefix_char = '\0';
73 49
74struct token { 50int token_profit[0x10000];
75 unsigned char data[MAX_TOK_SIZE];
76 unsigned char len;
77 /* profit: the number of bytes that could be saved by inserting this
78 * token into the table */
79 int profit;
80 struct token *next; /* next token on the hash list */
81 struct token *right; /* next token on the good/bad list */
82 struct token *left; /* previous token on the good/bad list */
83 struct token *smaller; /* token that is less one letter than this one */
84 };
85
86struct token bad_head, good_head;
87struct token *hash_table[HASH_TABLE_SIZE];
88 51
89/* the table that holds the result of the compression */ 52/* the table that holds the result of the compression */
90unsigned char best_table[256][MAX_TOK_SIZE+1]; 53unsigned char best_table[256][2];
91unsigned char best_table_len[256]; 54unsigned char best_table_len[256];
92 55
93 56
94static void 57static void usage(void)
95usage(void)
96{ 58{
97 fprintf(stderr, "Usage: kallsyms [--all-symbols] [--symbol-prefix=<prefix char>] < in.map > out.S\n"); 59 fprintf(stderr, "Usage: kallsyms [--all-symbols] [--symbol-prefix=<prefix char>] < in.map > out.S\n");
98 exit(1); 60 exit(1);
@@ -102,21 +64,19 @@ usage(void)
102 * This ignores the intensely annoying "mapping symbols" found 64 * This ignores the intensely annoying "mapping symbols" found
103 * in ARM ELF files: $a, $t and $d. 65 * in ARM ELF files: $a, $t and $d.
104 */ 66 */
105static inline int 67static inline int is_arm_mapping_symbol(const char *str)
106is_arm_mapping_symbol(const char *str)
107{ 68{
108 return str[0] == '$' && strchr("atd", str[1]) 69 return str[0] == '$' && strchr("atd", str[1])
109 && (str[2] == '\0' || str[2] == '.'); 70 && (str[2] == '\0' || str[2] == '.');
110} 71}
111 72
112static int 73static int read_symbol(FILE *in, struct sym_entry *s)
113read_symbol(FILE *in, struct sym_entry *s)
114{ 74{
115 char str[500]; 75 char str[500];
116 char *sym; 76 char *sym, stype;
117 int rc; 77 int rc;
118 78
119 rc = fscanf(in, "%llx %c %499s\n", &s->addr, &s->type, str); 79 rc = fscanf(in, "%llx %c %499s\n", &s->addr, &stype, str);
120 if (rc != 3) { 80 if (rc != 3) {
121 if (rc != EOF) { 81 if (rc != EOF) {
122 /* skip line */ 82 /* skip line */
@@ -143,7 +103,7 @@ read_symbol(FILE *in, struct sym_entry *s)
143 _sextratext = s->addr; 103 _sextratext = s->addr;
144 else if (strcmp(sym, "_eextratext") == 0) 104 else if (strcmp(sym, "_eextratext") == 0)
145 _eextratext = s->addr; 105 _eextratext = s->addr;
146 else if (toupper(s->type) == 'A') 106 else if (toupper(stype) == 'A')
147 { 107 {
148 /* Keep these useful absolute symbols */ 108 /* Keep these useful absolute symbols */
149 if (strcmp(sym, "__kernel_syscall_via_break") && 109 if (strcmp(sym, "__kernel_syscall_via_break") &&
@@ -153,22 +113,21 @@ read_symbol(FILE *in, struct sym_entry *s)
153 return -1; 113 return -1;
154 114
155 } 115 }
156 else if (toupper(s->type) == 'U' || 116 else if (toupper(stype) == 'U' ||
157 is_arm_mapping_symbol(sym)) 117 is_arm_mapping_symbol(sym))
158 return -1; 118 return -1;
159 119
160 /* include the type field in the symbol name, so that it gets 120 /* include the type field in the symbol name, so that it gets
161 * compressed together */ 121 * compressed together */
162 s->len = strlen(str) + 1; 122 s->len = strlen(str) + 1;
163 s->sym = (char *) malloc(s->len + 1); 123 s->sym = malloc(s->len + 1);
164 strcpy(s->sym + 1, str); 124 strcpy((char *)s->sym + 1, str);
165 s->sym[0] = s->type; 125 s->sym[0] = stype;
166 126
167 return 0; 127 return 0;
168} 128}
169 129
170static int 130static int symbol_valid(struct sym_entry *s)
171symbol_valid(struct sym_entry *s)
172{ 131{
173 /* Symbols which vary between passes. Passes 1 and 2 must have 132 /* Symbols which vary between passes. Passes 1 and 2 must have
174 * identical symbol lists. The kallsyms_* symbols below are only added 133 * identical symbol lists. The kallsyms_* symbols below are only added
@@ -214,30 +173,29 @@ symbol_valid(struct sym_entry *s)
214 } 173 }
215 174
216 /* Exclude symbols which vary between passes. */ 175 /* Exclude symbols which vary between passes. */
217 if (strstr(s->sym + offset, "_compiled.")) 176 if (strstr((char *)s->sym + offset, "_compiled."))
218 return 0; 177 return 0;
219 178
220 for (i = 0; special_symbols[i]; i++) 179 for (i = 0; special_symbols[i]; i++)
221 if( strcmp(s->sym + offset, special_symbols[i]) == 0 ) 180 if( strcmp((char *)s->sym + offset, special_symbols[i]) == 0 )
222 return 0; 181 return 0;
223 182
224 return 1; 183 return 1;
225} 184}
226 185
227static void 186static void read_map(FILE *in)
228read_map(FILE *in)
229{ 187{
230 while (!feof(in)) { 188 while (!feof(in)) {
231 if (cnt >= size) { 189 if (table_cnt >= table_size) {