Make -fstandalone-debug default on mingw

Yaron Keren yaron.keren at gmail.com
Mon Sep 8 02:30:03 PDT 2014


Hi,

It does not seem a gcc bug, but rather a MinGW bug, a roblem with debug
info from libstdc++. With your example,

#include <fstream>
int main() {
  std::ofstream f("foo.txt");
}

g++ a.cpp -g  (or clang) on both Windows and Ubuntu produce a
DW_AT_declaration.
That's identical.

The difference is with libstdc++, on MinGW 4.82 (and 4.91) on Windows 7:

(gdb) info sharedlibrary
>From        To          Syms Read   Shared Object Library
0x6fc41000  0x6fd32e00  Yes (*)
C:\Users\yaron\Downloads\mingw32\bin\libstdc++-6.dll
(*): Shared library is missing debugging information.

whereas with gcc 4.82 on Ubuntu 14:

(gdb) info sharedlibrary
>From                To                  Syms Read   Shared Object Library
0x00007ffff7b315c0  0x00007ffff7b9499a  Yes
/usr/lib/x86_64-linux-gnu/libstdc++.so.6

indeed 'print f' on MingW fails with incomplete type whereas on Ubuntu it
pulls the debuginfo from libstdc++ and succeeds.

I don't think clang should workaround this but rather that minGW libstdc++
should be same as Linux with debug info. I'll report this to MingW-w64.

Yaron




2014-09-05 21:17 GMT+03:00 David Blaikie <dblaikie at gmail.com>:

>
>
>
> On Mon, Sep 1, 2014 at 2:28 PM, Yaron Keren <yaron.keren at gmail.com> wrote:
>
>> There is no debug variant of libstdc++, just release DLL, import lib for
>> this DLL and a static lib. You can see all the files (even without actually
>> running Windows) in the install 7z file:
>>
>>
>> http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.9.1/threads-posix/dwarf/
>>
>> Anyhow, for your example,
>>
>> mingw (gcc 4.9.1)
>> ------------------------
>>
>> 0x00000072:   DW_TAG_structure_type [2] *
>>                 DW_AT_name [DW_FORM_string] ("foo")
>>                 DW_AT_declaration [DW_FORM_flag_present] (true)
>>                 DW_AT_sibling [DW_FORM_ref4] (cu + 0x008b =>
>> {0x0000008b})
>>
>> 0x0000007b:     DW_TAG_subprogram [3] *
>>                   DW_AT_external [DW_FORM_flag_present] (true)
>>                   DW_AT_name [DW_FORM_string] ("foo")
>>                   DW_AT_artificial [DW_FORM_flag_present] (true)
>>                   DW_AT_declaration [DW_FORM_flag_present] (true)
>>                   DW_AT_object_pointer [DW_FORM_ref4] (cu + 0x0084 =>
>> {0x00000084})
>>
>> 0x00000084:       DW_TAG_formal_parameter [4]
>>                     DW_AT_type [DW_FORM_ref4] (cu + 0x008b =>
>> {0x0000008b})
>>                     DW_AT_artificial [DW_FORM_flag_present] (true)
>>
>> 0x00000089:       NULL
>>
>> 0x0000008a:     NULL
>>
>>
>> clang trunk
>> --------------
>>
>> 0x00000037:   DW_TAG_structure_type [3] *
>>                 DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000048] =
>> "foo")
>>                 DW_AT_declaration [DW_FORM_flag_present] (true)
>>
>> 0x0000003c:     DW_TAG_subprogram [4] *
>>                   DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000048] =
>> "foo")
>>                   DW_AT_declaration [DW_FORM_flag_present] (true)
>>                   DW_AT_artificial [DW_FORM_flag_present] (true)
>>                   DW_AT_external [DW_FORM_flag_present] (true)
>>                   DW_AT_accessibility [DW_FORM_data1] (0x01)
>>
>> 0x00000042:       DW_TAG_formal_parameter [5]
>>                      DW_AT_type [DW_FORM_ref4] (cu + 0x005b =>
>> {0x0000005b})
>>                     DW_AT_artificial [DW_FORM_flag_present] (true)
>>
>> 0x00000047:       NULL
>>
>> 0x00000048:     NULL
>>
>> clang -fstandalone-debug
>> ----------------------------------
>>
>> 0x00000037:   DW_TAG_structure_type [3] *
>>                 DW_AT_containing_type [DW_FORM_ref4] (cu + 0x0037 =>
>> {0x00000037})
>>                 DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000007a] =
>> "foo")
>>                 DW_AT_byte_size [DW_FORM_data1] (0x04)
>>                 DW_AT_decl_file [DW_FORM_data1] (0x01)
>>                 DW_AT_decl_line [DW_FORM_data1] (0x01)
>>
>> 0x00000043:     DW_TAG_member [4]
>>                   DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000048] =
>> "_vptr$foo")
>>                   DW_AT_type [DW_FORM_ref4] (cu + 0x0075 => {0x00000075})
>>                   DW_AT_data_member_location [DW_FORM_data1] (0x00)
>>                   DW_AT_accessibility [DW_FORM_data1] (0x01)
>>                   DW_AT_artificial [DW_FORM_flag_present] (true)
>>
>> 0x0000004e:     DW_TAG_subprogram [5] *
>>                   DW_AT_MIPS_linkage_name [DW_FORM_strp] (
>> .debug_str[0x00000066] = "_ZN3foo4funcEv")
>>                   DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000075] =
>> "func")
>>                   DW_AT_decl_file [DW_FORM_data1] (0x01)
>>                   DW_AT_decl_line [DW_FORM_data1] (0x01)
>>                   DW_AT_virtuality [DW_FORM_data1] (0x01)
>>                   DW_AT_vtable_elem_location [DW_FORM_exprloc] (<0x2> 10
>> 00 )
>>                   DW_AT_declaration [DW_FORM_flag_present] (true)
>>                   DW_AT_external [DW_FORM_flag_present] (true)
>>                   DW_AT_accessibility [DW_FORM_data1] (0x01)
>>                   DW_AT_containing_type [DW_FORM_ref4] (cu + 0x0037 =>
>> {0x00000037})
>>
>> 0x00000062:       DW_TAG_formal_parameter [6]
>>                     DW_AT_type [DW_FORM_ref4] (cu + 0x008f =>
>> {0x0000008f})
>>                     DW_AT_artificial [DW_FORM_flag_present] (true)
>>
>> 0x00000067:       NULL
>>
>> 0x00000068:     DW_TAG_subprogram [7] *
>>                   DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000007a] =
>> "foo")
>>                   DW_AT_declaration [DW_FORM_flag_present] (true)
>>                   DW_AT_artificial [DW_FORM_flag_present] (true)
>>                   DW_AT_external [DW_FORM_flag_present] (true)
>>                   DW_AT_accessibility [DW_FORM_data1] (0x01)
>>
>> 0x0000006e:       DW_TAG_formal_parameter [6]
>>                     DW_AT_type [DW_FORM_ref4] (cu + 0x008f =>
>> {0x0000008f})
>>                     DW_AT_artificial [DW_FORM_flag_present] (true)
>>
>> 0x00000073:       NULL
>>
>> 0x00000074:     NULL
>>
>>
>> That's consistent.
>>
>> What's odd is for std::string gcc produces a definition while clang
>> produce a declaration only unless -fstandalone-debug. That what causes the
>> debug pretty printer problem.
>>
>
> Yep - that's because Clang has another similar, bit different,
> optimization that's founded on the same principle (the idea that you will
> compile your whole program/libraries with debug info), using explicit
> template instantiations as a hint that the debug info will be available
> elsewhere anyway. GCC doesn't implement that particular optimization, but
> my point in the above example is that it implements similar things that are
> just as problematic for a user without debug libraries.
>
> A specific STL example would be:
>
>   #include <fstream>
>
>   int main() {
>     std::ofstream f("foo.txt");
>   }
>
> Both Clang and GCC produce:
>
>   DW_TAG_class_type [5]
>     DW_AT_name [DW_FORM_strp]     ( .debug_str[0x000000c7] =
> "basic_ofstream<char, std::char_traits<char> >")
>     DW_AT_declaration [DW_FORM_flag_present]      (true)
>
> Because the vtable for basic_ofstream<char> is compiled into libstdc++.
>
>
>> #include <string>
>> int main() {
>>   std::string s("hello");
>> }
>>
>> Since both gcc and clang share the same header files, library files and
>> linker, it would seem that the decision rule when to produce a debug class
>> definition is different between gcc and clang at least for std::string.
>>
>
> Yep - the explicit template instantiation being the trigger clang is using
> for that. My vtable example was to demonstrate that GCC uses similar
> reasoning for other things (where GCC and Clang overlap more closely).
>
> That said, I know next to nothing about MinGW distribution and "GCC does
> this" isn't itself an argument for Clang to do something, so I'm not
> exactly going to block this patch.
>
> Do you have any idea if someone's filed a similar bug on GCC (do you care
> about GCC behavior, or only Clang?)? Any idea what their response was? (I
> imagine people in the GCC community might have more familiarity with
> MinGW/libstdc++ distribution practices than I do, and might have some other
> ideas about whether it's the right direction)
>
>
>>
>> Yaron
>>
>>
>>
>>
>> 2014-09-01 22:25 GMT+03:00 David Blaikie <dblaikie at gmail.com>:
>>
>>
>>>
>>>
>>> On Mon, Sep 1, 2014 at 11:38 AM, Yaron Keren <yaron.keren at gmail.com>
>>> wrote:
>>>
>>>> http://llvm.org/bugs/show_bug.cgi?id=20741
>>>>
>>>> With the current default, a programmer compiling his program with clang
>>>> -g will not get debug info for std::string members and thus the gdb pretty
>>>> printer for std::string will fail. That's how I noticed the problem in the
>>>> first place. Given that libstdc++ is used in every C++ program and that
>>>> std::string is quite popular, this isn't a good result.
>>>>
>>>
>>> On most linux distributions, there's a -dbg variant of libstdc++ that
>>> users can install to get the library's debug information (GCC relies on
>>> this for various parts of its debug output, for example - I'd be curious to
>>> know if their default is any different on MinGW). Is there no such thing on
>>> MinGW? (do you know if GCC does the same thing? try compiling this source
>>> file to an object file with gcc: "struct foo { virtual void func(); } foo
>>> f;" and see if GCC emits the definition of 'foo', or just a declaration -
>>> on Linux it'll only produce a declaration)
>>>
>>>
>>>>
>>>> This patch makes  -fstandalone-debug default on mingw.
>>>>
>>>>
>>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140908/d9d5e228/attachment.html>


More information about the cfe-commits mailing list