Fixed a problem where we couldn't call extern "C" functions.

Some compilers do not mark up C++ functions as extern "C" in the DWARF, so LLDB
has to fall back (if it is about to give up finding a symbol) to using the base
name of the function.

This fix also ensures that we search by full name rather than "auto," which
could cause unrelated C++ names to be found.  Finally, it adds a test case.

<rdar://problem/25094302>

llvm-svn: 271551
This commit is contained in:
Sean Callanan 2016-06-02 17:59:47 +00:00
parent b9c80fd8b5
commit 34ab28a470
5 changed files with 79 additions and 1 deletions

View File

@ -294,6 +294,10 @@ private:
const std::vector<SearchSpec> &C_specs,
const SymbolContext &sc);
void
CollectFallbackNames(std::vector<SearchSpec> &fallback_specs,
const std::vector<SearchSpec> &C_specs);
lldb::addr_t
FindInSymbols(const std::vector<SearchSpec> &specs,
const lldb_private::SymbolContext &sc);

View File

@ -0,0 +1,3 @@
LEVEL = ../../../make
C_SOURCES := main.c
include $(LEVEL)/Makefile.rules

View File

@ -0,0 +1,4 @@
from lldbsuite.test import lldbinline
from lldbsuite.test import decorators
lldbinline.MakeInlineTest(__file__, globals(), [])

View File

@ -0,0 +1,29 @@
//===-- main.cpp ------------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <stdio.h>
#include <stdint.h>
extern "C"
{
int foo();
};
int foo()
{
puts("foo");
return 2;
}
int main (int argc, char const *argv[], char const *envp[])
{
foo();
return 0; //% self.expect("expression -- foo()", substrs = ['2'])
}

View File

@ -758,7 +758,7 @@ struct IRExecutionUnit::SearchSpec
ConstString name;
uint32_t mask;
SearchSpec(ConstString n, uint32_t m = lldb::eFunctionNameTypeAuto) :
SearchSpec(ConstString n, uint32_t m = lldb::eFunctionNameTypeFull) :
name(n),
mask(m)
{
@ -819,6 +819,36 @@ IRExecutionUnit::CollectCandidateCPlusPlusNames(std::vector<IRExecutionUnit::Sea
}
}
void
IRExecutionUnit::CollectFallbackNames(std::vector<SearchSpec> &fallback_specs,
const std::vector<SearchSpec> &C_specs)
{
// As a last-ditch fallback, try the base name for C++ names. It's terrible,
// but the DWARF doesn't always encode "extern C" correctly.
for (const SearchSpec &C_spec : C_specs)
{
const ConstString &name = C_spec.name;
if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString()))
{
Mangled mangled_name(name);
ConstString demangled_name = mangled_name.GetDemangledName(lldb::eLanguageTypeC_plus_plus);
if (!demangled_name.IsEmpty())
{
const char *demangled_cstr = demangled_name.AsCString();
const char *lparen_loc = strchr(demangled_cstr, '(');
if (lparen_loc)
{
llvm::StringRef base_name(demangled_cstr, lparen_loc-demangled_cstr);
fallback_specs.push_back(ConstString(base_name));
}
}
}
}
}
lldb::addr_t
IRExecutionUnit::FindInSymbols(const std::vector<IRExecutionUnit::SearchSpec> &specs, const lldb_private::SymbolContext &sc)
{
@ -1019,6 +1049,14 @@ IRExecutionUnit::FindSymbol(const lldb_private::ConstString &name)
CollectCandidateCPlusPlusNames(candidate_CPlusPlus_names, candidate_C_names, m_sym_ctx);
ret = FindInSymbols(candidate_CPlusPlus_names, m_sym_ctx);
}
if (ret == LLDB_INVALID_ADDRESS)
{
std::vector<SearchSpec> candidate_fallback_names;
CollectFallbackNames(candidate_fallback_names, candidate_C_names);
ret = FindInSymbols(candidate_fallback_names, m_sym_ctx);
}
return ret;
}