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

Greg

> On Apr 9, 2015, at 10:20 AM, Ilia K <[email protected]> wrote:
> 
> Hello @clayborg,
> 
> The same thing on my Linux machine:
> 
>  1: test_with_dwarf_and_run_command 
> (TestDataFormatterSynthVal.DataFormatterSynthValueTestCase)
>     Test using Python synthetic children provider to provide a value. ... 
> (myInt) x = 3
>  (myInt) x = 3
>  error: call to a function 'myInt::myInt(int)' ('_ZN5myIntC1Ei') that is not 
> present in the target
>  error: The expression could not be prepared to run in the target
>  FAILURE
> 
>  ======================================================================
>  FAIL: test_with_dwarf_and_run_command 
> (TestDataFormatterSynthVal.DataFormatterSynthValueTestCase)
>     Test using Python synthetic children provider to provide a value.
>  ----------------------------------------------------------------------
>  Traceback (most recent call last):
>    File 
> "/home/testuser/build/workspace/LLDB_master_release_Linux/llvm_master/tools/lldb/test/lldbtest.py",
>  line 696, in wrapper
>      func(*args, **kwargs)
>    File 
> "/home/testuser/build/workspace/LLDB_master_release_Linux/llvm_master/tools/lldb/test/lldbtest.py",
>  line 479, in wrapper
>      return func(self, *args, **kwargs)
>    File 
> "/home/testuser/build/workspace/LLDB_master_release_Linux/llvm_master/tools/lldb/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py",
>  line 27, in test_with_dwarf_and_run_command
>      self.data_formatter_commands()
>    File 
> "/home/testuser/build/workspace/LLDB_master_release_Linux/llvm_master/tools/lldb/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py",
>  line 92, in data_formatter_commands
>      self.expect("expression struct S { myInt theInt{12}; }; S()", substrs = 
> ['(theInt = 12)'])
>    File 
> "/home/testuser/build/workspace/LLDB_master_release_Linux/llvm_master/tools/lldb/test/lldbtest.py",
>  line 2108, in expect
>      self.runCmd(str, msg=msg, trace = (True if trace else False), check = 
> not error, inHistory=inHistory)
>    File 
> "/home/testuser/build/workspace/LLDB_master_release_Linux/llvm_master/tools/lldb/test/lldbtest.py",
>  line 2034, in runCmd
>      msg if msg else CMD_MSG(cmd))
>  AssertionError: False is not True : Command 'expression struct S { myInt 
> theInt{12}; }; S()' returns successfully
>  Config=x86_64-clang
>  ----------------------------------------------------------------------
> 
> and
> 
>  error: call to a function 'foo::foo(int)' ('_ZN3fooC1Ei') that is not 
> present in the target
>  error: The expression could not be prepared to run in the target
>  FAILURE
> 
>  ======================================================================
>  FAIL: test_with_dwarf (TestFormatters.ExprFormattersTestCase)
>     Test expr + formatters for good interoperability.
>  ----------------------------------------------------------------------
>  Traceback (most recent call last):
>    File 
> "/home/testuser/build/workspace/LLDB_master_release_Linux/llvm_master/tools/lldb/test/lldbtest.py",
>  line 543, in wrapper
>      func(*args, **kwargs)
>    File 
> "/home/testuser/build/workspace/LLDB_master_release_Linux/llvm_master/tools/lldb/test/lldbtest.py",
>  line 479, in wrapper
>      return func(self, *args, **kwargs)
>    File 
> "/home/testuser/build/workspace/LLDB_master_release_Linux/llvm_master/tools/lldb/test/expression_command/formatters/TestFormatters.py",
>  line 33, in test_with_dwarf
>      self.do_my_test()
>    File 
> "/home/testuser/build/workspace/LLDB_master_release_Linux/llvm_master/tools/lldb/test/expression_command/formatters/TestFormatters.py",
>  line 60, in do_my_test
>      substrs = ['(int) a = 47', '(bar) b = {', '(int) i = 94', '(baz) b = {', 
> '(int) k = 99'])
>    File 
> "/home/testuser/build/workspace/LLDB_master_release_Linux/llvm_master/tools/lldb/test/lldbtest.py",
>  line 2108, in expect
>      self.runCmd(str, msg=msg, trace = (True if trace else False), check = 
> not error, inHistory=inHistory)
>    File 
> "/home/testuser/build/workspace/LLDB_master_release_Linux/llvm_master/tools/lldb/test/lldbtest.py",
>  line 2034, in runCmd
>      msg if msg else CMD_MSG(cmd))
>  AssertionError: False is not True : Command 'expression --show-types -- 
> *(new foo(47))' returns successfully
>  Config=x86_64-clang
>  ----------------------------------------------------------------------
> 
> Thanks,
> Ilia
> 
> 
> USERS
>  tberghammer (Auditor)
>  ki.stfu (Auditor)
> 
> http://reviews.llvm.org/rL234178
> 
> EMAIL PREFERENCES
>  http://reviews.llvm.org/settings/panel/emailpreferences/
> 
> 


_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to