Re: [RFC PATCH] x86_64: Add "-m elf_i386" when linking i386 object files.

2018-12-18 Thread George Rimar
Added Rui, an LLD code owner.

This patch contains the approach we discussed earlier during LLD development 
when
faced this issue first time (and as a result of the discussion,
the same fix was suggested: 
https://bugzilla.kernel.org/show_bug.cgi?id=194091#c0),
so I think it is fine.

Best regards,
George | Developer | Access Softek, Inc


От: Tri Vo 
Отправлено: 12 декабря 2018 г. 22:48
Кому: Nick Desaulniers
Копия: b...@alien8.de; x...@kernel.org; t...@linutronix.de; mi...@redhat.com; 
George Rimar; Dmitry Golovin; Bill Wendling; h...@zytor.com; 
linux-kernel@vger.kernel.org
Тема: Re: [RFC PATCH] x86_64: Add "-m elf_i386" when linking i386 object files.

CAUTION: This email originated from outside of the organization. Do not click 
links or open attachments unless you recognize the sender and know the content 
is safe.

Adding appropriate people, lists.
On Tue, Dec 11, 2018 at 1:07 PM Nick Desaulniers
 wrote:
>
> On Mon, Dec 10, 2018 at 2:50 PM Nick Desaulniers
>  wrote:
> >
> > On Mon, Dec 10, 2018 at 2:26 PM Tri Vo  wrote:
> > >
> > > From: George Rimar 
> > >
> > > Linux kernel uses OUTPUT_FORMAT in it's linker scripts. Most of the time
> > > -m option is passed to the linker with correct architecture, but
> > > sometimes (at least for x86_64) the -m option contradicts OUTPUT_FORMAT
> > > directive. Specifically, arch/x86/boot and arch/x86/realmode/rm modules
> > > have i386 object files, but are linked with -m elf_x86_64 linker flag
> > > when building for x86_64.
> > >
> > > BFD and Gold linkers are OK with this, but lld fails:
> > > ld.lld: error: arch/x86/realmode/rm/header.o is incompatible with 
> > > elf_x86_64
> > >
> > > Suggested fix: just add correct -m after incorrect one (it overrides
> > > it), so the linker invocation looks like this: ld -m elf_x86_64 -z
> > > max-page-size=0x20 -m elf_i386 --emit-relocs -T realmode.lds
> > > header.o trampoline_64.o stack.o reboot.o -o realmode.elf (it will also
> > > work with GNU ld, because it supports OUTPUT_FORMAT and just ignores -m
> > > options if this directive is in the linker script).
> > >
> > > Tested by building x86_64 kernel with GNU gcc/ld toolchain and booting
> > > it in QEMU.
> > >
> > > Suggested-by: Dmitry Golovin 
> > > Signed-off-by: Tri Vo 
> > > Tested-by: Tri Vo 
> >
> > This fixes the following linkage error I observe when linking an x86
> > kernel with LLD:
> >
> > ```
> >   LD  arch/x86/realmode/rm/realmode.elf
> > ld.lld: error: arch/x86/realmode/rm/header.o is incompatible with elf_x86_64
> > ld.lld: error: arch/x86/realmode/rm/trampoline_64.o is incompatible
> > with elf_x86_64
> > ld.lld: error: arch/x86/realmode/rm/stack.o is incompatible with elf_x86_64
> > ld.lld: error: arch/x86/realmode/rm/reboot.o is incompatible with elf_x86_64
> > ld.lld: error: arch/x86/realmode/rm/wakeup_asm.o is incompatible with 
> > elf_x86_64
> > ld.lld: error: arch/x86/realmode/rm/wakemain.o is incompatible with 
> > elf_x86_64
> > ld.lld: error: arch/x86/realmode/rm/video-mode.o is incompatible with 
> > elf_x86_64
> > ld.lld: error: arch/x86/realmode/rm/copy.o is incompatible with elf_x86_64
> > ld.lld: error: arch/x86/realmode/rm/bioscall.o is incompatible with 
> > elf_x86_64
> > ld.lld: error: arch/x86/realmode/rm/regs.o is incompatible with elf_x86_64
> > ld.lld: error: arch/x86/realmode/rm/video-vga.o is incompatible with 
> > elf_x86_64
> > ld.lld: error: arch/x86/realmode/rm/video-vesa.o is incompatible with 
> > elf_x86_64
> > ld.lld: error: arch/x86/realmode/rm/video-bios.o is incompatible with 
> > elf_x86_64
> > arch/x86/realmode/rm/Makefile:55: recipe for target
> > 'arch/x86/realmode/rm/realmode.elf' failed
> > ```
> > Tested-by: Nick Desaulniers 
> >
> > Looks like we still have a few other (unrelated) issues to track down
> > with LLD, but this gets us one step closer.
> >
> > Thanks for sending this, Tri!
>
> Just some additional thoughts on this:
>
> The kernel is adding -m elf_x86_64 to the linker command line
> parameters, but then relying on binutils tie-breaking-behavior by
> specifying a different architecture via linker script. So it's
> ambiguous which arch the kernel is trying to link for, and the kernel
> gets lucky/relies on the way ld.bfd happens to resolve this ambiguity
> without warning. An alternative fix may be to just filter out/remove
> the -m elf_x86_64 for this target's linker flags.
>
> >
> > > ---

Re: [PATCH v3] x86_64: Add "-m elf_i386" when linking i386 object files.

2019-01-12 Thread George Rimar
Signed-off-by: George Rimar 

Best regards,
George | Developer | Access Softek, Inc


От: Tri Vo 
Отправлено: 11 января 2019 г. 23:10
Кому: x...@kernel.org; t...@linutronix.de; mi...@redhat.com; b...@alien8.de; 
h...@zytor.com
Копия: George Rimar; d...@golovin.in; mo...@google.com; 
ndesaulni...@google.com; m...@suse.de; r...@google.com; 
linux-kernel@vger.kernel.org; Tri Vo
Тема: [PATCH v3] x86_64: Add "-m elf_i386" when linking i386 object files.

CAUTION: This email originated from outside of the organization. Do not click 
links or open attachments unless you recognize the sender and know the content 
is safe.  If you suspect potential phishing or spam email, report it to 
reports...@accesssoftek.com

From: George Rimar 

Linux kernel uses OUTPUT_FORMAT in it's linker scripts. Most of the time
-m option is passed to the linker with correct architecture, but
sometimes (at least for x86_64) the -m option contradicts OUTPUT_FORMAT
directive. Specifically, arch/x86/boot and arch/x86/realmode/rm modules
have i386 object files, but are linked with -m elf_x86_64 linker flag
when building for x86_64.

"man ld" doesn't explicitly state any tie-breakers between -m and
OUTPUT_FORMAT. BFD and Gold linkers override -m value with
OUTPUT_FORMAT. But LLVM lld has a different behavior. When supplied with
contradicting -m and OUTPUT_FORMAT values it fails with the following
error message:

  ld.lld: error: arch/x86/realmode/rm/header.o is incompatible with elf_x86_64

Suggested fix: just add correct -m after incorrect one (it overrides
it), so the linker invocation looks like this: ld -m elf_x86_64 -z
max-page-size=0x20 -m elf_i386 --emit-relocs -T realmode.lds
header.o trampoline_64.o stack.o reboot.o -o realmode.elf

This is not a functional change for GNU ld, because (although not
explicitly documented) it already overrides -m EMULATION with
OUTPUT_FORMAT.

Tested by building x86_64 kernel with GNU gcc/ld toolchain and booting
it in QEMU.

Suggested-by: Dmitry Golovin 
Signed-off-by: George Rimar 
Signed-off-by: Tri Vo 
Tested-by: Tri Vo 
Tested-by: Nick Desaulniers 
---
v2: updated commit message to clarify that ld documentation is ambiguous w.r.t
-m vs OUTPUT_FORMAT behavior.
v3: fixed/added SOB and "Tested-by" fields.

 arch/x86/boot/Makefile| 2 +-
 arch/x86/realmode/rm/Makefile | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 9b5adae9cc40..e2839b5c246c 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -100,7 +100,7 @@ $(obj)/zoffset.h: $(obj)/compressed/vmlinux FORCE
 AFLAGS_header.o += -I$(objtree)/$(obj)
 $(obj)/header.o: $(obj)/zoffset.h

-LDFLAGS_setup.elf  := -T
+LDFLAGS_setup.elf  := -m elf_i386 -T
 $(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE
$(call if_changed,ld)

diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile
index 4463fa72db94..96cb20de08af 100644
--- a/arch/x86/realmode/rm/Makefile
+++ b/arch/x86/realmode/rm/Makefile
@@ -47,7 +47,7 @@ $(obj)/pasyms.h: $(REALMODE_OBJS) FORCE
 targets += realmode.lds
 $(obj)/realmode.lds: $(obj)/pasyms.h

-LDFLAGS_realmode.elf := --emit-relocs -T
+LDFLAGS_realmode.elf := -m elf_i386 --emit-relocs -T
 CPPFLAGS_realmode.lds += -P -C -I$(objtree)/$(obj)

 targets += realmode.elf
--
2.20.1.97.g81188d93c3-goog



[tip:x86/build] x86/build: Specify elf_i386 linker emulation explicitly for i386 objects

2019-01-12 Thread tip-bot for George Rimar
Commit-ID:  927185c124d62a9a4d35878d7f6d432a166b74e3
Gitweb: https://git.kernel.org/tip/927185c124d62a9a4d35878d7f6d432a166b74e3
Author: George Rimar 
AuthorDate: Fri, 11 Jan 2019 12:10:12 -0800
Committer:  Borislav Petkov 
CommitDate: Sat, 12 Jan 2019 00:11:39 +0100

x86/build: Specify elf_i386 linker emulation explicitly for i386 objects

The kernel uses the OUTPUT_FORMAT linker script command in it's linker
scripts. Most of the time, the -m option is passed to the linker with
correct architecture, but sometimes (at least for x86_64) the -m option
contradicts the OUTPUT_FORMAT directive.

Specifically, arch/x86/boot and arch/x86/realmode/rm produce i386 object
files, but are linked with the -m elf_x86_64 linker flag when building
for x86_64.

The GNU linker manpage doesn't explicitly state any tie-breakers between
-m and OUTPUT_FORMAT. But with BFD and Gold linkers, OUTPUT_FORMAT
overrides the emulation value specified with the -m option.

LLVM lld has a different behavior, however. When supplied with
contradicting -m and OUTPUT_FORMAT values it fails with the following
error message:

  ld.lld: error: arch/x86/realmode/rm/header.o is incompatible with elf_x86_64

Therefore, just add the correct -m after the incorrect one (it overrides
it), so the linker invocation looks like this:

  ld -m elf_x86_64 -z max-page-size=0x20 -m elf_i386 --emit-relocs -T \
realmode.lds header.o trampoline_64.o stack.o reboot.o -o realmode.elf

This is not a functional change for GNU ld, because (although not
explicitly documented) OUTPUT_FORMAT overrides -m EMULATION.

Tested by building x86_64 kernel with GNU gcc/ld toolchain and booting
it in QEMU.

 [ bp: massage and clarify text. ]

Suggested-by: Dmitry Golovin 
Signed-off-by: George Rimar 
Signed-off-by: Tri Vo 
Signed-off-by: Borislav Petkov 
Tested-by: Tri Vo 
Tested-by: Nick Desaulniers 
Cc: "H. Peter Anvin" 
Cc: Ingo Molnar 
Cc: Michael Matz 
Cc: Thomas Gleixner 
Cc: mo...@google.com
Cc: ndesaulni...@google.com
Cc: r...@google.com
Cc: x86-ml 
Link: https://lkml.kernel.org/r/20190111201012.71210-1-tr...@android.com
---
 arch/x86/boot/Makefile| 2 +-
 arch/x86/realmode/rm/Makefile | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 9b5adae9cc40..e2839b5c246c 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -100,7 +100,7 @@ $(obj)/zoffset.h: $(obj)/compressed/vmlinux FORCE
 AFLAGS_header.o += -I$(objtree)/$(obj)
 $(obj)/header.o: $(obj)/zoffset.h
 
-LDFLAGS_setup.elf  := -T
+LDFLAGS_setup.elf  := -m elf_i386 -T
 $(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE
$(call if_changed,ld)
 
diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile
index 4463fa72db94..96cb20de08af 100644
--- a/arch/x86/realmode/rm/Makefile
+++ b/arch/x86/realmode/rm/Makefile
@@ -47,7 +47,7 @@ $(obj)/pasyms.h: $(REALMODE_OBJS) FORCE
 targets += realmode.lds
 $(obj)/realmode.lds: $(obj)/pasyms.h
 
-LDFLAGS_realmode.elf := --emit-relocs -T
+LDFLAGS_realmode.elf := -m elf_i386 --emit-relocs -T
 CPPFLAGS_realmode.lds += -P -C -I$(objtree)/$(obj)
 
 targets += realmode.elf