relax_segment loops forever on relaxing .gcc_except_table, with growth oscillating between 1 and -1.
Created attachment 1549 [details] Testcase
The problem is with rs_leb128 processing. When size needed for the new value is 0x3fff is 2 and the old size is 3, growth is -1. Then the next time the new value becomes 0x4000 and its size becomes 3. That is an infinite loop.
Created attachment 1564 [details] A kludge This kludge compiles the testcase. But I am not sure if it is correct.
A patch is posted at http://sourceware.org/ml/binutils/2007-02/msg00280.html
Reduced testcase. .data .align 4 .byte 0, 0 .uleb128 end - start start: .space 128*128 - 1 /* or -2 or -3 */ .align 4 end: I don't believe this is a gas bug. Instead, I believe gcc is asking the impossible of gas. The original testcase or the reduced one above has no correct solution. ie. this problem is caused by a design fault in the layout of .gcc_except_table data. Consider: We know the uleb128 is either two or three bytes long. If end-start is 128*128-1 or somewhat less, then it will be two bytes. If 128*128 or a little larger, then it will be three bytes. But, if the uleb128 is two bytes in size, then end-start is 128*128 If the uleb128 is three bytes, then end-start is 128*128-1 This results in a contradiction.
Assembler can do better to help gcc. We can turn it into .data .align 4 .byte 0, 0 .uleb128 end - start start: .space 128*128 - 1 /* or -2 or -3 */ .align 8 end:
Yes, we can modify the output, but we must do so in a way that does not confuse consumers of .gcc_except_table. I don't believe changing the .align is correct, because data normally follows the .align (a number of .long's before the end label). Changing alignment in a way that cures the uleb128 problem necessarily inserts zero bytes, which I think will confuse the unwinder.
The assembly code in question is .align 4 .long DW.ref._ZTIN10DSEBuiltin17ExceptionDeadLockE-. .long DW.ref._ZTI7DSEBomb-. .long DW.ref._ZTI12DSEException-. .long DW.ref._ZTISt9exception-. .long 0 .LLSDATT5533: If those data are accessed via .LLSDATT5533 as base, it is s safe to change .align 4 to .align 8. I think .align 8 is compatible with .align 4. If it isn't true, it is a bug in assembly code. Andreas, can you upload the preprocessed C++ source and assembly code generated with -dA?
A patch is posted at http://sourceware.org/ml/binutils/2007-03/msg00107.html
Ah, yes, it does seem as if the type_info table is stored in reverse order and accessed from the end. In that case increasing alignment padding should work.
http://sourceware.org/ml/binutils-cvs/2007-03/msg00070.html http://sourceware.org/ml/binutils-cvs/2007-03/msg00071.html
Fixed
FWIW: This issue affects the LLVM assembler, too: https://bugs.llvm.org/show_bug.cgi?id=35809.