aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruen@suse.de>2008-12-01 17:21:01 -0500
committerSam Ravnborg <sam@ravnborg.org>2008-12-03 16:33:11 -0500
commit64e6c1e12372840e7caf8e25325a9e9c5fd370e6 (patch)
treeaa47aa4e170dd4bb39c99cc7356231e2c61d64d2 /scripts
parenta680eedc6c621c75695c68198533fc3c98f4053b (diff)
genksyms: track symbol checksum changes
Sometimes it is preferable to avoid changes of exported symbol checksums (to avoid breaking externally provided modules). When a checksum change occurs, it can be hard to figure out what caused this change: underlying types may have changed, or additional type information may simply have become available at the point where a symbol is exported. Add a new --reference option to genksyms which allows it to report why checksums change, based on the type information dumps it creates with the --dump-types flag. Genksyms will read in such a dump from a previous run, and report which symbols have changed (and why). The behavior can be controlled for an entire build as follows: If KBUILD_SYMTYPES is set, genksyms uses --dump-types to produce *.symtypes dump files. If any *.symref files exist, those will be used as the reference to check against. If KBUILD_PRESERVE is set, checksum changes will fail the build. Signed-off-by: Andreas Gruenbacher <agruen@suse.de> Cc: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Makefile.build16
-rw-r--r--scripts/genksyms/genksyms.c236
-rw-r--r--scripts/genksyms/genksyms.h6
3 files changed, 239 insertions, 19 deletions
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 468fbc9016c7..d21f0eac2e52 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -153,12 +153,18 @@ $(obj)/%.i: $(src)/%.c FORCE
153 153
154quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@ 154quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
155cmd_cc_symtypes_c = \ 155cmd_cc_symtypes_c = \
156 set -e; \
156 $(CPP) -D__GENKSYMS__ $(c_flags) $< \ 157 $(CPP) -D__GENKSYMS__ $(c_flags) $< \
157 | $(GENKSYMS) -T $@ >/dev/null; \ 158 | $(GENKSYMS) -T $@ \
159 -r $(firstword $(wildcard \
160 $(@:.symtypes=.symref) /dev/null)) \
161 $(if $(KBUILD_PRESERVE),-p) \
162 -a $(ARCH) \
163 >/dev/null; \
158 test -s $@ || rm -f $@ 164 test -s $@ || rm -f $@
159 165
160$(obj)/%.symtypes : $(src)/%.c FORCE 166$(obj)/%.symtypes : $(src)/%.c FORCE
161 $(call if_changed_dep,cc_symtypes_c) 167 $(call cmd,cc_symtypes_c)
162 168
163# C (.c) files 169# C (.c) files
164# The C file is compiled and updated dependency information is generated. 170# The C file is compiled and updated dependency information is generated.
@@ -187,7 +193,11 @@ cmd_modversions = \
187 if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \ 193 if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \
188 $(CPP) -D__GENKSYMS__ $(c_flags) $< \ 194 $(CPP) -D__GENKSYMS__ $(c_flags) $< \
189 | $(GENKSYMS) $(if $(KBUILD_SYMTYPES), \ 195 | $(GENKSYMS) $(if $(KBUILD_SYMTYPES), \
190 -T $(@D)/$(@F:.o=.symtypes)) -a $(ARCH) \ 196 -T $(@:.o=.symtypes)) \
197 -r $(firstword $(wildcard \
198 $(@:.o=.symref) /dev/null)) \
199 $(if $(KBUILD_PRESERVE),-p) \
200 -a $(ARCH) \
191 > $(@D)/.tmp_$(@F:.o=.ver); \ 201 > $(@D)/.tmp_$(@F:.o=.ver); \
192 \ 202 \
193 $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \ 203 $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
index c249274e005a..ddac1746908e 100644
--- a/scripts/genksyms/genksyms.c
+++ b/scripts/genksyms/genksyms.c
@@ -42,7 +42,8 @@ static FILE *debugfile;
42int cur_line = 1; 42int cur_line = 1;
43char *cur_filename; 43char *cur_filename;
44 44
45static int flag_debug, flag_dump_defs, flag_dump_types, flag_warnings; 45static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
46 flag_preserve, flag_warnings;
46static const char *arch = ""; 47static const char *arch = "";
47static const char *mod_prefix = ""; 48static const char *mod_prefix = "";
48 49
@@ -58,6 +59,8 @@ static const char *const symbol_type_name[] = {
58 59
59static int equal_list(struct string_list *a, struct string_list *b); 60static int equal_list(struct string_list *a, struct string_list *b);
60static void print_list(FILE * f, struct string_list *list); 61static void print_list(FILE * f, struct string_list *list);
62static void print_location(void);
63static void print_type_name(enum symbol_type type, const char *name);
61 64
62/*----------------------------------------------------------------------*/ 65/*----------------------------------------------------------------------*/
63 66
@@ -151,27 +154,68 @@ struct symbol *find_symbol(const char *name, enum symbol_type ns)
151 154
152 for (sym = symtab[h]; sym; sym = sym->hash_next) 155 for (sym = symtab[h]; sym; sym = sym->hash_next)
153 if (map_to_ns(sym->type) == map_to_ns(ns) && 156 if (map_to_ns(sym->type) == map_to_ns(ns) &&
154 strcmp(name, sym->name) == 0) 157 strcmp(name, sym->name) == 0 &&
158 sym->is_declared)
155 break; 159 break;
156 160
157 return sym; 161 return sym;
158} 162}
159 163
160struct symbol *add_symbol(const char *name, enum symbol_type type, 164static int is_unknown_symbol(struct symbol *sym)
161 struct string_list *defn, int is_extern) 165{
166 struct string_list *defn;
167
168 return ((sym->type == SYM_STRUCT ||
169 sym->type == SYM_UNION ||
170 sym->type == SYM_ENUM) &&
171 (defn = sym->defn) && defn->tag == SYM_NORMAL &&
172 strcmp(defn->string, "}") == 0 &&
173 (defn = defn->next) && defn->tag == SYM_NORMAL &&
174 strcmp(defn->string, "UNKNOWN") == 0 &&
175 (defn = defn->next) && defn->tag == SYM_NORMAL &&
176 strcmp(defn->string, "{") == 0);
177}
178
179struct symbol *__add_symbol(const char *name, enum symbol_type type,
180 struct string_list *defn, int is_extern,
181 int is_reference)
162{ 182{
163 unsigned long h = crc32(name) % HASH_BUCKETS; 183 unsigned long h = crc32(name) % HASH_BUCKETS;
164 struct symbol *sym; 184 struct symbol *sym;
185 enum symbol_status status = STATUS_UNCHANGED;
165 186
166 for (sym = symtab[h]; sym; sym = sym->hash_next) { 187 for (sym = symtab[h]; sym; sym = sym->hash_next) {
167 if (map_to_ns(sym->type) == map_to_ns(type) 188 if (map_to_ns(sym->type) == map_to_ns(type) &&
168 && strcmp(name, sym->name) == 0) { 189 strcmp(name, sym->name) == 0) {
169 if (!equal_list(sym->defn, defn)) 190 if (is_reference)
191 /* fall through */ ;
192 else if (sym->type == type &&
193 equal_list(sym->defn, defn)) {
194 sym->is_declared = 1;
195 return sym;
196 } else if (!sym->is_declared) {
197 status = is_unknown_symbol(sym) ?
198 STATUS_DEFINED : STATUS_MODIFIED;
199 } else {
170 error_with_pos("redefinition of %s", name); 200 error_with_pos("redefinition of %s", name);
171 return sym; 201 return sym;
202 }
203 break;
172 } 204 }
173 } 205 }
174 206
207 if (sym) {
208 struct symbol **psym;
209
210 for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
211 if (*psym == sym) {
212 *psym = sym->hash_next;
213 break;
214 }
215 }
216 --nsyms;
217 }
218
175 sym = xmalloc(sizeof(*sym)); 219 sym = xmalloc(sizeof(*sym));
176 sym->name = name; 220 sym->name = name;
177 sym->type = type; 221 sym->type = type;
@@ -183,6 +227,9 @@ struct symbol *add_symbol(const char *name, enum symbol_type type,
183 sym->hash_next = symtab[h]; 227 sym->hash_next = symtab[h];
184 symtab[h] = sym; 228 symtab[h] = sym;
185 229
230 sym->is_declared = !is_reference;
231 sym->status = status;
232
186 if (flag_debug) { 233 if (flag_debug) {
187 fprintf(debugfile, "Defn for %s %s == <", 234 fprintf(debugfile, "Defn for %s %s == <",
188 symbol_type_name[type], name); 235 symbol_type_name[type], name);
@@ -196,6 +243,18 @@ struct symbol *add_symbol(const char *name, enum symbol_type type,
196 return sym; 243 return sym;
197} 244}
198 245
246struct symbol *add_symbol(const char *name, enum symbol_type type,
247 struct string_list *defn, int is_extern)
248{
249 return __add_symbol(name, type, defn, is_extern, 0);
250}
251
252struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
253 struct string_list *defn, int is_extern)
254{
255 return __add_symbol(name, type, defn, is_extern, 1);
256}
257
199/*----------------------------------------------------------------------*/