Merge tag 'kbuild-v5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild
Pull Kbuild updates from Masahiro Yamada:
- fix warnings in 'make clean' for ARCH=um, hexagon, h8300, unicore32
- ensure to rebuild all objects when the compiler is upgraded
- exclude system headers from dependency tracking and fixdep processing
- fix potential bit-size mismatch between the kernel and BPF user-mode
helper
- add the new syntax 'userprogs' to build user-space programs for the
target architecture (the same arch as the kernel)
- compile user-space sample code under samples/ for the target arch
instead of the host arch
- make headers_install fail if a CONFIG option is leaked to user-space
- sanitize the output format of scripts/checkstack.pl
- handle ARM 'push' instruction in scripts/checkstack.pl
- error out before modpost if a module name conflict is found
- error out when multiple directories are passed to M= because this
feature is broken for a long time
- add CONFIG_DEBUG_INFO_COMPRESSED to support compressed debug info
- a lot of cleanups of modpost
- dump vmlinux symbols out into vmlinux.symvers, and reuse it in the
second pass of modpost
- do not run the second pass of modpost if nothing in modules is
updated
- install modules.builtin(.modinfo) by 'make install' as well as by
'make modules_install' because it is useful even when
CONFIG_MODULES=n
- add new command line variables, GZIP, BZIP2, LZOP, LZMA, LZ4, and XZ
to allow users to use alternatives such as pigz, pbzip2, etc.
* tag 'kbuild-v5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild: (96 commits)
kbuild: add variables for compression tools
Makefile: install modules.builtin even if CONFIG_MODULES=n
mksysmap: Fix the mismatch of '.L' symbols in System.map
kbuild: doc: rename LDFLAGS to KBUILD_LDFLAGS
modpost: change elf_info->size to size_t
modpost: remove is_vmlinux() helper
modpost: strip .o from modname before calling new_module()
modpost: set have_vmlinux in new_module()
modpost: remove mod->skip struct member
modpost: add mod->is_vmlinux struct member
modpost: remove is_vmlinux() call in check_for_{gpl_usage,unused}()
modpost: remove mod->is_dot_o struct member
modpost: move -d option in scripts/Makefile.modpost
modpost: remove -s option
modpost: remove get_next_text() and make {grab,release_}file static
modpost: use read_text_file() and get_line() for reading text files
modpost: avoid false-positive file open error
modpost: fix potential mmap'ed file overrun in get_src_version()
modpost: add read_text_file() and get_line() helpers
modpost: do not call get_modinfo() for vmlinux(.o)
...
This commit is contained in:
+184
-200
@@ -30,8 +30,6 @@ static int have_vmlinux = 0;
|
||||
static int all_versions = 0;
|
||||
/* If we are modposting external module set to 1 */
|
||||
static int external_module = 0;
|
||||
/* Warn about section mismatch in vmlinux if set to 1 */
|
||||
static int vmlinux_section_warnings = 1;
|
||||
/* Only warn about unresolved symbols */
|
||||
static int warn_unresolved = 0;
|
||||
/* How a symbol is exported */
|
||||
@@ -90,20 +88,6 @@ static inline bool strends(const char *str, const char *postfix)
|
||||
return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
|
||||
}
|
||||
|
||||
static int is_vmlinux(const char *modname)
|
||||
{
|
||||
const char *myname;
|
||||
|
||||
myname = strrchr(modname, '/');
|
||||
if (myname)
|
||||
myname++;
|
||||
else
|
||||
myname = modname;
|
||||
|
||||
return (strcmp(myname, "vmlinux") == 0) ||
|
||||
(strcmp(myname, "vmlinux.o") == 0);
|
||||
}
|
||||
|
||||
void *do_nofail(void *ptr, const char *expr)
|
||||
{
|
||||
if (!ptr)
|
||||
@@ -112,6 +96,55 @@ void *do_nofail(void *ptr, const char *expr)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
char *read_text_file(const char *filename)
|
||||
{
|
||||
struct stat st;
|
||||
size_t nbytes;
|
||||
int fd;
|
||||
char *buf;
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror(filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (fstat(fd, &st) < 0) {
|
||||
perror(filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
buf = NOFAIL(malloc(st.st_size + 1));
|
||||
|
||||
nbytes = st.st_size;
|
||||
|
||||
while (nbytes) {
|
||||
ssize_t bytes_read;
|
||||
|
||||
bytes_read = read(fd, buf, nbytes);
|
||||
if (bytes_read < 0) {
|
||||
perror(filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
nbytes -= bytes_read;
|
||||
}
|
||||
buf[st.st_size] = '\0';
|
||||
|
||||
close(fd);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *get_line(char **stringp)
|
||||
{
|
||||
/* do not return the unwanted extra line at EOF */
|
||||
if (*stringp && **stringp == '\0')
|
||||
return NULL;
|
||||
|
||||
return strsep(stringp, "\n");
|
||||
}
|
||||
|
||||
/* A list of all modules we processed */
|
||||
static struct module *modules;
|
||||
|
||||
@@ -128,24 +161,20 @@ static struct module *find_module(const char *modname)
|
||||
static struct module *new_module(const char *modname)
|
||||
{
|
||||
struct module *mod;
|
||||
char *p;
|
||||
|
||||
mod = NOFAIL(malloc(sizeof(*mod)));
|
||||
mod = NOFAIL(malloc(sizeof(*mod) + strlen(modname) + 1));
|
||||
memset(mod, 0, sizeof(*mod));
|
||||
p = NOFAIL(strdup(modname));
|
||||
|
||||
/* strip trailing .o */
|
||||
if (strends(p, ".o")) {
|
||||
p[strlen(p) - 2] = '\0';
|
||||
mod->is_dot_o = 1;
|
||||
}
|
||||
|
||||
/* add to list */
|
||||
mod->name = p;
|
||||
strcpy(mod->name, modname);
|
||||
mod->is_vmlinux = (strcmp(modname, "vmlinux") == 0);
|
||||
mod->gpl_compatible = -1;
|
||||
mod->next = modules;
|
||||
modules = mod;
|
||||
|
||||
if (mod->is_vmlinux)
|
||||
have_vmlinux = 1;
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
@@ -161,12 +190,9 @@ struct symbol {
|
||||
int crc_valid;
|
||||
char *namespace;
|
||||
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) **/
|
||||
unsigned int is_static:1; /* 1 if symbol is not global */
|
||||
enum export export; /* Type of export */
|
||||
char name[0];
|
||||
char name[];
|
||||
};
|
||||
|
||||
static struct symbol *symbolhash[SYMBOL_HASH_SIZE];
|
||||
@@ -288,31 +314,34 @@ static enum export export_no(const char *s)
|
||||
return export_unknown;
|
||||
}
|
||||
|
||||
static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr)
|
||||
static void *sym_get_data_by_offset(const struct elf_info *info,
|
||||
unsigned int secindex, unsigned long offset)
|
||||
{
|
||||
return (void *)elf->hdr +
|
||||
elf->sechdrs[elf->secindex_strings].sh_offset +
|
||||
sechdr->sh_name;
|
||||
}
|
||||
|
||||
static const char *sec_name(struct elf_info *elf, int secindex)
|
||||
{
|
||||
return sech_name(elf, &elf->sechdrs[secindex]);
|
||||
}
|
||||
|
||||
static void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym)
|
||||
{
|
||||
unsigned int secindex = get_secindex(info, sym);
|
||||
Elf_Shdr *sechdr = &info->sechdrs[secindex];
|
||||
unsigned long offset;
|
||||
|
||||
offset = sym->st_value;
|
||||
if (info->hdr->e_type != ET_REL)
|
||||
offset -= sechdr->sh_addr;
|
||||
|
||||
return (void *)info->hdr + sechdr->sh_offset + offset;
|
||||
}
|
||||
|
||||
static void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym)
|
||||
{
|
||||
return sym_get_data_by_offset(info, get_secindex(info, sym),
|
||||
sym->st_value);
|
||||
}
|
||||
|
||||
static const char *sech_name(const struct elf_info *info, Elf_Shdr *sechdr)
|
||||
{
|
||||
return sym_get_data_by_offset(info, info->secindex_strings,
|
||||
sechdr->sh_name);
|
||||
}
|
||||
|
||||
static const char *sec_name(const struct elf_info *info, int secindex)
|
||||
{
|
||||
return sech_name(info, &info->sechdrs[secindex]);
|
||||
}
|
||||
|
||||
#define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0)
|
||||
|
||||
static enum export export_from_secname(struct elf_info *elf, unsigned int sec)
|
||||
@@ -386,17 +415,15 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod,
|
||||
|
||||
if (!s) {
|
||||
s = new_symbol(name, mod, export);
|
||||
} else if (!external_module || is_vmlinux(s->module->name) ||
|
||||
} else if (!external_module || s->module->is_vmlinux ||
|
||||
s->module == mod) {
|
||||
warn("%s: '%s' exported twice. Previous export was in %s%s\n",
|
||||
mod->name, name, s->module->name,
|
||||
is_vmlinux(s->module->name) ? "" : ".ko");
|
||||
s->module->is_vmlinux ? "" : ".ko");
|
||||
return s;
|
||||
}
|
||||
|
||||
s->module = mod;
|
||||
s->vmlinux = is_vmlinux(mod->name);
|
||||
s->kernel = 0;
|
||||
s->export = export;
|
||||
return s;
|
||||
}
|
||||
@@ -416,7 +443,7 @@ static void sym_set_crc(const char *name, unsigned int crc)
|
||||
s->crc_valid = 1;
|
||||
}
|
||||
|
||||
void *grab_file(const char *filename, unsigned long *size)
|
||||
static void *grab_file(const char *filename, size_t *size)
|
||||
{
|
||||
struct stat st;
|
||||
void *map = MAP_FAILED;
|
||||
@@ -438,41 +465,7 @@ failed:
|
||||
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)
|
||||
{
|
||||
static char line[4096];
|
||||
int skip = 1;
|
||||
size_t len = 0;
|
||||
signed char *p = (signed char *)file + *pos;
|
||||
char *s = line;
|
||||
|
||||
for (; *pos < size ; (*pos)++) {
|
||||
if (skip && isspace(*p)) {
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
skip = 0;
|
||||
if (*p != '\n' && (*pos < size)) {
|
||||
len++;
|
||||
*s++ = *p++;
|
||||
if (len > 4095)
|
||||
break; /* Too long, stop */
|
||||
} else {
|
||||
/* End of string */
|
||||
*s = '\0';
|
||||
return line;
|
||||
}
|
||||
}
|
||||
/* End of buffer */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void release_file(void *file, unsigned long size)
|
||||
static void release_file(void *file, size_t size)
|
||||
{
|
||||
munmap(file, size);
|
||||
}
|
||||
@@ -528,9 +521,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
|
||||
|
||||
/* Check if file offset is correct */
|
||||
if (hdr->e_shoff > info->size) {
|
||||
fatal("section header offset=%lu in file '%s' is bigger than "
|
||||
"filesize=%lu\n", (unsigned long)hdr->e_shoff,
|
||||
filename, info->size);
|
||||
fatal("section header offset=%lu in file '%s' is bigger than filesize=%zu\n",
|
||||
(unsigned long)hdr->e_shoff, filename, info->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -683,7 +675,7 @@ static void handle_modversion(const struct module *mod,
|
||||
|
||||
if (sym->st_shndx == SHN_UNDEF) {
|
||||
warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n",
|
||||
symname, mod->name, is_vmlinux(mod->name) ? "":".ko");
|
||||
symname, mod->name, mod->is_vmlinux ? "" : ".ko");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -705,8 +697,7 @@ static void handle_symbol(struct module *mod, struct elf_info *info,
|
||||
enum export export;
|
||||
const char *name;
|
||||
|
||||
if ((!is_vmlinux(mod->name) || mod->is_dot_o) &&
|
||||
strstarts(symname, "__ksymtab"))
|
||||
if (strstarts(symname, "__ksymtab"))
|
||||
export = export_from_secname(info, get_secindex(info, sym));
|
||||
else
|
||||
export = export_from_sec(info, get_secindex(info, sym));
|
||||
@@ -1752,11 +1743,7 @@ static void check_section_mismatch(const char *modname, struct elf_info *elf,
|
||||
static unsigned int *reloc_location(struct elf_info *elf,
|
||||
Elf_Shdr *sechdr, Elf_Rela *r)
|
||||
{
|
||||
Elf_Shdr *sechdrs = elf->sechdrs;
|
||||
int section = sechdr->sh_info;
|
||||
|
||||
return (void *)elf->hdr + sechdrs[section].sh_offset +
|
||||
r->r_offset;
|
||||
return sym_get_data_by_offset(elf, sechdr->sh_info, r->r_offset);
|
||||
}
|
||||
|
||||
static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
|
||||
@@ -2005,34 +1992,36 @@ static void read_symbols(const char *modname)
|
||||
if (!parse_elf(&info, modname))
|
||||
return;
|
||||
|
||||
mod = new_module(modname);
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
/* When there's no vmlinux, don't print warnings about
|
||||
* unresolved symbols (since there'll be too many ;) */
|
||||
if (is_vmlinux(modname)) {
|
||||
have_vmlinux = 1;
|
||||
mod->skip = 1;
|
||||
/* strip trailing .o */
|
||||
tmp = NOFAIL(strdup(modname));
|
||||
tmp[strlen(tmp) - 2] = '\0';
|
||||
mod = new_module(tmp);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
license = get_modinfo(&info, "license");
|
||||
if (!license && !is_vmlinux(modname))
|
||||
warn("missing MODULE_LICENSE() in %s\n"
|
||||
"see include/linux/module.h for "
|
||||
"more information\n", modname);
|
||||
while (license) {
|
||||
if (license_is_gpl_compatible(license))
|
||||
mod->gpl_compatible = 1;
|
||||
else {
|
||||
mod->gpl_compatible = 0;
|
||||
break;
|
||||
if (!mod->is_vmlinux) {
|
||||
license = get_modinfo(&info, "license");
|
||||
if (!license)
|
||||
warn("missing MODULE_LICENSE() in %s\n", modname);
|
||||
while (license) {
|
||||
if (license_is_gpl_compatible(license))
|
||||
mod->gpl_compatible = 1;
|
||||
else {
|
||||
mod->gpl_compatible = 0;
|
||||
break;
|
||||
}
|
||||
license = get_next_modinfo(&info, "license", license);
|
||||
}
|
||||
license = get_next_modinfo(&info, "license", license);
|
||||
}
|
||||
|
||||
namespace = get_modinfo(&info, "import_ns");
|
||||
while (namespace) {
|
||||
add_namespace(&mod->imported_namespaces, namespace);
|
||||
namespace = get_next_modinfo(&info, "import_ns", namespace);
|
||||
namespace = get_modinfo(&info, "import_ns");
|
||||
while (namespace) {
|
||||
add_namespace(&mod->imported_namespaces, namespace);
|
||||
namespace = get_next_modinfo(&info, "import_ns",
|
||||
namespace);
|
||||
}
|
||||
}
|
||||
|
||||
for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
|
||||
@@ -2070,16 +2059,14 @@ static void read_symbols(const char *modname)
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_vmlinux(modname) || vmlinux_section_warnings)
|
||||
check_sec_ref(mod, modname, &info);
|
||||
check_sec_ref(mod, modname, &info);
|
||||
|
||||
version = get_modinfo(&info, "version");
|
||||
if (version)
|
||||
maybe_frob_rcs_version(modname, version, info.modinfo,
|
||||
version - (char *)info.hdr);
|
||||
if (version || (all_versions && !is_vmlinux(modname)))
|
||||
get_src_version(modname, mod->srcversion,
|
||||
sizeof(mod->srcversion)-1);
|
||||
if (!mod->is_vmlinux) {
|
||||
version = get_modinfo(&info, "version");
|
||||
if (version || all_versions)
|
||||
get_src_version(modname, mod->srcversion,
|
||||
sizeof(mod->srcversion) - 1);
|
||||
}
|
||||
|
||||
parse_elf_finish(&info);
|
||||
|
||||
@@ -2143,20 +2130,18 @@ void buf_write(struct buffer *buf, const char *s, int len)
|
||||
|
||||
static void check_for_gpl_usage(enum export exp, const char *m, const char *s)
|
||||
{
|
||||
const char *e = is_vmlinux(m) ?"":".ko";
|
||||
|
||||
switch (exp) {
|
||||
case export_gpl:
|
||||
fatal("GPL-incompatible module %s%s "
|
||||
"uses GPL-only symbol '%s'\n", m, e, s);
|
||||
fatal("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n",
|
||||
m, s);
|
||||
break;
|
||||
case export_unused_gpl:
|
||||
fatal("GPL-incompatible module %s%s "
|
||||
"uses GPL-only symbol marked UNUSED '%s'\n", m, e, s);
|
||||
fatal("GPL-incompatible module %s.ko uses GPL-only symbol marked UNUSED '%s'\n",
|
||||
m, s);
|
||||
break;
|
||||
case export_gpl_future:
|
||||
warn("GPL-incompatible module %s%s "
|
||||
"uses future GPL-only symbol '%s'\n", m, e, s);
|
||||
warn("GPL-incompatible module %s.ko uses future GPL-only symbol '%s'\n",
|
||||
m, s);
|
||||
break;
|
||||
case export_plain:
|
||||
case export_unused:
|
||||
@@ -2168,13 +2153,11 @@ static void check_for_gpl_usage(enum export exp, const char *m, const char *s)
|
||||
|
||||
static void check_for_unused(enum export exp, const char *m, const char *s)
|
||||
{
|
||||
const char *e = is_vmlinux(m) ?"":".ko";
|
||||
|
||||
switch (exp) {
|
||||
case export_unused:
|
||||
case export_unused_gpl:
|
||||
warn("module %s%s "
|
||||
"uses symbol '%s' marked UNUSED\n", m, e, s);
|
||||
warn("module %s.ko uses symbol '%s' marked UNUSED\n",
|
||||
m, s);
|
||||
break;
|
||||
default:
|
||||
/* ignore */
|
||||
@@ -2349,7 +2332,7 @@ static void add_depends(struct buffer *b, struct module *mod)
|
||||
/* Clear ->seen flag of modules that own symbols needed by this. */
|
||||
for (s = mod->unres; s; s = s->next)
|
||||
if (s->module)
|
||||
s->module->seen = is_vmlinux(s->module->name);
|
||||
s->module->seen = s->module->is_vmlinux;
|
||||
|
||||
buf_printf(b, "\n");
|
||||
buf_printf(b, "MODULE_INFO(depends, \"");
|
||||
@@ -2382,6 +2365,25 @@ static void add_srcversion(struct buffer *b, struct module *mod)
|
||||
}
|
||||
}
|
||||
|
||||
static void write_buf(struct buffer *b, const char *fname)
|
||||
{
|
||||
FILE *file;
|
||||
|
||||
file = fopen(fname, "w");
|
||||
if (!file) {
|
||||
perror(fname);
|
||||
exit(1);
|
||||
}
|
||||
if (fwrite(b->p, 1, b->pos, file) != b->pos) {
|
||||
perror(fname);
|
||||
exit(1);
|
||||
}
|
||||
if (fclose(file) != 0) {
|
||||
perror(fname);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void write_if_changed(struct buffer *b, const char *fname)
|
||||
{
|
||||
char *tmp;
|
||||
@@ -2414,32 +2416,24 @@ static void write_if_changed(struct buffer *b, const char *fname)
|
||||
close_write:
|
||||
fclose(file);
|
||||
write:
|
||||
file = fopen(fname, "w");
|
||||
if (!file) {
|
||||
perror(fname);
|
||||
exit(1);
|
||||
}
|
||||
if (fwrite(b->p, 1, b->pos, file) != b->pos) {
|
||||
perror(fname);
|
||||
exit(1);
|
||||
}
|
||||
fclose(file);
|
||||
write_buf(b, fname);
|
||||
}
|
||||
|
||||
/* parse Module.symvers file. line format:
|
||||
* 0x12345678<tab>symbol<tab>module<tab>export<tab>namespace
|
||||
**/
|
||||
static void read_dump(const char *fname, unsigned int kernel)
|
||||
static void read_dump(const char *fname)
|
||||
{
|
||||
unsigned long size, pos = 0;
|
||||
void *file = grab_file(fname, &size);
|
||||
char *line;
|
||||
char *buf, *pos, *line;
|
||||
|
||||
if (!file)
|
||||
buf = read_text_file(fname);
|
||||
if (!buf)
|
||||
/* No symbol versions, silently ignore */
|
||||
return;
|
||||
|
||||
while ((line = get_next_line(&pos, file, size))) {
|
||||
pos = buf;
|
||||
|
||||
while ((line = get_line(&pos))) {
|
||||
char *symname, *namespace, *modname, *d, *export;
|
||||
unsigned int crc;
|
||||
struct module *mod;
|
||||
@@ -2463,21 +2457,18 @@ static void read_dump(const char *fname, unsigned int kernel)
|
||||
goto fail;
|
||||
mod = find_module(modname);
|
||||
if (!mod) {
|
||||
if (is_vmlinux(modname))
|
||||
have_vmlinux = 1;
|
||||
mod = new_module(modname);
|
||||
mod->skip = 1;
|
||||
mod->from_dump = 1;
|
||||
}
|
||||
s = sym_add_exported(symname, mod, export_no(export));
|
||||
s->kernel = kernel;
|
||||
s->is_static = 0;
|
||||
sym_set_crc(symname, crc);
|
||||
sym_update_namespace(symname, namespace);
|
||||
}
|
||||
release_file(file, size);
|
||||
free(buf);
|
||||
return;
|
||||
fail:
|
||||
release_file(file, size);
|
||||
free(buf);
|
||||
fatal("parse error in symbol dump file\n");
|
||||
}
|
||||
|
||||
@@ -2489,7 +2480,7 @@ static int dump_sym(struct symbol *sym)
|
||||
{
|
||||
if (!external_module)
|
||||
return 1;
|
||||
if (sym->vmlinux || sym->kernel)
|
||||
if (sym->module->from_dump)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -2515,7 +2506,7 @@ static void write_dump(const char *fname)
|
||||
symbol = symbol->next;
|
||||
}
|
||||
}
|
||||
write_if_changed(&buf, fname);
|
||||
write_buf(&buf, fname);
|
||||
free(buf.p);
|
||||
}
|
||||
|
||||
@@ -2527,7 +2518,7 @@ static void write_namespace_deps_files(const char *fname)
|
||||
|
||||
for (mod = modules; mod; mod = mod->next) {
|
||||
|
||||
if (mod->skip || !mod->missing_namespaces)
|
||||
if (mod->from_dump || !mod->missing_namespaces)
|
||||
continue;
|
||||
|
||||
buf_printf(&ns_deps_buf, "%s.ko:", mod->name);
|
||||
@@ -2542,8 +2533,8 @@ static void write_namespace_deps_files(const char *fname)
|
||||
free(ns_deps_buf.p);
|
||||
}
|
||||
|
||||
struct ext_sym_list {
|
||||
struct ext_sym_list *next;
|
||||
struct dump_list {
|
||||
struct dump_list *next;
|
||||
const char *file;
|
||||
};
|
||||
|
||||
@@ -2551,28 +2542,24 @@ int main(int argc, char **argv)
|
||||
{
|
||||
struct module *mod;
|
||||
struct buffer buf = { };
|
||||
char *kernel_read = NULL;
|
||||
char *missing_namespace_deps = NULL;
|
||||
char *dump_write = NULL, *files_source = NULL;
|
||||
int opt;
|
||||
int err;
|
||||
int n;
|
||||
struct ext_sym_list *extsym_iter;
|
||||
struct ext_sym_list *extsym_start = NULL;
|
||||
struct dump_list *dump_read_start = NULL;
|
||||
struct dump_list **dump_read_iter = &dump_read_start;
|
||||
|
||||
while ((opt = getopt(argc, argv, "i:e:mnsT:o:awENd:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "ei:mnT:o:awENd:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'i':
|
||||
kernel_read = optarg;
|
||||
external_module = 1;
|
||||
break;
|
||||
case 'e':
|
||||
external_module = 1;
|
||||
extsym_iter =
|
||||
NOFAIL(malloc(sizeof(*extsym_iter)));
|
||||
extsym_iter->next = extsym_start;
|
||||
extsym_iter->file = optarg;
|
||||
extsym_start = extsym_iter;
|
||||
break;
|
||||
case 'i':
|
||||
*dump_read_iter =
|
||||
NOFAIL(calloc(1, sizeof(**dump_read_iter)));
|
||||
(*dump_read_iter)->file = optarg;
|
||||
dump_read_iter = &(*dump_read_iter)->next;
|
||||
break;
|
||||
case 'm':
|
||||
modversions = 1;
|
||||
@@ -2586,9 +2573,6 @@ int main(int argc, char **argv)
|
||||
case 'a':
|
||||
all_versions = 1;
|
||||
break;
|
||||
case 's':
|
||||
vmlinux_section_warnings = 0;
|
||||
break;
|
||||
case 'T':
|
||||
files_source = optarg;
|
||||
break;
|
||||
@@ -2609,13 +2593,13 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (kernel_read)
|
||||
read_dump(kernel_read, 1);
|
||||
while (extsym_start) {
|
||||
read_dump(extsym_start->file, 0);
|
||||
extsym_iter = extsym_start->next;
|
||||
free(extsym_start);
|
||||
extsym_start = extsym_iter;
|
||||
while (dump_read_start) {
|
||||
struct dump_list *tmp;
|
||||
|
||||
read_dump(dump_read_start->file);
|
||||
tmp = dump_read_start->next;
|
||||
free(dump_read_start);
|
||||
dump_read_start = tmp;
|
||||
}
|
||||
|
||||
while (optind < argc)
|
||||
@@ -2624,12 +2608,19 @@ int main(int argc, char **argv)
|
||||
if (files_source)
|
||||
read_symbols_from_files(files_source);
|
||||
|
||||
/*
|
||||
* When there's no vmlinux, don't print warnings about
|
||||
* unresolved symbols (since there'll be too many ;)
|
||||
*/
|
||||
if (!have_vmlinux)
|
||||
warn("Symbol info of vmlinux is missing. Unresolved symbol check will be entirely skipped.\n");
|
||||
|
||||
err = 0;
|
||||
|
||||
for (mod = modules; mod; mod = mod->next) {
|
||||
char fname[PATH_MAX];
|
||||
|
||||
if (mod->skip)
|
||||
if (mod->is_vmlinux || mod->from_dump)
|
||||
continue;
|
||||
|
||||
buf.pos = 0;
|
||||
@@ -2662,13 +2653,6 @@ int main(int argc, char **argv)
|
||||
struct symbol *s;
|
||||
|
||||
for (s = symbolhash[n]; s; s = s->next) {
|
||||
/*
|
||||
* Do not check "vmlinux". This avoids the same warnings
|
||||
* shown twice, and false-positives for ARCH=um.
|
||||
*/
|
||||
if (is_vmlinux(s->module->name) && !s->module->is_dot_o)
|
||||
continue;
|
||||
|
||||
if (s->is_static)
|
||||
warn("\"%s\" [%s] is a static %s\n",
|
||||
s->name, s->module->name,
|
||||
|
||||
+7
-12
@@ -111,29 +111,29 @@ buf_write(struct buffer *buf, const char *s, int len);
|
||||
|
||||
struct namespace_list {
|
||||
struct namespace_list *next;
|
||||
char namespace[0];
|
||||
char namespace[];
|
||||
};
|
||||
|
||||
struct module {
|
||||
struct module *next;
|
||||
const char *name;
|
||||
int gpl_compatible;
|
||||
struct symbol *unres;
|
||||
int from_dump; /* 1 if module was loaded from *.symvers */
|
||||
int is_vmlinux;
|
||||
int seen;
|
||||
int skip;
|
||||
int has_init;
|
||||
int has_cleanup;
|
||||
struct buffer dev_table_buf;
|
||||
char srcversion[25];
|
||||
int is_dot_o;
|
||||
// Missing namespace dependencies
|
||||
struct namespace_list *missing_namespaces;
|
||||
// Actual imported namespaces
|
||||
struct namespace_list *imported_namespaces;
|
||||
char name[];
|
||||
};
|
||||
|
||||
struct elf_info {
|
||||
unsigned long size;
|
||||
size_t size;
|
||||
Elf_Ehdr *hdr;
|
||||
Elf_Shdr *sechdrs;
|
||||
Elf_Sym *symtab_start;
|
||||
@@ -187,16 +187,11 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
|
||||
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);
|
||||
char *read_text_file(const char *filename);
|
||||
char *get_line(char **stringp);
|
||||
|
||||
enum loglevel {
|
||||
LOG_WARN,
|
||||
|
||||
+20
-97
@@ -258,9 +258,8 @@ static int parse_file(const char *fname, struct md4_ctx *md)
|
||||
char *file;
|
||||
unsigned long i, len;
|
||||
|
||||
file = grab_file(fname, &len);
|
||||
if (!file)
|
||||
return 0;
|
||||
file = read_text_file(fname);
|
||||
len = strlen(file);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
/* Collapse and ignore \ and CR. */
|
||||
@@ -287,7 +286,7 @@ static int parse_file(const char *fname, struct md4_ctx *md)
|
||||
|
||||
add_char(file[i], md);
|
||||
}
|
||||
release_file(file, len);
|
||||
free(file);
|
||||
return 1;
|
||||
}
|
||||
/* Check whether the file is a static library or not */
|
||||
@@ -304,9 +303,8 @@ static int is_static_library(const char *objfile)
|
||||
* to figure out source files. */
|
||||
static int parse_source_files(const char *objfile, struct md4_ctx *md)
|
||||
{
|
||||
char *cmd, *file, *line, *dir;
|
||||
char *cmd, *file, *line, *dir, *pos;
|
||||
const char *base;
|
||||
unsigned long flen, pos = 0;
|
||||
int dirlen, ret = 0, check_files = 0;
|
||||
|
||||
cmd = NOFAIL(malloc(strlen(objfile) + sizeof("..cmd")));
|
||||
@@ -324,14 +322,12 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md)
|
||||
strncpy(dir, objfile, dirlen);
|
||||
dir[dirlen] = '\0';
|
||||
|
||||
file = grab_file(cmd, &flen);
|
||||
if (!file) {
|
||||
warn("could not find %s for %s\n", cmd, objfile);
|
||||
goto out;
|
||||
}
|
||||
file = read_text_file(cmd);
|
||||
|
||||
pos = file;
|
||||
|
||||
/* Sum all files in the same dir or subdirs. */
|
||||
while ((line = get_next_line(&pos, file, flen)) != NULL) {
|
||||
while ((line = get_line(&pos))) {
|
||||
char* p = line;
|
||||
|
||||
if (strncmp(line, "source_", sizeof("source_")-1) == 0) {
|
||||
@@ -382,8 +378,7 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md)
|
||||
/* Everyone parsed OK */
|
||||
ret = 1;
|
||||
out_file:
|
||||
release_file(file, flen);
|
||||
out:
|
||||
free(file);
|
||||
free(dir);
|
||||
free(cmd);
|
||||
return ret;
|
||||
@@ -392,106 +387,34 @@ out:
|
||||
/* Calc and record src checksum. */
|
||||
void get_src_version(const char *modname, char sum[], unsigned sumlen)
|
||||
{
|
||||
void *file;
|
||||
unsigned long len;
|
||||
char *buf, *pos, *firstline;
|
||||
struct md4_ctx md;
|
||||
char *sources, *end, *fname;
|
||||
char *fname;
|
||||
char filelist[PATH_MAX + 1];
|
||||
|
||||
/* objects for a module are listed in the first line of *.mod file. */
|
||||
snprintf(filelist, sizeof(filelist), "%.*smod",
|
||||
(int)strlen(modname) - 1, modname);
|
||||
|
||||
file = grab_file(filelist, &len);
|
||||
if (!file)
|
||||
/* not a module or .mod file missing - ignore */
|
||||
return;
|
||||
buf = read_text_file(filelist);
|
||||
|
||||
sources = file;
|
||||
|
||||
end = strchr(sources, '\n');
|
||||
if (!end) {
|
||||
pos = buf;
|
||||
firstline = get_line(&pos);
|
||||
if (!firstline) {
|
||||
warn("bad ending versions file for %s\n", modname);
|
||||
goto release;
|
||||
goto free;
|
||||
}
|
||||
*end = '\0';
|
||||
|
||||
md4_init(&md);
|
||||
while ((fname = strsep(&sources, " ")) != NULL) {
|
||||
while ((fname = strsep(&firstline, " "))) {
|
||||
if (!*fname)
|
||||
continue;
|
||||
if (!(is_static_library(fname)) &&
|
||||
!parse_source_files(fname, &md))
|
||||
goto release;
|
||||
goto free;
|
||||
}
|
||||
|
||||
md4_final_ascii(&md, sum, sumlen);
|
||||
release:
|
||||
release_file(file, len);
|
||||
}
|
||||
|
||||
static void write_version(const char *filename, const char *sum,
|
||||
unsigned long offset)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open(filename, O_RDWR);
|
||||
if (fd < 0) {
|
||||
warn("changing sum in %s failed: %s\n",
|
||||
filename, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
|
||||
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) {
|
||||
warn("writing sum in %s failed: %s\n",
|
||||
filename, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static int strip_rcs_crap(char *version)
|
||||
{
|
||||
unsigned int len, full_len;
|
||||
|
||||
if (strncmp(version, "$Revision", strlen("$Revision")) != 0)
|
||||
return 0;
|
||||
|
||||
/* Space for version string follows. */
|
||||
full_len = strlen(version) + strlen(version + strlen(version) + 1) + 2;
|
||||
|
||||
/* Move string to start with version number: prefix will be
|
||||
* $Revision$ or $Revision: */
|
||||
len = strlen("$Revision");
|
||||
if (version[len] == ':' || version[len] == '$')
|
||||
len++;
|
||||
while (isspace(version[len]))
|
||||
len++;
|
||||
memmove(version, version+len, full_len-len);
|
||||
full_len -= len;
|
||||
|
||||
/* Preserve up to next whitespace. */
|
||||
len = 0;
|
||||
while (version[len] && !isspace(version[len]))
|
||||
len++;
|
||||
memmove(version + len, version + strlen(version),
|
||||
full_len - strlen(version));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Clean up RCS-style version numbers. */
|
||||
void maybe_frob_rcs_version(const char *modfilename,
|
||||
char *version,
|
||||
void *modinfo,
|
||||
unsigned long version_offset)
|
||||
{
|
||||
if (strip_rcs_crap(version))
|
||||
write_version(modfilename, version, version_offset);
|
||||
free:
|
||||
free(buf);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user