diff options
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/Makefile.btf | 19 | ||||
| -rw-r--r-- | scripts/Makefile.build | 2 | ||||
| -rw-r--r-- | scripts/Makefile.host | 2 | ||||
| -rw-r--r-- | scripts/Makefile.modfinal | 5 | ||||
| -rw-r--r-- | scripts/Makefile.package | 10 | ||||
| -rw-r--r-- | scripts/Makefile.userprogs | 6 | ||||
| -rw-r--r-- | scripts/Makefile.vdsoinst | 45 | ||||
| -rwxr-xr-x | scripts/dummy-tools/gcc | 10 | ||||
| -rw-r--r-- | scripts/mod/Makefile | 4 | ||||
| -rw-r--r-- | scripts/mod/devicetable-offsets.c | 7 | ||||
| -rw-r--r-- | scripts/mod/file2alias.c | 31 | ||||
| -rw-r--r-- | scripts/mod/modpost.c | 201 | ||||
| -rw-r--r-- | scripts/mod/modpost.h | 50 | ||||
| -rw-r--r-- | scripts/mod/symsearch.c | 199 | ||||
| -rwxr-xr-x | scripts/package/mkspec | 6 | ||||
| -rwxr-xr-x | scripts/pahole-flags.sh | 30 | ||||
| -rwxr-xr-x | scripts/remove-stale-files | 2 | 
17 files changed, 410 insertions, 219 deletions
| diff --git a/scripts/Makefile.btf b/scripts/Makefile.btf new file mode 100644 index 000000000000..82377e470aed --- /dev/null +++ b/scripts/Makefile.btf @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 + +pahole-ver := $(CONFIG_PAHOLE_VERSION) +pahole-flags-y := + +# pahole 1.18 through 1.21 can't handle zero-sized per-CPU vars +ifeq ($(call test-le, $(pahole-ver), 121),y) +pahole-flags-$(call test-ge, $(pahole-ver), 118)	+= --skip_encoding_btf_vars +endif + +pahole-flags-$(call test-ge, $(pahole-ver), 121)	+= --btf_gen_floats + +pahole-flags-$(call test-ge, $(pahole-ver), 122)	+= -j + +pahole-flags-$(CONFIG_PAHOLE_HAS_LANG_EXCLUDE)		+= --lang_exclude=rust + +pahole-flags-$(call test-ge, $(pahole-ver), 125)	+= --skip_encoding_btf_inconsistent_proto --btf_gen_optimized + +export PAHOLE_FLAGS := $(pahole-flags-y) diff --git a/scripts/Makefile.build b/scripts/Makefile.build index da37bfa97211..9a3063735e71 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -425,7 +425,7 @@ $(obj)/lib.a: $(lib-y) FORCE  	$(call if_changed,ar)  quiet_cmd_ld_multi_m = LD [M]  $@ -      cmd_ld_multi_m = $(LD) $(ld_flags) -r -o $@ @$(patsubst %.o,%.mod,$@) $(cmd_objtool) +      cmd_ld_multi_m = $(LD) $(ld_flags) -r -o $@ @$< $(cmd_objtool)  define rule_ld_multi_m  	$(call cmd_and_savecmd,ld_multi_m) diff --git a/scripts/Makefile.host b/scripts/Makefile.host index 8f7f842b54f9..08d83d9db31a 100644 --- a/scripts/Makefile.host +++ b/scripts/Makefile.host @@ -91,6 +91,8 @@ hostcxx_flags  = -Wp,-MMD,$(depfile) \  # current working directory, which may be not accessible in the out-of-tree  # modules case.  hostrust_flags = --out-dir $(dir $@) --emit=dep-info=$(depfile) \ +		 -Clinker-flavor=gcc -Clinker=$(HOSTCC) \ +		 -Clink-args='$(call escsq,$(KBUILD_HOSTLDFLAGS))' \                   $(KBUILD_HOSTRUSTFLAGS) $(HOST_EXTRARUSTFLAGS) \                   $(HOSTRUSTFLAGS_$(target-stem)) diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal index b3a6aa8fbe8c..8568d256d6fb 100644 --- a/scripts/Makefile.modfinal +++ b/scripts/Makefile.modfinal @@ -28,14 +28,11 @@ quiet_cmd_cc_o_c = CC [M]  $@  %.mod.o: %.mod.c FORCE  	$(call if_changed_dep,cc_o_c) -ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink) -  quiet_cmd_ld_ko_o = LD [M]  $@        cmd_ld_ko_o +=							\  	$(LD) -r $(KBUILD_LDFLAGS)					\  		$(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE)		\ -		-T scripts/module.lds -o $@ $(filter %.o, $^);		\ -	$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true) +		-T scripts/module.lds -o $@ $(filter %.o, $^)  quiet_cmd_btf_ko = BTF [M] $@        cmd_btf_ko = 							\ diff --git a/scripts/Makefile.package b/scripts/Makefile.package index 2bcab02da965..3addd1c0b989 100644 --- a/scripts/Makefile.package +++ b/scripts/Makefile.package @@ -69,9 +69,9 @@ $(linux-tarballs): .tmp_HEAD FORCE  # ---------------------------------------------------------------------------  quiet_cmd_mkspec = GEN     $@ -      cmd_mkspec = $(srctree)/scripts/package/mkspec > $@ +      cmd_mkspec = $(srctree)/scripts/package/mkspec $@ -kernel.spec: FORCE +rpmbuild/SPECS/kernel.spec: FORCE  	$(call cmd,mkspec)  PHONY += rpm-sources @@ -88,14 +88,12 @@ srcrpm-pkg: private build-type := s  binrpm-pkg: private build-type := b  rpm-pkg srcrpm-pkg: rpm-sources -rpm-pkg srcrpm-pkg binrpm-pkg: kernel.spec -	+$(strip rpmbuild -b$(build-type) kernel.spec \ +rpm-pkg srcrpm-pkg binrpm-pkg: rpmbuild/SPECS/kernel.spec +	+$(strip rpmbuild -b$(build-type) rpmbuild/SPECS/kernel.spec \  	--define='_topdir $(abspath rpmbuild)' \  	$(if $(filter a b, $(build-type)), \  		--target $(UTS_MACHINE)-linux --build-in-place --noprep --define='_smp_mflags %{nil}' \  		$$(rpm -q rpm >/dev/null 2>&1 || echo --nodeps)) \ -	$(if $(filter b, $(build-type)), \ -		--without devel) \  	$(RPMOPTS))  # deb-pkg srcdeb-pkg bindeb-pkg diff --git a/scripts/Makefile.userprogs b/scripts/Makefile.userprogs index fb415297337a..f3a7e1ef3753 100644 --- a/scripts/Makefile.userprogs +++ b/scripts/Makefile.userprogs @@ -19,19 +19,19 @@ user-cobjs	:= $(addprefix $(obj)/, $(user-cobjs))  user_ccflags	= -Wp,-MMD,$(depfile) $(KBUILD_USERCFLAGS) $(userccflags) \  			$($(target-stem)-userccflags)  user_ldflags	= $(KBUILD_USERLDFLAGS) $(userldflags) $($(target-stem)-userldflags) +user_ldlibs	= $(userldlibs) $($(target-stem)-userldlibs)  # Create an executable from a single .c file  quiet_cmd_user_cc_c = CC [U]  $@        cmd_user_cc_c = $(CC) $(user_ccflags) $(user_ldflags) -o $@ $< \ -		      $($(target-stem)-userldlibs) +		      $(user_ldlibs)  $(user-csingle): $(obj)/%: $(src)/%.c FORCE  	$(call if_changed_dep,user_cc_c)  # Link an executable based on list of .o files  quiet_cmd_user_ld = LD [U]  $@        cmd_user_ld = $(CC) $(user_ldflags) -o $@ \ -		    $(addprefix $(obj)/, $($(target-stem)-objs)) \ -		    $($(target-stem)-userldlibs) +		    $(addprefix $(obj)/, $($(target-stem)-objs)) $(user_ldlibs)  $(user-cmulti): FORCE  	$(call if_changed,user_ld)  $(call multi_depend, $(user-cmulti), , -objs) diff --git a/scripts/Makefile.vdsoinst b/scripts/Makefile.vdsoinst new file mode 100644 index 000000000000..1022d9fdd976 --- /dev/null +++ b/scripts/Makefile.vdsoinst @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-2.0-only +# ========================================================================== +# Install unstripped copies of vDSO +# ========================================================================== + +PHONY := __default +__default: +	@: + +include $(srctree)/scripts/Kbuild.include + +install-dir := $(MODLIB)/vdso + +define gen_install_rules + +src := $$(firstword $$(subst :,$(space),$(1))) +dest := $(install-dir)/$$(or $$(word 2,$$(subst :,$(space),$(1))),$$(patsubst %.dbg,%,$$(notdir $(1)))) + +__default: $$(dest) +$$(dest): $$(src) FORCE +	$$(call cmd,install) + +# Some architectures create .build-id symlinks +ifneq ($(filter arm sparc x86, $(SRCARCH)),) +link := $(install-dir)/.build-id/$$(shell $(READELF) -n $$(src) | sed -n 's@^.*Build ID: \(..\)\(.*\)@\1/\2@p') + +__default: $$(link) +$$(link): $$(dest) FORCE +	$$(call cmd,symlink) +endif + +endef + +$(foreach x, $(sort $(INSTALL_FILES)), $(eval $(call gen_install_rules,$(x)))) + +quiet_cmd_install = INSTALL $@ +      cmd_install = mkdir -p $(dir $@); cp $< $@ + +quiet_cmd_symlink = SYMLINK $@ +      cmd_symlink = mkdir -p $(dir $@); ln -sf --relative $< $@ + +PHONY += FORCE +FORCE: + +.PHONY: $(PHONY) diff --git a/scripts/dummy-tools/gcc b/scripts/dummy-tools/gcc index 07f6dc4c5cf6..e6c41427c02f 100755 --- a/scripts/dummy-tools/gcc +++ b/scripts/dummy-tools/gcc @@ -91,6 +91,16 @@ if arg_contain -S "$@"; then  		fi  		exit 0  	fi + +	# For arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh +	if arg_contain -m64 "$@" && arg_contain -fpatchable-function-entry=2 "$@"; then +		echo "func:" +		echo ".section __patchable_function_entries" +		echo ".localentry" +		echo "  nop" +		echo "  nop" +		exit 0 +	fi  fi  # To set GCC_PLUGINS diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile index c9e38ad937fd..3c54125eb373 100644 --- a/scripts/mod/Makefile +++ b/scripts/mod/Makefile @@ -5,7 +5,7 @@ CFLAGS_REMOVE_empty.o += $(CC_FLAGS_LTO)  hostprogs-always-y	+= modpost mk_elfconfig  always-y		+= empty.o -modpost-objs	:= modpost.o file2alias.o sumversion.o +modpost-objs	:= modpost.o file2alias.o sumversion.o symsearch.o  devicetable-offsets-file := devicetable-offsets.h @@ -16,7 +16,7 @@ targets += $(devicetable-offsets-file) devicetable-offsets.s  # dependencies on generated files need to be listed explicitly -$(obj)/modpost.o $(obj)/file2alias.o $(obj)/sumversion.o: $(obj)/elfconfig.h +$(obj)/modpost.o $(obj)/file2alias.o $(obj)/sumversion.o $(obj)/symsearch.o: $(obj)/elfconfig.h  $(obj)/file2alias.o: $(obj)/$(devicetable-offsets-file)  quiet_cmd_elfconfig = MKELF   $@ diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c index abe65f8968dd..e91a3c38143b 100644 --- a/scripts/mod/devicetable-offsets.c +++ b/scripts/mod/devicetable-offsets.c @@ -265,7 +265,14 @@ int main(void)  	DEVID(cdx_device_id);  	DEVID_FIELD(cdx_device_id, vendor);  	DEVID_FIELD(cdx_device_id, device); +	DEVID_FIELD(cdx_device_id, subvendor); +	DEVID_FIELD(cdx_device_id, subdevice); +	DEVID_FIELD(cdx_device_id, class); +	DEVID_FIELD(cdx_device_id, class_mask);  	DEVID_FIELD(cdx_device_id, override_only); +	DEVID(vchiq_device_id); +	DEVID_FIELD(vchiq_device_id, name); +  	return 0;  } diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 7056751c29b1..4829680a0a6d 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -1348,13 +1348,13 @@ static int do_typec_entry(const char *filename, void *symval, char *alias)  /* Looks like: tee:uuid */  static int do_tee_entry(const char *filename, void *symval, char *alias)  { -	DEF_FIELD(symval, tee_client_device_id, uuid); +	DEF_FIELD_ADDR(symval, tee_client_device_id, uuid);  	sprintf(alias, "tee:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", -		uuid.b[0], uuid.b[1], uuid.b[2], uuid.b[3], uuid.b[4], -		uuid.b[5], uuid.b[6], uuid.b[7], uuid.b[8], uuid.b[9], -		uuid.b[10], uuid.b[11], uuid.b[12], uuid.b[13], uuid.b[14], -		uuid.b[15]); +		uuid->b[0], uuid->b[1], uuid->b[2], uuid->b[3], uuid->b[4], +		uuid->b[5], uuid->b[6], uuid->b[7], uuid->b[8], uuid->b[9], +		uuid->b[10], uuid->b[11], uuid->b[12], uuid->b[13], uuid->b[14], +		uuid->b[15]);  	add_wildcard(alias);  	return 1; @@ -1401,10 +1401,10 @@ static int do_mhi_ep_entry(const char *filename, void *symval, char *alias)  /* Looks like: ishtp:{guid} */  static int do_ishtp_entry(const char *filename, void *symval, char *alias)  { -	DEF_FIELD(symval, ishtp_device_id, guid); +	DEF_FIELD_ADDR(symval, ishtp_device_id, guid);  	strcpy(alias, ISHTP_MODULE_PREFIX "{"); -	add_guid(alias, guid); +	add_guid(alias, *guid);  	strcat(alias, "}");  	return 1; @@ -1458,6 +1458,10 @@ static int do_cdx_entry(const char *filename, void *symval,  {  	DEF_FIELD(symval, cdx_device_id, vendor);  	DEF_FIELD(symval, cdx_device_id, device); +	DEF_FIELD(symval, cdx_device_id, subvendor); +	DEF_FIELD(symval, cdx_device_id, subdevice); +	DEF_FIELD(symval, cdx_device_id, class); +	DEF_FIELD(symval, cdx_device_id, class_mask);  	DEF_FIELD(symval, cdx_device_id, override_only);  	switch (override_only) { @@ -1475,6 +1479,18 @@ static int do_cdx_entry(const char *filename, void *symval,  	ADD(alias, "v", vendor != CDX_ANY_ID, vendor);  	ADD(alias, "d", device != CDX_ANY_ID, device); +	ADD(alias, "sv", subvendor != CDX_ANY_ID, subvendor); +	ADD(alias, "sd", subdevice != CDX_ANY_ID, subdevice); +	ADD(alias, "c", class_mask == 0xFFFFFF, class); + +	return 1; +} + +static int do_vchiq_entry(const char *filename, void *symval, char *alias) +{ +	DEF_FIELD_ADDR(symval, vchiq_device_id, name); +	sprintf(alias, "vchiq:%s", *name); +  	return 1;  } @@ -1558,6 +1574,7 @@ static const struct devtable devtable[] = {  	{"dfl", SIZE_dfl_device_id, do_dfl_entry},  	{"ishtp", SIZE_ishtp_device_id, do_ishtp_entry},  	{"cdx", SIZE_cdx_device_id, do_cdx_entry}, +	{"vchiq", SIZE_vchiq_device_id, do_vchiq_entry},  };  /* Create MODULE_ALIAS() statements. diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index ea72af229d2b..973b5e5ae2dd 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -22,7 +22,6 @@  #include <errno.h>  #include "modpost.h"  #include "../../include/linux/license.h" -#include "../../include/linux/module_symbol.h"  static bool module_enabled;  /* Are we using CONFIG_MODVERSIONS? */ @@ -577,11 +576,14 @@ static int parse_elf(struct elf_info *info, const char *filename)  			*p = TO_NATIVE(*p);  	} +	symsearch_init(info); +  	return 1;  }  static void parse_elf_finish(struct elf_info *info)  { +	symsearch_finish(info);  	release_file(info->hdr, info->size);  } @@ -792,24 +794,16 @@ static void check_section(const char *modname, struct elf_info *elf,  #define ALL_INIT_DATA_SECTIONS \  	".init.setup", ".init.rodata", ".meminit.rodata", \  	".init.data", ".meminit.data" -#define ALL_EXIT_DATA_SECTIONS \ -	".exit.data", ".memexit.data" - -#define ALL_INIT_TEXT_SECTIONS \ -	".init.text", ".meminit.text" -#define ALL_EXIT_TEXT_SECTIONS \ -	".exit.text", ".memexit.text"  #define ALL_PCI_INIT_SECTIONS	\  	".pci_fixup_early", ".pci_fixup_header", ".pci_fixup_final", \  	".pci_fixup_enable", ".pci_fixup_resume", \  	".pci_fixup_resume_early", ".pci_fixup_suspend" -#define ALL_XXXINIT_SECTIONS MEM_INIT_SECTIONS -#define ALL_XXXEXIT_SECTIONS MEM_EXIT_SECTIONS +#define ALL_XXXINIT_SECTIONS ".meminit.*"  #define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS -#define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS +#define ALL_EXIT_SECTIONS ".exit.*"  #define DATA_SECTIONS ".data", ".data.rel"  #define TEXT_SECTIONS ".text", ".text.*", ".sched.text", \ @@ -819,20 +813,13 @@ static void check_section(const char *modname, struct elf_info *elf,  		".coldtext", ".softirqentry.text"  #define INIT_SECTIONS      ".init.*" -#define MEM_INIT_SECTIONS  ".meminit.*" -#define EXIT_SECTIONS      ".exit.*" -#define MEM_EXIT_SECTIONS  ".memexit.*" - -#define ALL_TEXT_SECTIONS  ALL_INIT_TEXT_SECTIONS, ALL_EXIT_TEXT_SECTIONS, \ +#define ALL_TEXT_SECTIONS  ".init.text", ".meminit.text", ".exit.text", \  		TEXT_SECTIONS, OTHER_TEXT_SECTIONS  enum mismatch { -	TEXT_TO_ANY_INIT, -	DATA_TO_ANY_INIT, -	TEXTDATA_TO_ANY_EXIT, +	TEXTDATA_TO_ANY_INIT_EXIT,  	XXXINIT_TO_SOME_INIT, -	XXXEXIT_TO_SOME_EXIT,  	ANY_INIT_TO_ANY_EXIT,  	ANY_EXIT_TO_ANY_INIT,  	EXTABLE_TO_NON_TEXT, @@ -863,19 +850,9 @@ static const struct sectioncheck sectioncheck[] = {   * normal code and data   */  { -	.fromsec = { TEXT_SECTIONS, NULL }, -	.bad_tosec = { ALL_INIT_SECTIONS, NULL }, -	.mismatch = TEXT_TO_ANY_INIT, -}, -{ -	.fromsec = { DATA_SECTIONS, NULL }, -	.bad_tosec = { ALL_XXXINIT_SECTIONS, INIT_SECTIONS, NULL }, -	.mismatch = DATA_TO_ANY_INIT, -}, -{  	.fromsec = { TEXT_SECTIONS, DATA_SECTIONS, NULL }, -	.bad_tosec = { ALL_EXIT_SECTIONS, NULL }, -	.mismatch = TEXTDATA_TO_ANY_EXIT, +	.bad_tosec = { ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL }, +	.mismatch = TEXTDATA_TO_ANY_INIT_EXIT,  },  /* Do not reference init code/data from meminit code/data */  { @@ -883,12 +860,6 @@ static const struct sectioncheck sectioncheck[] = {  	.bad_tosec = { INIT_SECTIONS, NULL },  	.mismatch = XXXINIT_TO_SOME_INIT,  }, -/* Do not reference exit code/data from memexit code/data */ -{ -	.fromsec = { ALL_XXXEXIT_SECTIONS, NULL }, -	.bad_tosec = { EXIT_SECTIONS, NULL }, -	.mismatch = XXXEXIT_TO_SOME_EXIT, -},  /* Do not use exit code/data from init code */  {  	.fromsec = { ALL_INIT_SECTIONS, NULL }, @@ -1006,19 +977,7 @@ static int secref_whitelist(const char *fromsec, const char *fromsym,  	/* symbols in data sections that may refer to any init/exit sections */  	if (match(fromsec, PATTERNS(DATA_SECTIONS)) &&  	    match(tosec, PATTERNS(ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS)) && -	    match(fromsym, PATTERNS("*_template", // scsi uses *_template a lot -				    "*_timer", // arm uses ops structures named _timer a lot -				    "*_sht", // scsi also used *_sht to some extent -				    "*_ops", -				    "*_probe", -				    "*_probe_one", -				    "*_console"))) -		return 0; - -	/* symbols in data sections that may refer to meminit sections */ -	if (match(fromsec, PATTERNS(DATA_SECTIONS)) && -	    match(tosec, PATTERNS(ALL_XXXINIT_SECTIONS, ALL_XXXEXIT_SECTIONS)) && -	    match(fromsym, PATTERNS("*driver"))) +	    match(fromsym, PATTERNS("*_ops", "*_probe", "*_console")))  		return 0;  	/* @@ -1028,7 +987,7 @@ static int secref_whitelist(const char *fromsec, const char *fromsym,  	 */  	if (!extra_warn &&  	    match(fromsec, PATTERNS(DATA_SECTIONS)) && -	    match(tosec, PATTERNS(EXIT_SECTIONS)) && +	    match(tosec, PATTERNS(ALL_EXIT_SECTIONS)) &&  	    match(fromsym, PATTERNS("*driver")))  		return 0; @@ -1050,71 +1009,10 @@ static int secref_whitelist(const char *fromsec, const char *fromsym,  	return 1;  } -/* - * If there's no name there, ignore it; likewise, ignore it if it's - * one of the magic symbols emitted used by current 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 bool is_valid_name(struct elf_info *elf, Elf_Sym *sym) -{ -	const char *name = elf->strtab + sym->st_name; - -	if (!name || !strlen(name)) -		return false; -	return !is_mapping_symbol(name); -} - -/* Look up the nearest symbol based on the section and the address */ -static Elf_Sym *find_nearest_sym(struct elf_info *elf, Elf_Addr addr, -				 unsigned int secndx, bool allow_negative, -				 Elf_Addr min_distance) -{ -	Elf_Sym *sym; -	Elf_Sym *near = NULL; -	Elf_Addr sym_addr, distance; -	bool is_arm = (elf->hdr->e_machine == EM_ARM); - -	for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { -		if (get_secindex(elf, sym) != secndx) -			continue; -		if (!is_valid_name(elf, sym)) -			continue; - -		sym_addr = sym->st_value; - -		/* -		 * For ARM Thumb instruction, the bit 0 of st_value is set -		 * if the symbol is STT_FUNC type. Mask it to get the address. -		 */ -		if (is_arm && ELF_ST_TYPE(sym->st_info) == STT_FUNC) -			 sym_addr &= ~1; - -		if (addr >= sym_addr) -			distance = addr - sym_addr; -		else if (allow_negative) -			distance = sym_addr - addr; -		else -			continue; - -		if (distance <= min_distance) { -			min_distance = distance; -			near = sym; -		} - -		if (min_distance == 0) -			break; -	} -	return near; -} -  static Elf_Sym *find_fromsym(struct elf_info *elf, Elf_Addr addr,  			     unsigned int secndx)  { -	return find_nearest_sym(elf, addr, secndx, false, ~0); +	return symsearch_find_nearest(elf, addr, secndx, false, ~0);  }  static Elf_Sym *find_tosym(struct elf_info *elf, Elf_Addr addr, Elf_Sym *sym) @@ -1127,7 +1025,8 @@ static Elf_Sym *find_tosym(struct elf_info *elf, Elf_Addr addr, Elf_Sym *sym)  	 * Strive to find a better symbol name, but the resulting name may not  	 * match the symbol referenced in the original code.  	 */ -	return find_nearest_sym(elf, addr, get_secindex(elf, sym), true, 20); +	return symsearch_find_nearest(elf, addr, get_secindex(elf, sym), +				      true, 20);  }  static bool is_executable_section(struct elf_info *elf, unsigned int secndx) @@ -1248,10 +1147,10 @@ static void check_export_symbol(struct module *mod, struct elf_info *elf,  	    ELF_ST_TYPE(sym->st_info) == STT_LOPROC)  		s->is_func = true; -	if (match(secname, PATTERNS(INIT_SECTIONS))) +	if (match(secname, PATTERNS(ALL_INIT_SECTIONS)))  		warn("%s: %s: EXPORT_SYMBOL used for init symbol. Remove __init or EXPORT_SYMBOL.\n",  		     mod->name, name); -	else if (match(secname, PATTERNS(EXIT_SECTIONS))) +	else if (match(secname, PATTERNS(ALL_EXIT_SECTIONS)))  		warn("%s: %s: EXPORT_SYMBOL used for exit symbol. Remove __exit or EXPORT_SYMBOL.\n",  		     mod->name, name);  } @@ -1468,32 +1367,20 @@ static void get_rel_type_and_sym(struct elf_info *elf, uint64_t r_info,  		return;  	} -	if (is_64bit) { -		Elf64_Xword r_info64 = r_info; - -		r_info = TO_NATIVE(r_info64); -	} else { -		Elf32_Word r_info32 = r_info; - -		r_info = TO_NATIVE(r_info32); -	} +	if (is_64bit) +		r_info = TO_NATIVE((Elf64_Xword)r_info); +	else +		r_info = TO_NATIVE((Elf32_Word)r_info);  	*r_type = ELF_R_TYPE(r_info);  	*r_sym = ELF_R_SYM(r_info);  }  static void section_rela(struct module *mod, struct elf_info *elf, -			 Elf_Shdr *sechdr) +			 unsigned int fsecndx, const char *fromsec, +			 const Elf_Rela *start, const Elf_Rela *stop)  { -	Elf_Rela *rela; -	unsigned int fsecndx = sechdr->sh_info; -	const char *fromsec = sec_name(elf, fsecndx); -	Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset; -	Elf_Rela *stop  = (void *)start + sechdr->sh_size; - -	/* if from section (name) is know good then skip it */ -	if (match(fromsec, section_white_list)) -		return; +	const Elf_Rela *rela;  	for (rela = start; rela < stop; rela++) {  		Elf_Addr taddr, r_offset; @@ -1523,17 +1410,10 @@ static void section_rela(struct module *mod, struct elf_info *elf,  }  static void section_rel(struct module *mod, struct elf_info *elf, -			Elf_Shdr *sechdr) +			unsigned int fsecndx, const char *fromsec, +			const Elf_Rel *start, const Elf_Rel *stop)  { -	Elf_Rel *rel; -	unsigned int fsecndx = sechdr->sh_info; -	const char *fromsec = sec_name(elf, fsecndx); -	Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset; -	Elf_Rel *stop  = (void *)start + sechdr->sh_size; - -	/* if from section (name) is know good then skip it */ -	if (match(fromsec, section_white_list)) -		return; +	const Elf_Rel *rel;  	for (rel = start; rel < stop; rel++) {  		Elf_Sym *tsym; @@ -1581,16 +1461,33 @@ static void section_rel(struct module *mod, struct elf_info *elf,  static void check_sec_ref(struct module *mod, struct elf_info *elf)  {  	int i; -	Elf_Shdr *sechdrs = elf->sechdrs;  	/* Walk through all sections */  	for (i = 0; i < elf->num_sections; i++) { -		check_section(mod->name, elf, &elf->sechdrs[i]); +		Elf_Shdr *sechdr = &elf->sechdrs[i]; + +		check_section(mod->name, elf, sechdr);  		/* We want to process only relocation sections and not .init */ -		if (sechdrs[i].sh_type == SHT_RELA) -			section_rela(mod, elf, &elf->sechdrs[i]); -		else if (sechdrs[i].sh_type == SHT_REL) -			section_rel(mod, elf, &elf->sechdrs[i]); +		if (sechdr->sh_type == SHT_REL || sechdr->sh_type == SHT_RELA) { +			/* section to which the relocation applies */ +			unsigned int secndx = sechdr->sh_info; +			const char *secname = sec_name(elf, secndx); +			const void *start, *stop; + +			/* If the section is known good, skip it */ +			if (match(secname, section_white_list)) +				continue; + +			start = sym_get_data_by_offset(elf, i, 0); +			stop = start + sechdr->sh_size; + +			if (sechdr->sh_type == SHT_RELA) +				section_rela(mod, elf, secndx, secname, +					     start, stop); +			else +				section_rel(mod, elf, secndx, secname, +					    start, stop); +		}  	}  } diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 5f94c2c9f2d9..69baf014da4f 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -1,4 +1,5 @@  /* SPDX-License-Identifier: GPL-2.0 */ +#include <byteswap.h>  #include <stdbool.h>  #include <stdio.h>  #include <stdlib.h> @@ -10,6 +11,7 @@  #include <fcntl.h>  #include <unistd.h>  #include <elf.h> +#include "../../include/linux/module_symbol.h"  #include "list.h"  #include "elfconfig.h" @@ -50,21 +52,19 @@  #define ELF_R_TYPE  ELF64_R_TYPE  #endif -#if KERNEL_ELFDATA != HOST_ELFDATA +#define bswap(x) \ +({ \ +	_Static_assert(sizeof(x) == 1 || sizeof(x) == 2 || \ +		       sizeof(x) == 4 || sizeof(x) == 8, "bug"); \ +	(typeof(x))(sizeof(x) == 2 ? bswap_16(x) : \ +		    sizeof(x) == 4 ? bswap_32(x) : \ +		    sizeof(x) == 8 ? bswap_64(x) : \ +		    x); \ +}) -static inline void __endian(const void *src, void *dest, unsigned int size) -{ -	unsigned int i; -	for (i = 0; i < size; i++) -		((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1]; -} +#if KERNEL_ELFDATA != HOST_ELFDATA -#define TO_NATIVE(x)						\ -({								\ -	typeof(x) __x;						\ -	__endian(&(x), &(__x), sizeof(__x));			\ -	__x;							\ -}) +#define TO_NATIVE(x) (bswap(x))  #else /* endianness matches */ @@ -128,6 +128,8 @@ struct elf_info {  	 * take shndx from symtab_shndx_start[N] instead */  	Elf32_Word   *symtab_shndx_start;  	Elf32_Word   *symtab_shndx_stop; + +	struct symsearch *symsearch;  };  /* Accessor for sym->st_shndx, hides ugliness of "64k sections" */ @@ -154,6 +156,28 @@ static inline unsigned int get_secindex(const struct elf_info *info,  	return index;  } +/* + * If there's no name there, ignore it; likewise, ignore it if it's + * one of the magic symbols emitted used by current tools. + * + * Internal symbols created by tools should be ignored by modpost. + */ +static inline bool is_valid_name(struct elf_info *elf, Elf_Sym *sym) +{ +	const char *name = elf->strtab + sym->st_name; + +	if (!name || !strlen(name)) +		return false; +	return !is_mapping_symbol(name); +} + +/* symsearch.c */ +void symsearch_init(struct elf_info *elf); +void symsearch_finish(struct elf_info *elf); +Elf_Sym *symsearch_find_nearest(struct elf_info *elf, Elf_Addr addr, +				unsigned int secndx, bool allow_negative, +				Elf_Addr min_distance); +  /* file2alias.c */  void handle_moddevtable(struct module *mod, struct elf_info *info,  			Elf_Sym *sym, const char *symname); diff --git a/scripts/mod/symsearch.c b/scripts/mod/symsearch.c new file mode 100644 index 000000000000..aa4ed51f9960 --- /dev/null +++ b/scripts/mod/symsearch.c @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Helper functions for finding the symbol in an ELF which is "nearest" + * to a given address. + */ + +#include "modpost.h" + +struct syminfo { +	unsigned int symbol_index; +	unsigned int section_index; +	Elf_Addr addr; +}; + +/* + * Container used to hold an entire binary search table. + * Entries in table are ascending, sorted first by section_index, + * then by addr, and last by symbol_index.  The sorting by + * symbol_index is used to ensure predictable behavior when + * multiple symbols are present with the same address; all + * symbols past the first are effectively ignored, by eliding + * them in symsearch_fixup(). + */ +struct symsearch { +	unsigned int table_size; +	struct syminfo table[]; +}; + +static int syminfo_compare(const void *s1, const void *s2) +{ +	const struct syminfo *sym1 = s1; +	const struct syminfo *sym2 = s2; + +	if (sym1->section_index > sym2->section_index) +		return 1; +	if (sym1->section_index < sym2->section_index) +		return -1; +	if (sym1->addr > sym2->addr) +		return 1; +	if (sym1->addr < sym2->addr) +		return -1; +	if (sym1->symbol_index > sym2->symbol_index) +		return 1; +	if (sym1->symbol_index < sym2->symbol_index) +		return -1; +	return 0; +} + +static unsigned int symbol_count(struct elf_info *elf) +{ +	unsigned int result = 0; + +	for (Elf_Sym *sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { +		if (is_valid_name(elf, sym)) +			result++; +	} +	return result; +} + +/* + * Populate the search array that we just allocated. + * Be slightly paranoid here.  The ELF file is mmap'd and could + * conceivably change between symbol_count() and symsearch_populate(). + * If we notice any difference, bail out rather than potentially + * propagating errors or crashing. + */ +static void symsearch_populate(struct elf_info *elf, +			       struct syminfo *table, +			       unsigned int table_size) +{ +	bool is_arm = (elf->hdr->e_machine == EM_ARM); + +	for (Elf_Sym *sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { +		if (is_valid_name(elf, sym)) { +			if (table_size-- == 0) +				fatal("%s: size mismatch\n", __func__); +			table->symbol_index = sym - elf->symtab_start; +			table->section_index = get_secindex(elf, sym); +			table->addr = sym->st_value; + +			/* +			 * For ARM Thumb instruction, the bit 0 of st_value is +			 * set if the symbol is STT_FUNC type. Mask it to get +			 * the address. +			 */ +			if (is_arm && ELF_ST_TYPE(sym->st_info) == STT_FUNC) +				table->addr &= ~1; + +			table++; +		} +	} + +	if (table_size != 0) +		fatal("%s: size mismatch\n", __func__); +} + +/* + * Do any fixups on the table after sorting. + * For now, this just finds adjacent entries which have + * the same section_index and addr, and it propagates + * the first symbol_index over the subsequent entries, + * so that only one symbol_index is seen for any given + * section_index and addr.  This ensures that whether + * we're looking at an address from "above" or "below" + * that we see the same symbol_index. + * This does leave some duplicate entries in the table; + * in practice, these are a small fraction of the + * total number of entries, and they are harmless to + * the binary search algorithm other than a few occasional + * unnecessary comparisons. + */ +static void symsearch_fixup(struct syminfo *table, unsigned int table_size) +{ +	/* Don't look at index 0, it will never change. */ +	for (unsigned int i = 1; i < table_size; i++) { +		if (table[i].addr == table[i - 1].addr && +		    table[i].section_index == table[i - 1].section_index) { +			table[i].symbol_index = table[i - 1].symbol_index; +		} +	} +} + +void symsearch_init(struct elf_info *elf) +{ +	unsigned int table_size = symbol_count(elf); + +	elf->symsearch = NOFAIL(malloc(sizeof(struct symsearch) + +				       sizeof(struct syminfo) * table_size)); +	elf->symsearch->table_size = table_size; + +	symsearch_populate(elf, elf->symsearch->table, table_size); +	qsort(elf->symsearch->table, table_size, +	      sizeof(struct syminfo), syminfo_compare); + +	symsearch_fixup(elf->symsearch->table, table_size); +} + +void symsearch_finish(struct elf_info *elf) +{ +	free(elf->symsearch); +	elf->symsearch = NULL; +} + +/* + * Find the syminfo which is in secndx and "nearest" to addr. + * allow_negative: allow returning a symbol whose address is > addr. + * min_distance: ignore symbols which are further away than this. + * + * Returns a pointer into the symbol table for success. + * Returns NULL if no legal symbol is found within the requested range. + */ +Elf_Sym *symsearch_find_nearest(struct elf_info *elf, Elf_Addr addr, +				unsigned int secndx, bool allow_negative, +				Elf_Addr min_distance) +{ +	unsigned int hi = elf->symsearch->table_size; +	unsigned int lo = 0; +	struct syminfo *table = elf->symsearch->table; +	struct syminfo target; + +	target.addr = addr; +	target.section_index = secndx; +	target.symbol_index = ~0;  /* compares greater than any actual index */ +	while (hi > lo) { +		unsigned int mid = lo + (hi - lo) / 2;  /* Avoids overflow */ + +		if (syminfo_compare(&table[mid], &target) > 0) +			hi = mid; +		else +			lo = mid + 1; +	} + +	/* +	 * table[hi], if it exists, is the first entry in the array which +	 * lies beyond target.  table[hi - 1], if it exists, is the last +	 * entry in the array which comes before target, including the +	 * case where it perfectly matches the section and the address. +	 * +	 * Note -- if the address we're looking up falls perfectly +	 * in the middle of two symbols, this is written to always +	 * prefer the symbol with the lower address. +	 */ +	Elf_Sym *result = NULL; + +	if (allow_negative && +	    hi < elf->symsearch->table_size && +	    table[hi].section_index == secndx && +	    table[hi].addr - addr <= min_distance) { +		min_distance = table[hi].addr - addr; +		result = &elf->symtab_start[table[hi].symbol_index]; +	} +	if (hi > 0 && +	    table[hi - 1].section_index == secndx && +	    addr - table[hi - 1].addr <= min_distance) { +		result = &elf->symtab_start[table[hi - 1].symbol_index]; +	} +	return result; +} diff --git a/scripts/package/mkspec b/scripts/package/mkspec index d41608efb747..ce201bfa8377 100755 --- a/scripts/package/mkspec +++ b/scripts/package/mkspec @@ -9,6 +9,12 @@  #	Patched for non-x86 by Opencon (L) 2002 <[email protected]>  # +output=$1 + +mkdir -p "$(dirname "${output}")" + +exec >"${output}" +  if grep -q CONFIG_MODULES=y include/config/auto.conf; then  echo '%define with_devel %{?_without_devel: 0} %{?!_without_devel: 1}'  else diff --git a/scripts/pahole-flags.sh b/scripts/pahole-flags.sh deleted file mode 100755 index 728d55190d97..000000000000 --- a/scripts/pahole-flags.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 - -extra_paholeopt= - -if ! [ -x "$(command -v ${PAHOLE})" ]; then -	exit 0 -fi - -pahole_ver=$($(dirname $0)/pahole-version.sh ${PAHOLE}) - -if [ "${pahole_ver}" -ge "118" ] && [ "${pahole_ver}" -le "121" ]; then -	# pahole 1.18 through 1.21 can't handle zero-sized per-CPU vars -	extra_paholeopt="${extra_paholeopt} --skip_encoding_btf_vars" -fi -if [ "${pahole_ver}" -ge "121" ]; then -	extra_paholeopt="${extra_paholeopt} --btf_gen_floats" -fi -if [ "${pahole_ver}" -ge "122" ]; then -	extra_paholeopt="${extra_paholeopt} -j" -fi -if [ "${pahole_ver}" -ge "124" ]; then -	# see PAHOLE_HAS_LANG_EXCLUDE -	extra_paholeopt="${extra_paholeopt} --lang_exclude=rust" -fi -if [ "${pahole_ver}" -ge "125" ]; then -	extra_paholeopt="${extra_paholeopt} --skip_encoding_btf_inconsistent_proto --btf_gen_optimized" -fi - -echo ${extra_paholeopt} diff --git a/scripts/remove-stale-files b/scripts/remove-stale-files index 8b1a636f8543..385610fe3936 100755 --- a/scripts/remove-stale-files +++ b/scripts/remove-stale-files @@ -38,4 +38,4 @@ rm -rf include/ksym  find . -name '*.usyms' | xargs rm -f -rm -f binkernel.spec +rm -f *.spec |