From cb80514d9c517cc1d101ef304529a0e9b76b4468 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 28 Jan 2006 16:57:26 +0100 Subject: kbuild: use warn()/fatal() consistent in modpost modpost.c provides warn() and fatal() - so use them all over the place. Signed-off-by: Sam Ravnborg --- scripts/mod/file2alias.c | 13 ++++++------- scripts/mod/modpost.c | 16 ++++++---------- scripts/mod/modpost.h | 7 ++++++- scripts/mod/sumversion.c | 23 +++++++++-------------- 4 files changed, 27 insertions(+), 32 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index be97caf664bb..1346223f7809 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -153,8 +153,8 @@ static void do_usb_table(void *symval, unsigned long size, const unsigned long id_size = sizeof(struct usb_device_id); if (size % id_size || size < id_size) { - fprintf(stderr, "*** Warning: %s ids %lu bad size " - "(each on %lu)\n", mod->name, size, id_size); + warn("%s ids %lu bad size " + "(each on %lu)\n", mod->name, size, id_size); } /* Leave last one: it's the terminator. */ size -= id_size; @@ -217,9 +217,8 @@ static int do_pci_entry(const char *filename, if ((baseclass_mask != 0 && baseclass_mask != 0xFF) || (subclass_mask != 0 && subclass_mask != 0xFF) || (interface_mask != 0 && interface_mask != 0xFF)) { - fprintf(stderr, - "*** Warning: Can't handle masks in %s:%04X\n", - filename, id->class_mask); + warn("Can't handle masks in %s:%04X\n", + filename, id->class_mask); return 0; } @@ -445,8 +444,8 @@ static void do_table(void *symval, unsigned long size, int (*do_entry)(const char *, void *entry, char *alias) = function; if (size % id_size || size < id_size) { - fprintf(stderr, "*** Warning: %s ids %lu bad size " - "(each on %lu)\n", mod->name, size, id_size); + warn("%s ids %lu bad size " + "(each on %lu)\n", mod->name, size, id_size); } /* Leave last one: it's the terminator. */ size -= id_size; diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index f70ff13d4818..a3c57ec7d54a 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -303,8 +303,7 @@ parse_elf(struct elf_info *info, const char *filename) sechdrs[sechdrs[i].sh_link].sh_offset; } if (!info->symtab_start) { - fprintf(stderr, "modpost: %s no symtab?\n", filename); - abort(); + fatal("%s has no symtab?\n", filename); } /* Fix endianness in symbols */ for (sym = info->symtab_start; sym < info->symtab_stop; sym++) { @@ -316,8 +315,7 @@ parse_elf(struct elf_info *info, const char *filename) return; truncated: - fprintf(stderr, "modpost: %s is truncated.\n", filename); - abort(); + fatal("%s is truncated.\n", filename); } void @@ -337,8 +335,7 @@ handle_modversions(struct module *mod, struct elf_info *info, switch (sym->st_shndx) { case SHN_COMMON: - fprintf(stderr, "*** Warning: \"%s\" [%s] is COMMON symbol\n", - symname, mod->name); + warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name); break; case SHN_ABS: /* CRC'd symbol */ @@ -562,8 +559,8 @@ add_versions(struct buffer *b, struct module *mod) exp = find_symbol(s->name); if (!exp || exp->module == mod) { if (have_vmlinux && !s->weak) - fprintf(stderr, "*** Warning: \"%s\" [%s.ko] " - "undefined!\n", s->name, mod->name); + warn("\"%s\" [%s.ko] undefined!\n", + s->name, mod->name); continue; } s->module = exp->module; @@ -584,8 +581,7 @@ add_versions(struct buffer *b, struct module *mod) continue; } if (!s->crc_valid) { - fprintf(stderr, "*** Warning: \"%s\" [%s.ko] " - "has no CRC!\n", + warn("\"%s\" [%s.ko] has no CRC!\n", s->name, mod->name); continue; } diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 7334d839145d..c0de7b98c24c 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -91,17 +91,22 @@ struct elf_info { unsigned int modinfo_len; }; +/* file2alias.c */ void handle_moddevtable(struct module *mod, struct elf_info *info, Elf_Sym *sym, const char *symname); - void add_moddevtable(struct buffer *buf, struct module *mod); +/* sumversion.c */ void maybe_frob_rcs_version(const char *modfilename, char *version, void *modinfo, unsigned long modinfo_offset); void get_src_version(const char *modname, char sum[], unsigned sumlen); +/* from modpost.c */ void *grab_file(const char *filename, unsigned long *size); char* get_next_line(unsigned long *pos, void *file, unsigned long size); void release_file(void *file, unsigned long size); + +void fatal(const char *fmt, ...); +void warn(const char *fmt, ...); diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c index 43271a1ca01e..5c0754526a26 100644 --- a/scripts/mod/sumversion.c +++ b/scripts/mod/sumversion.c @@ -316,8 +316,7 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md) file = grab_file(cmd, &flen); if (!file) { - fprintf(stderr, "Warning: could not find %s for %s\n", - cmd, objfile); + warn("could not find %s for %s\n", cmd, objfile); goto out; } @@ -355,9 +354,8 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md) /* Check if this file is in same dir as objfile */ if ((strstr(line, dir)+strlen(dir)-1) == strrchr(line, '/')) { if (!parse_file(line, md)) { - fprintf(stderr, - "Warning: could not open %s: %s\n", - line, strerror(errno)); + warn("could not open %s: %s\n", + line, strerror(errno)); goto out_file; } @@ -397,23 +395,20 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen) file = grab_file(filelist, &len); if (!file) { - fprintf(stderr, "Warning: could not find versions for %s\n", - filelist); + warn("could not find versions for %s\n", filelist); return; } sources = strchr(file, '\n'); if (!sources) { - fprintf(stderr, "Warning: malformed versions file for %s\n", - modname); + warn("malformed versions file for %s\n", modname); goto release; } sources++; end = strchr(sources, '\n'); if (!end) { - fprintf(stderr, "Warning: bad ending versions file for %s\n", - modname); + warn("bad ending versions file for %s\n", modname); goto release; } *end = '\0'; @@ -438,19 +433,19 @@ static void write_version(const char *filename, const char *sum, fd = open(filename, O_RDWR); if (fd < 0) { - fprintf(stderr, "Warning: changing sum in %s failed: %s\n", + warn("changing sum in %s failed: %s\n", filename, strerror(errno)); return; } if (lseek(fd, offset, SEEK_SET) == (off_t)-1) { - fprintf(stderr, "Warning: changing sum in %s:%lu failed: %s\n", + warn("changing sum in %s:%lu failed: %s\n", filename, offset, strerror(errno)); goto out; } if (write(fd, sum, strlen(sum)+1) != strlen(sum)+1) { - fprintf(stderr, "Warning: writing sum in %s failed: %s\n", + warn("writing sum in %s failed: %s\n", filename, strerror(errno)); goto out; } -- cgit v1.2.3 From 5c3ead8c72788d36d34c9f1689fb529d1339b405 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 28 Jan 2006 17:19:35 +0100 Subject: kbuild: apply CodingStyle to modpost.c Just some light CodingStyle updates - no functional changes. Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 124 ++++++++++++++++++++++---------------------------- 1 file changed, 54 insertions(+), 70 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index a3c57ec7d54a..4a2f2e38d27f 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -21,8 +21,7 @@ int have_vmlinux = 0; /* Is CONFIG_MODULE_SRCVERSION_ALL set? */ static int all_versions = 0; -void -fatal(const char *fmt, ...) +void fatal(const char *fmt, ...) { va_list arglist; @@ -35,8 +34,7 @@ fatal(const char *fmt, ...) exit(1); } -void -warn(const char *fmt, ...) +void warn(const char *fmt, ...) { va_list arglist; @@ -59,8 +57,7 @@ void *do_nofail(void *ptr, const char *expr) static struct module *modules; -struct module * -find_module(char *modname) +static struct module *find_module(char *modname) { struct module *mod; @@ -70,8 +67,7 @@ find_module(char *modname) return mod; } -struct module * -new_module(char *modname) +static struct module *new_module(char *modname) { struct module *mod; char *p, *s; @@ -122,11 +118,12 @@ static inline unsigned int tdb_hash(const char *name) return (1103515243 * value + 12345); } -/* Allocate a new symbols for use in the hash of exported symbols or - * the list of unresolved symbols per module */ - -struct symbol * -alloc_symbol(const char *name, unsigned int weak, struct symbol *next) +/** + * Allocate a new symbols for use in the hash of exported symbols or + * the list of unresolved symbols per module + **/ +static struct symbol *alloc_symbol(const char *name, unsigned int weak, + struct symbol *next) { struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1)); @@ -138,9 +135,8 @@ alloc_symbol(const char *name, unsigned int weak, struct symbol *next) } /* For the hash of exported symbols */ - -void -new_symbol(const char *name, struct module *module, unsigned int *crc) +static void new_symbol(const char *name, struct module *module, + unsigned int *crc) { unsigned int hash; struct symbol *new; @@ -154,8 +150,7 @@ new_symbol(const char *name, struct module *module, unsigned int *crc) } } -struct symbol * -find_symbol(const char *name) +static struct symbol *find_symbol(const char *name) { struct symbol *s; @@ -170,10 +165,12 @@ find_symbol(const char *name) return NULL; } -/* Add an exported symbol - it may have already been added without a - * CRC, in this case just update the CRC */ -void -add_exported_symbol(const char *name, struct module *module, unsigned int *crc) +/** + * Add an exported symbol - it may have already been added without a + * CRC, in this case just update the CRC + **/ +static void add_exported_symbol(const char *name, struct module *module, + unsigned int *crc) { struct symbol *s = find_symbol(name); @@ -187,8 +184,7 @@ add_exported_symbol(const char *name, struct module *module, unsigned int *crc) } } -void * -grab_file(const char *filename, unsigned long *size) +void *grab_file(const char *filename, unsigned long *size) { struct stat st; void *map; @@ -207,13 +203,12 @@ grab_file(const char *filename, unsigned long *size) return map; } -/* - Return a copy of the next line in a mmap'ed file. - spaces in the beginning of the line is trimmed away. - Return a pointer to a static buffer. -*/ -char* -get_next_line(unsigned long *pos, void *file, unsigned long size) +/** + * Return a copy of the next line in a mmap'ed file. + * spaces in the beginning of the line is trimmed away. + * Return a pointer to a static buffer. + **/ +char* get_next_line(unsigned long *pos, void *file, unsigned long size) { static char line[4096]; int skip = 1; @@ -243,14 +238,12 @@ get_next_line(unsigned long *pos, void *file, unsigned long size) return NULL; } -void -release_file(void *file, unsigned long size) +void release_file(void *file, unsigned long size) { munmap(file, size); } -void -parse_elf(struct elf_info *info, const char *filename) +static void parse_elf(struct elf_info *info, const char *filename) { unsigned int i; Elf_Ehdr *hdr = info->hdr; @@ -318,8 +311,7 @@ parse_elf(struct elf_info *info, const char *filename) fatal("%s is truncated.\n", filename); } -void -parse_elf_finish(struct elf_info *info) +static void parse_elf_finish(struct elf_info *info) { release_file(info->hdr, info->size); } @@ -327,9 +319,8 @@ parse_elf_finish(struct elf_info *info) #define CRC_PFX "__crc_" #define KSYMTAB_PFX "__ksymtab_" -void -handle_modversions(struct module *mod, struct elf_info *info, - Elf_Sym *sym, const char *symname) +static void handle_modversions(struct module *mod, struct elf_info *info, + Elf_Sym *sym, const char *symname) { unsigned int crc; @@ -397,8 +388,7 @@ handle_modversions(struct module *mod, struct elf_info *info, } } -int -is_vmlinux(const char *modname) +static int is_vmlinux(const char *modname) { const char *myname; @@ -410,7 +400,9 @@ is_vmlinux(const char *modname) return strcmp(myname, "vmlinux") == 0; } -/* Parse tag=value strings from .modinfo section */ +/** + * Parse tag=value strings from .modinfo section + **/ static char *next_string(char *string, unsigned long *secsize) { /* Skip non-zero chars */ @@ -443,8 +435,7 @@ static char *get_modinfo(void *modinfo, unsigned long modinfo_len, return NULL; } -void -read_symbols(char *modname) +static void read_symbols(char *modname) { const char *symname; char *version; @@ -496,8 +487,8 @@ read_symbols(char *modname) * following helper, then compare to the file on disk and * only update the later if anything changed */ -void __attribute__((format(printf, 2, 3))) -buf_printf(struct buffer *buf, const char *fmt, ...) +void __attribute__((format(printf, 2, 3))) buf_printf(struct buffer *buf, + const char *fmt, ...) { char tmp[SZ]; int len; @@ -514,8 +505,7 @@ buf_printf(struct buffer *buf, const char *fmt, ...) va_end(ap); } -void -buf_write(struct buffer *buf, const char *s, int len) +void buf_write(struct buffer *buf, const char *s, int len) { if (buf->size - buf->pos < len) { buf->size += len; @@ -525,10 +515,10 @@ buf_write(struct buffer *buf, const char *s, int len) buf->pos += len; } -/* Header for the generated file */ - -void -add_header(struct buffer *b, struct module *mod) +/** + * Header for the generated file + **/ +static void add_header(struct buffer *b, struct module *mod) { buf_printf(b, "#include \n"); buf_printf(b, "#include \n"); @@ -548,10 +538,10 @@ add_header(struct buffer *b, struct module *mod) buf_printf(b, "};\n"); } -/* Record CRCs for unresolved symbols */ - -void -add_versions(struct buffer *b, struct module *mod) +/** + * Record CRCs for unresolved symbols + **/ +static void add_versions(struct buffer *b, struct module *mod) { struct symbol *s, *exp; @@ -591,8 +581,8 @@ add_versions(struct buffer *b, struct module *mod) buf_printf(b, "};\n"); } -void -add_depends(struct buffer *b, struct module *mod, struct module *modules) +static void add_depends(struct buffer *b, struct module *mod, + struct module *modules) { struct symbol *s; struct module *m; @@ -622,8 +612,7 @@ add_depends(struct buffer *b, struct module *mod, struct module *modules) buf_printf(b, "\";\n"); } -void -add_srcversion(struct buffer *b, struct module *mod) +static void add_srcversion(struct buffer *b, struct module *mod) { if (mod->srcversion[0]) { buf_printf(b, "\n"); @@ -632,8 +621,7 @@ add_srcversion(struct buffer *b, struct module *mod) } } -void -write_if_changed(struct buffer *b, const char *fname) +static void write_if_changed(struct buffer *b, const char *fname) { char *tmp; FILE *file; @@ -677,8 +665,7 @@ write_if_changed(struct buffer *b, const char *fname) fclose(file); } -void -read_dump(const char *fname) +static void read_dump(const char *fname) { unsigned long size, pos = 0; void *file = grab_file(fname, &size); @@ -719,8 +706,7 @@ fail: fatal("parse error in symbol dump file\n"); } -void -write_dump(const char *fname) +static void write_dump(const char *fname) { struct buffer buf = { }; struct symbol *symbol; @@ -744,8 +730,7 @@ write_dump(const char *fname) write_if_changed(&buf, fname); } -int -main(int argc, char **argv) +int main(int argc, char **argv) { struct module *mod; struct buffer buf = { }; @@ -800,4 +785,3 @@ main(int argc, char **argv) return 0; } - -- cgit v1.2.3 From 040fcc819a2e7783a570f4bdcdd1f2a7f5f06837 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 28 Jan 2006 22:15:55 +0100 Subject: kbuild: improved modversioning support for external modules With following patch a second option is enabled to obtain symbol information from a second external module when a external module is build. The recommended approach is to use a common kbuild file but that may be impractical in certain cases. With this patch one can copy over a Module.symvers from one external module to make symbols (and symbol versions) available for another external module. Updated documentation in Documentation/kbuild/modules.txt Signed-off-by: Sam Ravnborg --- Documentation/kbuild/modules.txt | 87 ++++++++++++++++++++++++--- scripts/Makefile.modpost | 7 ++- scripts/mod/modpost.c | 123 +++++++++++++++++++++++---------------- 3 files changed, 158 insertions(+), 59 deletions(-) (limited to 'scripts/mod') diff --git a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt index 87d858df4e34..fcccf2432f98 100644 --- a/Documentation/kbuild/modules.txt +++ b/Documentation/kbuild/modules.txt @@ -23,7 +23,10 @@ In this document you will find information about: === 6. Module installation --- 6.1 INSTALL_MOD_PATH --- 6.2 INSTALL_MOD_DIR - === 7. Module versioning + === 7. Module versioning & Module.symvers + --- 7.1 Symbols fron the kernel (vmlinux + modules) + --- 7.2 Symbols and external modules + --- 7.3 Symbols from another external module === 8. Tips & Tricks --- 8.1 Testing for CONFIG_FOO_BAR @@ -89,7 +92,8 @@ when building an external module. make -C $KDIR M=$PWD modules_install Install the external module(s). Installation default is in /lib/modules//extra, - but may be prefixed with INSTALL_MOD_PATH - see separate chapter. + but may be prefixed with INSTALL_MOD_PATH - see separate + chapter. make -C $KDIR M=$PWD clean Remove all generated files for the module - the kernel @@ -433,7 +437,7 @@ External modules are installed in the directory: => Install dir: /lib/modules/$(KERNELRELEASE)/gandalf -=== 7. Module versioning +=== 7. Module versioning & Module.symvers Module versioning is enabled by the CONFIG_MODVERSIONS tag. @@ -443,11 +447,80 @@ when a module is loaded/used then the CRC values contained in the kernel are compared with similar values in the module. If they are not equal then the kernel refuses to load the module. -During a kernel build a file named Module.symvers will be generated. This -file includes the symbol version of all symbols within the kernel. If the -Module.symvers file is saved from the last full kernel compile one does not -have to do a full kernel compile to build a module version's compatible module. +Module.symvers contains a list of all exported symbols from a kernel build. +--- 7.1 Symbols fron the kernel (vmlinux + modules) + + During a kernel build a file named Module.symvers will be generated. + Module.symvers contains all exported symbols from the kernel and + compiled modules. For each symbols the corresponding CRC value + is stored too. + + The syntax of the Module.symvers file is: + + Sample: + 0x2d036834 scsi_remove_host drivers/scsi/scsi_mod + + For a kernel build without CONFIG_MODVERSIONING enabled the crc + would read: 0x00000000 + + Module.symvers serve two purposes. + 1) It list all exported symbols both from vmlinux and all modules + 2) It list CRC if CONFIG_MODVERSION is enabled + +--- 7.2 Symbols and external modules + + When building an external module the build system needs access to + the symbols from the kernel to check if all external symbols are + defined. This is done in the MODPOST step and to obtain all + symbols modpost reads Module.symvers from the kernel. + If a Module.symvers file is present in the directory where + the external module is being build this file will be read too. + During the MODPOST step a new Module.symvers file will be written + containing all exported symbols that was not defined in the kernel. + +--- 7.3 Symbols from another external module + + Sometimes one external module uses exported symbols from another + external module. Kbuild needs to have full knowledge on all symbols + to avoid spitting out warnings about undefined symbols. + Two solutions exist to let kbuild know all symbols of more than + one external module. + The method with a top-level kbuild file is recommended but may be + impractical in certain situations. + + Use a top-level Kbuild file + If you have two modules: 'foo', 'bar' and 'foo' needs symbols + from 'bar' then one can use a common top-level kbuild file so + both modules are compiled in same build. + + Consider following directory layout: + ./foo/ <= contains the foo module + ./bar/ <= contains the bar module + The top-level Kbuild file would then look like: + + #./Kbuild: (this file may also be named Makefile) + obj-y := foo/ bar/ + + Executing: + make -C $KDIR M=`pwd` + + will then do the expected and compile both modules with full + knowledge on symbols from both modules. + + Use an extra Module.symvers file + When an external module is build a Module.symvers file is + generated containing all exported symbols which are not + defined in the kernel. + To get access to symbols from module 'bar' one can copy the + Module.symvers file from the compilation of the 'bar' module + to the directory where the 'foo' module is build. + During the module build kbuild will read the Module.symvers + file in the directory of the external module and when the + build is finished a new Module.symvers file is created + containing the sum of all symbols defined and not part of the + kernel. + === 8. Tips & Tricks --- 8.1 Testing for CONFIG_FOO_BAR diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index bf96a61d4b86..563e3c5bd8dd 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -39,7 +39,8 @@ include .config include scripts/Kbuild.include include scripts/Makefile.lib -symverfile := $(objtree)/Module.symvers +kernelsymfile := $(objtree)/Module.symvers +modulesymfile := $(KBUILD_EXTMOD)/Modules.symvers # Step 1), find all modules listed in $(MODVERDIR)/ __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) @@ -54,7 +55,9 @@ quiet_cmd_modpost = MODPOST cmd_modpost = scripts/mod/modpost \ $(if $(CONFIG_MODVERSIONS),-m) \ $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \ - $(if $(KBUILD_EXTMOD),-i,-o) $(symverfile) \ + $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \ + $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \ + $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ $(filter-out FORCE,$^) .PHONY: __modpost diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 4a2f2e38d27f..976adf152db3 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -20,6 +20,8 @@ int modversions = 0; int have_vmlinux = 0; /* Is CONFIG_MODULE_SRCVERSION_ALL set? */ static int all_versions = 0; +/* If we are modposting external module set to 1 */ +static int external_module = 0; void fatal(const char *fmt, ...) { @@ -45,6 +47,18 @@ void warn(const char *fmt, ...) va_end(arglist); } +static int is_vmlinux(const char *modname) +{ + const char *myname; + + if ((myname = strrchr(modname, '/'))) + myname++; + else + myname = modname; + + return strcmp(myname, "vmlinux") == 0; +} + void *do_nofail(void *ptr, const char *expr) { if (!ptr) { @@ -100,6 +114,9 @@ struct symbol { unsigned int crc; int crc_valid; unsigned int weak:1; + unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ + unsigned int kernel:1; /* 1 if symbol is from kernel + * (only for external modules) **/ char name[0]; }; @@ -135,8 +152,7 @@ static struct symbol *alloc_symbol(const char *name, unsigned int weak, } /* For the hash of exported symbols */ -static void new_symbol(const char *name, struct module *module, - unsigned int *crc) +static struct symbol *new_symbol(const char *name, struct module *module) { unsigned int hash; struct symbol *new; @@ -144,10 +160,7 @@ static void new_symbol(const char *name, struct module *module, hash = tdb_hash(name) % SYMBOL_HASH_SIZE; new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); new->module = module; - if (crc) { - new->crc = *crc; - new->crc_valid = 1; - } + return new; } static struct symbol *find_symbol(const char *name) @@ -169,19 +182,27 @@ static struct symbol *find_symbol(const char *name) * Add an exported symbol - it may have already been added without a * CRC, in this case just update the CRC **/ -static void add_exported_symbol(const char *name, struct module *module, - unsigned int *crc) +static struct symbol *sym_add_exported(const char *name, struct module *mod) { struct symbol *s = find_symbol(name); - if (!s) { - new_symbol(name, module, crc); - return; - } - if (crc) { - s->crc = *crc; - s->crc_valid = 1; - } + if (!s) + s = new_symbol(name, mod); + + s->vmlinux = is_vmlinux(mod->name); + s->kernel = 0; + return s; +} + +static void sym_update_crc(const char *name, struct module *mod, + unsigned int crc) +{ + struct symbol *s = find_symbol(name); + + if (!s) + s = new_symbol(name, mod); + s->crc = crc; + s->crc_valid = 1; } void *grab_file(const char *filename, unsigned long *size) @@ -332,8 +353,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info, /* CRC'd symbol */ if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { crc = (unsigned int) sym->st_value; - add_exported_symbol(symname + strlen(CRC_PFX), - mod, &crc); + sym_update_crc(symname + strlen(CRC_PFX), mod, crc); } break; case SHN_UNDEF: @@ -377,8 +397,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info, default: /* All exported symbols */ if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { - add_exported_symbol(symname + strlen(KSYMTAB_PFX), - mod, NULL); + sym_add_exported(symname + strlen(KSYMTAB_PFX), mod); } if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0) mod->has_init = 1; @@ -388,18 +407,6 @@ static void handle_modversions(struct module *mod, struct elf_info *info, } } -static int is_vmlinux(const char *modname) -{ - const char *myname; - - if ((myname = strrchr(modname, '/'))) - myname++; - else - myname = modname; - - return strcmp(myname, "vmlinux") == 0; -} - /** * Parse tag=value strings from .modinfo section **/ @@ -450,9 +457,7 @@ static void read_symbols(char *modname) /* When there's no vmlinux, don't print warnings about * unresolved symbols (since there'll be too many ;) */ if (is_vmlinux(modname)) { - unsigned int fake_crc = 0; have_vmlinux = 1; - add_exported_symbol("struct_module", mod, &fake_crc); mod->skip = 1; } @@ -665,7 +670,7 @@ static void write_if_changed(struct buffer *b, const char *fname) fclose(file); } -static void read_dump(const char *fname) +static void read_dump(const char *fname, unsigned int kernel) { unsigned long size, pos = 0; void *file = grab_file(fname, &size); @@ -679,6 +684,7 @@ static void read_dump(const char *fname) char *symname, *modname, *d; unsigned int crc; struct module *mod; + struct symbol *s; if (!(symname = strchr(line, '\t'))) goto fail; @@ -699,13 +705,28 @@ static void read_dump(const char *fname) mod = new_module(NOFAIL(strdup(modname))); mod->skip = 1; } - add_exported_symbol(symname, mod, &crc); + s = sym_add_exported(symname, mod); + s->kernel = kernel; + sym_update_crc(symname, mod, crc); } return; fail: fatal("parse error in symbol dump file\n"); } +/* For normal builds always dump all symbols. + * For external modules only dump symbols + * that are not read from kernel Module.symvers. + **/ +static int dump_sym(struct symbol *sym) +{ + if (!external_module) + return 1; + if (sym->vmlinux || sym->kernel) + return 0; + return 1; +} + static void write_dump(const char *fname) { struct buffer buf = { }; @@ -715,15 +736,10 @@ static void write_dump(const char *fname) for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { symbol = symbolhash[n]; while (symbol) { - symbol = symbol->next; - } - } - - for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { - symbol = symbolhash[n]; - while (symbol) { - buf_printf(&buf, "0x%08x\t%s\t%s\n", symbol->crc, - symbol->name, symbol->module->name); + if (dump_sym(symbol)) + buf_printf(&buf, "0x%08x\t%s\t%s\n", + symbol->crc, symbol->name, + symbol->module->name); symbol = symbol->next; } } @@ -735,13 +751,18 @@ int main(int argc, char **argv) struct module *mod; struct buffer buf = { }; char fname[SZ]; - char *dump_read = NULL, *dump_write = NULL; + char *kernel_read = NULL, *module_read = NULL; + char *dump_write = NULL; int opt; - while ((opt = getopt(argc, argv, "i:mo:a")) != -1) { + while ((opt = getopt(argc, argv, "i:I:mo:a")) != -1) { switch(opt) { case 'i': - dump_read = optarg; + kernel_read = optarg; + break; + case 'I': + module_read = optarg; + external_module = 1; break; case 'm': modversions = 1; @@ -757,8 +778,10 @@ int main(int argc, char **argv) } } - if (dump_read) - read_dump(dump_read); + if (kernel_read) + read_dump(kernel_read, 1); + if (module_read) + read_dump(module_read, 0); while (optind < argc) { read_symbols(argv[optind++]); -- cgit v1.2.3 From 8e70c45887a6bbe40393342ea5b426b0dd836dff Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 28 Jan 2006 22:22:33 +0100 Subject: kbuild: warn about duplicate exported symbols In modpost introduce a check for symbols exported twice. This check caught only one victim (inet_bind_bucket_create) for which a patch is already sent to netdev. Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 976adf152db3..d901095ea8b7 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -117,6 +117,7 @@ struct symbol { unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ unsigned int kernel:1; /* 1 if symbol is from kernel * (only for external modules) **/ + unsigned int preloaded:1; /* 1 if symbol from Module.symvers */ char name[0]; }; @@ -186,9 +187,17 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod) { struct symbol *s = find_symbol(name); - if (!s) + if (!s) { s = new_symbol(name, mod); - + } else { + if (!s->preloaded) { + warn("%s: duplicate symbol '%s' previous definition " + "was in %s%s\n", mod->name, name, + s->module->name, + is_vmlinux(s->module->name) ?"":".ko"); + } + } + s->preloaded = 0; s->vmlinux = is_vmlinux(mod->name); s->kernel = 0; return s; @@ -706,7 +715,8 @@ static void read_dump(const char *fname, unsigned int kernel) mod->skip = 1; } s = sym_add_exported(symname, mod); - s->kernel = kernel; + s->kernel = kernel; + s->preloaded = 1; sym_update_crc(symname, mod, crc); } return; -- cgit v1.2.3 From b39927cf4cc5a9123d2b157ffd396884cb8156eb Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Fri, 17 Feb 2006 22:42:02 +0100 Subject: kbuild: check for section mismatch during modpost stage Section mismatch is identified as references to .init* sections from non .init sections. And likewise references to .exit.* sections outside .exit sections. .init.* sections are discarded after a module is initialized and references to .init.* sections are oops candidates. .exit.* sections are discarded when a module is built-in and thus references to .exit are also oops candidates. The checks were possible to do using 'make buildcheck' which called the two perl scripts: reference_discarded.pl and reference_init.pl. This patch just moves the same functionality inside modpost and the scripts are then obsoleted. They will though be kept for a while so users can do double checks - but note that some .o files are skipped by the perl scripts so result is not 1:1. All credit for the concept goes to Keith Owens who implemented the original perl scrips - this patch just moves it to modpost. Compared to the perl script the implmentation in modpost will be run for each kernel build - thus catching the error much sooner, but the downside is that the individual .o file are not always identified. Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 258 ++++++++++++++++++++++++++++++++++++++++++++++++++ scripts/mod/modpost.h | 10 ++ 2 files changed, 268 insertions(+) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index d901095ea8b7..a7360c379cba 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -451,6 +451,262 @@ static char *get_modinfo(void *modinfo, unsigned long modinfo_len, return NULL; } +/* + * Find symbols before or equal addr and after addr - in the section sec + **/ +static void find_symbols_between(struct elf_info *elf, Elf_Addr addr, + const char *sec, + Elf_Sym **before, Elf_Sym **after) +{ + Elf_Sym *sym; + Elf_Ehdr *hdr = elf->hdr; + Elf_Addr beforediff = ~0; + Elf_Addr afterdiff = ~0; + const char *secstrings = (void *)hdr + + elf->sechdrs[hdr->e_shstrndx].sh_offset; + + *before = NULL; + *after = NULL; + + for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { + const char *symsec; + + if (sym->st_shndx >= SHN_LORESERVE) + continue; + symsec = secstrings + elf->sechdrs[sym->st_shndx].sh_name; + if (strcmp(symsec, sec) != 0) + continue; + if (sym->st_value <= addr) { + if ((addr - sym->st_value) < beforediff) { + beforediff = addr - sym->st_value; + *before = sym; + } + } + else + { + if ((sym->st_value - addr) < afterdiff) { + afterdiff = sym->st_value - addr; + *after = sym; + } + } + } +} + +/** + * Print a warning about a section mismatch. + * Try to find symbols near it so user can find it. + **/ +static void warn_sec_mismatch(const char *modname, const char *fromsec, + struct elf_info *elf, Elf_Sym *sym, Elf_Rela r) +{ + Elf_Sym *before; + Elf_Sym *after; + Elf_Ehdr *hdr = elf->hdr; + Elf_Shdr *sechdrs = elf->sechdrs; + const char *secstrings = (void *)hdr + + sechdrs[hdr->e_shstrndx].sh_offset; + const char *secname = secstrings + sechdrs[sym->st_shndx].sh_name; + + find_symbols_between(elf, r.r_offset, fromsec, &before, &after); + + if (before && after) { + warn("%s - Section mismatch: reference to %s from %s " + "between '%s' (at offset 0x%lx) and '%s'\n", + modname, secname, fromsec, + elf->strtab + before->st_name, + (long)(r.r_offset - before->st_value), + elf->strtab + after->st_name); + } else if (before) { + warn("%s - Section mismatch: reference to %s from %s " + "after '%s' (at offset 0x%lx)\n", + modname, secname, fromsec, + elf->strtab + before->st_name, + (long)(r.r_offset - before->st_value)); + } else if (after) { + warn("%s - Section mismatch: reference to %s from %s " + "before '%s' (at offset -0x%lx)\n", + modname, secname, fromsec, + elf->strtab + before->st_name, + (long)(before->st_value - r.r_offset)); + } else { + warn("%s - Section mismatch: reference to %s from %s " + "(offset 0x%lx)\n", + modname, secname, fromsec, (long)r.r_offset); + } +} + +/** + * A module includes a number of sections that are discarded + * either when loaded or when used as built-in. + * For loaded modules all functions marked __init and all data + * marked __initdata will be discarded when the module has been intialized. + * Likewise for modules used built-in the sections marked __exit + * are discarded because __exit marked function are supposed to be called + * only when a moduel is unloaded which never happes for built-in modules. + * The check_sec_ref() function traverses all relocation records + * to find all references to a section that reference a section that will + * be discarded and warns about it. + **/ +static void check_sec_ref(struct module *mod, const char *modname, + struct elf_info *elf, + int section(const char*), + int section_ref_ok(const char *)) +{ + int i; + Elf_Sym *sym; + Elf_Ehdr *hdr = elf->hdr; + Elf_Shdr *sechdrs = elf->sechdrs; + const char *secstrings = (void *)hdr + + sechdrs[hdr->e_shstrndx].sh_offset; + + /* Walk through all sections */ + for (i = 0; i < hdr->e_shnum; i++) { + const char *name = secstrings + sechdrs[i].sh_name + + strlen(".rela"); + /* We want to process only relocation sections and not .init */ + if (section_ref_ok(name) || (sechdrs[i].sh_type != SHT_RELA)) + continue; + Elf_Rela *rela; + Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset; + Elf_Rela *stop = (void*)start + sechdrs[i].sh_size; + + for (rela = start; rela < stop; rela++) { + Elf_Rela r; + const char *secname; + r.r_offset = TO_NATIVE(rela->r_offset); + r.r_info = TO_NATIVE(rela->r_info); + sym = elf->symtab_start + ELF_R_SYM(r.r_info); + secname = secstrings + sechdrs[sym->st_shndx].sh_name; + /* Skip special sections */ + if (sym->st_shndx >= SHN_LORESERVE) + continue; + + if (section(secname)) + warn_sec_mismatch(modname, name, elf, sym, r); + } + } +} + +/** + * Functions used only during module init is marked __init and is stored in + * a .init.text section. Likewise data is marked __initdata and stored in + * a .init.data section. + * If this section is one of these sections return 1 + * See include/linux/init.h for the details + **/ +static int init_section(const char *name) +{ + if (strcmp(name, ".init") == 0) + return 1; + if (strncmp(name, ".init.", strlen(".init.")) == 0) + return 1; + return 0; +} + +/** + * Identify sections from which references to a .init section is OK. + * + * Unfortunately references to read only data that referenced .init + * sections had to be excluded. Almost all of these are false + * positives, they are created by gcc. The downside of excluding rodata + * is that there really are some user references from rodata to + * init code, e.g. drivers/video/vgacon.c: + * + * const struct consw vga_con = { + * con_startup: vgacon_startup, + * + * where vgacon_startup is __init. If you want to wade through the false + * positives, take out the check for rodata. + **/ +static int init_section_ref_ok(const char *name) +{ + const char **s; + /* Absolute section names */ + const char *namelist1[] = { + ".init", + ".stab", + ".rodata", + ".text.lock", + ".pci_fixup_header", + ".pci_fixup_final", + ".pdr", + "__param", + NULL + }; + /* Start of section names */ + const char *namelist2[] = { + ".init.", + ".altinstructions", + ".eh_frame", + ".debug", + NULL + }; + + for (s = namelist1; *s; s++) + if (strcmp(*s, name) == 0) + return 1; + for (s = namelist2; *s; s++) + if (strncmp(*s, name, strlen(*s)) == 0) + return 1; + return 0; +} + +/* + * Functions used only during module exit is marked __exit and is stored in + * a .exit.text section. Likewise data is marked __exitdata and stored in + * a .exit.data section. + * If this section is one of these sections return 1 + * See include/linux/init.h for the details + **/ +static int exit_section(const char *name) +{ + if (strcmp(name, ".exit.text") == 0) + return 1; + if (strcmp(name, ".exit.data") == 0) + return 1; + return 0; + +} + +/* + * Identify sections from which references to a .exit section is OK. + * + * [OPD] Keith Ownes commented: + * For our future {in}sanity, add a comment that this is the ppc .opd + * section, not the ia64 .opd section. + * ia64 .opd should not point to discarded sections. + **/ +static int exit_section_ref_ok(const char *name) +{ + const char **s; + /* Absolute section names */ + const char *namelist1[] = { + ".exit.text", + ".exit.data", + ".init.text", + ".opd", /* See comment [OPD] */ + ".altinstructions", + ".pdr", + ".exitcall.exit", + ".eh_frame", + ".stab", + NULL + }; + /* Start of section names */ + const char *namelist2[] = { + ".debug", + NULL + }; + + for (s = namelist1; *s; s++) + if (strcmp(*s, name) == 0) + return 1; + for (s = namelist2; *s; s++) + if (strncmp(*s, name, strlen(*s)) == 0) + return 1; + return 0; +} + static void read_symbols(char *modname) { const char *symname; @@ -476,6 +732,8 @@ static void read_symbols(char *modname) handle_modversions(mod, &info, sym, symname); handle_moddevtable(mod, &info, sym, symname); } + check_sec_ref(mod, modname, &info, init_section, init_section_ref_ok); + check_sec_ref(mod, modname, &info, exit_section, exit_section_ref_ok); version = get_modinfo(info.modinfo, info.modinfo_len, "version"); if (version) diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index c0de7b98c24c..3b5319dd937f 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -16,17 +16,27 @@ #define Elf_Ehdr Elf32_Ehdr #define Elf_Shdr Elf32_Shdr #define Elf_Sym Elf32_Sym +#define Elf_Addr Elf32_Addr +#define Elf_Section Elf32_Section #define ELF_ST_BIND ELF32_ST_BIND #define ELF_ST_TYPE ELF32_ST_TYPE +#define Elf_Rela Elf32_Rela +#define ELF_R_SYM ELF32_R_SYM +#define ELF_R_TYPE ELF32_R_TYPE #else #define Elf_Ehdr Elf64_Ehdr #define Elf_Shdr Elf64_Shdr #define Elf_Sym Elf64_Sym +#define Elf_Addr Elf64_Addr +#define Elf_Section Elf64_Section #define ELF_ST_BIND ELF64_ST_BIND #define ELF_ST_TYPE ELF64_ST_TYPE +#define Elf_Rela Elf64_Rela +#define ELF_R_SYM ELF64_R_SYM +#define ELF_R_TYPE ELF64_R_TYPE #endif #if KERNEL_ELFDATA != HOST_ELFDATA -- cgit v1.2.3 From 41370d3b5ec6401c5cf0df82297ed989c03a64bd Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 19 Feb 2006 00:49:37 +0100 Subject: kbuild: do not segfault in modpost if MODVERDIR is not defined A combination of calling modpost with option -a and MODVERDIR undefined caused segmentation fault. So provide a default value and accept the error messages it generates instead. Signed-off-by: Sam Ravnborg --- scripts/mod/sumversion.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c index 5c0754526a26..8a2875689e4d 100644 --- a/scripts/mod/sumversion.c +++ b/scripts/mod/sumversion.c @@ -381,8 +381,11 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen) struct md4_ctx md; char *sources, *end, *fname; const char *basename; - char filelist[strlen(getenv("MODVERDIR")) + strlen("/") + - strlen(modname) - strlen(".o") + strlen(".mod") + 1 ]; + char filelist[PATH_MAX + 1]; + char *modverdir = getenv("MODVERDIR"); + + if (!modverdir) + modverdir = "."; /* Source files for module are in .tmp_versions/modname.mod, after the first line. */ @@ -390,7 +393,7 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen) basename = strrchr(modname, '/') + 1; else basename = modname; - sprintf(filelist, "%s/%.*s.mod", getenv("MODVERDIR"), + sprintf(filelist, "%s/%.*s.mod", modverdir, (int) strlen(basename) - 2, basename); file = grab_file(filelist, &len); -- cgit v1.2.3 From 8ea80ca4f583e377c902811d42626ccfce16913f Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 19 Feb 2006 09:56:18 +0100 Subject: kbuild: fix segfault in modpost Do not try to look up section name until we know it is not a special section. Otherwise we will address outside legal space and segfault. Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index a7360c379cba..eeaf57476820 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -576,11 +576,11 @@ static void check_sec_ref(struct module *mod, const char *modname, r.r_offset = TO_NATIVE(rela->r_offset); r.r_info = TO_NATIVE(rela->r_info); sym = elf->symtab_start + ELF_R_SYM(r.r_info); - secname = secstrings + sechdrs[sym->st_shndx].sh_name; /* Skip special sections */ if (sym->st_shndx >= SHN_LORESERVE) continue; + secname = secstrings + sechdrs[sym->st_shndx].sh_name; if (section(secname)) warn_sec_mismatch(modname, name, elf, sym, r); } -- cgit v1.2.3 From 93684d3b8062d1cebdeaed398ec6d1f354cb41a9 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 19 Feb 2006 11:53:35 +0100 Subject: kbuild: include symbol names in section mismatch warnings Try to look up the symbol that is referenced. Include the symbol name in the warning message. Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 64 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 17 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index eeaf57476820..844f84b0818a 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -451,6 +451,29 @@ static char *get_modinfo(void *modinfo, unsigned long modinfo_len, return NULL; } +/** + * Find symbol based on relocation record info. + * In some cases the symbol supplied is a valid symbol so + * return refsym. If st_name != 0 we assume this is a valid symbol. + * In other cases the symbol needs to be looked up in the symbol table + * based on section and address. + * **/ +static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr, + Elf_Sym *relsym) +{ + Elf_Sym *sym; + + if (relsym->st_name != 0) + return relsym; + for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { + if (sym->st_shndx != relsym->st_shndx) + continue; + if (sym->st_value == addr) + return sym; + } + return NULL; +} + /* * Find symbols before or equal addr and after addr - in the section sec **/ @@ -499,8 +522,9 @@ static void find_symbols_between(struct elf_info *elf, Elf_Addr addr, static void warn_sec_mismatch(const char *modname, const char *fromsec, struct elf_info *elf, Elf_Sym *sym, Elf_Rela r) { - Elf_Sym *before; - Elf_Sym *after; + const char *refsymname = ""; + Elf_Sym *before, *after; + Elf_Sym *refsym; Elf_Ehdr *hdr = elf->hdr; Elf_Shdr *sechdrs = elf->sechdrs; const char *secstrings = (void *)hdr + @@ -509,29 +533,34 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, find_symbols_between(elf, r.r_offset, fromsec, &before, &after); + refsym = find_elf_symbol(elf, r.r_addend, sym); + if (refsym && strlen(elf->strtab + refsym->st_name)) + refsymname = elf->strtab + refsym->st_name; + if (before && after) { - warn("%s - Section mismatch: reference to %s from %s " - "between '%s' (at offset 0x%lx) and '%s'\n", - modname, secname, fromsec, + warn("%s - Section mismatch: reference to %s:%s from %s " + "between '%s' (at offset 0x%llx) and '%s'\n", + modname, secname, refsymname, fromsec, elf->strtab + before->st_name, - (long)(r.r_offset - before->st_value), + (long long)r.r_offset, elf->strtab + after->st_name); } else if (before) { - warn("%s - Section mismatch: reference to %s from %s " - "after '%s' (at offset 0x%lx)\n", - modname, secname, fromsec, + warn("%s - Section mismatch: reference to %s:%s from %s " + "after '%s' (at offset 0x%llx)\n", + modname, secname, refsymname, fromsec, elf->strtab + before->st_name, - (long)(r.r_offset - before->st_value)); + (long long)r.r_offset); } else if (after) { - warn("%s - Section mismatch: reference to %s from %s " - "before '%s' (at offset -0x%lx)\n", - modname, secname, fromsec, + warn("%s - Section mismatch: reference to %s:%s from %s " + "before '%s' (at offset -0x%llx)\n", + modname, secname, refsymname, fromsec, elf->strtab + before->st_name, - (long)(before->st_value - r.r_offset)); + (long long)r.r_offset); } else { - warn("%s - Section mismatch: reference to %s from %s " - "(offset 0x%lx)\n", - modname, secname, fromsec, (long)r.r_offset); + warn("%s - Section mismatch: reference to %s:%s from %s " + "(offset 0x%llx)\n", + modname, secname, fromsec, refsymname, + (long long)r.r_offset); } } @@ -575,6 +604,7 @@ static void check_sec_ref(struct module *mod, const char *modname, const char *secname; r.r_offset = TO_NATIVE(rela->r_offset); r.r_info = TO_NATIVE(rela->r_info); + r.r_addend = TO_NATIVE(rela->r_addend); sym = elf->symtab_start + ELF_R_SYM(r.r_info); /* Skip special sections */ if (sym->st_shndx >= SHN_LORESERVE) -- cgit v1.2.3 From fededcd2af6219de69b252b7d3ea4b4ec2f33c7a Mon Sep 17 00:00:00 2001 From: "akpm@osdl.org" Date: Wed, 22 Feb 2006 03:19:54 -0800 Subject: kbuild: fix modpost compile with older gcc The kernel now requires that CC be 3.1.0 or higher. But we shouldn't place that requirement upon HOSTCC unless we really need to. Fixes my ia64 problem. Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 844f84b0818a..5b076ef51996 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -590,14 +590,14 @@ static void check_sec_ref(struct module *mod, const char *modname, /* Walk through all sections */ for (i = 0; i < hdr->e_shnum; i++) { + Elf_Rela *rela; + Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset; + Elf_Rela *stop = (void*)start + sechdrs[i].sh_size; const char *name = secstrings + sechdrs[i].sh_name + strlen(".rela"); /* We want to process only relocation sections and not .init */ if (section_ref_ok(name) || (sechdrs[i].sh_type != SHT_RELA)) continue; - Elf_Rela *rela; - Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset; - Elf_Rela *stop = (void*)start + sechdrs[i].sh_size; for (rela = start; rela < stop; rela++) { Elf_Rela r; -- cgit v1.2.3 From 6e10133fa4b2366e8ef18bc2ce34afe727b1c4ba Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Wed, 22 Feb 2006 21:24:50 +0100 Subject: kbuild: do not warn when unwind sections references .init/.exit sections Andrew Morton reported a number of false positives for ia64 - like these: WARNING: drivers/acpi/button.o - Section mismatch: reference to .init.text: from .IA_64.unwind.init.text after '' (at offset 0x0) WARNING: drivers/acpi/button.o - Section mismatch: reference to .exit.text: from .IA_64.unwind.exit.text after '' (at offset 0x0) WARNING: drivers/acpi/processor.o - Section mismatch: reference to .init.text: from .IA_64.unwind after '' (at offset 0x1e8) They are all false positives - or at least the .c code looks OK. It is not known why sometimes a section name is appended and sometimes not. Fix is to accept references from all sections that includes "unwind." in the name. Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 5b076ef51996..7f25354deba2 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -671,13 +671,21 @@ static int init_section_ref_ok(const char *name) ".debug", NULL }; - + /* part of section name */ + const char *namelist3 [] = { + ".unwind", /* sample: IA_64.unwind.init.text */ + NULL + }; + for (s = namelist1; *s; s++) if (strcmp(*s, name) == 0) return 1; for (s = namelist2; *s; s++) if (strncmp(*s, name, strlen(*s)) == 0) return 1; + for (s = namelist3; *s; s++) + if (strstr(*s, name) != NULL) + return 1; return 0; } @@ -727,6 +735,11 @@ static int exit_section_ref_ok(const char *name) ".debug", NULL }; + /* part of section name */ + const char *namelist3 [] = { + ".unwind", /* Sample: IA_64.unwind.exit.text */ + NULL + }; for (s = namelist1; *s; s++) if (strcmp(*s, name) == 0) @@ -734,6 +747,9 @@ static int exit_section_ref_ok(const char *name) for (s = namelist2; *s; s++) if (strncmp(*s, name, strlen(*s)) == 0) return 1; + for (s = namelist3; *s; s++) + if (strstr(*s, name) != NULL) + return 1; return 0; } -- cgit v1.2.3 From 382168f4791822de7d44d9c634fbfdf8bc08c91b Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 26 Feb 2006 20:11:17 +0100 Subject: kbuild: Add copyright to modpost.c It seems popular to protect your work with copyright, so I decided to do so for modpost which I patch a great deal atm. Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 7f25354deba2..de0a9ee1de16 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2,7 +2,7 @@ * * Copyright 2003 Kai Germaschewski * Copyright 2002-2004 Rusty Russell, IBM Corporation - * + * Copyright 2006 Sam Ravnborg * Based in part on module-init-tools/depmod.c,file2alias * * This software may be used and distributed according to the terms -- cgit v1.2.3 From 4c8fbca5836aaafd165aa8732d92ab5d4f3a6841 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 26 Feb 2006 22:18:11 +0100 Subject: kbuild: whitelist false section mismatch warnings In several cases the section mismatch check triggered false warnings. Following patch introduce a whitelist to 'false positives' are not warned of. Two types of patterns are recognised: 1) Typical case when a module parameter is _initdata 2) When a function pointer is assigned to a driver structure In both patterns we rely on the actual name of the variable assigned Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index de0a9ee1de16..663b1eff757b 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -451,6 +451,89 @@ static char *get_modinfo(void *modinfo, unsigned long modinfo_len, return NULL; } +/** + * Test if string s ends in string sub + * return 0 if match + **/ +static int strrcmp(const char *s, const char *sub) +{ + int slen, sublen; + + if (!s || !sub) + return 1; + + slen = strlen(s); + sublen = strlen(sub); + + if ((slen == 0) || (sublen == 0)) + return 1; + + if (sublen > slen) + return 1; + + return memcmp(s + slen - sublen, sub, sublen); +} + +/** + * Whitelist to allow certain references to pass with no warning. + * Pattern 1: + * If a module parameter is declared __initdata and permissions=0 + * then this is legal despite the warning generated. + * We cannot see value of permissions here, so just ignore + * this pattern. + * The pattern is identified by: + * tosec = .init.data + * fromsec = .data + * atsym =__param* + * + * Pattern 2: + * Many drivers utilise a *_driver container with references to + * add, remove, probe functions etc. + * These functions may often be marked __init and we do not want to + * warn here. + * the pattern is identified by: + * tosec = .init.text | .exit.text + * fromsec = .data + * atsym = *_driver, *_ops, *_probe, *probe_one + **/ +static int secref_whitelist(const char *tosec, const char *fromsec, + const char *atsym) +{ + int f1 = 1, f2 = 1; + const char **s; + const char *pat2sym[] = { + "_driver", + "_ops", + "_probe", + "_probe_one", + NULL + }; + + /* Check for pattern 1 */ + if (strcmp(tosec, ".init.data") != 0) + f1 = 0; + if (strcmp(fromsec, ".data") != 0) + f1 = 0; + if (strncmp(atsym, "__param", strlen("__param")) != 0) + f1 = 0; + + if (f1) + return f1; + + /* Check for pattern 2 */ + if ((strcmp(tosec, ".init.text") != 0) && + (strcmp(tosec, ".exit.text") != 0)) + f2 = 0; + if (strcmp(fromsec, ".data") != 0) + f2 = 0; + + for (s = pat2sym; *s; s++) + if (strrcmp(atsym, *s) == 0) + f1 = 1; + + return f1 && f2; +} + /** * Find symbol based on relocation record info. * In some cases the symbol supplied is a valid symbol so @@ -518,6 +601,7 @@ static void find_symbols_between(struct elf_info *elf, Elf_Addr addr, /** * Print a warning about a section mismatch. * Try to find symbols near it so user can find it. + * Check whitelist before warning - it may be a false positive. **/ static void warn_sec_mismatch(const char *modname, const char *fromsec, struct elf_info *elf, Elf_Sym *sym, Elf_Rela r) @@ -536,6 +620,11 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, refsym = find_elf_symbol(elf, r.r_addend, sym); if (refsym && strlen(elf->strtab + refsym->st_name)) refsymname = elf->strtab + refsym->st_name; + + /* check whitelist - we may ignore it */ + if (before && + secref_whitelist(secname, fromsec, elf->strtab + before->st_name)) + return; if (before && after) { warn("%s - Section mismatch: reference to %s:%s from %s " -- cgit v1.2.3 From 62070fa42c4ac23d1d71146a4c14702302b80245 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Fri, 3 Mar 2006 16:46:04 +0100 Subject: kbuild: kill trailing whitespace in modpost & friends Signed-off-by: Sam Ravnborg --- scripts/mod/file2alias.c | 4 +-- scripts/mod/mk_elfconfig.c | 4 +-- scripts/mod/modpost.c | 70 +++++++++++++++++++++++----------------------- scripts/mod/modpost.h | 8 +++--- 4 files changed, 43 insertions(+), 43 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 1346223f7809..e7b5350b65ce 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -34,7 +34,7 @@ typedef uint16_t __u16; typedef unsigned char __u8; /* Big exception to the "don't include kernel headers into userspace, which - * even potentially has different endianness and word sizes, since + * even potentially has different endianness and word sizes, since * we handle those differences explicitly below */ #include "../../include/linux/mod_devicetable.h" #include "../../include/linux/input.h" @@ -228,7 +228,7 @@ static int do_pci_entry(const char *filename, return 1; } -/* looks like: "ccw:tNmNdtNdmN" */ +/* looks like: "ccw:tNmNdtNdmN" */ static int do_ccw_entry(const char *filename, struct ccw_device_id *id, char *alias) { diff --git a/scripts/mod/mk_elfconfig.c b/scripts/mod/mk_elfconfig.c index de2aabf89fb3..3c92c83733f4 100644 --- a/scripts/mod/mk_elfconfig.c +++ b/scripts/mod/mk_elfconfig.c @@ -6,7 +6,7 @@ int main(int argc, char **argv) { - unsigned char ei[EI_NIDENT]; + unsigned char ei[EI_NIDENT]; union { short s; char c[2]; } endian_test; if (argc != 2) { @@ -57,7 +57,7 @@ main(int argc, char **argv) if ((strcmp(argv[1], "v850") == 0) || (strcmp(argv[1], "h8300") == 0)) printf("#define MODULE_SYMBOL_PREFIX \"_\"\n"); - else + else printf("#define MODULE_SYMBOL_PREFIX \"\"\n"); return 0; diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 663b1eff757b..5de3c63091e9 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -85,7 +85,7 @@ static struct module *new_module(char *modname) { struct module *mod; char *p, *s; - + mod = NOFAIL(malloc(sizeof(*mod))); memset(mod, 0, sizeof(*mod)); p = NOFAIL(strdup(modname)); @@ -320,9 +320,9 @@ static void parse_elf(struct elf_info *info, const char *filename) continue; info->symtab_start = (void *)hdr + sechdrs[i].sh_offset; - info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset + info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset + sechdrs[i].sh_size; - info->strtab = (void *)hdr + + info->strtab = (void *)hdr + sechdrs[sechdrs[i].sh_link].sh_offset; } if (!info->symtab_start) { @@ -387,15 +387,15 @@ static void handle_modversions(struct module *mod, struct elf_info *info, /* Ignore register directives. */ if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER) break; - if (symname[0] == '.') { - char *munged = strdup(symname); - munged[0] = '_'; - munged[1] = toupper(munged[1]); - symname = munged; - } + if (symname[0] == '.') { + char *munged = strdup(symname); + munged[0] = '_'; + munged[1] = toupper(munged[1]); + symname = munged; + } } #endif - + if (memcmp(symname, MODULE_SYMBOL_PREFIX, strlen(MODULE_SYMBOL_PREFIX)) == 0) mod->unres = alloc_symbol(symname + @@ -458,13 +458,13 @@ static char *get_modinfo(void *modinfo, unsigned long modinfo_len, static int strrcmp(const char *s, const char *sub) { int slen, sublen; - + if (!s || !sub) return 1; - + slen = strlen(s); sublen = strlen(sub); - + if ((slen == 0) || (sublen == 0)) return 1; @@ -485,7 +485,7 @@ static int strrcmp(const char *s, const char *sub) * tosec = .init.data * fromsec = .data * atsym =__param* - * + * * Pattern 2: * Many drivers utilise a *_driver container with references to * add, remove, probe functions etc. @@ -508,7 +508,7 @@ static int secref_whitelist(const char *tosec, const char *fromsec, "_probe_one", NULL }; - + /* Check for pattern 1 */ if (strcmp(tosec, ".init.data") != 0) f1 = 0; @@ -521,7 +521,7 @@ static int secref_whitelist(const char *tosec, const char *fromsec, return f1; /* Check for pattern 2 */ - if ((strcmp(tosec, ".init.text") != 0) && + if ((strcmp(tosec, ".init.text") != 0) && (strcmp(tosec, ".exit.text") != 0)) f2 = 0; if (strcmp(fromsec, ".data") != 0) @@ -570,7 +570,7 @@ static void find_symbols_between(struct elf_info *elf, Elf_Addr addr, Elf_Addr afterdiff = ~0; const char *secstrings = (void *)hdr + elf->sechdrs[hdr->e_shstrndx].sh_offset; - + *before = NULL; *after = NULL; @@ -614,7 +614,7 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, const char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; const char *secname = secstrings + sechdrs[sym->st_shndx].sh_name; - + find_symbols_between(elf, r.r_offset, fromsec, &before, &after); refsym = find_elf_symbol(elf, r.r_addend, sym); @@ -622,10 +622,10 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, refsymname = elf->strtab + refsym->st_name; /* check whitelist - we may ignore it */ - if (before && + if (before && secref_whitelist(secname, fromsec, elf->strtab + before->st_name)) return; - + if (before && after) { warn("%s - Section mismatch: reference to %s:%s from %s " "between '%s' (at offset 0x%llx) and '%s'\n", @@ -636,13 +636,13 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, } else if (before) { warn("%s - Section mismatch: reference to %s:%s from %s " "after '%s' (at offset 0x%llx)\n", - modname, secname, refsymname, fromsec, + modname, secname, refsymname, fromsec, elf->strtab + before->st_name, (long long)r.r_offset); } else if (after) { warn("%s - Section mismatch: reference to %s:%s from %s " "before '%s' (at offset -0x%llx)\n", - modname, secname, refsymname, fromsec, + modname, secname, refsymname, fromsec, elf->strtab + before->st_name, (long long)r.r_offset); } else { @@ -676,7 +676,7 @@ static void check_sec_ref(struct module *mod, const char *modname, Elf_Shdr *sechdrs = elf->sechdrs; const char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; - + /* Walk through all sections */ for (i = 0; i < hdr->e_shnum; i++) { Elf_Rela *rela; @@ -724,13 +724,13 @@ static int init_section(const char *name) /** * Identify sections from which references to a .init section is OK. - * + * * Unfortunately references to read only data that referenced .init * sections had to be excluded. Almost all of these are false * positives, they are created by gcc. The downside of excluding rodata * is that there really are some user references from rodata to * init code, e.g. drivers/video/vgacon.c: - * + * * const struct consw vga_con = { * con_startup: vgacon_startup, * @@ -769,10 +769,10 @@ static int init_section_ref_ok(const char *name) for (s = namelist1; *s; s++) if (strcmp(*s, name) == 0) return 1; - for (s = namelist2; *s; s++) + for (s = namelist2; *s; s++) if (strncmp(*s, name, strlen(*s)) == 0) return 1; - for (s = namelist3; *s; s++) + for (s = namelist3; *s; s++) if (strstr(*s, name) != NULL) return 1; return 0; @@ -792,12 +792,12 @@ static int exit_section(const char *name) if (strcmp(name, ".exit.data") == 0) return 1; return 0; - + } /* * Identify sections from which references to a .exit section is OK. - * + * * [OPD] Keith Ownes commented: * For our future {in}sanity, add a comment that this is the ppc .opd * section, not the ia64 .opd section. @@ -829,14 +829,14 @@ static int exit_section_ref_ok(const char *name) ".unwind", /* Sample: IA_64.unwind.exit.text */ NULL }; - + for (s = namelist1; *s; s++) if (strcmp(*s, name) == 0) return 1; - for (s = namelist2; *s; s++) + for (s = namelist2; *s; s++) if (strncmp(*s, name, strlen(*s)) == 0) return 1; - for (s = namelist3; *s; s++) + for (s = namelist3; *s; s++) if (strstr(*s, name) != NULL) return 1; return 0; @@ -900,7 +900,7 @@ void __attribute__((format(printf, 2, 3))) buf_printf(struct buffer *buf, char tmp[SZ]; int len; va_list ap; - + va_start(ap, fmt); len = vsnprintf(tmp, SZ, fmt, ap); if (buf->size - buf->pos < len + 1) { @@ -1129,7 +1129,7 @@ static int dump_sym(struct symbol *sym) return 0; return 1; } - + static void write_dump(const char *fname) { struct buffer buf = { }; @@ -1141,7 +1141,7 @@ static void write_dump(const char *fname) while (symbol) { if (dump_sym(symbol)) buf_printf(&buf, "0x%08x\t%s\t%s\n", - symbol->crc, symbol->name, + symbol->crc, symbol->name, symbol->module->name); symbol = symbol->next; } diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 3b5319dd937f..b14255c72a37 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -13,8 +13,8 @@ #if KERNEL_ELFCLASS == ELFCLASS32 -#define Elf_Ehdr Elf32_Ehdr -#define Elf_Shdr Elf32_Shdr +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Shdr Elf32_Shdr #define Elf_Sym Elf32_Sym #define Elf_Addr Elf32_Addr #define Elf_Section Elf32_Section @@ -26,8 +26,8 @@ #define ELF_R_TYPE ELF32_R_TYPE #else -#define Elf_Ehdr Elf64_Ehdr -#define Elf_Shdr Elf64_Shdr +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Shdr Elf64_Shdr #define Elf_Sym Elf64_Sym #define Elf_Addr Elf64_Addr #define Elf_Section Elf64_Section -- cgit v1.2.3 From 9209aed0726c77ad13b8d83e73a3cf9f59a8c2b2 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 5 Mar 2006 00:16:26 +0100 Subject: kbuild: kill false positives from section mismatch warnings for powerpc Building an allmodconfig kernel for ppc64 revealed a number of false positives - originally reported by Andrew Morton. This patch removes most if not all false positives for ppc64: Section .opd The .opd section contains function descriptors at least for ppc64. So ignore it for .init.text (was ignored for .exit.text). See description of function descriptors here: http://www.linuxbase.org/spec/ELF/ppc64/PPC-elf64abi-1.7.html Section .toc1 ppc64 places some static variables in .toc1 - ignore the. Section __bug_tabe BUG() and friends uses __bug_table. Ignore warnings from that section. Module parameters are placed in .data.rel for ppc64, for adjust pattern to match on section named .data* Tested with gcc: 3.4.0 and binutils 2.15.90.0.3 Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 5de3c63091e9..c4dc1d72d02e 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -483,7 +483,7 @@ static int strrcmp(const char *s, const char *sub) * this pattern. * The pattern is identified by: * tosec = .init.data - * fromsec = .data + * fromsec = .data* * atsym =__param* * * Pattern 2: @@ -512,7 +512,7 @@ static int secref_whitelist(const char *tosec, const char *fromsec, /* Check for pattern 1 */ if (strcmp(tosec, ".init.data") != 0) f1 = 0; - if (strcmp(fromsec, ".data") != 0) + if (strncmp(fromsec, ".data", strlen(".data")) != 0) f1 = 0; if (strncmp(atsym, "__param", strlen("__param")) != 0) f1 = 0; @@ -743,9 +743,12 @@ static int init_section_ref_ok(const char *name) /* Absolute section names */ const char *namelist1[] = { ".init", + ".opd", /* see comment [OPD] at exit_section_ref_ok() */ + ".toc1", /* used by ppc64 */ ".stab", ".rodata", ".text.lock", + "__bug_table", /* used by powerpc for BUG() */ ".pci_fixup_header", ".pci_fixup_final", ".pdr", @@ -812,8 +815,10 @@ static int exit_section_ref_ok(const char *name) ".exit.data", ".init.text", ".opd", /* See comment [OPD] */ + ".toc1", /* used by ppc64 */ ".altinstructions", ".pdr", + "__bug_table", /* used by powerpc for BUG() */ ".exitcall.exit", ".eh_frame", ".stab", -- cgit v1.2.3 From e835a39c1c1f023ef443f735b0e98b08660ae0e4 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 5 Mar 2006 11:34:15 +0100 Subject: kbuild: fix section mismatch check for unwind on IA64 Parameters to strstr() was reversed. Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index c4dc1d72d02e..3b570b18c2e4 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -776,7 +776,7 @@ static int init_section_ref_ok(const char *name) if (strncmp(*s, name, strlen(*s)) == 0) return 1; for (s = namelist3; *s; s++) - if (strstr(*s, name) != NULL) + if (strstr(name, *s) != NULL) return 1; return 0; } @@ -842,7 +842,7 @@ static int exit_section_ref_ok(const char *name) if (strncmp(*s, name, strlen(*s)) == 0) return 1; for (s = namelist3; *s; s++) - if (strstr(*s, name) != NULL) + if (strstr(name, *s) != NULL) return 1; return 0; } -- cgit v1.2.3 From 43c74d179596ba1f8eceb8c6a5c7e11afe233662 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 5 Mar 2006 12:02:46 +0100 Subject: kbuild: in the section mismatch check try harder to find symbols When searching for symbols the only check performed was if offset equals st_value. Adding an additional check to see if st_name points t a valid name made us sort out a few more false positives and let us report more correct names in warnings. Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 3b570b18c2e4..3648683a26c5 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -558,7 +558,10 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr, } /* - * Find symbols before or equal addr and after addr - in the section sec + * Find symbols before or equal addr and after addr - in the section sec. + * If we find two symbols with equal offset prefer one with a valid name. + * The ELF format may have a better way to detect what type of symbol + * it is, but this works for now. **/ static void find_symbols_between(struct elf_info *elf, Elf_Addr addr, const char *sec, @@ -587,6 +590,12 @@ static void find_symbols_between(struct elf_info *elf, Elf_Addr addr, beforediff = addr - sym->st_value; *before = sym; } + else if ((addr - sym->st_value) == beforediff) { + /* equal offset, valid name? */ + const char *name = elf->strtab + sym->st_name; + if (name && strlen(name)) + *before = sym; + } } else { @@ -594,6 +603,12 @@ static void find_symbols_between(struct elf_info *elf, Elf_Addr addr, afterdiff = sym->st_value - addr; *after = sym; } + else if ((sym->st_value - addr) == afterdiff) { + /* equal offset, valid name? */ + const char *name = elf->strtab + sym->st_name; + if (name && strlen(name)) + *after = sym; + } } } } -- cgit v1.2.3 From 7b75b13cda8bd21e8636ea985f76e1ce5bd1a470 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 5 Mar 2006 13:48:58 +0100 Subject: kbuild: when warning symbols exported twice now tell user this is the problem Warning now looks like this: WARNING: vmlinux: 'strcpy' exported twice. Previous export was in vmlinux Which gives much better hint how to fix it. Signed-off-by: Sam Ravnborg --- scripts/mod/modpost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 3648683a26c5..e2bf4c927dd3 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -191,7 +191,7 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod) s = new_symbol(name, mod); } else { if (!s->preloaded) { - warn("%s: duplicate symbol '%s' previous definition " + warn("%s: '%s' exported twice. Previous export " "was in %s%s\n", mod->name, name, s->module->name, is_vmlinux(s->module->name) ?"":".ko"); -- cgit v1.2.3 From f7b05e64bdb2fcc4b2dc94a4bd9426adc70c9599 Mon Sep 17 00:00:00 2001 From: Luke Yang Date: Thu, 2 Mar 2006 18:35:31 +0800 Subject: kbuild: Fix bug in crc symbol generating of kernel and modules The scripts/genksyms/genksyms.c uses hardcoded "__crc_" prefix for crc symbols in kernel and modules. The prefix should be replaced by "MODULE_SYMBOL_PREFIX##__crc_" otherwise there will be warnings when MODULE_SYMBOL_PREFIX is not NULL. I am sorry my last patch for this issue is actually wrong. I revert it in this patch. Signed-off-by: Luke Yang Signed-off-by: Sam Ravnborg --- scripts/genksyms/genksyms.c | 4 ++-- scripts/mod/modpost.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c index 416a694b0998..ef8822e59cda 100644 --- a/scripts/genksyms/genksyms.c +++ b/scripts/genksyms/genksyms.c @@ -32,7 +32,7 @@ #endif /* __GNU_LIBRARY__ */ #include "genksyms.h" - +#include "../mod/elfconfig.h" /*----------------------------------------------------------------------*/ #define HASH_BUCKETS 4096 @@ -458,7 +458,7 @@ export_symbol(const char *name) fputs(">\n", debugfile); /* Used as a linker script. */ - printf("__crc_%s = 0x%08lx ;\n", name, crc); + printf("%s__crc_%s = 0x%08lx ;\n", MODULE_SYMBOL_PREFIX, name, crc); } } diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index e2bf4c927dd3..30f3ac8eb43c 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -346,8 +346,8 @@ static void parse_elf_finish(struct elf_info *info) release_file(info->hdr, info->size); } -#define CRC_PFX "__crc_" -#define KSYMTAB_PFX "__ksymtab_" +#define CRC_PFX MODULE_SYMBOL_PREFIX "__crc_" +#define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_" static void handle_modversions(struct module *mod, struct elf_info *info, Elf_Sym *sym, const char *symname) -- cgit v1.2.3