clang 3.9.0 vs. TARGET_ARCH=powerpc: fsck_ufs and "df -m" are example failures: __floatdidf gets SIGSEGV's in both of them. [Code generation error involved.]

Mark Millard markmi at dsl-only.net
Sun Nov 27 09:31:47 UTC 2016


[This adds notes about a code generation error for r30 handling in what
FreeBSD's clang 3.9.0 generated for TARGET_ARCH=powerpc.]

On 2016-Nov-26, at 7:47 PM, Mark Millard <markmi at dsl-only.net> wrote:

> [Short top post of where floatdidf definitions seem to be for TARGET_ARCH=powerpc.]
> 
> libcompiler_rt , libc , and libgcc each seem to be places with
> floatdidf definitions:
> 
> # grep floatdidf ~/sys_typescripts/typescript_make_powerpcvtsc_nodebug_clang_bootstrap_world-amd64-host-2016-11-26:11:38:36
> Building /usr/obj/powerpcvtsc_clang_world/powerpc.powerpc/usr/src/lib/libcompiler_rt/floatdidf.o
> Building /usr/obj/powerpcvtsc_clang_world/powerpc.powerpc/usr/src/lib/libc/floatdidf.o
> Building /usr/obj/powerpcvtsc_clang_world/powerpc.powerpc/usr/src/lib/libc/floatdidf.pico
> Building /usr/obj/powerpcvtsc_clang_world/powerpc.powerpc/usr/src/gnu/lib/libgcc/_floatdidf.pico
> Building /usr/obj/powerpcvtsc_clang_world/powerpc.powerpc/usr/src/lib/libcompiler_rt/floatdidf.po
> Building /usr/obj/powerpcvtsc_clang_world/powerpc.powerpc/usr/src/lib/libc/floatdidf.po
> 
> For .o:    just libcompiler_rt and libc
> For .po:   just libcompiler_rt and libc
> For .pico: just libgcc         and libc
> 
> Only libc is common to all 3 types of files. But the libc copy is
> not used by fsck_ufs or df. (The larger address routine is from
> /lib/libc.so.7 and the smaller one from the "local exec file".)
> 
> I've no clue if this sort of thing is unique to powerpc or not.

Independent of the above potential issue I've added a new comment to llvm's
26519 about the code generated for compiler_rt's __floatdidf being wrong:
it misuses r30. . .

Unfortunately there are problems handling use of r30, at least when floating
point is involved.

The used code from the compliler_rt __floatdidf seems to be just wrong in part
of its use of r30. The below initially uses the "df -m" example failure and its
code.

At first is saves r30 on the stack as part of the function preamble:

Dump of assembler code for function __floatdidf:
0x018029b8 <__floatdidf+0>:	mflr    r0
0x018029bc <__floatdidf+4>:	stw     r0,4(r1)
0x018029c0 <__floatdidf+8>:	stwu    r1,-32(r1)
0x018029c4 <__floatdidf+12>:	stw     r31,28(r1)
0x018029c8 <__floatdidf+16>:	stw     r30,24(r1)

Later it uses r30 for other things.

Then it restores it from the stack:

0x01802a08 <__floatdidf+80>:	lwz     r30,24(r1)

What it does with r30 next effectively makes r30 a parameter to the routine and
not just saved/restored:

0x01802a10 <__floatdidf+88>:	lwz     r3,-8(r30)

In the above the r30 from the caller's context is being used as the base for
accessing memory and putting that memory content in r3.

What it does next with r3 is one of the points where SIGSEGV is happening: For
"df -m" r3 ends up being 0 and the following fails.

0x01802a18 <__floatdidf+96>:	lfs     f12,0(r3)


In the fsck_ufs example it is the same sort of thing but r30 happens to be
initially 0 so it fails at an earlier stage.

Again there is the preamble that saves r30:

0x0181afcc <__floatdidf+0>:	mflr    r0
0x0181afd0 <__floatdidf+4>:	stw     r0,4(r1)
0x0181afd4 <__floatdidf+8>:	stwu    r1,-32(r1)
0x0181afd8 <__floatdidf+12>:	stw     r31,28(r1)
0x0181afdc <__floatdidf+16>:	stw     r30,24(r1)

Later it uses r30 for other things.

Then it restores it from the stack:

0x0181b01c <__floatdidf+80>:	lwz     r30,24(r1)

What it does with r30 next effectively makes r30 a parameter to the routine and
not just saved/restored:

0x0181b024 <__floatdidf+88>:	lwz     r3,-12(r30)

Again: In the above the r30 from the caller's context is being used as the base
for accessing memory and putting that memory content in r3.

But this time it turns out that r30 is 0 and the above also fails.

If the code had gotten that far it would have done the same thing with r3 that
"df -m" did in its failure:

0x0181b02c <__floatdidf+96>:	lfs     f12,0(r3)


For reference compiler-rt/lib/builtins/floatdidf.c has:

COMPILER_RT_ABI double
__floatdidf(di_int a)
{
    static const double twop52 = 4503599627370496.0; // 0x1.0p52
    static const double twop32 = 4294967296.0; // 0x1.0p32

    union { int64_t x; double d; } low = { .d = twop52 };

    const double high = (int32_t)(a >> 32) * twop32;
    low.x |= a & INT64_C(0x00000000ffffffff);

    const double result = (high - twop52) + low.d;
    return result;
}

and the matching assembler code for the fsck_ufs example is (from gdb):

<The older material below already lists the code that starts at 0x181afcc
so I'll not repeat it here.>

===
Mark Millard
markmi at dsl-only.net

On 2016-Nov-26, at 4:41 PM, Mark Millard <markmi at dsl-only.net> wrote:

> [Summary: Looking around with gdb at fsck_ufs I found two __floatdidf routines
> with different code. df has the same.]
> 
> On 2016-Nov-26, at 3:39 PM, Mark Millard <markmi at dsl-only.net> wrote:
> 
>> I updated to head -r309197 (with a work around for -r309144 breaking the build).
>> 
>> This was on amd64, then used it to try to cross buildworld using clang 3.9.0 for
>> TARGET_ARCH=powerpc . The build completed. (I've been using clang 3.8.0 this way
>> for a long time.)
>> 
>> [The kernel here was cross built via gcc 4.2.1, as has been my normal procedure.
>> The kernel still has my "red zone for signal delivery" hack that was a workaround
>> for clang 3.8.0 stack-handling ABI violations.]
>> 
>> Booting, however, had problems because of fsck_ufs getting signal 11 and ended up
>> initially in single user mode.
>> 
>> Exiting single user did finish the boot. But "df -m" core dumps. (I've not
>> explored much else.)
>> 
>> Turns out that both fsck_ufs and "df -m" fail in the same routine for a SIGSEGV:
>> __floatdidf
>> 
>> 
>> The details. . .
>> 
>> First the boot and fsck_ufs:
>> 
>>> Copyright (c) 1992-2016 The FreeBSD Project.
>>> Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
>>>      The Regents of the University of California. All rights reserved.
>>> FreeBSD is a registered trademark of The FreeBSD Foundation.
>>> FreeBSD 12.0-CURRENT #9 r309179M: Sat Nov 26 12:53:11 PST 2016
>>>  markmi at FreeBSDx64:/usr/obj/powerpcvtsc_clang_gcc421_kernel/powerpc.powerpc/usr/src/sys/GENERICvtsc-NODBG powerpc
>>> gcc version 4.2.1 20070831 patched [FreeBSD]
>>> cpu0: IBM PowerPC 970MP revision 1.1, 18446744071914.91 MHz
>>> cpu0: Features dc000000<PPC32,PPC64,ALTIVEC,FPU,MMU>
>>> cpu0: HID0 1511081<DEEPNAP,NAP,DPM,NHR,TBEN,ENATTN>
>>> real memory  = 2118565888 (2020 MB)
>>> avail memory = 2014863360 (1921 MB)
>>> FreeBSD/SMP: Multiprocessor System Detected: 4 CPUs
>>> . . .
>>> Trying to mount root  from ufs:/dev/ufs/FBSDG4Srootfs [rw,noatime]...
>>> . . .
>>> pid 53 (fsck_ufs), uid 0: exited on signal 11
>> 
>> 
>> Manually running fsck later gets a segmentation fault core file in /var/crash/
>> and I used this too see a point of failure (__floatdidf):
>> 
>>> # fsck /
>>> ** /dev/ufs/FBSDG4Srootfs (NO WRITE)
>>> ** Last Mounted on /
>>> ** Root file system
>>> ** Phase 1 - Check Blocks and Sizes
>>> INCORRECT BLOCK COUNT I=11538459 (8 should be 0)
>>> CORRECT? no
>>> 
>>> ** Phase 2 - Check Pathnames
>>> ** Phase 3 - Check Connectivity
>>> ** Phase 4 - Check Reference Counts
>>> LINK COUNT FILE I=10016041  OWNER=operator MODE=100400
>>> SIZE=4096 MTIME=Nov 26 14:44 2016  COUNT 2 SHOULD BE 1
>>> ADJUST? no
>>> 
>>> LINK COUNT FILE I=10016049  OWNER=operator MODE=100400
>>> SIZE=4096 MTIME=Nov 26 14:55 2016  COUNT 2 SHOULD BE 1
>>> ADJUST? no
>>> 
>>> LINK COUNT FILE I=10016089  OWNER=operator MODE=100400
>>> SIZE=4096 MTIME=Nov 26 15:00 2016  COUNT 2 SHOULD BE 1
>>> ADJUST? no
>>> 
>>> UNREF FILE  I=11538459  OWNER=root MODE=100600
>>> SIZE=0 MTIME=Nov 26 15:11 2016 
>>> RECONNECT? no
>>> 
>>> 
>>> CLEAR? no
>>> 
>>> ** Phase 5 - Check Cyl groups
>>> FREE BLK COUNT(S) WRONG IN SUPERBLK
>>> SALVAGE? no
>>> 
>>> SUMMARY INFORMATION BAD
>>> SALVAGE? no
>>> 
>>> BLK(S) MISSING IN BIT MAPS
>>> SALVAGE? no
>>> 
>>> fsck: /dev/ufs/FBSDG4Srootfs: Segmentation fault
>> 
>> 
>>> # gdb fsck_ufs /var/crash/fsck_ufs.1129.core 
>>> GNU gdb 6.1.1 [FreeBSD]
>>> Copyright 2004 Free Software Foundation, Inc.
>>> GDB is free software, covered by the GNU General Public License, and you are
>>> welcome to change it and/or distribute copies of it under certain conditions.
>>> Type "show copying" to see the conditions.
>>> There is absolutely no warranty for GDB.  Type "show warranty" for details.
>>> This GDB was configured as "powerpc-marcel-freebsd"...
>>> Core was generated by `fsck_ufs /dev/ufs/FBSDG4Srootfs'.
>>> Program terminated with signal 11, Segmentation fault.
>>> Reading symbols from /lib/libufs.so.6...Reading symbols from /usr/lib/debug//lib/libufs.so.6.debug...done.
>>> done.
>>> Loaded symbols for /lib/libufs.so.6
>>> Reading symbols from /lib/libc.so.7...Reading symbols from /usr/lib/debug//lib/libc.so.7.debug...done.
>>> done.
>>> Loaded symbols for /lib/libc.so.7
>>> Reading symbols from /libexec/ld-elf.so.1...Reading symbols from /usr/lib/debug//libexec/ld-elf.so.1.debug...done.
>>> done.
>>> Loaded symbols for /libexec/ld-elf.so.1
>>> #0  0x0181b024 in __floatdidf ()
>>> (gdb) bt
>>> #0  0x0181b024 in __floatdidf ()
>>> #1  0x0180a8e0 in main (argc=<value optimized out>, argv=<value optimized out>) at /usr/src/sbin/fsck_ffs/main.c:519
>>> #2  0x01801664 in _start ()
>>> #3  0x418303a0 in .text () at /usr/src/libexec/rtld-elf/powerpc/rtld_start.S:112
>> 
>> main.c's line 519 is part of:
>> 
>>>      printf("(%ju frags, %ju blocks, %.1f%% fragmentation)\n",
>>>          (uintmax_t)n_ffree, (uintmax_t)n_bfree,
>>>          n_ffree * 100.0 / sblock.fs_dsize);
>> 
>> 
>> 
>> As for "df -m" --it failed in __floatdidf as well:
>> 
>>> # gdb df /var/crash/df.1056.core                                                                                                                                                                        GNU gdb 6.1.1 [FreeBSD]
>>> Copyright 2004 Free Software Foundation, Inc.
>>> GDB is free software, covered by the GNU General Public License, and you are
>>> welcome to change it and/or distribute copies of it under certain conditions.
>>> Type "show copying" to see the conditions.
>>> There is absolutely no warranty for GDB.  Type "show warranty" for details.
>>> This GDB was configured as "powerpc-marcel-freebsd"...
>>> Core was generated by `df -m'.
>>> Program terminated with signal 11, Segmentation fault.
>>> Reading symbols from /lib/libxo.so.0...Reading symbols from /usr/lib/debug//lib/libxo.so.0.debug...done.
>>> done.
>>> Loaded symbols for /lib/libxo.so.0
>>> Reading symbols from /lib/libutil.so.9...Reading symbols from /usr/lib/debug//lib/libutil.so.9.debug...done.
>>> done.
>>> Loaded symbols for /lib/libutil.so.9
>>> Reading symbols from /lib/libc.so.7...Reading symbols from /usr/lib/debug//lib/libc.so.7.debug...done.
>>> done.
>>> Loaded symbols for /lib/libc.so.7
>>> Reading symbols from /libexec/ld-elf.so.1...Reading symbols from /usr/lib/debug//libexec/ld-elf.so.1.debug...done.
>>> done.
>>> Loaded symbols for /libexec/ld-elf.so.1
>>> #0  0x01802a18 in __floatdidf ()
>>> (gdb) bt
>>> #0  0x01802a18 in __floatdidf ()
>>> #1  0x01802538 in prtstat (sfsp=0x41e24000, mwp=0xffffd930) at /usr/src/bin/df/df.c:503
>>> #2  0x01801df0 in main (argc=<value optimized out>, argv=<value optimized out>) at /usr/src/bin/df/df.c:308
>>> #3  0x01800cdc in _start ()
>>> #4  0x418153a0 in .text () at /usr/src/libexec/rtld-elf/powerpc/rtld_start.S:112
>> 
>> df.c's line 503 was part of:
>> 
>>>      xo_emit(" {:used-percent/%5.0f}{U:%%}",
>>>          availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0);
>> 
>> 
>> 
>> Context details:
>> 
>>> # head ~/sys_typescripts/typescript_make_powerpcvtsc_nodebug_clang_bootstrap_world-amd64-host-2016-11-26:11:38:36 
>>> Script started on Sat Nov 26 11:38:36 2016
>>> Command: env __MAKE_CONF=/root/src.configs/make.conf SRCCONF=/dev/null SRC_ENV_CONF=/root/src.configs/src.conf.powerpc-clang-bootstrap.amd64-host WITH_META_MODE=yes MAKEOBJDIRPREFIX=/usr/obj/powerpcvtsc_clang_world make -j 5 buildworld
>>> --- buildworld ---
>> 
>> . . .
>> 
>> 
>>> # more ~/src.configs/src.conf.powerpc-clang-bootstrap.amd64-host
>>> TO_TYPE=powerpc
>>> #
>>> KERNCONF=GENERICvtsc-NODBG
>>> TARGET=${TO_TYPE}
>>> .if ${.MAKE.LEVEL} == 0
>>> TARGET_ARCH=${TO_TYPE}
>>> .export TARGET_ARCH
>>> .endif
>>> #
>>> WITH_CROSS_COMPILER=
>>> WITHOUT_SYSTEM_COMPILER=
>>> #
>>> WITH_LIBCPLUSPLUS=
>>> WITH_BINUTILS_BOOTSTRAP=
>>> WITH_CLANG_BOOTSTRAP=
>>> WITH_CLANG=
>>> WITH_CLANG_IS_CC=
>>> WITH_CLANG_FULL=
>>> WITH_CLANG_EXTRAS=
>>> # lldb requires missing atomic 8-byte operations for powerpc (non-64)
>>> WITHOUT_LLDB=
>>> #
>>> WITH_BOOT=
>>> WITHOUT_LIB32=
>>> #
>>> WITHOUT_ELFTOOLCHAIN_BOOTSTRAP=
>>> WITHOUT_GCC_BOOTSTRAP=
>>> WITHOUT_GCC=
>>> WITHOUT_GCC_IS_CC=
>>> WITHOUT_GNUCXX=
>>> #
>>> NO_WERROR=
>>> #WERROR=
>>> MALLOC_PRODUCTION=
>>> #
>>> WITH_DEBUG_FILES=
>> 
>> 
>>> # more ~/src.configs/make.conf 
>>> CFLAGS.gcc+= -v
> 
> Looking around in gdb there seem to be two __floatdidf routines with differing code.
> 
> First showing the one that was used and failed:
> 
> (gdb) x/50i 0x0181afc0
> . . .
> 0x181afcc <__floatdidf>:	mflr    r0
> 0x181afd0 <__floatdidf+4>:	stw     r0,4(r1)
> 0x181afd4 <__floatdidf+8>:	stwu    r1,-32(r1)
> 0x181afd8 <__floatdidf+12>:	stw     r31,28(r1)
> 0x181afdc <__floatdidf+16>:	stw     r30,24(r1)
> 0x181afe0 <__floatdidf+20>:	bl      0x182e96c <.got+20>
> 0x181afe4 <__floatdidf+24>:	mr      r31,r1
> 0x181afe8 <__floatdidf+28>:	xoris   r3,r3,32768
> 0x181afec <__floatdidf+32>:	lis     r5,17200
> 0x181aff0 <__floatdidf+36>:	mflr    r30
> 0x181aff4 <__floatdidf+40>:	stw     r3,12(r31)
> 0x181aff8 <__floatdidf+44>:	stw     r5,8(r31)
> 0x181affc <__floatdidf+48>:	lwz     r3,-16(r30)
> 0x181b000 <__floatdidf+52>:	lwz     r6,-20(r30)
> 0x181b004 <__floatdidf+56>:	lfd     f1,8(r31)
> 0x181b008 <__floatdidf+60>:	stw     r4,20(r31)
> 0x181b00c <__floatdidf+64>:	stw     r5,16(r31)
> 0x181b010 <__floatdidf+68>:	lfd     f13,16(r31)
> 0x181b014 <__floatdidf+72>:	lwz     r0,36(r1)
> 0x181b018 <__floatdidf+76>:	lwz     r31,28(r1)
> 0x181b01c <__floatdidf+80>:	lwz     r30,24(r1)
> 0x181b020 <__floatdidf+84>:	lfs     f2,0(r3)
> 0x181b024 <__floatdidf+88>:	lwz     r3,-12(r30)
> 0x181b028 <__floatdidf+92>:	lfs     f0,0(r6)
> 0x181b02c <__floatdidf+96>:	lfs     f12,0(r3)
> 0x181b030 <__floatdidf+100>:	fsub    f0,f1,f0
> 0x181b034 <__floatdidf+104>:	fmul    f0,f0,f2
> 0x181b038 <__floatdidf+108>:	fadd    f0,f0,f12
> 0x181b03c <__floatdidf+112>:	fadd    f1,f13,f0
> 0x181b040 <__floatdidf+116>:	addi    r1,r1,32
> 0x181b044 <__floatdidf+120>:	mtlr    r0
> 0x181b048 <__floatdidf+124>:	blr
> . . .
> 
> Then showing the one that was not used that I found:
> 
> (gdb) disass __floatdidf
> Dump of assembler code for function __floatdidf:
> 0x4199fc8c <__floatdidf+0>:	mflr    r0
> 0x4199fc90 <__floatdidf+4>:	stw     r0,4(r1)
> 0x4199fc94 <__floatdidf+8>:	stwu    r1,-32(r1)
> 0x4199fc98 <__floatdidf+12>:	stw     r31,28(r1)
> 0x4199fc9c <__floatdidf+16>:	stw     r30,24(r1)
> 0x4199fca0 <__floatdidf+20>:	mr      r31,r1
> 0x4199fca4 <__floatdidf+24>:	srawi   r5,r3,31
> 0x4199fca8 <__floatdidf+28>:	bl      0x41a0a288 <.got+14428>
> 0x4199fcac <__floatdidf+32>:	cmpwi   r3,0
> 0x4199fcb0 <__floatdidf+36>:	addc    r6,r4,r5
> 0x4199fcb4 <__floatdidf+40>:	adde    r6,r3,r5
> 0x4199fcb8 <__floatdidf+44>:	lis     r3,17200
> 0x4199fcbc <__floatdidf+48>:	xor     r5,r6,r5
> 0x4199fcc0 <__floatdidf+52>:	mflr    r30
> 0x4199fcc4 <__floatdidf+56>:	bge-    0x4199fccc <__floatdidf+64>
> 0x4199fcc8 <__floatdidf+60>:	neg     r4,r4
> 0x4199fccc <__floatdidf+64>:	lwz     r12,-3124(r30)
> 0x4199fcd0 <__floatdidf+68>:	stw     r5,20(r31)
> 0x4199fcd4 <__floatdidf+72>:	stw     r4,12(r31)
> 0x4199fcd8 <__floatdidf+76>:	lwz     r4,-3120(r30)
> 0x4199fcdc <__floatdidf+80>:	stw     r3,16(r31)
> 0x4199fce0 <__floatdidf+84>:	stw     r3,8(r31)
> 0x4199fce4 <__floatdidf+88>:	lfd     f1,16(r31)
> 0x4199fce8 <__floatdidf+92>:	lfd     f3,8(r31)
> 0x4199fcec <__floatdidf+96>:	lfs     f0,0(r12)
> 0x4199fcf0 <__floatdidf+100>:	lfs     f2,0(r4)
> 0x4199fcf4 <__floatdidf+104>:	fsub    f1,f1,f0
> 0x4199fcf8 <__floatdidf+108>:	fsub    f0,f3,f0
> 0x4199fcfc <__floatdidf+112>:	fmul    f1,f1,f2
> 0x4199fd00 <__floatdidf+116>:	fadd    f1,f0,f1
> 0x4199fd04 <__floatdidf+120>:	bge-    0x4199fd0c <__floatdidf+128>
> 0x4199fd08 <__floatdidf+124>:	fneg    f1,f1
> 0x4199fd0c <__floatdidf+128>:	lwz     r0,36(r1)
> 0x4199fd10 <__floatdidf+132>:	lwz     r31,28(r1)
> 0x4199fd14 <__floatdidf+136>:	lwz     r30,24(r1)
> 0x4199fd18 <__floatdidf+140>:	addi    r1,r1,32
> 0x4199fd1c <__floatdidf+144>:	mtlr    r0
> 0x4199fd20 <__floatdidf+148>:	blr
> End of assembler dump.
> 
> ===
> Mark Millard
> markmi at dsl-only.net


_______________________________________________
freebsd-ppc at freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-ppc
To unsubscribe, send any mail to "freebsd-ppc-unsubscribe at freebsd.org"



More information about the freebsd-toolchain mailing list