Bug 19197 - gold trunk cannot build LInux kernel
Summary: gold trunk cannot build LInux kernel
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: gold (show other bugs)
Version: 2.26
: P2 normal
Target Milestone: 2.26
Assignee: H.J. Lu
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-11-01 09:06 UTC by Markus Trippelsdorf
Modified: 2015-11-19 12:30 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Markus Trippelsdorf 2015-11-01 09:06:44 UTC
markus@x4 linux % cat arch/x86/boot/bioscall.S
/* -----------------------------------------------------------------------
 *
 *   Copyright 2009-2014 Intel Corporation; author H. Peter Anvin
 *
 *   This file is part of the Linux kernel, and is made available under
 *   the terms of the GNU General Public License version 2 or (at your
 *   option) any later version; incorporated herein by reference.
 *
 * ----------------------------------------------------------------------- */

/*
 * "Glove box" for BIOS calls.  Avoids the constant problems with BIOSes
 * touching registers they shouldn't be.
 */

        .code16
        .section ".inittext","ax"
        .globl  intcall
        .type   intcall, @function
intcall:
        /* Self-modify the INT instruction.  Ugly, but works. */
        cmpb    %al, 3f
        je      1f
        movb    %al, 3f
        jmp     1f              /* Synchronize pipeline */
1:
        /* Save state */
        pushfl
        pushw   %fs
        pushw   %gs
        pushal

        /* Copy input state to stack frame */
        subw    $44, %sp
        movw    %dx, %si
        movw    %sp, %di
        movw    $11, %cx
        rep; movsd

        /* Pop full state from the stack */
        popal
        popw    %gs
        popw    %fs
        popw    %es
        popw    %ds
        popfl

        /* Actual INT */
        .byte   0xcd            /* INT opcode */
3:      .byte   0

        /* Push full state to the stack */
        pushfl
        pushw   %ds
        pushw   %es
        pushw   %fs
        pushw   %gs
        pushal

        /* Re-establish C environment invariants */
        cld
        movzwl  %sp, %esp
        movw    %cs, %ax
        movw    %ax, %ds
        movw    %ax, %es

        /* Copy output state from stack frame */
        movw    68(%esp), %di   /* Original %cx == 3rd argument */
        andw    %di, %di
        jz      4f
        movw    %sp, %si
        movw    $11, %cx
        rep; movsd
4:      addw    $44, %sp

        /* Restore state and return */
        popal
        popw    %gs
        popw    %fs
        popfl
        retl
        .size   intcall, .-intcall

markus@x4 linux % gcc -m16 -c -o foo.o arch/x86/boot/bioscall.S

markus@x4 linux % ld -m elf_x86_64 foo.o
ld: error: input file is incompatible with elf_x86_64 output emulation
Comment 1 Markus Trippelsdorf 2015-11-01 09:24:07 UTC
Sorry I forgot the linker script (,otherwise ld.bfd also fails):

markus@x4 linux % cat arch/x86/boot/setup.ld
/*
 * setup.ld
 *
 * Linker script for the i386 setup code
 */
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)

SECTIONS
{
        . = 0;
        .bstext         : { *(.bstext) }
        .bsdata         : { *(.bsdata) }

        . = 495;
        .header         : { *(.header) }
        .entrytext      : { *(.entrytext) }
        .inittext       : { *(.inittext) }
        .initdata       : { *(.initdata) }
        __end_init = .;

        .text           : { *(.text) }
        .text32         : { *(.text32) }

        . = ALIGN(16);
        .rodata         : { *(.rodata*) }

        .videocards     : {
                video_cards = .;
                *(.videocards)
                video_cards_end = .;
        }

        . = ALIGN(16);
        .data           : { *(.data*) }

        .signature      : {
                setup_sig = .;
                LONG(0x5a5aaa55)
        }


        . = ALIGN(16);
        .bss            :
        {
                __bss_start = .;
                *(.bss)
                __bss_end = .;
        }
        . = ALIGN(16);
        _end = .;

        /DISCARD/ : { *(.note*) }

        /*
         * The ASSERT() sink to . is intentional, for binutils 2.14 compatibility:
         */
        . = ASSERT(_end <= 0x8000, "Setup too big!");
        . = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!");
        /* Necessary for the very-old-loader check to work... */
        . = ASSERT(__end_init <= 5*512, "init sections too big!");

}
markus@x4 linux % ld -m elf_x86_64 -T arch/x86/boot/setup.ld foo.o
ld: error: input file is incompatible with elf_x86_64 output emulation
Comment 2 Markus Trippelsdorf 2015-11-01 09:30:46 UTC
markus@x4 linux % cat foo.c
void foo () {};

markus@x4 linux % cat setup.ld
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)

markus@x4 linux % ld.bfd -m elf_x86_64 -T setup.ld foo.o
markus@x4 linux % ld.gold -m elf_x86_64 -T setup.ld foo.o
ld: error: input file is incompatible with elf_x86_64 output emulation
Comment 3 Markus Trippelsdorf 2015-11-01 09:31:28 UTC
And of course:

markus@x4 linux % gcc -m16 -c -o foo.o foo.c
Comment 4 Markus Trippelsdorf 2015-11-01 09:39:12 UTC
Caused by H.J.'s 6457197210144f50a6

    Don't ignore "-m emulation" command line option
    
    Gold shouldn't ignore "-m emulation" command line option, which may
    lead to incorrect output.
    
    	PR gold/19119
    	* options.h (General_options): Remove "obsolete" from -m.
    	* parameters.cc (set_parameters_target): Check if input target
    	is compatible with output emulation set by "-m emulation".
Comment 5 H.J. Lu 2015-11-02 13:26:28 UTC
(In reply to Markus Trippelsdorf from comment #2)
> markus@x4 linux % cat foo.c
> void foo () {};
> 
> markus@x4 linux % cat setup.ld
> OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
> OUTPUT_ARCH(i386)
> 
> markus@x4 linux % ld.bfd -m elf_x86_64 -T setup.ld foo.o

What does "readelf -h a.out" say here?

> markus@x4 linux % ld.gold -m elf_x86_64 -T setup.ld foo.o
> ld: error: input file is incompatible with elf_x86_64 output emulation

What if you remove "-m elf_x86_64" here for both ld.gold and ld.bfd?
Comment 6 Markus Trippelsdorf 2015-11-02 13:36:20 UTC
(In reply to H.J. Lu from comment #5)
> (In reply to Markus Trippelsdorf from comment #2)
> > markus@x4 linux % cat foo.c
> > void foo () {};
> > 
> > markus@x4 linux % cat setup.ld
> > OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
> > OUTPUT_ARCH(i386)
> > 
> > markus@x4 linux % ld.bfd -m elf_x86_64 -T setup.ld foo.o
> 
> What does "readelf -h a.out" say here?

The linker script overwrites the -m argument with ld.bfd:

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
...
 
> > markus@x4 linux % ld.gold -m elf_x86_64 -T setup.ld foo.o
> > ld: error: input file is incompatible with elf_x86_64 output emulation
> 
> What if you remove "-m elf_x86_64" here for both ld.gold and ld.bfd?

Well, of course this works. But I didn't make up this example, I took
it from the Linux kernel. And I agree that it is bizarre to specify
-m elf_x86_64 and then use OUTPUT_ARCH(i386) in the linker script.
Comment 7 H.J. Lu 2015-11-02 21:24:12 UTC
(In reply to Markus Trippelsdorf from comment #6)
> (In reply to H.J. Lu from comment #5)
> > (In reply to Markus Trippelsdorf from comment #2)
> > > markus@x4 linux % cat foo.c
> > > void foo () {};
> > > 
> > > markus@x4 linux % cat setup.ld
> > > OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
> > > OUTPUT_ARCH(i386)
> > > 
> > > markus@x4 linux % ld.bfd -m elf_x86_64 -T setup.ld foo.o
> > 
> > What does "readelf -h a.out" say here?
> 
> The linker script overwrites the -m argument with ld.bfd:
> 
> ELF Header:
>   Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
>   Class:                             ELF32
> ...
>  
> > > markus@x4 linux % ld.gold -m elf_x86_64 -T setup.ld foo.o
> > > ld: error: input file is incompatible with elf_x86_64 output emulation
> > 
> > What if you remove "-m elf_x86_64" here for both ld.gold and ld.bfd?
> 
> Well, of course this works. But I didn't make up this example, I took
> it from the Linux kernel. And I agree that it is bizarre to specify
> -m elf_x86_64 and then use OUTPUT_ARCH(i386) in the linker script.

I will take care of it this weekend.
Comment 8 Markus Trippelsdorf 2015-11-03 16:04:19 UTC
Andy, would it be possible to just get rid of LDFLAGS for the x86 kernel?

diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 747860c696e1..b786a2ce58b5 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -169,8 +169,6 @@ avx2_instr :=$(call as-instr,vpbroadcastb %xmm0$(comma)%ymm1,-DCONFIG_AS_AVX2=1)
 KBUILD_AFLAGS += $(asinstr) $(avx_instr) $(avx2_instr)
 KBUILD_CFLAGS += $(asinstr) $(avx_instr) $(avx2_instr)
 
-LDFLAGS := -m elf_$(UTS_MACHINE)
-
 # Speed up the build
 KBUILD_CFLAGS += -pipe
 # Workaround for a gcc prelease that unfortunately was shipped in a suse release

Currently it calls "ld -m elf_x86_64" and then uses OUTPUT_ARCH(i386) in 
linker scripts several times during the build.
Comment 9 luto 2015-11-03 18:43:57 UTC
On Tue, Nov 3, 2015 at 8:04 AM, markus at trippelsdorf dot de
<sourceware-bugzilla@sourceware.org> wrote:
> https://sourceware.org/bugzilla/show_bug.cgi?id=19197
>
> Markus Trippelsdorf <markus at trippelsdorf dot de> changed:
>
>            What    |Removed                     |Added
> ----------------------------------------------------------------------------
>                  CC|                            |luto at kernel dot org
>
> --- Comment #8 from Markus Trippelsdorf <markus at trippelsdorf dot de> ---
> Andy, would it be possible to just get rid of LDFLAGS for the x86 kernel?
>
> diff --git a/arch/x86/Makefile b/arch/x86/Makefile
> index 747860c696e1..b786a2ce58b5 100644
> --- a/arch/x86/Makefile
> +++ b/arch/x86/Makefile
> @@ -169,8 +169,6 @@ avx2_instr :=$(call as-instr,vpbroadcastb
> %xmm0$(comma)%ymm1,-DCONFIG_AS_AVX2=1)
>  KBUILD_AFLAGS += $(asinstr) $(avx_instr) $(avx2_instr)
>  KBUILD_CFLAGS += $(asinstr) $(avx_instr) $(avx2_instr)
>
> -LDFLAGS := -m elf_$(UTS_MACHINE)
> -
>  # Speed up the build
>  KBUILD_CFLAGS += -pipe
>  # Workaround for a gcc prelease that unfortunately was shipped in a suse
> release
>
> Currently it calls "ld -m elf_x86_64" and then uses OUTPUT_ARCH(i386) in
> linker scripts several times during the build.
>

I don't know the history here.  hpa?  Andi?

Presumably we could strip the problematic -m argument from just the
32-bit things is we care.

--Andy
Comment 10 Sourceware Commits 2015-11-05 21:19:15 UTC
The master branch has been updated by Cary Coutant <ccoutant@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=96f9814df23564e16909bb5ba00de4a202c63417

commit 96f9814df23564e16909bb5ba00de4a202c63417
Author: Cary Coutant <ccoutant@gmail.com>
Date:   Thu Nov 5 12:59:02 2015 -0800

    Revert patch for PR 19119, which led to PR 19172 and 19197.
    
    Gold does not support all the emulations that Gnu ld does, and supports
    only one spelling per target. The -m option is used only in the rare case
    where there are no ELF input files, and we produce an empty output file.
    In those cases, users are expected to supply a -m option naming one of
    the supported emulations. In the many cases where a build script provides
    an unnecessary -m option naming an emulation that gold does not support,
    we will simply ignore the option, as we did before the reverted patch.
    
    gold/
    	PR gold/19119
    	PR gold/19172
    	PR gold/19197
    	Revert commit 6457197210144f50a696097c0d308d81d46d5510:
    
    	2015-10-16  H.J. Lu  <hongjiu.lu@intel.com>
    
    		* options.h (General_options): Remove "obsolete" from -m.
    		* parameters.cc (set_parameters_target): Check if input target
    		is compatible with output emulation set by "-m emulation".
Comment 11 Andi Kleen 2015-11-06 03:20:19 UTC
> I don't know the history here.  hpa?  Andi?
> 
> Presumably we could strip the problematic -m argument from just the
> 32-bit things is we care.

I don't think it was intentional or there from the beginning, probably a bug
added somewhere on the way. Removing it seems fine.

-Andi
Comment 12 Markus Trippelsdorf 2015-11-19 12:30:17 UTC
Fixed. Closing.