Created attachment 42407 [details] testcase If the attached file is compiled with "g++ test.cpp -fPIC -g -O3 -m32", the produced dwarf has DW_AT_location len 0x0001: 52: DW_OP_reg2 Which means an argument is begin passed in edx. It also has DW_AT_GNU_call_site_value len 0x000e: 730003000000001c030000000022: DW_OP_breg3+0 DW_OP_addr 0x00000000 DW_OP_minus DW_OP_addr 0x00000000 DW_OP_plus The first DW_op_addr is .long _GLOBAL_OFFSET_TABLE_ and the second one is .long .LC0 The first line actually produces a R_386_GOTPC, so it looks like the expression is computing (ebx - (GOTEND - PC)) + LC0 The code using LC0 is _Z3fn3Pi: pushl %esi pushl %ebx xorl %ebx, %ebx call __x86.get_pc_thunk.si addl $_GLOBAL_OFFSET_TABLE_, %esi subl $12, %esp movl 24(%esp), %eax leal .LC0@GOTOFF(%esi), %edx pushl %ebx movl %esi, %ebx pushl %eax call _ZL3fn2PiPKc1C.constprop.0 So at the point of the call ebx is GOTEND. This suggests that gcc is actually trying to compute (ebx - GOTEND) + LC0 but getting R_386_GOTPC wrong. But the expression also simplifies to just LC0, which is what is actually in edx.
*** Bug 82631 has been marked as a duplicate of this bug. ***
The problem is the assembler's special treatment of _GLOBAL_OFFSET_TABLE_, that .long _GLOBAL_OFFSET_TABLE_ or .quad _GLOBAL_OFFSET_TABLE_ on x86 doesn't actually assemble as normal relocation against that symbol, but as a special relocation. The reason why we end up with this is that during var-tracking/dwarf2out in this case we fail to prove that %ebx at that point contains _GLOBAL_OFFSET_TABLE_ and so delegitimization offsers the last possibility, verification of that at debug time. The question is if it is actually possible to somehow emit an address of _GLOBAL_OFFSET_TABLE_ into the debug info when .byte 0x3 # DW_OP_addr .long _GLOBAL_OFFSET_TABLE_ doesn't work. I've tried .set .LC1000 = _GLOBAL_OFFSET_TABLE_ .long .LC1000 but that doesn't work either. If we have some local symbol emitted in allocatable sections, we could emit: .byte 0x3 # DW_OP_addr .long .LC0 .byte 0x3 # DW_OP_addr .long .LC0@GOTOFF .byte 0x1c # DW_OP_minus because symbol@GOTOFF is symbol - _GLOBAL_OFFSET_TABLE_, but that is very nasty and large. In the end, it is pitty that for the R_386_GOTPC etc. relocations the x86 assembler doesn't use some @gotpc or similar suffixes; or we could get away with a suffix that would undo this special handling of _GLOBAL_OFFSET_TABLE_ symbol.
(In reply to Jakub Jelinek from comment #2) > The problem is the assembler's special treatment of _GLOBAL_OFFSET_TABLE_, > that > .long _GLOBAL_OFFSET_TABLE_ or .quad _GLOBAL_OFFSET_TABLE_ on x86 doesn't > actually assemble as normal relocation against that symbol, but as a special > relocation. Should I change assembler to generate R_386_32 for .long _GLOBAL_OFFSET_TABLE_
Then it would be unclear what that generates (something with the old assembler, something else with the new assembler). Trying now to change gcc so that it actually doesn't delegitimize UNSPEC_GOTOFF in this case, but let it be accepted. That should result in better debuginfo size anyway.
Created attachment 42412 [details] gcc8-pr82630.patch Untested fix.
(In reply to H.J. Lu from comment #3) > (In reply to Jakub Jelinek from comment #2) > > The problem is the assembler's special treatment of _GLOBAL_OFFSET_TABLE_, > > that > > .long _GLOBAL_OFFSET_TABLE_ or .quad _GLOBAL_OFFSET_TABLE_ on x86 doesn't > > actually assemble as normal relocation against that symbol, but as a special > > relocation. > > Should I change assembler to generate R_386_32 for > > .long _GLOBAL_OFFSET_TABLE_ I would love for the _GLOBAL_OFFSET_TABLE_ special case to go away, but for doing that gcc would first have to change from printing call __x86.get_pc_thunk.bx addl $_GLOBAL_OFFSET_TABLE_, %ebx to printing call __x86.get_pc_thunk.bx addl $_GLOBAL_OFFSET_TABLE_ - ., %ebx which already produces the exactly same binary with gas.
Author: jakub Date: Mon Oct 23 20:39:59 2017 New Revision: 254025 URL: https://gcc.gnu.org/viewcvs?rev=254025&root=gcc&view=rev Log: PR debug/82630 * target.def (const_not_ok_for_debug_p): Default to default_const_not_ok_for_debug_p instead of hook_bool_rtx_false. * targhooks.h (default_const_not_ok_for_debug_p): New declaration. * targhooks.c (default_const_not_ok_for_debug_p): New function. * dwarf2out.c (const_ok_for_output_1): Only reject UNSPECs for which targetm.const_not_ok_for_debug_p returned true. * config/arm/arm.c (arm_const_not_ok_for_debug_p): Return true for UNSPECs. * config/powerpcspe/powerpcspe.c (rs6000_const_not_ok_for_debug_p): Likewise. * config/rs6000/rs6000.c (rs6000_const_not_ok_for_debug_p): Likewise. * config/i386/i386.c (ix86_delegitimize_address_1): Don't delegitimize UNSPEC_GOTOFF with addend into addend - _GLOBAL_OFFSET_TABLE_ + symbol if !base_term_p. (ix86_const_not_ok_for_debug_p): New function. (i386_asm_output_addr_const_extra): Handle UNSPEC_GOTOFF. (TARGET_CONST_NOT_OK_FOR_DEBUG_P): Redefine. * g++.dg/guality/pr82630.C: New test. Added: trunk/gcc/testsuite/g++.dg/guality/pr82630.C Modified: trunk/gcc/ChangeLog trunk/gcc/config/arm/arm.c trunk/gcc/config/i386/i386.c trunk/gcc/config/powerpcspe/powerpcspe.c trunk/gcc/config/rs6000/rs6000.c trunk/gcc/dwarf2out.c trunk/gcc/target.def trunk/gcc/targhooks.c trunk/gcc/targhooks.h trunk/gcc/testsuite/ChangeLog
Fixed.