aboutsummaryrefslogtreecommitdiff
path: root/scripts/mod
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/mod')
-rw-r--r--scripts/mod/.gitignore1
-rw-r--r--scripts/mod/devicetable-offsets.c3
-rw-r--r--scripts/mod/file2alias.c80
-rw-r--r--scripts/mod/mk_elfconfig.c1
-rw-r--r--scripts/mod/modpost.c117
-rw-r--r--scripts/mod/modpost.h2
-rw-r--r--scripts/mod/sumversion.c6
7 files changed, 138 insertions, 72 deletions
diff --git a/scripts/mod/.gitignore b/scripts/mod/.gitignore
index 33bae0df4de..3bd11b60317 100644
--- a/scripts/mod/.gitignore
+++ b/scripts/mod/.gitignore
@@ -2,4 +2,3 @@ elfconfig.h
mk_elfconfig
modpost
devicetable-offsets.h
-
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
index bb5d115ca67..f282516acc7 100644
--- a/scripts/mod/devicetable-offsets.c
+++ b/scripts/mod/devicetable-offsets.c
@@ -174,6 +174,9 @@ int main(void)
DEVID_FIELD(x86_cpu_id, model);
DEVID_FIELD(x86_cpu_id, vendor);
+ DEVID(cpu_feature);
+ DEVID_FIELD(cpu_feature, feature);
+
DEVID(mei_cl_device_id);
DEVID_FIELD(mei_cl_device_id, name);
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 23708636b05..e614ef689ee 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -42,7 +42,7 @@ typedef unsigned char __u8;
/* This array collects all instances that use the generic do_table */
struct devtable {
- const char *device_id; /* name of table, __mod_<name>_device_table. */
+ const char *device_id; /* name of table, __mod_<name>__*_device_table. */
unsigned long id_size;
void *function;
};
@@ -146,7 +146,8 @@ static void device_id_check(const char *modname, const char *device_id,
if (size % id_size || size < id_size) {
fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
- "of the size of section __mod_%s_device_table=%lu.\n"
+ "of the size of "
+ "section __mod_%s__<identifier>_device_table=%lu.\n"
"Fix definition of struct %s_device_id "
"in mod_devicetable.h\n",
modname, device_id, id_size, device_id, size, device_id);
@@ -210,8 +211,8 @@ static void do_usb_entry(void *symval,
range_lo < 0x9 ? "[%X-9" : "[%X",
range_lo);
sprintf(alias + strlen(alias),
- range_hi > 0xA ? "a-%X]" : "%X]",
- range_lo);
+ range_hi > 0xA ? "A-%X]" : "%X]",
+ range_hi);
}
}
if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1))
@@ -643,28 +644,26 @@ ADD_TO_DEVTABLE("pcmcia", pcmcia_device_id, do_pcmcia_entry);
static int do_of_entry (const char *filename, void *symval, char *alias)
{
- int len;
- char *tmp;
- DEF_FIELD_ADDR(symval, of_device_id, name);
- DEF_FIELD_ADDR(symval, of_device_id, type);
- DEF_FIELD_ADDR(symval, of_device_id, compatible);
-
- len = sprintf (alias, "of:N%sT%s",
- (*name)[0] ? *name : "*",
- (*type)[0] ? *type : "*");
-
- if (compatible[0])
- sprintf (&alias[len], "%sC%s",
- (*type)[0] ? "*" : "",
- *compatible);
-
- /* Replace all whitespace with underscores */
- for (tmp = alias; tmp && *tmp; tmp++)
- if (isspace (*tmp))
- *tmp = '_';
-
- add_wildcard(alias);
- return 1;
+ int len;
+ char *tmp;
+ DEF_FIELD_ADDR(symval, of_device_id, name);
+ DEF_FIELD_ADDR(symval, of_device_id, type);
+ DEF_FIELD_ADDR(symval, of_device_id, compatible);
+
+ len = sprintf(alias, "of:N%sT%s", (*name)[0] ? *name : "*",
+ (*type)[0] ? *type : "*");
+
+ if (compatible[0])
+ sprintf(&alias[len], "%sC%s", (*type)[0] ? "*" : "",
+ *compatible);
+
+ /* Replace all whitespace with underscores */
+ for (tmp = alias; tmp && *tmp; tmp++)
+ if (isspace (*tmp))
+ *tmp = '_';
+
+ add_wildcard(alias);
+ return 1;
}
ADD_TO_DEVTABLE("of", of_device_id, do_of_entry);
@@ -1110,7 +1109,7 @@ static int do_amba_entry(const char *filename,
}
ADD_TO_DEVTABLE("amba", amba_id, do_amba_entry);
-/* LOOKS like x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature:*,FEAT,*
+/* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,*
* All fields are numbers. It would be nicer to use strings for vendor
* and feature, but getting those out of the build system here is too
* complicated.
@@ -1124,10 +1123,10 @@ static int do_x86cpu_entry(const char *filename, void *symval,
DEF_FIELD(symval, x86_cpu_id, model);
DEF_FIELD(symval, x86_cpu_id, vendor);
- strcpy(alias, "x86cpu:");
- ADD(alias, "vendor:", vendor != X86_VENDOR_ANY, vendor);
- ADD(alias, ":family:", family != X86_FAMILY_ANY, family);
- ADD(alias, ":model:", model != X86_MODEL_ANY, model);
+ strcpy(alias, "cpu:type:x86,");
+ ADD(alias, "ven", vendor != X86_VENDOR_ANY, vendor);
+ ADD(alias, "fam", family != X86_FAMILY_ANY, family);
+ ADD(alias, "mod", model != X86_MODEL_ANY, model);
strcat(alias, ":feature:*");
if (feature != X86_FEATURE_ANY)
sprintf(alias + strlen(alias), "%04X*", feature);
@@ -1135,6 +1134,16 @@ static int do_x86cpu_entry(const char *filename, void *symval,
}
ADD_TO_DEVTABLE("x86cpu", x86_cpu_id, do_x86cpu_entry);
+/* LOOKS like cpu:type:*:feature:*FEAT* */
+static int do_cpu_entry(const char *filename, void *symval, char *alias)
+{
+ DEF_FIELD(symval, cpu_feature, feature);
+
+ sprintf(alias, "cpu:type:*:feature:*%04X*", feature);
+ return 1;
+}
+ADD_TO_DEVTABLE("cpu", cpu_feature, do_cpu_entry);
+
/* Looks like: mei:S */
static int do_mei_entry(const char *filename, void *symval,
char *alias)
@@ -1206,7 +1215,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
{
void *symval;
char *zeros = NULL;
- const char *name;
+ const char *name, *identifier;
unsigned int namelen;
/* We're looking for a section relative symbol */
@@ -1217,7 +1226,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
return;
- /* All our symbols are of form <prefix>__mod_XXX_device_table. */
+ /* All our symbols are of form <prefix>__mod_<name>__<identifier>_device_table. */
name = strstr(symname, "__mod_");
if (!name)
return;
@@ -1227,7 +1236,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
return;
if (strcmp(name + namelen - strlen("_device_table"), "_device_table"))
return;
- namelen -= strlen("_device_table");
+ identifier = strstr(name, "__");
+ if (!identifier)
+ return;
+ namelen = identifier - name;
/* Handle all-NULL symbols allocated into .bss */
if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) {
diff --git a/scripts/mod/mk_elfconfig.c b/scripts/mod/mk_elfconfig.c
index 639bca7ba55..a4fd71d71d6 100644
--- a/scripts/mod/mk_elfconfig.c
+++ b/scripts/mod/mk_elfconfig.c
@@ -54,4 +54,3 @@ main(int argc, char **argv)
return 0;
}
-
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 8247979e8f6..9d9c5b905b3 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -17,6 +17,7 @@
#include <string.h>
#include <limits.h>
#include <stdbool.h>
+#include <errno.h>
#include "modpost.h"
#include "../../include/generated/autoconf.h"
#include "../../include/linux/license.h"
@@ -37,6 +38,8 @@ static int warn_unresolved = 0;
/* How a symbol is exported */
static int sec_mismatch_count = 0;
static int sec_mismatch_verbose = 1;
+/* ignore missing files */
+static int ignore_missing_files;
enum export {
export_plain, export_unused, export_gpl,
@@ -161,7 +164,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 */
+ unsigned int preloaded:1; /* 1 if symbol from Module.symvers, or crc */
enum export export; /* Type of export */
char name[0];
};
@@ -313,7 +316,7 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod,
s->module->name,
is_vmlinux(s->module->name) ?"":".ko");
} else {
- /* In case Modules.symvers was out of date */
+ /* In case Module.symvers was out of date */
s->module = mod;
}
}
@@ -329,8 +332,11 @@ static void sym_update_crc(const char *name, struct module *mod,
{
struct symbol *s = find_symbol(name);
- if (!s)
+ if (!s) {
s = new_symbol(name, mod, export);
+ /* Don't complain when we find it later. */
+ s->preloaded = 1;
+ }
s->crc = crc;
s->crc_valid = 1;
}
@@ -407,6 +413,11 @@ static int parse_elf(struct elf_info *info, const char *filename)
hdr = grab_file(filename, &info->size);
if (!hdr) {
+ if (ignore_missing_files) {
+ fprintf(stderr, "%s: %s (ignored)\n", filename,
+ strerror(errno));
+ return 0;
+ }
perror(filename);
exit(1);
}
@@ -573,12 +584,16 @@ static int ignore_undef_symbol(struct elf_info *info, const char *symname)
if (strncmp(symname, "_restgpr_", sizeof("_restgpr_") - 1) == 0 ||
strncmp(symname, "_savegpr_", sizeof("_savegpr_") - 1) == 0 ||
strncmp(symname, "_rest32gpr_", sizeof("_rest32gpr_") - 1) == 0 ||
- strncmp(symname, "_save32gpr_", sizeof("_save32gpr_") - 1) == 0)
+ strncmp(symname, "_save32gpr_", sizeof("_save32gpr_") - 1) == 0 ||
+ strncmp(symname, "_restvr_", sizeof("_restvr_") - 1) == 0 ||
+ strncmp(symname, "_savevr_", sizeof("_savevr_") - 1) == 0)
return 1;
if (info->hdr->e_machine == EM_PPC64)
/* Special register function linked on all modules during final link of .ko */
if (strncmp(symname, "_restgpr0_", sizeof("_restgpr0_") - 1) == 0 ||
- strncmp(symname, "_savegpr0_", sizeof("_savegpr0_") - 1) == 0)
+ strncmp(symname, "_savegpr0_", sizeof("_savegpr0_") - 1) == 0 ||
+ strncmp(symname, "_restvr_", sizeof("_restvr_") - 1) == 0 ||
+ strncmp(symname, "_savevr_", sizeof("_savevr_") - 1) == 0)
return 1;
/* Do not ignore this symbol */
return 0;
@@ -599,17 +614,19 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
else
export = export_from_sec(info, get_secindex(info, sym));
+ /* CRC'd symbol */
+ if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
+ crc = (unsigned int) sym->st_value;
+ sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
+ export);
+ }
+
switch (sym->st_shndx) {
case SHN_COMMON:
- warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name);
- break;
- case SHN_ABS:
- /* CRC'd symbol */
- if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
- crc = (unsigned int) sym->st_value;
- sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
- export);
- }
+ if (!strncmp(symname, "__gnu_lto_", sizeof("__gnu_lto_")-1)) {
+ /* Should warn here, but modpost runs before the linker */
+ } else
+ warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name);
break;
case SHN_UNDEF:
/* undefined symbol */
@@ -835,6 +852,7 @@ static const char *section_white_list[] =
".xt.lit", /* xtensa */
".arcextmap*", /* arc */
".gnu.linkonce.arcext*", /* arc : modules */
+ ".gnu.lto*",
NULL
};
@@ -844,7 +862,7 @@ static const char *section_white_list[] =
* without "ax" / "aw".
*/
static void check_section(const char *modname, struct elf_info *elf,
- Elf_Shdr *sechdr)
+ Elf_Shdr *sechdr)
{
const char *sec = sech_name(elf, sechdr);
@@ -1278,12 +1296,12 @@ static void print_section_list(const char * const list[20])
*/
static void report_sec_mismatch(const char *modname,
const struct sectioncheck *mismatch,
- const char *fromsec,
- unsigned long long fromaddr,
- const char *fromsym,
- int from_is_func,
- const char *tosec, const char *tosym,
- int to_is_func)
+ const char *fromsec,
+ unsigned long long fromaddr,
+ const char *fromsym,
+ int from_is_func,
+ const char *tosec, const char *tosym,
+ int to_is_func)
{
const char *from, *from_p;
const char *to, *to_p;
@@ -1423,7 +1441,7 @@ static void report_sec_mismatch(const char *modname,
}
static void check_section_mismatch(const char *modname, struct elf_info *elf,
- Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
+ Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
{
const char *tosec;
const struct sectioncheck *mismatch;
@@ -1441,6 +1459,10 @@ static void check_section_mismatch(const char *modname, struct elf_info *elf,
to = find_elf_symbol(elf, r->r_addend, sym);
tosym = sym_name(elf, to);
+ if (!strncmp(fromsym, "reference___initcall",
+ sizeof("reference___initcall")-1))
+ return;
+
/* check whitelist - we may ignore it */
if (secref_whitelist(mismatch,
fromsec, fromsym, tosec, tosym)) {
@@ -1488,6 +1510,16 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
#define R_ARM_JUMP24 29
#endif
+#ifndef R_ARM_THM_CALL
+#define R_ARM_THM_CALL 10
+#endif
+#ifndef R_ARM_THM_JUMP24
+#define R_ARM_THM_JUMP24 30
+#endif
+#ifndef R_ARM_THM_JUMP19
+#define R_ARM_THM_JUMP19 51
+#endif
+
static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
{
unsigned int r_typ = ELF_R_TYPE(r->r_info);
@@ -1496,15 +1528,18 @@ static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
case R_ARM_ABS32:
/* From ARM ABI: (S + A) | T */
r->r_addend = (int)(long)
- (elf->symtab_start + ELF_R_SYM(r->r_info));
+ (elf->symtab_start + ELF_R_SYM(r->r_info));
break;
case R_ARM_PC24:
case R_ARM_CALL:
case R_ARM_JUMP24:
+ case R_ARM_THM_CALL:
+ case R_ARM_THM_JUMP24:
+ case R_ARM_THM_JUMP19:
/* From ARM ABI: ((S + A) | T) - P */
r->r_addend = (int)(long)(elf->hdr +
- sechdr->sh_offset +
- (r->r_offset - sechdr->sh_addr));
+ sechdr->sh_offset +
+ (r->r_offset - sechdr->sh_addr));
break;
default:
return 1;
@@ -1536,7 +1571,7 @@ static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
}
static void section_rela(const char *modname, struct elf_info *elf,
- Elf_Shdr *sechdr)
+ Elf_Shdr *sechdr)
{
Elf_Sym *sym;
Elf_Rela *rela;
@@ -1580,7 +1615,7 @@ static void section_rela(const char *modname, struct elf_info *elf,
}
static void section_rel(const char *modname, struct elf_info *elf,
- Elf_Shdr *sechdr)
+ Elf_Shdr *sechdr)
{
Elf_Sym *sym;
Elf_Rel *rel;
@@ -1650,7 +1685,7 @@ static void section_rel(const char *modname, struct elf_info *elf,
* be discarded and warns about it.
**/
static void check_sec_ref(struct module *mod, const char *modname,
- struct elf_info *elf)
+ struct elf_info *elf)
{
int i;
Elf_Shdr *sechdrs = elf->sechdrs;
@@ -1666,6 +1701,19 @@ static void check_sec_ref(struct module *mod, const char *modname,
}
}
+static char *remove_dot(char *s)
+{
+ char *end;
+ int n = strcspn(s, ".");
+
+ if (n > 0 && s[n] != 0) {
+ strtoul(s + n + 1, &end, 10);
+ if (end > s + n + 1 && (*end == '.' || *end == 0))
+ s[n] = 0;
+ }
+ return s;
+}
+
static void read_symbols(char *modname)
{
const char *symname;
@@ -1704,7 +1752,7 @@ static void read_symbols(char *modname)
}
for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
- symname = info.strtab + sym->st_name;
+ symname = remove_dot(info.strtab + sym->st_name);
handle_modversions(mod, &info, sym, symname);
handle_moddevtable(mod, &info, sym, symname);
@@ -1853,7 +1901,7 @@ static void add_header(struct buffer *b, struct module *mod)
buf_printf(b, "\n");
buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
buf_printf(b, "\n");
- buf_printf(b, "struct module __this_module\n");
+ buf_printf(b, "__visible struct module __this_module\n");
buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n");
buf_printf(b, "\t.name = KBUILD_MODNAME,\n");
if (mod->has_init)
@@ -1897,7 +1945,7 @@ static int add_versions(struct buffer *b, struct module *mod)
s->name, mod->name);
} else {
merror("\"%s\" [%s.ko] undefined!\n",
- s->name, mod->name);
+ s->name, mod->name);
err = 1;
}
}
@@ -2065,8 +2113,10 @@ static void read_dump(const char *fname, unsigned int kernel)
s->preloaded = 1;
sym_update_crc(symname, mod, crc, export_no(export));
}
+ release_file(file, size);
return;
fail:
+ release_file(file, size);
fatal("parse error in symbol dump file\n");
}
@@ -2119,7 +2169,7 @@ int main(int argc, char **argv)
struct ext_sym_list *extsym_iter;
struct ext_sym_list *extsym_start = NULL;
- while ((opt = getopt(argc, argv, "i:I:e:msST:o:awM:K:")) != -1) {
+ while ((opt = getopt(argc, argv, "i:I:e:mnsST:o:awM:K:")) != -1) {
switch (opt) {
case 'i':
kernel_read = optarg;
@@ -2139,6 +2189,9 @@ int main(int argc, char **argv)
case 'm':
modversions = 1;
break;
+ case 'n':
+ ignore_missing_files = 1;
+ break;
case 'o':
dump_write = optarg;
break;
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 51207e4d5f8..168b43dc0a5 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -127,7 +127,7 @@ struct elf_info {
Elf_Section export_gpl_sec;
Elf_Section export_unused_gpl_sec;
Elf_Section export_gpl_future_sec;
- const char *strtab;
+ char *strtab;
char *modinfo;
unsigned int modinfo_len;
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
index 9dfcd6d988d..944418da9fe 100644
--- a/scripts/mod/sumversion.c
+++ b/scripts/mod/sumversion.c
@@ -214,7 +214,7 @@ static void md4_final_ascii(struct md4_ctx *mctx, char *out, unsigned int len)
mctx->block[14] = mctx->byte_count << 3;
mctx->block[15] = mctx->byte_count >> 29;
le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
- sizeof(uint64_t)) / sizeof(uint32_t));
+ sizeof(uint64_t)) / sizeof(uint32_t));
md4_transform(mctx->hash, mctx->block);
cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(uint32_t));
@@ -367,7 +367,7 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md)
break;
/* Terminate line at first space, to get rid of final ' \' */
while (*p) {
- if (isspace(*p)) {
+ if (isspace(*p)) {
*p = '\0';
break;
}
@@ -416,7 +416,7 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen)
basename = strrchr(modname, '/') + 1;
else
basename = modname;
- sprintf(filelist, "%s/%.*s.mod", modverdir,
+ snprintf(filelist, sizeof(filelist), "%s/%.*s.mod", modverdir,
(int) strlen(basename) - 2, basename);
file = grab_file(filelist, &len);