Re: [RFC PATCH] kbuild: pass objects instead of archives to linker

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Masahiro,

On Wed, 2 Nov 2022 at 10:13, Masahiro Yamada <masahiroy@xxxxxxxxxx> wrote:
>
> This is an experimental patch, driven by the feedback from Jiri Slaby
> and Michael Matz. [1]
>
> Michael Matz says:
>  "I know of no linker (outside LTO-like modes) that processes
>   archives in a different order than first-to-last-member (under
>   whole-archive), but that's not guaranteed anywhere. So relying on
>   member-order within archives is always brittle."
>
> It is pretty easy to pass the list of objects instead of a thin archive
> because the linker supports the '@file' syntax, where command line
> arguments are read from 'file'.
>

Can you explain which problem is solved by doing this?

If we can only produce a working kernel if each object is linked in
the order it appears in the archive, I think we have bigger problems
that need solving regardless. And for the .head.text objects that need
to appear at the start of the binary image, I think the reported issue
with __head annotated C functions on x86 needs to be addressed by
getting rid of __head entirely (which seems to have been introduced
without proper justification)


> Without this patch, the linker receives
>
>   --whole-archive vmlinux.a --no-whole-archive
>
> With this patch, the linker will receive
>
>   @vmlinux.order
>
> Here, vmlinux.order is a text file that lists built-in objects in the
> correct link order.
>
> I am not a toolchain expert. I just want to know if this makes any
> difference from the linker perspective and from (non-upstreamed) GCC-LTO
> perspective.
>
> (I know this patch does not work for Clang LTO because I did not touch
> scripts/generate_initcall_order.pl)
>
> This patch may be unneeded because more correct patches were submitted [2]
> but I am still curious about "thin archive vs direct object list".
>
> [1]: https://lore.kernel.org/linux-kbuild/alpine.LSU.2.20.2210251210140.29399@xxxxxxxxxxxxx/
> [2]: https://lore.kernel.org/all/20221101161529.1634188-1-alexandr.lobakin@xxxxxxxxx/
>
> Signed-off-by: Masahiro Yamada <masahiroy@xxxxxxxxxx>
> ---
>
>  Makefile                                    | 21 ++++++++++-----------
>  scripts/Makefile.modpost                    |  5 +++--
>  scripts/Makefile.vmlinux_o                  |  6 +++---
>  scripts/clang-tools/gen_compile_commands.py | 21 ++++++++++++++++++++-
>  scripts/link-vmlinux.sh                     |  8 ++++----
>  5 files changed, 40 insertions(+), 21 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index e9e7eff906a5..511484a3dacb 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1213,19 +1213,18 @@ quiet_cmd_autoksyms_h = GEN     $@
>  $(autoksyms_h):
>         $(call cmd,autoksyms_h)
>
> -# '$(AR) mPi' needs 'T' to workaround the bug of llvm-ar <= 14
> -quiet_cmd_ar_vmlinux.a = AR      $@
> -      cmd_ar_vmlinux.a = \
> -       rm -f $@; \
> -       $(AR) cDPrST $@ $(KBUILD_VMLINUX_OBJS); \
> -       $(AR) mPiT $$($(AR) t $@ | sed -n 1p) $@ $$($(AR) t $@ | grep -F -f $(srctree)/scripts/head-object-list.txt)
> +quiet_cmd_vmlinux_order = GEN     $@
> +      cmd_vmlinux_order = \
> +       { $(foreach m, $(KBUILD_VMLINUX_OBJS), $(AR) t $m;) :; } > $(tmp-target) ; \
> +       grep -F -f $(srctree)/scripts/head-object-list.txt $(tmp-target) > $@; \
> +       grep -F -f $(srctree)/scripts/head-object-list.txt $(tmp-target) -v >> $@
>
> -targets += vmlinux.a
> -vmlinux.a: $(KBUILD_VMLINUX_OBJS) scripts/head-object-list.txt autoksyms_recursive FORCE
> -       $(call if_changed,ar_vmlinux.a)
> +targets += vmlinux.order
> +vmlinux.order: $(KBUILD_VMLINUX_OBJS) scripts/head-object-list.txt autoksyms_recursive FORCE
> +       $(call if_changed,vmlinux_order)
>
>  PHONY += vmlinux_o
> -vmlinux_o: vmlinux.a $(KBUILD_VMLINUX_LIBS)
> +vmlinux_o: vmlinux.order $(KBUILD_VMLINUX_LIBS)
>         $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.vmlinux_o
>
>  vmlinux.o modules.builtin.modinfo modules.builtin: vmlinux_o
> @@ -2037,7 +2036,7 @@ quiet_cmd_gen_compile_commands = GEN     $@
>        cmd_gen_compile_commands = $(PYTHON3) $< -a $(AR) -o $@ $(filter-out $<, $(real-prereqs))
>
>  $(extmod_prefix)compile_commands.json: scripts/clang-tools/gen_compile_commands.py \
> -       $(if $(KBUILD_EXTMOD),, vmlinux.a $(KBUILD_VMLINUX_LIBS)) \
> +       $(if $(KBUILD_EXTMOD),, vmlinux.order $(KBUILD_VMLINUX_LIBS)) \
>         $(if $(CONFIG_MODULES), $(MODORDER)) FORCE
>         $(call if_changed,gen_compile_commands)
>
> diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
> index e41dee64d429..1d6847da39bd 100644
> --- a/scripts/Makefile.modpost
> +++ b/scripts/Makefile.modpost
> @@ -70,12 +70,13 @@ quiet_cmd_vmlinux_objs = GEN     $@
>         for f in $(real-prereqs); do    \
>                 case $${f} in           \
>                 *libgcc.a) ;;           \
> -               *) $(AR) t $${f} ;;     \
> +               *.a) $(AR) t $${f} ;;   \
> +               *) cat $${f} ;;         \
>                 esac                    \
>         done > $@
>
>  targets += .vmlinux.objs
> -.vmlinux.objs: vmlinux.a $(KBUILD_VMLINUX_LIBS) FORCE
> +.vmlinux.objs: vmlinux.order $(KBUILD_VMLINUX_LIBS) FORCE
>         $(call if_changed,vmlinux_objs)
>
>  vmlinux.o-if-present := $(wildcard vmlinux.o)
> diff --git a/scripts/Makefile.vmlinux_o b/scripts/Makefile.vmlinux_o
> index 0edfdb40364b..6eb07f2bb39f 100644
> --- a/scripts/Makefile.vmlinux_o
> +++ b/scripts/Makefile.vmlinux_o
> @@ -18,7 +18,7 @@ quiet_cmd_gen_initcalls_lds = GEN     $@
>         $(PERL) $(real-prereqs) > $@
>
>  .tmp_initcalls.lds: $(srctree)/scripts/generate_initcall_order.pl \
> -               vmlinux.a $(KBUILD_VMLINUX_LIBS) FORCE
> +               vmlinux.order $(KBUILD_VMLINUX_LIBS) FORCE
>         $(call if_changed,gen_initcalls_lds)
>
>  targets := .tmp_initcalls.lds
> @@ -48,7 +48,7 @@ quiet_cmd_ld_vmlinux.o = LD      $@
>        cmd_ld_vmlinux.o = \
>         $(LD) ${KBUILD_LDFLAGS} -r -o $@ \
>         $(addprefix -T , $(initcalls-lds)) \
> -       --whole-archive vmlinux.a --no-whole-archive \
> +       @vmlinux.order \
>         --start-group $(KBUILD_VMLINUX_LIBS) --end-group \
>         $(cmd_objtool)
>
> @@ -57,7 +57,7 @@ define rule_ld_vmlinux.o
>         $(call cmd,gen_objtooldep)
>  endef
>
> -vmlinux.o: $(initcalls-lds) vmlinux.a $(KBUILD_VMLINUX_LIBS) FORCE
> +vmlinux.o: $(initcalls-lds) vmlinux.order $(KBUILD_VMLINUX_LIBS) FORCE
>         $(call if_changed_rule,ld_vmlinux.o)
>
>  targets += vmlinux.o
> diff --git a/scripts/clang-tools/gen_compile_commands.py b/scripts/clang-tools/gen_compile_commands.py
> index d800b2c0af97..c8ba9f084bd0 100755
> --- a/scripts/clang-tools/gen_compile_commands.py
> +++ b/scripts/clang-tools/gen_compile_commands.py
> @@ -57,7 +57,7 @@ def parse_arguments():
>      parser.add_argument('-a', '--ar', type=str, default='llvm-ar', help=ar_help)
>
>      paths_help = ('directories to search or files to parse '
> -                  '(files should be *.o, *.a, or modules.order). '
> +                  '(files should be *.o, *.a, or *.order). '
>                    'If nothing is specified, the current directory is searched')
>      parser.add_argument('paths', type=str, nargs='*', help=paths_help)
>
> @@ -124,6 +124,23 @@ def cmdfiles_for_a(archive, ar):
>          yield to_cmdfile(obj)
>
>
> +def cmdfiles_for_vmlinux_order(vmlinux_order):
> +    """Generate the iterator of .cmd files associated with the vmlinux.order.
> +
> +    Parse the given vmlinux.order, and yield every .cmd file used to build the
> +    contained modules.
> +
> +    Args:
> +        vmlinux_order: The vmlinux.order file to parse
> +
> +    Yields:
> +        The path to every .cmd file found
> +    """
> +    with open(vmlinux_order) as f:
> +        for line in f:
> +            yield to_cmdfile(line.rstrip())
> +
> +
>  def cmdfiles_for_modorder(modorder):
>      """Generate the iterator of .cmd files associated with the modules.order.
>
> @@ -203,6 +220,8 @@ def main():
>              cmdfiles = cmdfiles_in_dir(path)
>          elif path.endswith('.a'):
>              cmdfiles = cmdfiles_for_a(path, ar)
> +        elif path.endswith('vmlinux.order'):
> +            cmdfiles = cmdfiles_for_vmlinux_order(path)
>          elif path.endswith('modules.order'):
>              cmdfiles = cmdfiles_for_modorder(path)
>          else:
> diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
> index 918470d768e9..617ed443e377 100755
> --- a/scripts/link-vmlinux.sh
> +++ b/scripts/link-vmlinux.sh
> @@ -3,15 +3,15 @@
>  #
>  # link vmlinux
>  #
> -# vmlinux is linked from the objects in vmlinux.a and $(KBUILD_VMLINUX_LIBS).
> -# vmlinux.a contains objects that are linked unconditionally.
> +# vmlinux is linked from the objects in vmlinux.order and $(KBUILD_VMLINUX_LIBS).
> +# vmlinux.order is a text file that contains objects that are linked unconditionally.
>  # $(KBUILD_VMLINUX_LIBS) are archives which are linked conditionally
>  # (not within --whole-archive), and do not require symbol indexes added.
>  #
>  # vmlinux
>  #   ^
>  #   |
> -#   +--< vmlinux.a
> +#   +--< vmlinux.order
>  #   |
>  #   +--< $(KBUILD_VMLINUX_LIBS)
>  #   |    +--< lib/lib.a + more
> @@ -65,7 +65,7 @@ vmlinux_link()
>                 objs=vmlinux.o
>                 libs=
>         else
> -               objs=vmlinux.a
> +               objs=@vmlinux.order
>                 libs="${KBUILD_VMLINUX_LIBS}"
>         fi
>
> --
> 2.34.1
>



[Index of Archives]     [Linux&nblp;USB Development]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite Secrets]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux