Bug 82630 - Bogus DW_AT_GNU_call_site_value
Summary: Bogus DW_AT_GNU_call_site_value
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: debug (show other bugs)
Version: 8.0
: P3 normal
Target Milestone: ---
Assignee: Jakub Jelinek
URL:
Keywords: wrong-debug
: 82631 (view as bug list)
Depends on:
Blocks:
 
Reported: 2017-10-20 01:40 UTC by Rafael Avila de Espindola
Modified: 2017-12-15 09:20 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2017-10-20 00:00:00


Attachments
testcase (217 bytes, text/plain)
2017-10-20 01:40 UTC, Rafael Avila de Espindola
Details
gcc8-pr82630.patch (2.95 KB, patch)
2017-10-20 13:45 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Rafael Avila de Espindola 2017-10-20 01:40:16 UTC
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.
Comment 1 Richard Biener 2017-10-20 09:10:10 UTC
*** Bug 82631 has been marked as a duplicate of this bug. ***
Comment 2 Jakub Jelinek 2017-10-20 10:19:10 UTC
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.
Comment 3 H.J. Lu 2017-10-20 12:04:05 UTC
(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_
Comment 4 Jakub Jelinek 2017-10-20 12:06:51 UTC
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.
Comment 5 Jakub Jelinek 2017-10-20 13:45:25 UTC
Created attachment 42412 [details]
gcc8-pr82630.patch

Untested fix.
Comment 6 Rafael Avila de Espindola 2017-10-20 15:56:48 UTC
(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.
Comment 7 Jakub Jelinek 2017-10-23 20:40:30 UTC
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
Comment 8 Jakub Jelinek 2017-12-15 09:20:16 UTC
Fixed.