2018-07-20 09:06 AEST

View Issue Details Jump to Notes ]
IDProjectCategoryView StatusLast Update
0000453mercuryBugpublic2018-03-16 15:15
Reporterwangp 
Assigned To 
PrioritynormalSeveritycrashReproducibilityalways
StatusnewResolutionopen 
Product Version 
Target VersionFixed in Version 
Summary0000453: asm_fast does not work with gcc 5.4
DescriptionOne of the test cases (of many) which crash is hard_coded/bit_buffer_test.

This configuration crashes:
Ubuntu 16.04 i386
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9)
Mercury rotd 2016-02-18 and rotd 2018-03-07
asm_fast.gc
(none.gc, reg.gc, hlc.gc are OK)
TagsNo tags attached.
Attached Files

-Relationships
+Relationships

-Notes

~0000976

wangp (developer)

The previous configuration (gcc 5.4.0, asm_fast.gc, x86) passes bootcheck if the Mercury libraries are statically linked, i.e. ./configure --disable-dynamic-link

~0000988

wangp (developer)

I can reproduce a crash more simply with a call to string.count_codepoints/2. I've copied that predicate to a separate module for ease of debugging, and generated the assembly with mmake string2.pic_s. Then we can edit the assembly and create libmer_std.so with: as -g string2.pic_s -o string2.pic_o && mmake libmer_std.so


This is the start of string2.count_codepoints:

           .globl _entry_mercury__string2__count_codepoints_2_0
   .type _entry_mercury__string2__count_codepoints_2_0,@function
_entry_mercury__string2__count_codepoints_2_0:
   call 0f
0:
   popl %ebx
   addl $_GLOBAL_OFFSET_TABLE_+[.-0b],%ebx
      
# 0 "" 2
.LDL1:
#NO_APP
.L4:
        movl -12(%ebp), %ebx
        leal .L5@GOTOFF(%ebx), %eax
.LBB2:
        .loc 1 281 0
        movl MR_engine_base@GOT(%ebx), %eax
        movl 8(%eax), %ecx
        ...

The four lines beginning with "call 0f" are due to MR_INLINE_ASM_FIXUP_REGS, to (as I understand it) load the position of the code into ebx. Right afterwards, gcc has added an instruction to copy something off the stack into ebx (presumably it would have stashed the correct value on the stack, but we've jumped into the middle of a C function).

Inserting an instruction "movl %ebx, -12(%ebp)" to cancel out that instruction makes this particular predicate work, so I think this is on the right track.

~0000989

wangp (developer)

On the other hand... x86 usage is only decreasing, linking with Mercury shared libraries is not very important, and inter-function jumps were never officially supported by gcc anyway. Maybe it is time to drop support for the combination?

~0000990

juliensf (administrator)

If you disable optimization in GCC (e.g. -O0) does the problem still occur?

~0000991

wangp (developer)

It works at -O0, but not -O1, and not at -O1 with -f* options I could find disabled (everything listed by "gcc -O1 -Q --help=optimizers").

~0000992

wangp (developer)

My guess is that it is related to this change in GCC 5.0:

https://software.intel.com/en-us/blogs/2014/12/26/new-optimizations-for-x86-in-upcoming-gcc-50-32bit-pic-mode
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54232

Previously EBX was reserved for the GOT address so GCC probably had no need to save/restore it. If EBX can be used for other purposes then GCC might try to restore a value from the stack after our inline asm. The question is how to convince GCC not to do that.

~0000993

wangp (developer)

(convince GCC not to restore the GOT address from the stack, not only directly after the MR_INLINE_ASM_FIXUP_REGS sequence)

~0000994

juliensf (administrator)

You could try starting at -O0 and adding optimizations. (Past experience of this
kind of thing indicates that GCC is not entirely truthful about which optimizations it applies at which optimization level.)

~0000995

wangp (developer)

Ok, bootcheck still passes with these options (which are what gcc reports as being enabled by -O1):

-fbranch-count-reg
-fcombine-stack-adjustments
-fcompare-elim
-fcprop-registers
-fforward-propagate
-fguess-branch-probability
-fif-conversion
-fif-conversion2
-finline-functions-called-once
-fipa-profile
-fipa-pure-const
-fipa-reference
-freorder-blocks
-fshrink-wrap
-fsplit-wide-types
-fssa-phiopt
-ftree-bit-ccp
-ftree-builtin-call-dce
-ftree-ccp
-ftree-ch
-ftree-coalesce-vars
-ftree-copy-prop
-ftree-dce
-ftree-dse
-ftree-fre
-ftree-pta
-ftree-sink
-ftree-slsr
-ftree-sra
-ftree-ter


Regardless, gcc 5 and up do not use a fixed PIC register on x86. Jumping into the middle of a function and putting the GOT address into EBX is not going to work if the rest of the function is not expecting it there.
+Notes

-Issue History
Date Modified Username Field Change
2018-03-09 15:57 wangp New Issue
2018-03-13 14:23 wangp Note Added: 0000976
2018-03-15 12:57 wangp Note Added: 0000988
2018-03-15 14:59 wangp Note Added: 0000989
2018-03-15 16:14 juliensf Note Added: 0000990
2018-03-15 16:26 wangp Note Added: 0000991
2018-03-15 16:40 wangp Note Added: 0000992
2018-03-15 17:04 wangp Note Added: 0000993
2018-03-15 17:11 juliensf Note Added: 0000994
2018-03-16 15:15 wangp Note Added: 0000995
+Issue History