From 5818c683a619c534c113e1f66d24f636defc29bc Mon Sep 17 00:00:00 2001 From: Sami Tolvanen Date: Tue, 23 Oct 2018 15:15:35 -0700 Subject: modpost: validate symbol names also in find_elf_symbol If an ARM mapping symbol shares an address with a valid symbol, find_elf_symbol can currently return the mapping symbol instead, as the symbol is not validated. This can result in confusing warnings: WARNING: vmlinux.o(.text+0x18f4028): Section mismatch in reference from the function set_reset_devices() to the variable .init.text:$x.0 This change adds a call to is_valid_name to find_elf_symbol, similarly to how it's already used in find_elf_symbol2. Signed-off-by: Sami Tolvanen Signed-off-by: Masahiro Yamada --- scripts/mod/modpost.c | 50 ++++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 24 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 0d998c54564d..b709b2e623d6 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1204,6 +1204,30 @@ static int secref_whitelist(const struct sectioncheck *mismatch, return 1; } +static inline int is_arm_mapping_symbol(const char *str) +{ + return str[0] == '$' && strchr("axtd", str[1]) + && (str[2] == '\0' || str[2] == '.'); +} + +/* + * If there's no name there, ignore it; likewise, ignore it if it's + * one of the magic symbols emitted used by current ARM tools. + * + * Otherwise if find_symbols_between() returns those symbols, they'll + * fail the whitelist tests and cause lots of false alarms ... fixable + * only by merging __exit and __init sections into __text, bloating + * the kernel (which is especially evil on embedded platforms). + */ +static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym) +{ + const char *name = elf->strtab + sym->st_name; + + if (!name || !strlen(name)) + return 0; + return !is_arm_mapping_symbol(name); +} + /** * Find symbol based on relocation record info. * In some cases the symbol supplied is a valid symbol so @@ -1229,6 +1253,8 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr, continue; if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) continue; + if (!is_valid_name(elf, sym)) + continue; if (sym->st_value == addr) return sym; /* Find a symbol nearby - addr are maybe negative */ @@ -1247,30 +1273,6 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr, return NULL; } -static inline int is_arm_mapping_symbol(const char *str) -{ - return str[0] == '$' && strchr("axtd", str[1]) - && (str[2] == '\0' || str[2] == '.'); -} - -/* - * If there's no name there, ignore it; likewise, ignore it if it's - * one of the magic symbols emitted used by current ARM tools. - * - * Otherwise if find_symbols_between() returns those symbols, they'll - * fail the whitelist tests and cause lots of false alarms ... fixable - * only by merging __exit and __init sections into __text, bloating - * the kernel (which is especially evil on embedded platforms). - */ -static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym) -{ - const char *name = elf->strtab + sym->st_name; - - if (!name || !strlen(name)) - return 0; - return !is_arm_mapping_symbol(name); -} - /* * 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. -- cgit v1.2.3 From 0987abcbeea4c87aef80a6138efc13ed0798fcf2 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 14 Nov 2018 16:56:01 -0800 Subject: modpost: drop unused command line switches Drop modpost command line switches that are no longer used by makefile.modpost, upon request from Sam Ravnborg , who wrote: modpost is not supposed to be used outside the kernel build. [...] I checked if there were any options supported by modpost that was not configurable in Makefile.modpost. And I could see that the -M and -K options in getopt() were leftovers. The code that used these option was dropped in: commit a8773769d1a1 ("Kbuild: clear marker out of modpost") Could you add a patch that delete these on top of what you already have. https://lore.kernel.org/lkml/20181020140835.GA3351@ravnborg.org/ Suggested-by: Sam Ravnborg Signed-off-by: Paul Walmsley Signed-off-by: Paul Walmsley Acked-by: Sam Ravnborg Signed-off-by: Masahiro Yamada --- 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 b709b2e623d6..c64066dcd2e4 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2418,7 +2418,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:mnsST:o:awM:K:E")) != -1) { + while ((opt = getopt(argc, argv, "i:I:e:mnsST:o:awE")) != -1) { switch (opt) { case 'i': kernel_read = optarg; -- cgit v1.2.3 From a4d26f1a0958bb1c2b60c6f1e67c6f5d43e2647b Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 21 Nov 2018 13:14:13 -0800 Subject: modpost: skip ELF local symbols during section mismatch check During development of a serial console driver with a gcc 8.2.0 toolchain for RISC-V, the following modpost warning appeared: ---- WARNING: vmlinux.o(.data+0x19b10): Section mismatch in reference from the variable .LANCHOR1 to the function .init.text:sifive_serial_console_setup() The variable .LANCHOR1 references the function __init sifive_serial_console_setup() If the reference is valid then annotate the variable with __init* or __refdata (see linux/init.h) or name the variable: *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console ---- ".LANCHOR1" is an ELF local symbol, automatically created by gcc's section anchor generation code: https://gcc.gnu.org/onlinedocs/gccint/Anchored-Addresses.html https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/varasm.c;h=cd9591a45617464946dcf9a126dde277d9de9804;hb=9fb89fa845c1b2e0a18d85ada0b077c84508ab78#l7473 This was verified by compiling the kernel with -fno-section-anchors and observing that the ".LANCHOR1" ELF local symbol disappeared, and modpost no longer warned about the section mismatch. The serial driver code idiom triggering the warning is standard Linux serial driver practice that has a specific whitelist inclusion in modpost.c. I'm neither a modpost nor an ELF expert, but naively, it doesn't seem useful for modpost to report section mismatch warnings caused by ELF local symbols by default. Local symbols have compiler-generated names, and thus bypass modpost's whitelisting algorithm, which relies on the presence of a non-autogenerated symbol name. This increases the likelihood that false positive warnings will be generated (as in the above case). Thus, disable section mismatch reporting on ELF local symbols. The rationale here is similar to that of commit 2e3a10a1551d ("ARM: avoid ARM binutils leaking ELF local symbols") and of similar code already present in modpost.c: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/scripts/mod/modpost.c?h=v4.19-rc4&id=7876320f88802b22d4e2daf7eb027dd14175a0f8#n1256 This third version of the patch implements a suggestion from Masahiro Yamada to restructure the code as an additional pattern matching step inside secref_whitelist(), and further improves the patch description. Signed-off-by: Paul Walmsley Signed-off-by: Paul Walmsley Acked-by: Sam Ravnborg Signed-off-by: Masahiro Yamada --- scripts/mod/modpost.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index c64066dcd2e4..3aab410f020e 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1163,6 +1163,14 @@ static const struct sectioncheck *section_mismatch( * fromsec = text section * refsymname = *.constprop.* * + * Pattern 6: + * Hide section mismatch warnings for ELF local symbols. The goal + * is to eliminate false positive modpost warnings caused by + * compiler-generated ELF local symbol names such as ".LANCHOR1". + * Autogenerated symbol names bypass modpost's "Pattern 2" + * whitelisting, which relies on pattern-matching against symbol + * names to work. (One situation where gcc can autogenerate ELF + * local symbols is when "-fsection-anchors" is used.) **/ static int secref_whitelist(const struct sectioncheck *mismatch, const char *fromsec, const char *fromsym, @@ -1201,6 +1209,10 @@ static int secref_whitelist(const struct sectioncheck *mismatch, match(fromsym, optim_symbols)) return 0; + /* Check for pattern 6 */ + if (strstarts(fromsym, ".L")) + return 0; + return 1; } -- cgit v1.2.3 From ec91e78d378cc5d4b43805a1227d8e04e5dfa17d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 22 Nov 2018 13:28:41 +0900 Subject: modpost: file2alias: go back to simple devtable lookup Commit e49ce14150c6 ("modpost: use linker section to generate table.") was not so cool as we had expected first; it ended up with ugly section hacks when commit dd2a3acaecd7 ("mod/file2alias: make modpost compile on darwin again") came in. Given a certain degree of unknowledge about the link stage of host programs, I really want to see simple, stupid table lookup so that this works in the same way regardless of the underlying executable format. Signed-off-by: Masahiro Yamada Acked-by: Mathieu Malaterre --- scripts/mod/file2alias.c | 144 ++++++++++++++++------------------------------- 1 file changed, 49 insertions(+), 95 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 28a61665bb9c..7e4aededfd37 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -50,46 +50,6 @@ struct devtable { void *function; }; -#define ___cat(a,b) a ## b -#define __cat(a,b) ___cat(a,b) - -/* we need some special handling for this host tool running eventually on - * Darwin. The Mach-O section handling is a bit different than ELF section - * handling. The differnces in detail are: - * a) we have segments which have sections - * b) we need a API call to get the respective section symbols */ -#if defined(__MACH__) -#include - -#define INIT_SECTION(name) do { \ - unsigned long name ## _len; \ - char *__cat(pstart_,name) = getsectdata("__TEXT", \ - #name, &__cat(name,_len)); \ - char *__cat(pstop_,name) = __cat(pstart_,name) + \ - __cat(name, _len); \ - __cat(__start_,name) = (void *)__cat(pstart_,name); \ - __cat(__stop_,name) = (void *)__cat(pstop_,name); \ - } while (0) -#define SECTION(name) __attribute__((section("__TEXT, " #name))) - -struct devtable **__start___devtable, **__stop___devtable; -#else -#define INIT_SECTION(name) /* no-op for ELF */ -#define SECTION(name) __attribute__((section(#name))) - -/* We construct a table of pointers in an ELF section (pointers generally - * go unpadded by gcc). ld creates boundary syms for us. */ -extern struct devtable *__start___devtable[], *__stop___devtable[]; -#endif /* __MACH__ */ - -#if !defined(__used) -# if __GNUC__ == 3 && __GNUC_MINOR__ < 3 -# define __used __attribute__((__unused__)) -# else -# define __used __attribute__((__used__)) -# endif -#endif - /* Define a variable f that holds the value of field f of struct devid * based at address m. */ @@ -110,16 +70,6 @@ extern struct devtable *__start___devtable[], *__stop___devtable[]; #define DEF_FIELD_ADDR(m, devid, f) \ DEF_FIELD_ADDR_VAR(m, devid, f, f) -/* Add a table entry. We test function type matches while we're here. */ -#define ADD_TO_DEVTABLE(device_id, type, function) \ - static struct devtable __cat(devtable,__LINE__) = { \ - device_id + 0*sizeof((function)((const char *)NULL, \ - (void *)NULL, \ - (char *)NULL)), \ - SIZE_##type, (function) }; \ - static struct devtable *SECTION(__devtable) __used \ - __cat(devtable_ptr,__LINE__) = &__cat(devtable,__LINE__) - #define ADD(str, sep, cond, field) \ do { \ strcat(str, sep); \ @@ -439,7 +389,6 @@ static int do_hid_entry(const char *filename, return 1; } -ADD_TO_DEVTABLE("hid", hid_device_id, do_hid_entry); /* Looks like: ieee1394:venNmoNspNverN */ static int do_ieee1394_entry(const char *filename, @@ -464,7 +413,6 @@ static int do_ieee1394_entry(const char *filename, add_wildcard(alias); return 1; } -ADD_TO_DEVTABLE("ieee1394", ieee1394_device_id, do_ieee1394_entry); /* Looks like: pci:vNdNsvNsdNbcNscNiN. */ static int do_pci_entry(const char *filename, @@ -508,7 +456,6 @@ static int do_pci_entry(const char *filename, add_wildcard(alias); return 1; } -ADD_TO_DEVTABLE("pci", pci_device_id, do_pci_entry); /* looks like: "ccw:tNmNdtNdmN" */ static int do_ccw_entry(const char *filename, @@ -532,7 +479,6 @@ static int do_ccw_entry(const char *filename, add_wildcard(alias); return 1; } -ADD_TO_DEVTABLE("ccw", ccw_device_id, do_ccw_entry); /* looks like: "ap:tN" */ static int do_ap_entry(const char *filename, @@ -543,7 +489,6 @@ static int do_ap_entry(const char *filename, sprintf(alias, "ap:t%02X*", dev_type); return 1; } -ADD_TO_DEVTABLE("ap", ap_device_id, do_ap_entry); /* looks like: "css:tN" */ static int do_css_entry(const char *filename, @@ -554,7 +499,6 @@ static int do_css_entry(const char *filename, sprintf(alias, "css:t%01X", type); return 1; } -ADD_TO_DEVTABLE("css", css_device_id, do_css_entry); /* Looks like: "serio:tyNprNidNexN" */ static int do_serio_entry(const char *filename, @@ -574,7 +518,6 @@ static int do_serio_entry(const char *filename, add_wildcard(alias); return 1; } -ADD_TO_DEVTABLE("serio", serio_device_id, do_serio_entry); /* looks like: "acpi:ACPI0003" or "acpi:PNP0C0B" or "acpi:LNXVIDEO" or * "acpi:bbsspp" (bb=base-class, ss=sub-class, pp=prog-if) @@ -612,7 +555,6 @@ static int do_acpi_entry(const char *filename, } return 1; } -ADD_TO_DEVTABLE("acpi", acpi_device_id, do_acpi_entry); /* looks like: "pnp:dD" */ static void do_pnp_device_entry(void *symval, unsigned long size, @@ -736,7 +678,6 @@ static int do_pcmcia_entry(const char *filename, add_wildcard(alias); return 1; } -ADD_TO_DEVTABLE("pcmcia", pcmcia_device_id, do_pcmcia_entry); static int do_vio_entry(const char *filename, void *symval, char *alias) @@ -756,7 +697,6 @@ static int do_vio_entry(const char *filename, void *symval, add_wildcard(alias); return 1; } -ADD_TO_DEVTABLE("vio", vio_device_id, do_vio_entry); #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) @@ -829,7 +769,6 @@ static int do_input_entry(const char *filename, void *symval, do_input(alias, *swbit, 0, INPUT_DEVICE_ID_SW_MAX); return 1; } -ADD_TO_DEVTABLE("input", input_device_id, do_input_entry); static int do_eisa_entry(const char *filename, void *symval, char *alias) @@ -841,7 +780,6 @@ static int do_eisa_entry(const char *filename, void *symval, strcat(alias, "*"); return 1; } -ADD_TO_DEVTABLE("eisa", eisa_device_id, do_eisa_entry); /* Looks like: parisc:tNhvNrevNsvN */ static int do_parisc_entry(const char *filename, void *symval, @@ -861,7 +799,6 @@ static int do_parisc_entry(const char *filename, void *symval, add_wildcard(alias); return 1; } -ADD_TO_DEVTABLE("parisc", parisc_device_id, do_parisc_entry); /* Looks like: sdio:cNvNdN. */ static int do_sdio_entry(const char *filename, @@ -878,7 +815,6 @@ static int do_sdio_entry(const char *filename, add_wildcard(alias); return 1; } -ADD_TO_DEVTABLE("sdio", sdio_device_id, do_sdio_entry); /* Looks like: ssb:vNidNrevN. */ static int do_ssb_entry(const char *filename, @@ -895,7 +831,6 @@ static int do_ssb_entry(const char *filename, add_wildcard(alias); return 1; } -ADD_TO_DEVTABLE("ssb", ssb_device_id, do_ssb_entry); /* Looks like: bcma:mNidNrevNclN. */ static int do_bcma_entry(const char *filename, @@ -914,7 +849,6 @@ static int do_bcma_entry(const char *filename, add_wildcard(alias); return 1; } -ADD_TO_DEVTABLE("bcma", bcma_device_id, do_bcma_entry); /* Looks like: virtio:dNvN */ static int do_virtio_entry(const char *filename, void *symval, @@ -930,7 +864,6 @@ static int do_virtio_entry(const char *filename, void *symval, add_wildcard(alias); return 1; } -ADD_TO_DEVTABLE("virtio", virtio_device_id, do_virtio_entry); /* * Looks like: vmbus:guid @@ -953,7 +886,6 @@ static int do_vmbus_entry(const char *filename, void *symval, return 1; } -ADD_TO_DEVTABLE("vmbus", hv_vmbus_device_id, do_vmbus_entry); /* Looks like: rpmsg:S */ static int do_rpmsg_entry(const char *filename, void *symval, @@ -964,7 +896,6 @@ static int do_rpmsg_entry(const char *filename, void *symval, return 1; } -ADD_TO_DEVTABLE("rpmsg", rpmsg_device_id, do_rpmsg_entry); /* Looks like: i2c:S */ static int do_i2c_entry(const char *filename, void *symval, @@ -975,7 +906,6 @@ static int do_i2c_entry(const char *filename, void *symval, return 1; } -ADD_TO_DEVTABLE("i2c", i2c_device_id, do_i2c_entry); /* Looks like: spi:S */ static int do_spi_entry(const char *filename, void *symval, @@ -986,7 +916,6 @@ static int do_spi_entry(const char *filename, void *symval, return 1; } -ADD_TO_DEVTABLE("spi", spi_device_id, do_spi_entry); static const struct dmifield { const char *prefix; @@ -1041,7 +970,6 @@ static int do_dmi_entry(const char *filename, void *symval, strcat(alias, ":"); return 1; } -ADD_TO_DEVTABLE("dmi", dmi_system_id, do_dmi_entry); static int do_platform_entry(const char *filename, void *symval, char *alias) @@ -1050,7 +978,6 @@ static int do_platform_entry(const char *filename, sprintf(alias, PLATFORM_MODULE_PREFIX "%s", *name); return 1; } -ADD_TO_DEVTABLE("platform", platform_device_id, do_platform_entry); static int do_mdio_entry(const char *filename, void *symval, char *alias) @@ -1075,7 +1002,6 @@ static int do_mdio_entry(const char *filename, return 1; } -ADD_TO_DEVTABLE("mdio", mdio_device_id, do_mdio_entry); /* Looks like: zorro:iN. */ static int do_zorro_entry(const char *filename, void *symval, @@ -1086,7 +1012,6 @@ static int do_zorro_entry(const char *filename, void *symval, ADD(alias, "i", id != ZORRO_WILDCARD, id); return 1; } -ADD_TO_DEVTABLE("zorro", zorro_device_id, do_zorro_entry); /* looks like: "pnp:dD" */ static int do_isapnp_entry(const char *filename, @@ -1102,7 +1027,6 @@ static int do_isapnp_entry(const char *filename, (function >> 12) & 0x0f, (function >> 8) & 0x0f); return 1; } -ADD_TO_DEVTABLE("isapnp", isapnp_device_id, do_isapnp_entry); /* Looks like: "ipack:fNvNdN". */ static int do_ipack_entry(const char *filename, @@ -1118,7 +1042,6 @@ static int do_ipack_entry(const char *filename, add_wildcard(alias); return 1; } -ADD_TO_DEVTABLE("ipack", ipack_device_id, do_ipack_entry); /* * Append a match expression for a single masked hex digit. @@ -1189,7 +1112,6 @@ static int do_amba_entry(const char *filename, return 1; } -ADD_TO_DEVTABLE("amba", amba_id, do_amba_entry); /* * looks like: "mipscdmm:tN" @@ -1205,7 +1127,6 @@ static int do_mips_cdmm_entry(const char *filename, sprintf(alias, "mipscdmm:t%02X*", type); return 1; } -ADD_TO_DEVTABLE("mipscdmm", mips_cdmm_device_id, do_mips_cdmm_entry); /* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,* * All fields are numbers. It would be nicer to use strings for vendor @@ -1230,7 +1151,6 @@ static int do_x86cpu_entry(const char *filename, void *symval, sprintf(alias + strlen(alias), "%04X*", feature); return 1; } -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) @@ -1240,7 +1160,6 @@ static int do_cpu_entry(const char *filename, void *symval, char *alias) sprintf(alias, "cpu:type:*:feature:*%04X*", feature); return 1; } -ADD_TO_DEVTABLE("cpu", cpu_feature, do_cpu_entry); /* Looks like: mei:S:uuid:N:* */ static int do_mei_entry(const char *filename, void *symval, @@ -1259,7 +1178,6 @@ static int do_mei_entry(const char *filename, void *symval, return 1; } -ADD_TO_DEVTABLE("mei", mei_cl_device_id, do_mei_entry); /* Looks like: rapidio:vNdNavNadN */ static int do_rio_entry(const char *filename, @@ -1279,7 +1197,6 @@ static int do_rio_entry(const char *filename, add_wildcard(alias); return 1; } -ADD_TO_DEVTABLE("rapidio", rio_device_id, do_rio_entry); /* Looks like: ulpi:vNpN */ static int do_ulpi_entry(const char *filename, void *symval, @@ -1292,7 +1209,6 @@ static int do_ulpi_entry(const char *filename, void *symval, return 1; } -ADD_TO_DEVTABLE("ulpi", ulpi_device_id, do_ulpi_entry); /* Looks like: hdaudio:vNrNaN */ static int do_hda_entry(const char *filename, void *symval, char *alias) @@ -1309,7 +1225,6 @@ static int do_hda_entry(const char *filename, void *symval, char *alias) add_wildcard(alias); return 1; } -ADD_TO_DEVTABLE("hdaudio", hda_device_id, do_hda_entry); /* Looks like: sdw:mNpN */ static int do_sdw_entry(const char *filename, void *symval, char *alias) @@ -1324,7 +1239,6 @@ static int do_sdw_entry(const char *filename, void *symval, char *alias) add_wildcard(alias); return 1; } -ADD_TO_DEVTABLE("sdw", sdw_device_id, do_sdw_entry); /* Looks like: fsl-mc:vNdN */ static int do_fsl_mc_entry(const char *filename, void *symval, @@ -1336,7 +1250,6 @@ static int do_fsl_mc_entry(const char *filename, void *symval, sprintf(alias, "fsl-mc:v%08Xd%s", vendor, *obj_type); return 1; } -ADD_TO_DEVTABLE("fslmc", fsl_mc_device_id, do_fsl_mc_entry); /* Looks like: tbsvc:kSpNvNrN */ static int do_tbsvc_entry(const char *filename, void *symval, char *alias) @@ -1361,7 +1274,6 @@ static int do_tbsvc_entry(const char *filename, void *symval, char *alias) add_wildcard(alias); return 1; } -ADD_TO_DEVTABLE("tbsvc", tb_service_id, do_tbsvc_entry); /* Looks like: typec:idNmN */ static int do_typec_entry(const char *filename, void *symval, char *alias) @@ -1374,7 +1286,6 @@ static int do_typec_entry(const char *filename, void *symval, char *alias) return 1; } -ADD_TO_DEVTABLE("typec", typec_device_id, do_typec_entry); /* Does namelen bytes of name exactly match the symbol? */ static bool sym_is(const char *name, unsigned namelen, const char *symbol) @@ -1407,6 +1318,48 @@ static void do_table(void *symval, unsigned long size, } } +static const struct devtable devtable[] = { + {"hid", SIZE_hid_device_id, do_hid_entry}, + {"ieee1394", SIZE_ieee1394_device_id, do_ieee1394_entry}, + {"pci", SIZE_pci_device_id, do_pci_entry}, + {"ccw", SIZE_ccw_device_id, do_ccw_entry}, + {"ap", SIZE_ap_device_id, do_ap_entry}, + {"css", SIZE_css_device_id, do_css_entry}, + {"serio", SIZE_serio_device_id, do_serio_entry}, + {"acpi", SIZE_acpi_device_id, do_acpi_entry}, + {"pcmcia", SIZE_pcmcia_device_id, do_pcmcia_entry}, + {"vio", SIZE_vio_device_id, do_vio_entry}, + {"input", SIZE_input_device_id, do_input_entry}, + {"eisa", SIZE_eisa_device_id, do_eisa_entry}, + {"parisc", SIZE_parisc_device_id, do_parisc_entry}, + {"sdio", SIZE_sdio_device_id, do_sdio_entry}, + {"ssb", SIZE_ssb_device_id, do_ssb_entry}, + {"bcma", SIZE_bcma_device_id, do_bcma_entry}, + {"virtio", SIZE_virtio_device_id, do_virtio_entry}, + {"vmbus", SIZE_hv_vmbus_device_id, do_vmbus_entry}, + {"rpmsg", SIZE_rpmsg_device_id, do_rpmsg_entry}, + {"i2c", SIZE_i2c_device_id, do_i2c_entry}, + {"spi", SIZE_spi_device_id, do_spi_entry}, + {"dmi", SIZE_dmi_system_id, do_dmi_entry}, + {"platform", SIZE_platform_device_id, do_platform_entry}, + {"mdio", SIZE_mdio_device_id, do_mdio_entry}, + {"zorro", SIZE_zorro_device_id, do_zorro_entry}, + {"isapnp", SIZE_isapnp_device_id, do_isapnp_entry}, + {"ipack", SIZE_ipack_device_id, do_ipack_entry}, + {"amba", SIZE_amba_id, do_amba_entry}, + {"mipscdmm", SIZE_mips_cdmm_device_id, do_mips_cdmm_entry}, + {"x86cpu", SIZE_x86_cpu_id, do_x86cpu_entry}, + {"cpu", SIZE_cpu_feature, do_cpu_entry}, + {"mei", SIZE_mei_cl_device_id, do_mei_entry}, + {"rapidio", SIZE_rio_device_id, do_rio_entry}, + {"ulpi", SIZE_ulpi_device_id, do_ulpi_entry}, + {"hdaudio", SIZE_hda_device_id, do_hda_entry}, + {"sdw", SIZE_sdw_device_id, do_sdw_entry}, + {"fslmc", SIZE_fsl_mc_device_id, do_fsl_mc_entry}, + {"tbsvc", SIZE_tb_service_id, do_tbsvc_entry}, + {"typec", SIZE_typec_device_id, do_typec_entry}, +}; + /* Create MODULE_ALIAS() statements. * At this time, we cannot write the actual output C source yet, * so we write into the mod->dev_table_buf buffer. */ @@ -1460,13 +1413,14 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, else if (sym_is(name, namelen, "pnp_card")) do_pnp_card_entries(symval, sym->st_size, mod); else { - struct devtable **p; - INIT_SECTION(__devtable); + int i; + + for (i = 0; i < ARRAY_SIZE(devtable); i++) { + const struct devtable *p = &devtable[i]; - for (p = __start___devtable; p < __stop___devtable; p++) { - if (sym_is(name, namelen, (*p)->device_id)) { - do_table(symval, sym->st_size, (*p)->id_size, - (*p)->device_id, (*p)->function, mod); + if (sym_is(name, namelen, p->device_id)) { + do_table(symval, sym->st_size, p->id_size, + p->device_id, p->function, mod); break; } } -- cgit v1.2.3 From f880eea68fe593342fa6e09be9bb661f3c297aec Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 22 Nov 2018 13:28:42 +0900 Subject: modpost: file2alias: check prototype of handler Use specific prototype instead of an opaque pointer so that the compiler can catch function prototype mismatch. Signed-off-by: Masahiro Yamada Reviewed-by: Mathieu Malaterre --- scripts/mod/file2alias.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 7e4aededfd37..a37af7d71973 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -47,7 +47,7 @@ typedef struct { struct devtable { const char *device_id; /* name of table, __mod___*_device_table. */ unsigned long id_size; - void *function; + int (*do_entry)(const char *filename, void *symval, char *alias); }; /* Define a variable f that holds the value of field f of struct devid @@ -1299,12 +1299,11 @@ static bool sym_is(const char *name, unsigned namelen, const char *symbol) static void do_table(void *symval, unsigned long size, unsigned long id_size, const char *device_id, - void *function, + int (*do_entry)(const char *filename, void *symval, char *alias), struct module *mod) { unsigned int i; char alias[500]; - int (*do_entry)(const char *, void *entry, char *alias) = function; device_id_check(mod->name, device_id, size, id_size, symval); /* Leave last one: it's the terminator. */ @@ -1420,7 +1419,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, if (sym_is(name, namelen, p->device_id)) { do_table(symval, sym->st_size, p->id_size, - p->device_id, p->function, mod); + p->device_id, p->do_entry, mod); break; } } -- cgit v1.2.3 From d2665ca8e3310d045b62397590ab54dc485e035e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 23 Nov 2018 16:57:21 +0900 Subject: modpost: refactor seen flag clearing in add_depends() You do not need to iterate over all modules for resetting ->seen flag because add_depends() is only interested in modules that export symbols referenced from the given 'mod'. This also avoids shadowing the 'modules' parameter of add_depends(). Signed-off-by: Masahiro Yamada --- scripts/mod/modpost.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 3aab410f020e..eedc2742dc8e 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2241,15 +2241,15 @@ static int add_versions(struct buffer *b, struct module *mod) return err; } -static void add_depends(struct buffer *b, struct module *mod, - struct module *modules) +static void add_depends(struct buffer *b, struct module *mod) { struct symbol *s; - struct module *m; int first = 1; - for (m = modules; m; m = m->next) - m->seen = is_vmlinux(m->name); + /* 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); buf_printf(b, "\n"); buf_printf(b, "static const char __module_depends[]\n"); @@ -2518,7 +2518,7 @@ int main(int argc, char **argv) add_retpoline(&buf); add_staging_flag(&buf, mod->name); err |= add_versions(&buf, mod); - add_depends(&buf, mod, modules); + add_depends(&buf, mod); add_moddevtable(&buf, mod); add_srcversion(&buf, mod); -- cgit v1.2.3 From c6826ad8a49f1230dcbc45dac26b54d492b13280 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 23 Nov 2018 16:57:22 +0900 Subject: modpost: merge module iterations Probably, this is just a matter of the order of error/warning messages. Merge the two for-loops. Signed-off-by: Masahiro Yamada --- scripts/mod/modpost.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index eedc2742dc8e..963a0b69b9a3 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2496,12 +2496,6 @@ int main(int argc, char **argv) if (files_source) read_symbols_from_files(files_source); - for (mod = modules; mod; mod = mod->next) { - if (mod->skip) - continue; - check_exports(mod); - } - err = 0; for (mod = modules; mod; mod = mod->next) { @@ -2513,6 +2507,7 @@ int main(int argc, char **argv) buf.pos = 0; err |= check_modname_len(mod); + check_exports(mod); add_header(&buf, mod); add_intree_flag(&buf, !external_module); add_retpoline(&buf); -- cgit v1.2.3 From 3b4152880348287b6b3d9a0708f1e2f4c540f3d0 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 23 Nov 2018 16:57:23 +0900 Subject: modpost: move unresolved symbol checks to check_exports() This will fit better in check_exports() than add_versions(). Signed-off-by: Masahiro Yamada --- scripts/mod/modpost.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'scripts/mod') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 963a0b69b9a3..0de2fb236640 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2097,15 +2097,27 @@ static void check_for_unused(enum export exp, const char *m, const char *s) } } -static void check_exports(struct module *mod) +static int check_exports(struct module *mod) { struct symbol *s, *exp; + int err = 0; for (s = mod->unres; s; s = s->next) { const char *basename; exp = find_symbol(s->name); - if (!exp || exp->module == mod) + if (!exp || exp->module == mod) { + if (have_vmlinux && !s->weak) { + if (warn_unresolved) { + warn("\"%s\" [%s.ko] undefined!\n", + s->name, mod->name); + } else { + merror("\"%s\" [%s.ko] undefined!\n", + s->name, mod->name); + err = 1; + } + } continue; + } basename = strrchr(mod->name, '/'); if (basename) basename++; @@ -2115,6 +2127,8 @@ static void check_exports(struct module *mod) check_for_gpl_usage(exp->export, basename, exp->name); check_for_unused(exp->export, basename, exp->name); } + + return err; } static int check_modname_len(struct module *mod) @@ -2192,19 +2206,8 @@ static int add_versions(struct buffer *b, struct module *mod) for (s = mod->unres; s; s = s->next) { exp = find_symbol(s->name); - if (!exp || exp->module == mod) { - if (have_vmlinux && !s->weak) { - if (warn_unresolved) { - warn("\"%s\" [%s.ko] undefined!\n", - s->name, mod->name); - } else { - merror("\"%s\" [%s.ko] undefined!\n", - s->name, mod->name); - err = 1; - } - } + if (!exp || exp->module == mod) continue; - } s->module = exp->module; s->crc_valid = exp->crc_valid; s->crc = exp->crc; @@ -2507,7 +2510,7 @@ int main(int argc, char **argv) buf.pos = 0; err |= check_modname_len(mod); - check_exports(mod); + err |= check_exports(mod); add_header(&buf, mod); add_intree_flag(&buf, !external_module); add_retpoline(&buf); -- cgit v1.2.3 From 60df1aee2aecb53efb4218b4dfdf7d6c80a5a3de Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 29 Nov 2018 12:13:24 +0900 Subject: kbuild: move modpost out of 'scripts' target I am eagar to build under the scripts/ directory only with $(HOSTCC), but scripts/mod/ highly depends on the $(CC) and target arch headers. That it why the 'scripts' target must depend on 'asm-generic', 'gcc-plugins', and $(autoksyms_h). Move it to the 'prepare0' stage. I know this is a cheesy workaround, but better than the current situation. Signed-off-by: Masahiro Yamada --- Makefile | 3 ++- scripts/Makefile | 3 +-- scripts/mod/Makefile | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) (limited to 'scripts/mod') diff --git a/Makefile b/Makefile index bfab340453c6..6da46310a662 100644 --- a/Makefile +++ b/Makefile @@ -1075,7 +1075,7 @@ include/config/kernel.release: $(srctree)/Makefile FORCE # Carefully list dependencies so we do not try to build scripts twice # in parallel PHONY += scripts -scripts: scripts_basic scripts_dtc asm-generic gcc-plugins $(autoksyms_h) +scripts: scripts_basic scripts_dtc $(Q)$(MAKE) $(build)=$(@) # Things we need to do before we recursively start building the kernel @@ -1113,6 +1113,7 @@ macroprepare: prepare1 archmacros archprepare: archheaders archscripts macroprepare scripts_basic gcc-plugins prepare0: archprepare + $(Q)$(MAKE) $(build)=scripts/mod $(Q)$(MAKE) $(build)=. # All the preparing.. diff --git a/scripts/Makefile b/scripts/Makefile index ece52ff20171..b48259d30280 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -37,9 +37,8 @@ build_unifdef: $(obj)/unifdef @: subdir-$(CONFIG_MODVERSIONS) += genksyms -subdir-y += mod subdir-$(CONFIG_SECURITY_SELINUX) += selinux subdir-$(CONFIG_GDB_SCRIPTS) += gdb # Let clean descend into subdirs -subdir- += basic dtc kconfig package gcc-plugins +subdir- += basic dtc kconfig mod package gcc-plugins diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile index a5b4af47987a..42c5d50f2bcc 100644 --- a/scripts/mod/Makefile +++ b/scripts/mod/Makefile @@ -4,8 +4,6 @@ OBJECT_FILES_NON_STANDARD := y hostprogs-y := modpost mk_elfconfig always := $(hostprogs-y) empty.o -CFLAGS_REMOVE_empty.o := $(ASM_MACRO_FLAGS) - modpost-objs := modpost.o file2alias.o sumversion.o devicetable-offsets-file := devicetable-offsets.h -- cgit v1.2.3