Please file a bug for this and I will relate it to our internal apple bug that tracks this issue.
> On Mar 10, 2016, at 2:03 PM, Greg Clayton via lldb-dev > <lldb-dev@lists.llvm.org> wrote: > > Thanks for the example, this is indeed a new regression. It used to work > (Xcode 7.2), but now with top of tree it doesn't. Sean Callanan recently > pulled out a bunch of work around we used to have in the expression/JIT so > that we can avoid certain issues that were caused by said work arounds, and > those are causing problems now. I looked at the old expression parser and it > will still making up the name _Z6myfuncP3$_0, but it would first try the > mangled name, and if it didn't find that, then it would fall back to just > looking for the demangled basename ("myfunc"). We removed this work around > because now we are trying to be more correct, and that caused this > regression. Sean Callanan will take a look at this and get a fix for it > sometime soon. What is probably happening is we are removing the typedef > sugar from the function arguments somewhere that we shouldn't be (like maybe > in the clang::ASTImporter or our lldb_private::ClangASTImporter). We should > be trying to lookup the mangle name "_Z6myfuncP18my_untagged_struct", but > somehow when we go to lookup the type we lost the my_untagged_struct and are > looking for an anonymous struct "$_0" instead. > > Greg Clayton > >> On Mar 10, 2016, at 10:20 AM, Luke Drummond <luke.drumm...@codeplay.com> >> wrote: >> >> Hi Greg >> >> First of all thanks for taking the time to help out with this. >> >> On 10/03/16 00:18, Greg Clayton wrote: >>> So we ran into a problem where we had anonymous structs in modules. They >>> have no name, so we had no way to say "module A, please give me a struct >>> named... nothing in the namespace 'foo'". Obviously this doesn't work, so >>> we always try to make sure a typedef doesn't come from a module first, by >>> asking us to get the typedef from the DWO file: >>> >>> type_sp = ParseTypeFromDWO(die, log); >>> >>> If this fails, it just means we have the typedef in hand. If I compile your >>> example I end up with: >>> >>> 0x0000000b: TAG_compile_unit [1] * >>> AT_producer( "Apple LLVM version 8.0.0 (clang-800.0.5.3)" ) >>> AT_language( DW_LANG_C99 ) >>> AT_name( "main.c" ) >>> AT_stmt_list( 0x00000000 ) >>> AT_comp_dir( "/tmp" ) >>> AT_low_pc( 0x0000000100000f60 ) >>> AT_high_pc( 0x0000000100000fb0 ) >>> >>> 0x0000002e: TAG_subprogram [2] * >>> AT_low_pc( 0x0000000100000f60 ) >>> AT_high_pc( 0x0000000100000f85 ) >>> AT_frame_base( rbp ) >>> AT_name( "myfunc" ) >>> AT_decl_file( "/private/tmp/main.c" ) >>> AT_decl_line( 6 ) >>> AT_prototyped( 0x01 ) >>> AT_external( 0x01 ) >>> >>> 0x00000049: TAG_formal_parameter [3] >>> AT_location( fbreg -8 ) >>> AT_name( "s" ) >>> AT_decl_file( "/private/tmp/main.c" ) >>> AT_decl_line( 6 ) >>> AT_type( {0x0000008c} ( my_untagged_struct* ) ) >>> >>> 0x00000057: NULL >>> >>> 0x00000058: TAG_subprogram [4] * >>> AT_low_pc( 0x0000000100000f90 ) >>> AT_high_pc( 0x0000000100000fb0 ) >>> AT_frame_base( rbp ) >>> AT_name( "main" ) >>> AT_decl_file( "/private/tmp/main.c" ) >>> AT_decl_line( 12 ) >>> AT_type( {0x00000085} ( int ) ) >>> AT_external( 0x01 ) >>> >>> 0x00000076: TAG_variable [5] >>> AT_location( fbreg -16 ) >>> AT_name( "s" ) >>> AT_decl_file( "/private/tmp/main.c" ) >>> AT_decl_line( 14 ) >>> AT_type( {0x00000091} ( my_untagged_struct ) ) >>> >>> 0x00000084: NULL >>> >>> 0x00000085: TAG_base_type [6] >>> AT_name( "int" ) >>> AT_encoding( DW_ATE_signed ) >>> AT_byte_size( 0x04 ) >>> >>> 0x0000008c: TAG_pointer_type [7] >>> AT_type( {0x00000091} ( my_untagged_struct ) ) >>> >>> 0x00000091: TAG_typedef [8] >>> AT_type( {0x0000009c} ( struct ) ) >>> AT_name( "my_untagged_struct" ) >>> AT_decl_file( "/private/tmp/main.c" ) >>> AT_decl_line( 4 ) >>> >>> 0x0000009c: TAG_structure_type [9] * >>> AT_byte_size( 0x08 ) >>> AT_decl_file( "/private/tmp/main.c" ) >>> AT_decl_line( 1 ) >>> >>> 0x000000a0: TAG_member [10] >>> AT_name( "i" ) >>> AT_type( {0x00000085} ( int ) ) >>> AT_decl_file( "/private/tmp/main.c" ) >>> AT_decl_line( 2 ) >>> AT_data_member_location( +0 ) >>> >>> 0x000000ae: TAG_member [10] >>> AT_name( "f" ) >>> AT_type( {0x000000bd} ( float ) ) >>> AT_decl_file( "/private/tmp/main.c" ) >>> AT_decl_line( 3 ) >>> AT_data_member_location( +4 ) >>> >>> 0x000000bc: NULL >>> >>> 0x000000bd: TAG_base_type [6] >>> AT_name( "float" ) >>> AT_encoding( DW_ATE_float ) >>> AT_byte_size( 0x04 ) >>> >>> 0x000000c4: NULL >>> >>> >>> Note that the typedef is at 0x00000091, and it is a typedef to 0x0000009c. >>> Also note that the DWARF DIE at 0x0000009c is a complete definition as it >>> has children describing its members and 0x0000009c doesn't have a >>> DW_AT_declaration(1) attribute. Is this how your DWARF looks for your >>> stuff? The DWARF you had looked like: >>> >>> 0x0000005c: DW_TAG_typedef [6] >>> DW_AT_name( "my_untagged_struct" ) >>> DW_AT_decl_file("/home/luke/main.cpp") >>> DW_AT_decl_line(4) >>> DW_AT_type({0x0000002d}) >>> >>> >>> What did the type at 0x0000002d look like? Similar to 0x0000009c in my >>> DWARF I presume? >> >> In the case of C89/C99, yes, but regrettably when you compile my example as >> C++ or use __attribute__((overloadable)) the DWARF does not include the >> DW_AT_name for the typedef in the formal parameter[0] of myfunc >> >> COMPILE_UNIT<header overall offset = 0x00000000>: >> < 0><0x0000000b> DW_TAG_compile_unit >> DW_AT_producer "GNU C++ 4.8.4 -mtune=generic >> -march=x86-64 -g -fstack-protector" >> DW_AT_language DW_LANG_C_plus_plus >> DW_AT_name "main.cpp" >> DW_AT_comp_dir "/tmp" >> DW_AT_low_pc 0x004004ed >> DW_AT_high_pc <offset-from-lowpc>60 >> DW_AT_stmt_list 0x00000000 >> >> LOCAL_SYMBOLS: >> < 1><0x0000002d> DW_TAG_structure_type >> DW_AT_byte_size 0x00000008 >> DW_AT_decl_file 0x00000001 /tmp/main.cpp >> DW_AT_decl_line 0x00000001 >> DW_AT_linkage_name "18my_untagged_struct" >> DW_AT_sibling <0x0000004e> >> < 2><0x00000039> DW_TAG_member >> DW_AT_name "i" >> DW_AT_decl_file 0x00000001 /tmp/main.cpp >> DW_AT_decl_line 0x00000002 >> DW_AT_type <0x0000004e> >> DW_AT_data_member_location 0 >> < 2><0x00000043> DW_TAG_member >> DW_AT_name "f" >> DW_AT_decl_file 0x00000001 /tmp/main.cpp >> DW_AT_decl_line 0x00000003 >> DW_AT_type <0x00000055> >> DW_AT_data_member_location 4 >> < 1><0x0000004e> DW_TAG_base_type >> DW_AT_byte_size 0x00000004 >> DW_AT_encoding DW_ATE_signed >> DW_AT_name "int" >> < 1><0x00000055> DW_TAG_base_type >> DW_AT_byte_size 0x00000004 >> DW_AT_encoding DW_ATE_float >> DW_AT_name "float" >> < 1><0x0000005c> DW_TAG_typedef >> DW_AT_name "my_untagged_struct" >> DW_AT_decl_file 0x00000001 /tmp/main.cpp >> DW_AT_decl_line 0x00000004 >> DW_AT_type <0x0000002d> >> < 1><0x00000067> DW_TAG_subprogram >> DW_AT_external yes(1) >> DW_AT_name "myfunc" >> DW_AT_decl_file 0x00000001 /tmp/main.cpp >> DW_AT_decl_line 0x00000006 >> DW_AT_linkage_name "_Z6myfuncP18my_untagged_struct" >> DW_AT_low_pc 0x004004ed >> DW_AT_high_pc <offset-from-lowpc>33 >> DW_AT_frame_base len 0x0001: 9c: >> DW_OP_call_frame_cfa >> DW_AT_GNU_all_call_sites yes(1) >> DW_AT_sibling <0x00000095> >> < 2><0x00000088> DW_TAG_formal_parameter >> DW_AT_name "s" >> DW_AT_decl_file 0x00000001 /tmp/main.cpp >> DW_AT_decl_line 0x00000006 >> DW_AT_type <0x00000095> >> DW_AT_location len 0x0002: 9168: >> DW_OP_fbreg -24 >> < 1><0x00000095> DW_TAG_pointer_type >> DW_AT_byte_size 0x00000008 >> DW_AT_type <0x0000005c> >> < 1><0x0000009b> DW_TAG_subprogram >> DW_AT_external yes(1) >> DW_AT_name "main" >> DW_AT_decl_file 0x00000001 /tmp/main.cpp >> DW_AT_decl_line 0x0000000c >> DW_AT_type <0x0000004e> >> DW_AT_low_pc 0x0040050e >> DW_AT_high_pc <offset-from-lowpc>27 >> DW_AT_frame_base len 0x0001: 9c: >> DW_OP_call_frame_cfa >> DW_AT_GNU_all_tail_call_sitesyes(1) >> < 2><0x000000b8> DW_TAG_lexical_block >> DW_AT_low_pc 0x00400516 >> DW_AT_high_pc <offset-from-lowpc>17 >> < 3><0x000000c9> DW_TAG_variable >> DW_AT_name "s" >> DW_AT_decl_file 0x00000001 /tmp/main.cpp >> DW_AT_decl_line 0x0000000e >> DW_AT_type <0x0000005c> >> DW_AT_location len 0x0002: 9160: >> DW_OP_fbreg -32 >> >> >>> >>> The DWARFASTParserClang class is responsible for making up a clang type in >>> the clang::ASTContext for this typedef. What will happen in the code where >>> the flow falls through is the we will make a lldb_private::Type that says >>> "I am a typedef to type whose user ID is 0x0000002d (in your example)". A >>> NULL pointer should not be returned from the >>> DWARFASTParserClang::ParseTypeFromDWARF() function. If it is, please step >>> through and figure out why. I compiled your example and did the following: >>> >>> >>> % lldb a.out >>> (lldb) b main >>> (lldb) r >>> Process 89808 launched: '/private/tmp/a.out' (x86_64) >>> Process 89808 stopped >>> * thread #1: tid = 0xf7473, 0x0000000100000fa3 a.out main + 19, stop reason >>> = breakpoint 1.1, queue = com.apple.main-thread >>> frame #0: 0x0000000100000fa3 a.out main + 19 at main.c:15 >>> 12 int main() >>> 13 { >>> 14 my_untagged_struct s; >>> -> 15 myfunc(&s); >>> 16 return 0; >>> 17 } >>> (lldb) p myfunc(&s) >>> (lldb) >>> >>> So I was able to call this function. Are you not able to call it? >> >> I tried compiling with standard C99, and as you note, this works fine; >> however, C++ fails: >> >> $ lldb a.out -o 'b 15' -o 'process launch' >> (lldb) target create "a.out" >> Current executable set to 'a.out' (x86_64). >> (lldb) b 15 >> Breakpoint 1: where = a.out`main + 8 at main.cpp:15, address = >> 0x0000000000400516 >> (lldb) process launch >> Process 18718 stopped >> * thread #1: tid = 18718, 0x0000000000400516 a.out`main + 8 at main.cpp:15, >> name = 'a.out', stop reason = breakpoint 1.1 >> frame #0: 0x0000000000400516 a.out`main + 8 at main.cpp:15 >> >> Process 18718 launched: '/tmp/a.out' (x86_64) >> (lldb) expr myfunc(&s) >> error: Couldn't lookup symbols: >> myfunc($_0*) >> (lldb) >> >> >>> >>> Likewise if I step into this function I can see the variable: >>> >>> (lldb) s >>> (lldb) fr var s >>> (my_untagged_struct *) s = 0x00007fff5fbff8d0 >>> (lldb) fr var *s >>> (my_untagged_struct) *s = (i = 0, f = 3.1400001) >> >> This does indeed seem to work >> >> (lldb) s >> Process 18769 stopped >> * thread #1: tid = 18769, 0x00000000004004f5 >> a.out`myfunc(s=0x00007fffffffe2b0) + 8 at main.cpp:8, name = 'a.out', stop >> reason = step in >> frame #0: 0x00000000004004f5 a.out`myfunc(s=0x00007fffffffe2b0) + 8 at >> main.cpp:8 >> (lldb) fr var s >> (my_untagged_struct *) s = 0x00007fffffffe2b0 >> (lldb) fr var *s >> (my_untagged_struct) *s = (i = -7264, f = >> 0.0000000000000000000000000000000000000000459163468) >> (lldb) >> >>> >>> So to sum up: when we parse the DW_TAG_typedef in >>> DWARFASTParserClang::ParseTypeFromDWARF(), we should return a valid TypeSP >>> that contains a valid pointer. If that isn't happening, that is a bug. Feel >>> free to send me the example binary and I can figure things out if you have >>> any trouble. I wrote all of this code so I am quite familiar with it. >>> >> >> I've confirmed you're absolutely right about returning a non-null TypeSP >> after fallthrough in DWARFASTParserClang::ParseTypeFromDWARF, but it seems >> that with an empty name it doesn't allow clang to resolve the type, failing >> to locate mangled function as the typename is wrong (_Z6myfuncP3$_0). >> >> A colleague took a look at this today, and as a quick sanity test, threw >> together this hack: >> >> --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp >> +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp >> @@ -553,6 +553,19 @@ DWARFASTParserClang::ParseTypeFromDWARF (const >> SymbolContext& sc, >> } >> } >> >> + { >> + uint32_t list_size = type_list->GetSize(); >> + for (uint32_t i = 0; i < list_size; ++i) >> + { >> + TypeSP t = type_list->GetTypeAtIndex(i); >> + if (t->IsTypedef()) >> + { >> + type_name_const_str = t->GetName(); >> + type_name_cstr = t->GetName().AsCString(); >> + } >> + } >> + } >> >> >> It seems to fix our problem here and expression evaluation works again for >> the presented case, but unfortunately, a few other tests break, which is a >> little frustrating. If you have time to take another look at why this might >> be the case, it'd be very much appreciated. >> >> I've attached an example Mac binary of this issue in action built with an >> older Apple clang++, (it's simply the test above) but the result is the same >> for me on Linux with upstream clang++ and g++5.3, so I don't think the age >> of the compiler is a problem here. >> >> Thanks again >> >> Luke >> >>> Greg Clayton >>> >>> >>>> On Mar 9, 2016, at 3:54 PM, luke Drummond via lldb-dev >>>> <lldb-dev@lists.llvm.org> wrote: >>>> >>>> Hi All >>>> >>>> I'm hoping that someone might be able to give me some direction >>>> regarding `Type` resolution from DWARF informationfor functions taking >>>> anonymous structs hidden behind a typedef >>>> >>>> e.g. >>>> >>>> ``` >>>> typedef struct { >>>> int i; >>>> float f; >>>> } my_untagged_struct; >>>> >>>> void __attribute__((noinline)) myfunc(my_untagged_struct *s) >>>> { >>>> s->i = 0; >>>> s->f = 3.14f; >>>> } >>>> >>>> int main() >>>> { >>>> my_untagged_struct s; >>>> myfunc(&s); >>>> return 0; >>>> } >>>> >>>> ``` >>>> >>>> I [recently reported a >>>> bug](https://llvm.org/bugs/show_bug.cgi?id=26790) relating to the >>>> clang expression evaluator no longer being able to resolve calls to >>>> functions with arguments to typedefed anonymous structs, after a cleanup >>>> to the expression parsing code. >>>> I was perfectly wrong in my assumptions about the cause of the bug, and >>>> after some more digging, I think I've tracked it down to a section of >>>> code in `DWARFASTParserClang::ParseTypeFromDWARF`. >>>> >>>> >>>> (DWARFASTParserClang::ParseTypeFromDwarf:254) >>>> ``` >>>> switch (tag) >>>> { >>>> case DW_TAG_typedef: >>>> // Try to parse a typedef from the DWO file first as modules >>>> // can contain typedef'ed structures that have no names like: >>>> // >>>> // typedef struct { int a; } Foo; >>>> // >>>> // In this case we will have a structure with no name and a >>>> // typedef named "Foo" that points to this unnamed structure. >>>> // The name in the typedef is the only identifier for the >>>> struct, // so always try to get typedefs from DWO files if possible. >>>> // >>>> // The type_sp returned will be empty if the typedef doesn't >>>> exist // in a DWO file, so it is cheap to call this function just to >>>> check. // >>>> // If we don't do this we end up creating a TypeSP that says >>>> this // is a typedef to type 0x123 (the DW_AT_type value would be 0x123 >>>> // in the DW_TAG_typedef), and this is the unnamed structure >>>> type. // We will have a hard time tracking down an unnammed structure >>>> // type in the module DWO file, so we make sure we don't get >>>> into // this situation by always resolving typedefs from the DWO file. >>>> type_sp = ParseTypeFromDWO(die, log); >>>> if (type_sp) >>>> return type_sp; >>>> LLVM_FALLTHROUGH >>>> ``` >>>> >>>> In my case, the type information for the typedef is included within the >>>> main executable's DWARF rather than an external .dwo file (snippet from >>>> the DWARF included the end of this message), and therefore the `case` >>>> for `DW_TAG_typedef` falls through as `ParseTypeFromDWO` returns a NULL >>>> value. >>>> >>>> >>>> As this is code I'm not familiar with, I'd appreciate if any one on the >>>> list was able to give some guidance as to the best way to resolve this >>>> issue, so that `ClangExpressionDeclMap::FindExternalVisibleDecls` can >>>> correctly resolve calls to functions taking typedef names to anonymous >>>> structs. I'm happy to take a whack at implementing this feature, but >>>> I'm a bit stuck as to how to resolve this type given the current DIE >>>> object. >>>> >>>> Any help or guidance on where to start with this would be really >>>> helpful. >>>> >>>> All the best >>>> >>>> Luke >>>> >>>> >>>> >>>> >>>> -------- >>>> This is a snippet from the output of llvm-dwarfdump on the above code >>>> example. >>>> >>>> `g++ -g main.cpp && llvm-dwarfdump a.out | grep DW_TAG_typedef -A 35` >>>> -------- >>>> >>>> 0x0000005c: DW_TAG_typedef [6] >>>> DW_AT_name [DW_FORM_strp] >>>> ( .debug_str[0x00000069] = "my_untagged_struct") DW_AT_decl_file >>>> [DW_FORM_data1] ("/home/luke/main.cpp") DW_AT_decl_line >>>> [DW_FORM_data1] (4) DW_AT_type [DW_FORM_ref4] (cu + >>>> 0x002d => {0x0000002d}) >>>> >>>> 0x00000067: DW_TAG_subprogram [7] * >>>> DW_AT_external [DW_FORM_flag_present] (true) >>>> DW_AT_name [DW_FORM_strp] >>>> ( .debug_str[0x00000006] = "myfunc") DW_AT_decl_file >>>> [DW_FORM_data1] ("/home/luke/main.cpp") DW_AT_decl_line >>>> [DW_FORM_data1] (6) DW_AT_linkage_name [DW_FORM_strp] >>>> ( .debug_str[0x0000005d] = "_Z6myfuncP18my_untagged_struct") >>>> DW_AT_low_pc [DW_FORM_addr] (0x0000000000400566) DW_AT_high_pc >>>> [DW_FORM_data8] (0x0000000000000026) DW_AT_frame_base >>>> [DW_FORM_exprloc] (<0x1> 9c ) DW_AT_Unknown_2117 >>>> [DW_FORM_flag_present] (true) DW_AT_sibling >>>> [DW_FORM_ref4] (cu + 0x0095 => {0x00000095}) >>>> >>>> 0x00000088: DW_TAG_formal_parameter [8] >>>> DW_AT_name [DW_FORM_string] ("s") >>>> DW_AT_decl_file [DW_FORM_data1] >>>> ("/home/luke/main.cpp") DW_AT_decl_line [DW_FORM_data1] (6) >>>> DW_AT_type [DW_FORM_ref4] (cu + 0x0095 => >>>> {0x00000095}) DW_AT_location [DW_FORM_exprloc] (<0x2> 91 68 ) >>>> >>>> 0x00000094: NULL >>>> >>>> 0x00000095: DW_TAG_pointer_type [9] >>>> DW_AT_byte_size [DW_FORM_data1] (0x08) >>>> DW_AT_type [DW_FORM_ref4] (cu + 0x005c => >>>> {0x0000005c}) >>>> >>>> _______________________________________________ >>>> lldb-dev mailing list >>>> lldb-dev@lists.llvm.org >>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev >>> >> <mac-expr-anon-struct-example.tar.gz> > > _______________________________________________ > lldb-dev mailing list > lldb-dev@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev _______________________________________________ lldb-dev mailing list lldb-dev@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev