diff mbox

[5/5] ARM: add support for building ARM kernel with clang

Message ID 20180320230206.25289-6-stefan@agner.ch (mailing list archive)
State New, archived
Headers show

Commit Message

Stefan Agner March 20, 2018, 11:02 p.m. UTC
Use cc-options call for compiler options which are not available
in clang. With this patch an ARMv7 multi platform kernel can be
successfully build using clang (tested with version 5.0.1).

Based-on-patches-by: Behan Webster <behanw@converseincode.com>
Signed-off-by: Stefan Agner <stefan@agner.ch>
---
 arch/arm/Makefile                 | 2 +-
 arch/arm/boot/compressed/Makefile | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

Comments

Russell King (Oracle) March 20, 2018, 11:18 p.m. UTC | #1
On Wed, Mar 21, 2018 at 12:02:06AM +0100, Stefan Agner wrote:
> Use cc-options call for compiler options which are not available
> in clang. With this patch an ARMv7 multi platform kernel can be
> successfully build using clang (tested with version 5.0.1).
> 
> Based-on-patches-by: Behan Webster <behanw@converseincode.com>
> Signed-off-by: Stefan Agner <stefan@agner.ch>
> ---
>  arch/arm/Makefile                 | 2 +-
>  arch/arm/boot/compressed/Makefile | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/Makefile b/arch/arm/Makefile
> index e9e3fde3c657..20e9fee1ccc5 100644
> --- a/arch/arm/Makefile
> +++ b/arch/arm/Makefile
> @@ -39,7 +39,7 @@ KBUILD_CFLAGS	+= $(call cc-option,-mno-unaligned-access)
>  endif
>  
>  ifeq ($(CONFIG_FRAME_POINTER),y)
> -KBUILD_CFLAGS	+=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
> +KBUILD_CFLAGS	+=-fno-omit-frame-pointer $(call cc-option,-mapcs,) $(call cc-option,-mno-sched-prolog,)

Some of these options here are to ensure that we generate the following
code, so we can backtrace:

	mov	ip, sp
	stmfd	sp!, {fp, ip, lr, pc}
	sub	fp, ip, #4

If clang isn't producing that code at the start of functions with
CONFIG_FRAME_POINTER=y, then backtracing will not work, and arguably
CONFIG_FRAME_POINTER=y is useless there.  In that circumstance, it's
probably better to fail so the user can configure something more
debuggable, rather than having the kernel potentially producing
undebuggable oopses.
Matthias Kaehlcke March 21, 2018, 12:20 a.m. UTC | #2
El Tue, Mar 20, 2018 at 11:18:33PM +0000 Russell King - ARM Linux ha dit:

> On Wed, Mar 21, 2018 at 12:02:06AM +0100, Stefan Agner wrote:
> > Use cc-options call for compiler options which are not available
> > in clang. With this patch an ARMv7 multi platform kernel can be
> > successfully build using clang (tested with version 5.0.1).
> > 
> > Based-on-patches-by: Behan Webster <behanw@converseincode.com>
> > Signed-off-by: Stefan Agner <stefan@agner.ch>

Great to see your work on bringing clang support for 32-bit ARM
upstream!

> > ---
> >  arch/arm/Makefile                 | 2 +-
> >  arch/arm/boot/compressed/Makefile | 2 +-
> >  2 files changed, 2 insertions(+), 2 deletions(-)
> > 
> > diff --git a/arch/arm/Makefile b/arch/arm/Makefile
> > index e9e3fde3c657..20e9fee1ccc5 100644
> > --- a/arch/arm/Makefile
> > +++ b/arch/arm/Makefile
> > @@ -39,7 +39,7 @@ KBUILD_CFLAGS	+= $(call cc-option,-mno-unaligned-access)
> >  endif
> >  
> >  ifeq ($(CONFIG_FRAME_POINTER),y)
> > -KBUILD_CFLAGS	+=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
> > +KBUILD_CFLAGS	+=-fno-omit-frame-pointer $(call cc-option,-mapcs,) $(call cc-option,-mno-sched-prolog,)
> 
> Some of these options here are to ensure that we generate the following
> code, so we can backtrace:
> 
> 	mov	ip, sp
> 	stmfd	sp!, {fp, ip, lr, pc}
> 	sub	fp, ip, #4
> 
> If clang isn't producing that code at the start of functions with
> CONFIG_FRAME_POINTER=y, then backtracing will not work, and arguably
> CONFIG_FRAME_POINTER=y is useless there.  In that circumstance, it's
> probably better to fail so the user can configure something more
> debuggable, rather than having the kernel potentially producing
> undebuggable oopses.

Which option in particular is important to generate the above code for
backstracing?

According to the gcc doc -mapcs(-frame) is deprecated.

For -mno-sched-prolog the doc says:

"Prevent the reordering of instructions in the function prologue, or
the merging of those instruction with the instructions in the
function’s body. This means that all functions start with a
recognizable set of instructions (or in fact one of a choice from a
small set of different function prologues), and this information can
be used to locate the start of functions inside an executable piece of
code. The default is -msched-prolog."

Thanks

Matthias
Stefan Agner March 21, 2018, 9:03 a.m. UTC | #3
On 21.03.2018 01:20, Matthias Kaehlcke wrote:
> El Tue, Mar 20, 2018 at 11:18:33PM +0000 Russell King - ARM Linux ha dit:
> 
>> On Wed, Mar 21, 2018 at 12:02:06AM +0100, Stefan Agner wrote:
>> > Use cc-options call for compiler options which are not available
>> > in clang. With this patch an ARMv7 multi platform kernel can be
>> > successfully build using clang (tested with version 5.0.1).
>> >
>> > Based-on-patches-by: Behan Webster <behanw@converseincode.com>
>> > Signed-off-by: Stefan Agner <stefan@agner.ch>
> 
> Great to see your work on bringing clang support for 32-bit ARM
> upstream!
> 
>> > ---
>> >  arch/arm/Makefile                 | 2 +-
>> >  arch/arm/boot/compressed/Makefile | 2 +-
>> >  2 files changed, 2 insertions(+), 2 deletions(-)
>> >
>> > diff --git a/arch/arm/Makefile b/arch/arm/Makefile
>> > index e9e3fde3c657..20e9fee1ccc5 100644
>> > --- a/arch/arm/Makefile
>> > +++ b/arch/arm/Makefile
>> > @@ -39,7 +39,7 @@ KBUILD_CFLAGS	+= $(call cc-option,-mno-unaligned-access)
>> >  endif
>> >
>> >  ifeq ($(CONFIG_FRAME_POINTER),y)
>> > -KBUILD_CFLAGS	+=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
>> > +KBUILD_CFLAGS	+=-fno-omit-frame-pointer $(call cc-option,-mapcs,) $(call cc-option,-mno-sched-prolog,)
>>
>> Some of these options here are to ensure that we generate the following
>> code, so we can backtrace:
>>
>> 	mov	ip, sp
>> 	stmfd	sp!, {fp, ip, lr, pc}
>> 	sub	fp, ip, #4
>>
>> If clang isn't producing that code at the start of functions with
>> CONFIG_FRAME_POINTER=y, then backtracing will not work, and arguably
>> CONFIG_FRAME_POINTER=y is useless there.  In that circumstance, it's
>> probably better to fail so the user can configure something more
>> debuggable, rather than having the kernel potentially producing
>> undebuggable oopses.

With clang and -fno-omit-frame-pointer function prologue looks something
like this:

   0:   e92d4ff0        push    {r4, r5, r6, r7, r8, r9, sl, fp, lr}    
                                                                   
   4:   e28db01c        add     fp, sp, #28
...

This bug seems to be related:
https://bugs.llvm.org/show_bug.cgi?id=18505 

It seems that LLVM/clang does not plan to add APCS format/gcc
interoperability for the same frame layout.

I guess it would be possible to support the LLVM/clang frame layout?

But until then, I am with Russel here: Better just let clang fail on
CONFIG_FRAME_POINTER=y.

Most configs probably anyway use CONFIG_ARM_UNWIND. At least
multi_v7_defconfig does.

> 
> Which option in particular is important to generate the above code for
> backstracing?

For gcc, I guess really all of them.

--
Stefan

> 
> According to the gcc doc -mapcs(-frame) is deprecated.
> 
> For -mno-sched-prolog the doc says:
> 
> "Prevent the reordering of instructions in the function prologue, or
> the merging of those instruction with the instructions in the
> function’s body. This means that all functions start with a
> recognizable set of instructions (or in fact one of a choice from a
> small set of different function prologues), and this information can
> be used to locate the start of functions inside an executable piece of
> code. The default is -msched-prolog."
> 
> Thanks
> 
> Matthias
Stefan Agner March 25, 2018, 1:24 p.m. UTC | #4
On 21.03.2018 00:18, Russell King - ARM Linux wrote:
> On Wed, Mar 21, 2018 at 12:02:06AM +0100, Stefan Agner wrote:
>> Use cc-options call for compiler options which are not available
>> in clang. With this patch an ARMv7 multi platform kernel can be
>> successfully build using clang (tested with version 5.0.1).
>>
>> Based-on-patches-by: Behan Webster <behanw@converseincode.com>
>> Signed-off-by: Stefan Agner <stefan@agner.ch>
>> ---
>>  arch/arm/Makefile                 | 2 +-
>>  arch/arm/boot/compressed/Makefile | 2 +-
>>  2 files changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm/Makefile b/arch/arm/Makefile
>> index e9e3fde3c657..20e9fee1ccc5 100644
>> --- a/arch/arm/Makefile
>> +++ b/arch/arm/Makefile
>> @@ -39,7 +39,7 @@ KBUILD_CFLAGS	+= $(call cc-option,-mno-unaligned-access)
>>  endif
>>
>>  ifeq ($(CONFIG_FRAME_POINTER),y)
>> -KBUILD_CFLAGS	+=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
>> +KBUILD_CFLAGS	+=-fno-omit-frame-pointer $(call cc-option,-mapcs,) $(call cc-option,-mno-sched-prolog,)
> 
> Some of these options here are to ensure that we generate the following
> code, so we can backtrace:
> 
> 	mov	ip, sp
> 	stmfd	sp!, {fp, ip, lr, pc}
> 	sub	fp, ip, #4
> 
> If clang isn't producing that code at the start of functions with
> CONFIG_FRAME_POINTER=y, then backtracing will not work, and arguably
> CONFIG_FRAME_POINTER=y is useless there.  In that circumstance, it's
> probably better to fail so the user can configure something more
> debuggable, rather than having the kernel potentially producing
> undebuggable oopses.

Just for the records, compiled with clang, this patchset applied and
CONFIG_FRAME_POINTER=y as expected leads to a non functional backtrace:

[    4.583711] ------------[ cut here ]------------
[    4.588347] WARNING: CPU: 0 PID: 1 at init/main.c:1012
kernel_init+0x60/0x238
[    4.595505] Modules linked in:
[    4.598590] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       
4.16.0-rc5-00019-g686ee524148e-dirty #42
[    4.608514] Hardware name: Freescale i.MX7 Dual (Device Tree)
[    4.614266] Backtrace: 
[    4.616728] [<dc063f34>] (0xdc063f34) from [<00000000>] (  (null))
[    4.622918] Backtrace aborted due to bad frame pointer <8c0165e4>
[    4.629046] ---[ end trace 200951c950497708 ]---

clang with CONFIG_FRAME_POINTER=y should really error out. Without the
cc-option calls building witih clang will print the following errors:

...
  CC      kernel/bounds.s
clang-6.0: error: unknown argument: '-mapcs'
clang-6.0: error: unknown argument: '-mno-sched-prolog'
...

Using CONFIG_ARM_UNWIND=y compiles fine and backtraces do work fine too:

[    4.630877] ------------[ cut here ]------------
[    4.635515] WARNING: CPU: 0 PID: 1 at init/main.c:1012
kernel_init+0x5c/0x234
[    4.642672] Modules linked in:
[    4.645742] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       
4.16.0-rc5-00019-g686ee524148e-dirty #41
[    4.655666] Hardware name: Freescale i.MX7 Dual (Device Tree)
[    4.661437] [<c0110a9c>] (unwind_backtrace) from [<c010ca6c>]
(show_stack+0x10/0x14)
[    4.669200] [<c010ca6c>] (show_stack) from [<c0959ebc>]
(dump_stack+0x9c/0xac)
[    4.676442] [<c0959ebc>] (dump_stack) from [<c01214c4>]
(__warn+0xb4/0x120)
[    4.683419] [<c01214c4>] (__warn) from [<c01215f4>]
(warn_slowpath_null+0x40/0x48)
[    4.691003] [<c01215f4>] (warn_slowpath_null) from [<c096e7b8>]
(kernel_init+0x5c/0x234)
[    4.699111] [<c096e7b8>] (kernel_init) from [<c01010e8>]
(ret_from_fork+0x14/0x2c)
[    4.706691] Exception stack(0xdc063fb0 to 0xdc063ff8)
[    4.711752] 3fa0:                                     00000000
00000000 00000000 00000000
[    4.719943] 3fc0: 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000
[    4.728133] 3fe0: 00000000 00000000 00000000 00000000 00000013
00000000
[    4.734792] ---[ end trace 200951c950497708 ]---

--
Stefan
diff mbox

Patch

diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index e9e3fde3c657..20e9fee1ccc5 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -39,7 +39,7 @@  KBUILD_CFLAGS	+= $(call cc-option,-mno-unaligned-access)
 endif
 
 ifeq ($(CONFIG_FRAME_POINTER),y)
-KBUILD_CFLAGS	+=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
+KBUILD_CFLAGS	+=-fno-omit-frame-pointer $(call cc-option,-mapcs,) $(call cc-option,-mno-sched-prolog,)
 endif
 
 ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 45a6b9b7af2a..6a5c4ac97703 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -113,7 +113,7 @@  CFLAGS_fdt_ro.o := $(nossp_flags)
 CFLAGS_fdt_rw.o := $(nossp_flags)
 CFLAGS_fdt_wip.o := $(nossp_flags)
 
-ccflags-y := -fpic -mno-single-pic-base -fno-builtin -I$(obj)
+ccflags-y := -fpic $(call cc-option,-mno-single-pic-base,) -fno-builtin -I$(obj)
 asflags-y := -DZIMAGE
 
 # Supply kernel BSS size to the decompressor via a linker symbol.