Make -fstandalone-debug default on mingw

David Blaikie dblaikie at gmail.com
Fri Sep 5 11:17:07 PDT 2014


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/20140905/2ca29943/attachment.html>


More information about the cfe-commits mailing list