diff --git a/Documentation/kbuild/kbuild.txt b/Documentation/kbuild/kbuild.txt index 0d8addbb0fae..1e5165aa9e4e 100644 --- a/Documentation/kbuild/kbuild.txt +++ b/Documentation/kbuild/kbuild.txt @@ -22,11 +22,33 @@ building C files and assembler files. KAFLAGS -------------------------------------------------- -Additional options to the assembler. +Additional options to the assembler (for built-in and modules). + +AFLAGS_MODULE +-------------------------------------------------- +Addtional module specific options to use for $(AS). + +AFLAGS_KERNEL +-------------------------------------------------- +Addtional options for $(AS) when used for assembler +code for code that is compiled as built-in. KCFLAGS -------------------------------------------------- -Additional options to the C compiler. +Additional options to the C compiler (for built-in and modules). + +CFLAGS_KERNEL +-------------------------------------------------- +Addtional options for $(CC) when used to compile +code that is compiled as built-in. + +CFLAGS_MODULE +-------------------------------------------------- +Addtional module specific options to use for $(CC). + +LDFLAGS_MODULE +-------------------------------------------------- +Additional options used for $(LD) when linking modules. KBUILD_VERBOSE -------------------------------------------------- diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index 8abd041b605d..c375313cb128 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -921,16 +921,33 @@ When kbuild executes, the following steps are followed (roughly): The first example utilises the trick that a config option expands to 'y' when selected. - CFLAGS_KERNEL $(CC) options specific for built-in + KBUILD_AFLAGS_KERNEL $(AS) options specific for built-in - $(CFLAGS_KERNEL) contains extra C compiler flags used to compile + $(KBUILD_AFLAGS_KERNEL) contains extra C compiler flags used to compile resident kernel code. - CFLAGS_MODULE $(CC) options specific for modules + KBUILD_AFLAGS_MODULE Options for $(AS) when building modules - $(CFLAGS_MODULE) contains extra C compiler flags used to compile code - for loadable kernel modules. + $(KBUILD_AFLAGS_MODULE) is used to add arch specific options that + are used for $(AS). + From commandline AFLAGS_MODULE shall be used (see kbuild.txt). + KBUILD_CFLAGS_KERNEL $(CC) options specific for built-in + + $(KBUILD_CFLAGS_KERNEL) contains extra C compiler flags used to compile + resident kernel code. + + KBUILD_CFLAGS_MODULE Options for $(CC) when building modules + + $(KBUILD_CFLAGS_MODULE) is used to add arch specific options that + are used for $(CC). + From commandline CFLAGS_MODULE shall be used (see kbuild.txt). + + KBUILD_LDFLAGS_MODULE Options for $(LD) when linking modules + + $(KBUILD_LDFLAGS_MODULE) is used to add arch specific options + used when linking modules. This is often a linker script. + From commandline LDFLAGS_MODULE shall be used (see kbuild.txt). --- 6.2 Add prerequisites to archprepare: diff --git a/Makefile b/Makefile index 141da26fda4b..968ac2af763b 100644 --- a/Makefile +++ b/Makefile @@ -332,10 +332,9 @@ CHECK = sparse CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \ -Wbitwise -Wno-return-void $(CF) -MODFLAGS = -DMODULE -CFLAGS_MODULE = $(MODFLAGS) -AFLAGS_MODULE = $(MODFLAGS) -LDFLAGS_MODULE = -T $(srctree)/scripts/module-common.lds +CFLAGS_MODULE = +AFLAGS_MODULE = +LDFLAGS_MODULE = CFLAGS_KERNEL = AFLAGS_KERNEL = CFLAGS_GCOV = -fprofile-arcs -ftest-coverage @@ -354,7 +353,12 @@ KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ -Werror-implicit-function-declaration \ -Wno-format-security \ -fno-delete-null-pointer-checks +KBUILD_AFLAGS_KERNEL := +KBUILD_CFLAGS_KERNEL := KBUILD_AFLAGS := -D__ASSEMBLY__ +KBUILD_AFLAGS_MODULE := -DMODULE +KBUILD_CFLAGS_MODULE := -DMODULE +KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds # Read KERNELRELEASE from include/config/kernel.release (if it exists) KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null) @@ -369,6 +373,8 @@ export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE +export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE +export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL # When compiling out-of-tree modules, put MODVERDIR in the module # tree rather than in the kernel tree. The kernel tree might @@ -414,7 +420,7 @@ endif no-dot-config-targets := clean mrproper distclean \ cscope TAGS tags help %docs check% \ include/linux/version.h headers_% \ - kernelrelease kernelversion + kernelversion config-targets := 0 mixed-targets := 0 @@ -557,6 +563,10 @@ KBUILD_CFLAGS += -g KBUILD_AFLAGS += -gdwarf-2 endif +ifdef CONFIG_DEBUG_INFO_REDUCED +KBUILD_CFLAGS += $(call cc-option, -femit-struct-debug-baseonly) +endif + ifdef CONFIG_FUNCTION_TRACER KBUILD_CFLAGS += -pg endif @@ -603,7 +613,7 @@ endif # Use --build-id when available. LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\ $(call cc-ldoption, -Wl$(comma)--build-id,)) -LDFLAGS_MODULE += $(LDFLAGS_BUILD_ID) +KBUILD_LDFLAGS_MODULE += $(LDFLAGS_BUILD_ID) LDFLAGS_vmlinux += $(LDFLAGS_BUILD_ID) ifeq ($(CONFIG_STRIP_ASM_SYMS),y) @@ -1393,9 +1403,9 @@ checkstack: $(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \ $(PERL) $(src)/scripts/checkstack.pl $(CHECKSTACK_ARCH) -kernelrelease: - $(if $(wildcard include/config/kernel.release), $(Q)echo $(KERNELRELEASE), \ - $(error kernelrelease not valid - run 'make prepare' to update it)) +kernelrelease: include/config/kernel.release + @echo $(KERNELRELEASE) + kernelversion: @echo $(KERNELVERSION) @@ -1472,6 +1482,7 @@ cmd_crmodverdir = $(Q)mkdir -p $(MODVERDIR) \ $(if $(KBUILD_MODULES),; rm -f $(MODVERDIR)/*) a_flags = -Wp,-MD,$(depfile) $(KBUILD_AFLAGS) $(AFLAGS_KERNEL) \ + $(KBUILD_AFLAGS_KERNEL) \ $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(KBUILD_CPPFLAGS) \ $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(basetarget).o) diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile index ead8a75203a9..22fb66590dcd 100644 --- a/arch/avr32/Makefile +++ b/arch/avr32/Makefile @@ -13,7 +13,7 @@ KBUILD_DEFCONFIG := atstk1002_defconfig KBUILD_CFLAGS += -pipe -fno-builtin -mno-pic KBUILD_AFLAGS += -mrelax -mno-pic -CFLAGS_MODULE += -mno-relax +KBUILD_CFLAGS_MODULE += -mno-relax LDFLAGS_vmlinux += --relax cpuflags-$(CONFIG_PLATFORM_AT32AP) += -march=ap diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile index 5a97a31d4bbd..9d5ffaf5492a 100644 --- a/arch/blackfin/Makefile +++ b/arch/blackfin/Makefile @@ -18,8 +18,8 @@ ifeq ($(CONFIG_ROMKERNEL),y) KBUILD_CFLAGS += -mlong-calls endif KBUILD_AFLAGS += $(call cc-option,-mno-fdpic) -CFLAGS_MODULE += -mlong-calls -LDFLAGS_MODULE += -m elf32bfin +KBUILD_CFLAGS_MODULE += -mlong-calls +KBUILD_LDFLAGS_MODULE += -m elf32bfin KALLSYMS += --symbol-prefix=_ KBUILD_DEFCONFIG := BF537-STAMP_defconfig diff --git a/arch/frv/Makefile b/arch/frv/Makefile index 310c47a663f8..7ff84575b186 100644 --- a/arch/frv/Makefile +++ b/arch/frv/Makefile @@ -23,20 +23,14 @@ # Copyright (C) 1994 by Hamish Macdonald # -CCSPECS := $(shell $(CC) -v 2>&1 | grep "^Reading specs from " | head -1 | cut -c20-) -CCDIR := $(strip $(patsubst %/specs,%,$(CCSPECS))) -CPUCLASS := fr400 - -# test for cross compiling -COMPILE_ARCH = $(shell uname -m) - ifdef CONFIG_MMU UTS_SYSNAME = -DUTS_SYSNAME=\"Linux\" else UTS_SYSNAME = -DUTS_SYSNAME=\"uClinux\" endif -ARCHMODFLAGS += -G0 -mlong-calls +KBUILD_AFLAGS_MODULE += -G0 -mlong-calls +KBUILD_CFLAGS_MODULE += -G0 -mlong-calls ifdef CONFIG_GPREL_DATA_8 KBUILD_CFLAGS += -G8 @@ -54,7 +48,6 @@ endif ifdef CONFIG_GC_SECTIONS KBUILD_CFLAGS += -ffunction-sections -fdata-sections -LINKFLAGS += --gc-sections endif ifndef CONFIG_FRAME_POINTER @@ -64,16 +57,13 @@ endif ifdef CONFIG_CPU_FR451_COMPILE KBUILD_CFLAGS += -mcpu=fr450 KBUILD_AFLAGS += -mcpu=fr450 -ASFLAGS += -mcpu=fr450 else ifdef CONFIG_CPU_FR551_COMPILE KBUILD_CFLAGS += -mcpu=fr550 KBUILD_AFLAGS += -mcpu=fr550 -ASFLAGS += -mcpu=fr550 else KBUILD_CFLAGS += -mcpu=fr400 KBUILD_AFLAGS += -mcpu=fr400 -ASFLAGS += -mcpu=fr400 endif endif @@ -83,14 +73,12 @@ endif KBUILD_CFLAGS += -mno-fdpic -mgpr-32 -msoft-float -mno-media KBUILD_CFLAGS += -ffixed-fcc3 -ffixed-cc3 -ffixed-gr15 -ffixed-icc2 KBUILD_AFLAGS += -mno-fdpic -ASFLAGS += -mno-fdpic # make sure the .S files get compiled with debug info # and disable optimisations that are unhelpful whilst debugging ifdef CONFIG_DEBUG_INFO #KBUILD_CFLAGS += -O1 KBUILD_AFLAGS += -Wa,--gdwarf2 -ASFLAGS += -Wa,--gdwarf2 endif head-y := arch/frv/kernel/head.o arch/frv/kernel/init_task.o @@ -105,11 +93,5 @@ all: Image Image: vmlinux $(Q)$(MAKE) $(build)=arch/frv/boot $@ -bootstrap: - $(Q)$(MAKEBOOT) bootstrap - archclean: $(Q)$(MAKE) $(clean)=arch/frv/boot - -archdep: scripts/mkdep symlinks - $(Q)$(MAKE) $(build)=arch/frv/boot dep diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 8ae0d2604ce1..be7bfa12b705 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -22,13 +22,13 @@ CHECKFLAGS += -m64 -D__ia64=1 -D__ia64__=1 -D_LP64 -D__LP64__ OBJCOPYFLAGS := --strip-all LDFLAGS_vmlinux := -static -LDFLAGS_MODULE += -T $(srctree)/arch/ia64/module.lds -AFLAGS_KERNEL := -mconstant-gp +KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/ia64/module.lds +KBUILD_AFLAGS_KERNEL := -mconstant-gp EXTRA := cflags-y := -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f12-f15,f32-f127 \ -falign-functions=32 -frename-registers -fno-optimize-sibling-calls -CFLAGS_KERNEL := -mconstant-gp +KBUILD_CFLAGS_KERNEL := -mconstant-gp GAS_STATUS = $(shell $(srctree)/arch/ia64/scripts/check-gas "$(CC)" "$(OBJDUMP)") KBUILD_CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags "$(CC)" "$(OBJDUMP)" "$(READELF)") diff --git a/arch/m32r/Makefile b/arch/m32r/Makefile index 469766b24e22..8ff5ba0ea26c 100644 --- a/arch/m32r/Makefile +++ b/arch/m32r/Makefile @@ -12,8 +12,8 @@ OBJCOPYFLAGS := -O binary -R .note -R .comment -S LDFLAGS_vmlinux := KBUILD_CFLAGS += -pipe -fno-schedule-insns -CFLAGS_KERNEL += -mmodel=medium -CFLAGS_MODULE += -mmodel=large +KBUILD_CFLAGS_KERNEL += -mmodel=medium +KBUILD_CFLAGS_MODULE += -mmodel=large ifdef CONFIG_CHIP_VDEC2 cflags-$(CONFIG_ISA_M32R2) += -DNO_FPU -Wa,-bitinst diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile index 570d85c3f97f..b06a7e3cbcd6 100644 --- a/arch/m68k/Makefile +++ b/arch/m68k/Makefile @@ -18,7 +18,7 @@ KBUILD_DEFCONFIG := multi_defconfig # override top level makefile AS += -m68020 LDFLAGS := -m m68kelf -LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds +KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds ifneq ($(SUBARCH),$(ARCH)) ifeq ($(CROSS_COMPILE),) CROSS_COMPILE := $(call cc-cross-prefix, \ diff --git a/arch/mips/Makefile b/arch/mips/Makefile index f0d196090e94..f4a4b663ebb3 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -93,7 +93,8 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlinuz cflags-y += -G 0 -mno-abicalls -fno-pic -pipe cflags-y += -msoft-float LDFLAGS_vmlinux += -G 0 -static -n -nostdlib -MODFLAGS += -mlong-calls +KBUILD_AFLAGS_MODULE += -mlong-calls +KBUILD_CFLAGS_MODULE += -mlong-calls cflags-y += -ffreestanding @@ -165,7 +166,8 @@ cflags-$(CONFIG_CPU_DADDI_WORKAROUNDS) += $(call cc-option,-mno-daddi,) ifdef CONFIG_CPU_SB1 ifdef CONFIG_SB1_PASS_1_WORKAROUNDS -MODFLAGS += -msb1-pass1-workarounds +KBUILD_AFLAGS_MODULE += -msb1-pass1-workarounds +KBUILD_CFLAGS_MODULE += -msb1-pass1-workarounds endif endif diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 77cfe7a29e25..5d42f5eae70f 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -94,7 +94,7 @@ else endif endif -LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o +KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o ifeq ($(CONFIG_TUNE_CELL),y) KBUILD_CFLAGS += $(call cc-option,-mtune=cell) diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 30c5f01f93b0..0c9e6c6d2a64 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -24,7 +24,8 @@ CHECKFLAGS += -D__s390__ -msize-long else LD_BFD := elf64-s390 LDFLAGS := -m elf64_s390 -MODFLAGS += -fpic -D__PIC__ +KBUILD_AFLAGS_MODULE += -fpic -D__PIC__ +KBUILD_CFLAGS_MODULE += -fpic -D__PIC__ KBUILD_CFLAGS += -m64 KBUILD_AFLAGS += -m64 UTS_MACHINE := s390x diff --git a/arch/score/Makefile b/arch/score/Makefile index 68e0cd06d5c9..d77dc639d8e3 100644 --- a/arch/score/Makefile +++ b/arch/score/Makefile @@ -20,7 +20,8 @@ cflags-y += -G0 -pipe -mel -mnhwloop -D__SCOREEL__ \ # KBUILD_AFLAGS += $(cflags-y) KBUILD_CFLAGS += $(cflags-y) -MODFLAGS += -mlong-calls +KBUILD_AFLAGS_MODULE += -mlong-calls +KBUILD_CFLAGS_MODULE += -mlong-calls LDFLAGS += --oformat elf32-littlescore LDFLAGS_vmlinux += -G0 -static -nostdlib diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 154ff43aaa81..67fa774f9572 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -628,6 +628,19 @@ config DEBUG_INFO If unsure, say N. +config DEBUG_INFO_REDUCED + bool "Reduce debugging information" + depends on DEBUG_INFO + help + If you say Y here gcc is instructed to generate less debugging + information for structure types. This means that tools that + need full debugging information (like kgdb or systemtap) won't + be happy. But if you merely need debugging information to + resolve line numbers there is no loss. Advantage is that + build directory object sizes shrink dramatically over a full + DEBUG_INFO build and compile times are reduced too. + Only works with newer gcc versions. + config DEBUG_VM bool "Debug VM" depends on DEBUG_KERNEL diff --git a/scripts/Makefile.build b/scripts/Makefile.build index e4deb73e9a84..a1a5cf95a68d 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -115,7 +115,10 @@ endif # --------------------------------------------------------------------------- # Default is built-in, unless we know otherwise -modkern_cflags = $(if $(part-of-module), $(CFLAGS_MODULE), $(CFLAGS_KERNEL)) +modkern_cflags = \ + $(if $(part-of-module), \ + $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE), \ + $(KBUILD_CFLAGS_KERNEL) $(CFLAGS_KERNEL)) quiet_modtag := $(empty) $(empty) $(real-objs-m) : part-of-module := y @@ -156,14 +159,14 @@ $(obj)/%.i: $(src)/%.c FORCE cmd_gensymtypes = \ $(CPP) -D__GENKSYMS__ $(c_flags) $< | \ - $(GENKSYMS) -T $@ -a $(ARCH) \ + $(GENKSYMS) $(if $(1), -T $(2)) -a $(ARCH) \ $(if $(KBUILD_PRESERVE),-p) \ - $(if $(1),-r $(firstword $(wildcard $(@:.symtypes=.symref) /dev/null))) + -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null)) quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@ cmd_cc_symtypes_c = \ set -e; \ - $(call cmd_gensymtypes, true) >/dev/null; \ + $(call cmd_gensymtypes,true,$@) >/dev/null; \ test -s $@ || rm -f $@ $(obj)/%.symtypes : $(src)/%.c FORCE @@ -192,16 +195,16 @@ else # the actual value of the checksum generated by genksyms cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $< -cmd_modversions = \ - if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \ - $(call cmd_gensymtypes, $(KBUILD_SYMTYPES)) \ - > $(@D)/.tmp_$(@F:.o=.ver); \ - \ - $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \ - -T $(@D)/.tmp_$(@F:.o=.ver); \ - rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \ - else \ - mv -f $(@D)/.tmp_$(@F) $@; \ +cmd_modversions = \ + if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \ + $(call cmd_gensymtypes,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ + > $(@D)/.tmp_$(@F:.o=.ver); \ + \ + $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \ + -T $(@D)/.tmp_$(@F:.o=.ver); \ + rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \ + else \ + mv -f $(@D)/.tmp_$(@F) $@; \ fi; endif @@ -248,10 +251,10 @@ $(obj)/%.lst: $(src)/%.c FORCE # Compile assembler sources (.S) # --------------------------------------------------------------------------- -modkern_aflags := $(AFLAGS_KERNEL) +modkern_aflags := $(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL) -$(real-objs-m) : modkern_aflags := $(AFLAGS_MODULE) -$(real-objs-m:.o=.s): modkern_aflags := $(AFLAGS_MODULE) +$(real-objs-m) : modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE) +$(real-objs-m:.o=.s): modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE) quiet_cmd_as_s_S = CPP $(quiet_modtag) $@ cmd_as_s_S = $(CPP) $(a_flags) -o $@ $< diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 8f14c81abbc7..7d22056582c1 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -30,7 +30,7 @@ # - See include/linux/module.h for more details # Step 4 is solely used to allow module versioning in external modules, -# where the CRC of each module is retrieved from the Module.symers file. +# where the CRC of each module is retrieved from the Module.symvers file. # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined # symbols in the final module linking stage @@ -107,7 +107,7 @@ $(modules:.ko=.mod.c): __modpost ; modname = $(notdir $(@:.mod.o=)) quiet_cmd_cc_o_c = CC $@ - cmd_cc_o_c = $(CC) $(c_flags) $(CFLAGS_MODULE) \ + cmd_cc_o_c = $(CC) $(c_flags) $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE) \ -c -o $@ $< $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE @@ -117,8 +117,9 @@ targets += $(modules:.ko=.mod.o) # Step 6), final link of the modules quiet_cmd_ld_ko_o = LD [M] $@ - cmd_ld_ko_o = $(LD) -r $(LDFLAGS) $(LDFLAGS_MODULE) -o $@ \ - $(filter-out FORCE,$^) + cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ + $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ + -o $@ $(filter-out FORCE,$^) $(modules): %.ko :%.o %.mod.o FORCE $(call if_changed,ld_ko_o) diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 5758aab0d8bb..88f3f07205f8 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -884,16 +884,16 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, char *zeros = NULL; /* We're looking for a section relative symbol */ - if (!sym->st_shndx || sym->st_shndx >= info->hdr->e_shnum) + if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections) return; /* Handle all-NULL symbols allocated into .bss */ - if (info->sechdrs[sym->st_shndx].sh_type & SHT_NOBITS) { + if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) { zeros = calloc(1, sym->st_size); symval = zeros; } else { symval = (void *)info->hdr - + info->sechdrs[sym->st_shndx].sh_offset + + info->sechdrs[get_secindex(info, sym)].sh_offset + sym->st_value; } diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index f6127b9f5aca..c827309c29cf 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -253,7 +253,7 @@ static enum export export_no(const char *s) return export_unknown; } -static enum export export_from_sec(struct elf_info *elf, Elf_Section sec) +static enum export export_from_sec(struct elf_info *elf, unsigned int sec) { if (sec == elf->export_sec) return export_plain; @@ -373,6 +373,8 @@ static int parse_elf(struct elf_info *info, const char *filename) Elf_Ehdr *hdr; Elf_Shdr *sechdrs; Elf_Sym *sym; + const char *secstrings; + unsigned int symtab_idx = ~0U, symtab_shndx_idx = ~0U; hdr = grab_file(filename, &info->size); if (!hdr) { @@ -417,8 +419,27 @@ static int parse_elf(struct elf_info *info, const char *filename) return 0; } + if (hdr->e_shnum == 0) { + /* + * There are more than 64k sections, + * read count from .sh_size. + * note: it doesn't need shndx2secindex() + */ + info->num_sections = TO_NATIVE(sechdrs[0].sh_size); + } + else { + info->num_sections = hdr->e_shnum; + } + if (hdr->e_shstrndx == SHN_XINDEX) { + info->secindex_strings = + shndx2secindex(TO_NATIVE(sechdrs[0].sh_link)); + } + else { + info->secindex_strings = hdr->e_shstrndx; + } + /* Fix endianness in section headers */ - for (i = 0; i < hdr->e_shnum; i++) { + for (i = 0; i < info->num_sections; i++) { sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type); sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags); @@ -431,9 +452,8 @@ static int parse_elf(struct elf_info *info, const char *filename) sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize); } /* Find symbol table. */ - for (i = 1; i < hdr->e_shnum; i++) { - const char *secstrings - = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + secstrings = (void *)hdr + sechdrs[info->secindex_strings].sh_offset; + for (i = 1; i < info->num_sections; i++) { const char *secname; int nobits = sechdrs[i].sh_type == SHT_NOBITS; @@ -461,14 +481,26 @@ static int parse_elf(struct elf_info *info, const char *filename) else if (strcmp(secname, "__ksymtab_gpl_future") == 0) info->export_gpl_future_sec = i; - if (sechdrs[i].sh_type != SHT_SYMTAB) - continue; + if (sechdrs[i].sh_type == SHT_SYMTAB) { + unsigned int sh_link_idx; + symtab_idx = i; + info->symtab_start = (void *)hdr + + sechdrs[i].sh_offset; + info->symtab_stop = (void *)hdr + + sechdrs[i].sh_offset + sechdrs[i].sh_size; + sh_link_idx = shndx2secindex(sechdrs[i].sh_link); + info->strtab = (void *)hdr + + sechdrs[sh_link_idx].sh_offset; + } - info->symtab_start = (void *)hdr + sechdrs[i].sh_offset; - info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset - + sechdrs[i].sh_size; - info->strtab = (void *)hdr + - sechdrs[sechdrs[i].sh_link].sh_offset; + /* 32bit section no. table? ("more than 64k sections") */ + if (sechdrs[i].sh_type == SHT_SYMTAB_SHNDX) { + symtab_shndx_idx = i; + info->symtab_shndx_start = (void *)hdr + + sechdrs[i].sh_offset; + info->symtab_shndx_stop = (void *)hdr + + sechdrs[i].sh_offset + sechdrs[i].sh_size; + } } if (!info->symtab_start) fatal("%s has no symtab?\n", filename); @@ -480,6 +512,21 @@ static int parse_elf(struct elf_info *info, const char *filename) sym->st_value = TO_NATIVE(sym->st_value); sym->st_size = TO_NATIVE(sym->st_size); } + + if (symtab_shndx_idx != ~0U) { + Elf32_Word *p; + if (symtab_idx != + shndx2secindex(sechdrs[symtab_shndx_idx].sh_link)) + fatal("%s: SYMTAB_SHNDX has bad sh_link: %u!=%u\n", + filename, + shndx2secindex(sechdrs[symtab_shndx_idx].sh_link), + symtab_idx); + /* Fix endianness */ + for (p = info->symtab_shndx_start; p < info->symtab_shndx_stop; + p++) + *p = TO_NATIVE(*p); + } + return 1; } @@ -519,7 +566,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info, Elf_Sym *sym, const char *symname) { unsigned int crc; - enum export export = export_from_sec(info, sym->st_shndx); + enum export export = export_from_sec(info, get_secindex(info, sym)); switch (sym->st_shndx) { case SHN_COMMON: @@ -661,19 +708,19 @@ static const char *sym_name(struct elf_info *elf, Elf_Sym *sym) return "(unknown)"; } -static const char *sec_name(struct elf_info *elf, int shndx) +static const char *sec_name(struct elf_info *elf, int secindex) { Elf_Shdr *sechdrs = elf->sechdrs; return (void *)elf->hdr + - elf->sechdrs[elf->hdr->e_shstrndx].sh_offset + - sechdrs[shndx].sh_name; + elf->sechdrs[elf->secindex_strings].sh_offset + + sechdrs[secindex].sh_name; } static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr) { return (void *)elf->hdr + - elf->sechdrs[elf->hdr->e_shstrndx].sh_offset + - sechdr->sh_name; + elf->sechdrs[elf->secindex_strings].sh_offset + + sechdr->sh_name; } /* if sym is empty or point to a string @@ -1052,11 +1099,14 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr, Elf_Sym *near = NULL; Elf64_Sword distance = 20; Elf64_Sword d; + unsigned int relsym_secindex; if (relsym->st_name != 0) return relsym; + + relsym_secindex = get_secindex(elf, relsym); for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { - if (sym->st_shndx != relsym->st_shndx) + if (get_secindex(elf, sym) != relsym_secindex) continue; if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) continue; @@ -1118,9 +1168,9 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { const char *symsec; - if (sym->st_shndx >= SHN_LORESERVE) + if (is_shndx_special(sym->st_shndx)) continue; - symsec = sec_name(elf, sym->st_shndx); + symsec = sec_name(elf, get_secindex(elf, sym)); if (strcmp(symsec, sec) != 0) continue; if (!is_valid_name(elf, sym)) @@ -1316,7 +1366,7 @@ static void check_section_mismatch(const char *modname, struct elf_info *elf, const char *tosec; const struct sectioncheck *mismatch; - tosec = sec_name(elf, sym->st_shndx); + tosec = sec_name(elf, get_secindex(elf, sym)); mismatch = section_mismatch(fromsec, tosec); if (mismatch) { Elf_Sym *to; @@ -1344,7 +1394,7 @@ 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; + int section = shndx2secindex(sechdr->sh_info); return (void *)elf->hdr + sechdrs[section].sh_offset + r->r_offset - sechdrs[section].sh_addr; @@ -1452,7 +1502,7 @@ static void section_rela(const char *modname, struct elf_info *elf, r.r_addend = TO_NATIVE(rela->r_addend); sym = elf->symtab_start + r_sym; /* Skip special sections */ - if (sym->st_shndx >= SHN_LORESERVE) + if (is_shndx_special(sym->st_shndx)) continue; check_section_mismatch(modname, elf, &r, sym, fromsec); } @@ -1510,7 +1560,7 @@ static void section_rel(const char *modname, struct elf_info *elf, } sym = elf->symtab_start + r_sym; /* Skip special sections */ - if (sym->st_shndx >= SHN_LORESERVE) + if (is_shndx_special(sym->st_shndx)) continue; check_section_mismatch(modname, elf, &r, sym, fromsec); } @@ -1535,7 +1585,7 @@ static void check_sec_ref(struct module *mod, const char *modname, Elf_Shdr *sechdrs = elf->sechdrs; /* Walk through all sections */ - for (i = 0; i < elf->hdr->e_shnum; i++) { + for (i = 0; i < elf->num_sections; i++) { check_section(modname, elf, &elf->sechdrs[i]); /* We want to process only relocation sections and not .init */ if (sechdrs[i].sh_type == SHT_RELA) diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index be987a44f250..0388cfccac8d 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -129,8 +129,51 @@ struct elf_info { const char *strtab; char *modinfo; unsigned int modinfo_len; + + /* support for 32bit section numbers */ + + unsigned int num_sections; /* max_secindex + 1 */ + unsigned int secindex_strings; + /* if Nth symbol table entry has .st_shndx = SHN_XINDEX, + * take shndx from symtab_shndx_start[N] instead */ + Elf32_Word *symtab_shndx_start; + Elf32_Word *symtab_shndx_stop; }; +static inline int is_shndx_special(unsigned int i) +{ + return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE; +} + +/* shndx is in [0..SHN_LORESERVE) U (SHN_HIRESERVE, 0xfffffff], thus: + * shndx == 0 <=> sechdrs[0] + * ...... + * shndx == SHN_LORESERVE-1 <=> sechdrs[SHN_LORESERVE-1] + * shndx == SHN_HIRESERVE+1 <=> sechdrs[SHN_LORESERVE] + * shndx == SHN_HIRESERVE+2 <=> sechdrs[SHN_LORESERVE+1] + * ...... + * fyi: sym->st_shndx is uint16, SHN_LORESERVE = ff00, SHN_HIRESERVE = ffff, + * so basically we map 0000..feff -> 0000..feff + * ff00..ffff -> (you are a bad boy, dont do it) + * 10000..xxxx -> ff00..(xxxx-0x100) + */ +static inline unsigned int shndx2secindex(unsigned int i) +{ + if (i <= SHN_HIRESERVE) + return i; + return i - (SHN_HIRESERVE + 1 - SHN_LORESERVE); +} + +/* Accessor for sym->st_shndx, hides ugliness of "64k sections" */ +static inline unsigned int get_secindex(const struct elf_info *info, + const Elf_Sym *sym) +{ + if (sym->st_shndx != SHN_XINDEX) + return sym->st_shndx; + return shndx2secindex(info->symtab_shndx_start[sym - + info->symtab_start]); +} + /* file2alias.c */ extern unsigned int cross_build; void handle_moddevtable(struct module *mod, struct elf_info *info,