[Lldb-commits] [Diffusion] rL234178: We have an issue where if you use a C function right now that has no prototype…

Greg Clayton clayborg at gmail.com
Thu Apr 9 11:28:05 PDT 2015


Siva: You will need to forward this to the clang lists to see if this is a correct fix.

> On Apr 9, 2015, at 11:16 AM, Siva Chandra <sivachandra at google.com> wrote:
> 
> Hi all,
> 
> I do not have anything concrete. However, the attached patch for clang
> fixes both the failing tests. I do not know if my fix is correct. Even
> if it is, we should find a way to "workaround" in LLDB so that older
> versions of clang are OK. I have some ideas for this, will share when
> I am able to put them into concrete words.
> 
> Thanks,
> Siva Chandra
> 
> On Thu, Apr 9, 2015 at 11:09 AM, Tamas Berghammer
> <tberghammer at google.com> wrote:
>> +sivachandra
>> 
>> Siva is looking into this issue. The problem is that lldb looks for a
>> mangled name _ZN3fooC1Ei while the object file (compiled by clang) contains
>> it with _ZN3fooC2Ei. The difference is that the first one belongs to the
>> complete constructor and the second one belongs to the base constructor.
>> 
>> On Thu, Apr 9, 2015 at 7:05 PM, Ilia K <ki.stfu at gmail.com> wrote:
>>> 
>>> @clayborg wrote:
>>> 
>>>> This probably fails after my recent change to
>>>> ClangExpressionDeclMap::GetFunctionAddress() from revision 234178.
>>> 
>>>> 
>>> 
>>>> The problem was that you might have an expression like:
>>> 
>>>> 
>>> 
>>>> (lldb) p (int)printf("%i\n", 123)
>>> 
>>>> 
>>> 
>>>> And we would mangle printf as a C++ function and get "_Z...printf..."
>>>> which of course doesn't exist as a mangled name. Prior to my fix, this
>>>> function would always do:
>>> 
>>>> 
>>> 
>>>>  Mangled mangled(name, is_mangled);
>>> 
>>>> 
>>> 
>>>>  CPPLanguageRuntime::MethodName
>>>> method_name(mangled.GetDemangledName());
>>> 
>>>> 
>>> 
>>>>  llvm::StringRef basename = method_name.GetBasename();
>>> 
>>>> 
>>> 
>>>>  if (!basename.empty())
>>> 
>>>>  {
>>> 
>>>>      FindCodeSymbolInContext(ConstString(basename),
>>>> m_parser_vars->m_sym_ctx, sc_list);
>>> 
>>>>      sc_list_size = sc_list.GetSize();
>>> 
>>>>  }
>>> 
>>>> 
>>> 
>>>> This is just plain wrong. It needs to be:
>>> 
>>>> 
>>> 
>>>>  Mangled mangled(name, is_mangled);
>>> 
>>>> 
>>> 
>>>>  CPPLanguageRuntime::MethodName
>>>> method_name(mangled.GetDemangledName());
>>> 
>>>> 
>>> 
>>>>  // the C++ context must be empty before we can think of searching for
>>>> symbol by a simple basename
>>> 
>>>>  if (method_name.GetContext().empty())
>>> 
>>>>  {
>>> 
>>>>      llvm::StringRef basename = method_name.GetBasename();
>>> 
>>>> 
>>> 
>>>>      if (!basename.empty())
>>> 
>>>>      {
>>> 
>>>>          FindCodeSymbolInContext(ConstString(basename),
>>>> m_parser_vars->m_sym_ctx, sc_list);
>>> 
>>>>          sc_list_size = sc_list.GetSize();
>>> 
>>>>      }
>>> 
>>>>  }
>>> 
>>>> 
>>> 
>>>> Note that we now check for the method's context (namespace and
>>>> containing classes) to be empty. So this works for "_Z...printf..." because
>>>> the context is empty and the basename is "printf".
>>> 
>>>> 
>>> 
>>>> The problem with ignoring if the context is empty is you can end up
>>>> getting some mangled name like:
>>> 
>>>> 
>>> 
>>>> _ZNSt3__16vectorIcNS_9allocatorIcEEEixEm
>>> 
>>>> 
>>> 
>>>> which demangles to:
>>> 
>>>> 
>>> 
>>>> std::__1::vector<char, std::__1::allocator<char> >::operator[](unsigned
>>>> long)
>>> 
>>>> 
>>> 
>>>> The "method_name.GetContext()" returns "std::__1::vector<char,
>>>> std::__1::allocator<char> >"
>>> 
>>>> and "method_name.GetBasename()" returns "operator[]"
>>> 
>>>> 
>>> 
>>>> Now if we don't check for the context being empty, we are happy to
>>>> accept _any_ function whose basename is "operator[]". So if the exact
>>>> mangled name is not in your program because you never used that function so
>>>> the template was never instantiated or used, then we will search for any
>>>> function whose basename is "operator[]" which will match
>>>> std::basic_string<char>::operator[] since all C++ standard libraries
>>>> explicitly instantiate std::string. So now your function would happily run
>>>> using the completely wrong function.
>>> 
>>>> 
>>> 
>>>> In your first case "myInt::myInt(int)" will give a context of "myInt"
>>>> and we won't try to lookup "myInt" by basename. So the bug here is that you
>>>> have no symbol for _ZN5myIntC1Ei in your executable's symbol table and you
>>>> probably should.
>>> 
>>>> 
>>> 
>>>> Same goes for "_ZN3fooC1Ei" which demangles to "foo::foo(int)".
>>> 
>>>> 
>>> 
>>>> If you have a class like:
>>> 
>>>> 
>>> 
>>>> template <class T>
>>> 
>>>> namespace my_stuff {
>>> 
>>>> 
>>> 
>>>>  class my_class {
>>> 
>>>>      static void foo();
>>> 
>>>>  }
>>> 
>>>> 
>>> 
>>>> }
>>> 
>>>> 
>>> 
>>>> Any you don't instantiate this template and yet you still have
>>>> "foo::foo(int) like the second example, you really don't want to have a call
>>>> to "my_stuff::my_class::foo()" actually fall "foo::foo()" because we grab
>>>> the basename from "my_stuff::my_class::foo()" and have it just call any
>>>> function whose basename if "foo".
>>> 
>>>> 
>>> 
>>>> So my fix needs to stay in and we need to figure out why there is no
>>>> symbol for constructors that are supposed to exist, or we need to change the
>>>> code so that those symbols do exist. I know constructors have "in charge"
>>>> and "not in charge" constructors and maybe the test case code only generates
>>>> on of them and then the expression tries to use the other?
>>> 
>>>> 
>>> 
>>>> Dump the symbol table of the "a.out" file and see what symbols it has.
>>>> That should tell us more. We will need to see the mangled names, so use the
>>>> following command:
>>> 
>>>> 
>>> 
>>>> (lldb) image dump symtab --show-mangled-names a.out
>>> 
>>> 
>>> The DataFormatterSynthValueTestCase.test_with_dwarf_and_run_command test
>>> declares a new struct type in run-time. It can't be in the object file :)
>>> 
>>>  self.expect("expression struct S { myInt theInt{12}; }; S()", substrs =
>>> ['(theInt = 12)'])
>>> 
>>> 
>>> USERS
>>>  tberghammer (Auditor)
>>>  ki.stfu (Auditor)
>>> 
>>> http://reviews.llvm.org/rL234178
>>> 
>>> EMAIL PREFERENCES
>>>  http://reviews.llvm.org/settings/panel/emailpreferences/
>>> 
>>> 
>> 
> <clang.patch>





More information about the lldb-commits mailing list