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:42 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-ppc
mailing list