Patchwork libgcc regparm workaround

login
register
about
Submitter Stefan Reinauer
Date 2009-09-25 22:03:30
Message ID <4ABD3E32.4050307@coresystems.de>
Download mbox | patch
Permalink /patch/299/
State Accepted
Headers show

Comments

Stefan Reinauer - 2009-09-25 22:03:30
programs that are compiled with non-default regparm values are
miscompiled if they use libgcc.
This patch works around the problem for coreboot.
* drop libgcc from coreboot_apc.o, not needed.
* wrap libgcc calls into regparm(0) variants so that coreboot can be compiled
  with other regparm values

Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
Carl-Daniel Hailfinger - 2009-09-26 00:54:57
On 26.09.2009 00:03, Stefan Reinauer wrote:
> programs that are compiled with non-default regparm values are
> miscompiled if they use libgcc.
> This patch works around the problem for coreboot.
>
> * drop libgcc from coreboot_apc.o, not needed.
> * wrap libgcc calls into regparm(0) variants so that coreboot can be compiled
>   with other regparm values
>
> Signed-off-by: Stefan Reinauer <stepan@coresystems.de>

I'm worried about any libgcc compiled with regparm!=0, but for now this
patch improves the situation.

Acked-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>

Regards,
Carl-Daniel
Segher Boessenkool - 2009-09-26 10:08:27
> programs that are compiled with non-default regparm values are
> miscompiled if they use libgcc.
> This patch works around the problem for coreboot.

Please mention the GCC bugreport # in the source near every workaround;
that way, you can one day get rid of it.  This is PR41055.

>  makerule coreboot_ram.o
>  	depends	"src/arch/$(CONFIG_ARCH)/lib/c_start.o $(DRIVER)  
> coreboot.a $(LIBGCC_FILE_NAME)"
> -	action	"$(CC) $(DISTRO_LFLAGS) -nostdlib -r -o $@ src/arch/$ 
> (CONFIG_ARCH)/lib/c_start.o $(DRIVER) -Wl,-\( coreboot.a $ 
> (LIBGCC_FILE_NAME) -Wl,-\)"
> +	action	"$(CC) $(DISTRO_LFLAGS) -nostdlib -r -o $@ src/arch/$ 
> (CONFIG_ARCH)/lib/c_start.o $(DRIVER) -Wl,--wrap,__divdi3 -Wl,-- 
> wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,-\ 
> ( coreboot.a $(LIBGCC_FILE_NAME) -Wl,-\)"
>  end

You don't need the -( -) here, FWIW.  libgcc does not require symbols  
from
coreboot.a ;-)


Segher
Segher Boessenkool - 2009-09-26 10:10:08
> I'm worried about any libgcc compiled with regparm!=0, but for now  
> this
> patch improves the situation.

libgcc uses the default calling convention.  The problem is that
the (implicit) calls to the routines in libgcc are done with the
-mregparm from the command line.


Segher
Stefan Reinauer - 2009-09-26 15:43:06
Segher Boessenkool wrote:
>> programs that are compiled with non-default regparm values are
>> miscompiled if they use libgcc.
>> This patch works around the problem for coreboot.
>
> Please mention the GCC bugreport # in the source near every workaround;
> that way, you can one day get rid of it.  This is PR41055.
>
>>  makerule coreboot_ram.o
>>      depends    "src/arch/$(CONFIG_ARCH)/lib/c_start.o $(DRIVER)
>> coreboot.a $(LIBGCC_FILE_NAME)"
>> -    action    "$(CC) $(DISTRO_LFLAGS) -nostdlib -r -o $@
>> src/arch/$(CONFIG_ARCH)/lib/c_start.o $(DRIVER) -Wl,-\( coreboot.a
>> $(LIBGCC_FILE_NAME) -Wl,-\)"
>> +    action    "$(CC) $(DISTRO_LFLAGS) -nostdlib -r -o $@
>> src/arch/$(CONFIG_ARCH)/lib/c_start.o $(DRIVER) -Wl,--wrap,__divdi3
>> -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,-\(
>> coreboot.a $(LIBGCC_FILE_NAME) -Wl,-\)"
>>  end
>
> You don't need the -( -) here, FWIW.  libgcc does not require symbols
> from
> coreboot.a ;-) 
Yes, actually it does. On powerpc libgcc uses external symbols that it
does not provide.

Stefan
Stefan Reinauer - 2009-09-26 15:52:47
Carl-Daniel Hailfinger wrote:
> On 26.09.2009 00:03, Stefan Reinauer wrote:
>   
>> programs that are compiled with non-default regparm values are
>> miscompiled if they use libgcc.
>> This patch works around the problem for coreboot.
>>
>> * drop libgcc from coreboot_apc.o, not needed.
>> * wrap libgcc calls into regparm(0) variants so that coreboot can be compiled
>>   with other regparm values
>>
>> Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
>>     
>
> I'm worried about any libgcc compiled with regparm!=0, but for now this
> patch improves the situation.
>   

Is there any way around this? Using stdcall or something? We could query
the compiler flags used to build gcc, but I think as long as this works
for the "normal" gcc case we should be fine. If people do use odd tool
chains, they're on their own..

Stefan
Stefan Reinauer - 2009-09-26 15:54:15
Segher Boessenkool wrote:
>> I'm worried about any libgcc compiled with regparm!=0, but for now this
>> patch improves the situation.
>
> libgcc uses the default calling convention. 
Is there an attribute to say "this function uses the default calling
convention no matter what CFLAGS we have right now"?
Segher Boessenkool - 2009-09-27 14:38:14
>> You don't need the -( -) here, FWIW.  libgcc does not require symbols
>> from
>> coreboot.a ;-)
> Yes, actually it does. On powerpc libgcc uses external symbols that it
> does not provide.

Do you mean abort()?  Yeah, you need to provide that yourself, on all  
targets
(nothing special about PowerPC); the same is true for memcpy(), memset 
(),
memmove(), memcmp().  FWIW, any GCC-compiled code can require those, not
only code in libgcc.


Segher
Segher Boessenkool - 2009-09-27 14:38:48
>>> I'm worried about any libgcc compiled with regparm!=0, but for  
>>> now this
>>> patch improves the situation.
>>
>> libgcc uses the default calling convention.
> Is there an attribute to say "this function uses the default calling
> convention no matter what CFLAGS we have right now"?

Sure, and you're already using that: the default on i386 is regparm=0.


Segher
Carl-Daniel Hailfinger - 2009-09-27 14:52:25
On 27.09.2009 16:38, Segher Boessenkool wrote:
>>>> I'm worried about any libgcc compiled with regparm!=0, but for now
>>>> this
>>>> patch improves the situation.
>>>
>>> libgcc uses the default calling convention.
>> Is there an attribute to say "this function uses the default calling
>> convention no matter what CFLAGS we have right now"?
>
> Sure, and you're already using that: the default on i386 is regparm=0.

What happens to libgcc if someone compiles gcc with regparm=3? Will
libgcc still be compiled with regparm=0? (Disclaimer: I'm not a Gentoo
user and won't try that.)

Regards,
Carl-Daniel
Stefan Reinauer - 2009-09-27 14:54:42
Segher Boessenkool wrote:
>>> You don't need the -( -) here, FWIW.  libgcc does not require symbols
>>> from
>>> coreboot.a ;-)
>> Yes, actually it does. On powerpc libgcc uses external symbols that it
>> does not provide.
>
> Do you mean abort()?
Obviously.

> Yeah, you need to provide that yourself, on all targets (nothing
> special about PowerPC); 
See, that's why the -( -) is there. :-)

I read the libgcc source code, and only powerpc's libgcc is calling
abort(). So while theoretically others may, they don't.

I agree completely with you that gcc might change its behavior on other
platforms, which is exactly why the -( -) construct is not only used for
our powerpc port.

> the same is true for memcpy(), memset(),  memmove(), memcmp().  FWIW,
> any GCC-compiled code can require those, not
> only code in libgcc.
The -( -) construct is only needed for symbols used in libgcc, so
everything is fine. At the current point no mem* functions are used in
the libgcc functions we "use".
Even if we did, the construct would work for us without changes.

Stefan
Segher Boessenkool - 2009-09-27 23:37:17
> What happens to libgcc if someone compiles gcc with regparm=3?

Nothing.  It doesn't matter how the compiler itself is compiled.

> Will libgcc still be compiled with regparm=0?

Yes.


Segher
Segher Boessenkool - 2009-09-27 23:52:40
>>>> You don't need the -( -) here, FWIW.  libgcc does not require  
>>>> symbols
>>>> from
>>>> coreboot.a ;-)
>>> Yes, actually it does. On powerpc libgcc uses external symbols  
>>> that it
>>> does not provide.
>>
>> Do you mean abort()?
> Obviously.

Obvious to you perhaps, but not to me, that's why I asked :-)

>> Yeah, you need to provide that yourself, on all targets (nothing
>> special about PowerPC);
> See, that's why the -( -) is there. :-)

Yes, sure, supposedly nothing else requires the object file where  
abort()
is defined.  I see.

> I read the libgcc source code, and only powerpc's libgcc is calling
> abort(). So while theoretically others may, they don't.

I think you read wrong then: every single target uses abort().  The
difference you are seeing could be that PowerPC uses it in the  
trampoline
code?

> I agree completely with you that gcc might change its behavior on  
> other
> platforms, which is exactly why the -( -) construct is not only  
> used for
> our powerpc port.
>
>> the same is true for memcpy(), memset(),  memmove(), memcmp().  FWIW,
>> any GCC-compiled code can require those, not
>> only code in libgcc.
> The -( -) construct is only needed for symbols used in libgcc,

Yes.

> so
> everything is fine. At the current point no mem* functions are used in
> the libgcc functions we "use".
> Even if we did, the construct would work for us without changes.

Yes.

Look, it just looked to me like some legacy thing that could use some
cleaning up.  Obviously it still has value.


Segher

Patch

Index: src/config/Config.lb
===================================================================
--- src/config/Config.lb	(revision 4675)
+++ src/config/Config.lb	(working copy)
@@ -47,7 +47,7 @@ 
 
 makerule coreboot_ram.o
 	depends	"src/arch/$(CONFIG_ARCH)/lib/c_start.o $(DRIVER) coreboot.a $(LIBGCC_FILE_NAME)" 
-	action	"$(CC) $(DISTRO_LFLAGS) -nostdlib -r -o $@ src/arch/$(CONFIG_ARCH)/lib/c_start.o $(DRIVER) -Wl,-\( coreboot.a $(LIBGCC_FILE_NAME) -Wl,-\)"
+	action	"$(CC) $(DISTRO_LFLAGS) -nostdlib -r -o $@ src/arch/$(CONFIG_ARCH)/lib/c_start.o $(DRIVER) -Wl,--wrap,__divdi3 -Wl,--wrap,__udivdi3 -Wl,--wrap,__moddi3 -Wl,--wrap,__umoddi3 -Wl,-\( coreboot.a $(LIBGCC_FILE_NAME) -Wl,-\)"
 end
 
 makerule coreboot_ram
@@ -89,7 +89,7 @@ 
 	end
 
 	makerule coreboot_apc.o
-		depends "src/arch/$(CONFIG_ARCH)/lib/c_start.o coreboot_apc.a $(LIBGCC_FILE_NAME)"
+		depends "src/arch/$(CONFIG_ARCH)/lib/c_start.o coreboot_apc.a"
         	action  "$(CC) $(DISTRO_LFLAGS) -nostdlib -r -o $@ $^"
 	end
 
Index: src/lib/Makefile.inc
===================================================================
--- src/lib/Makefile.inc	(revision 4675)
+++ src/lib/Makefile.inc	(working copy)
@@ -12,6 +12,7 @@ 
 obj-y += cbfs.o
 obj-y += lzma.o
 #obj-y += lzmadecode.o
+obj-y += gcc.o
 
 initobj-y += uart8250.o
 initobj-y += memset.o
Index: src/lib/Config.lb
===================================================================
--- src/lib/Config.lb	(revision 4675)
+++ src/lib/Config.lb	(working copy)
@@ -17,6 +17,8 @@ 
 object fallback_boot.o
 object compute_ip_checksum.o
 object version.o
+object gcc.o
+
 # Force version.o to recompile every time
 makedefine .PHONY : version.o
 
Index: src/lib/gcc.c
===================================================================
--- src/lib/gcc.c	(revision 0)
+++ src/lib/gcc.c	(revision 0)
@@ -0,0 +1,34 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+/* GCC's libgcc handling is quite broken. While the libgcc functions
+ * are always regparm(0) the code that calls them uses whatever the
+ * compiler call specifies. Therefore we need a wrapper around those
+ * functions.
+ */
+
+#define WRAP_LIBGCC_CALL(type, name) \
+	type __real_##name(type a, type b) __attribute__((regparm(0))); \
+	type __wrap_##name(type a, type b) { return __real_##name(a, b); }
+
+WRAP_LIBGCC_CALL(long long, __divdi3)
+WRAP_LIBGCC_CALL(unsigned long long, __udivdi3)
+WRAP_LIBGCC_CALL(long long, __moddi3)
+WRAP_LIBGCC_CALL(unsigned long long, __umoddi3)
+