Vendor import of lldb trunk r303291:

https://llvm.org/svn/llvm-project/lldb/trunk@303291
This commit is contained in:
Dimitry Andric 2017-05-17 20:23:22 +00:00
parent b76161e41b
commit 5a5de6ea39
17 changed files with 360 additions and 121 deletions

View File

@ -235,6 +235,29 @@ class SymbolContext {
bool GetAddressRangeFromHereToEndLine(uint32_t end_line, AddressRange &range,
Status &error);
//------------------------------------------------------------------
/// Find the best global data symbol visible from this context.
///
/// Symbol priority is:
/// - extern symbol in the current module if there is one
/// - non-extern symbol in the current module if there is one
/// - extern symbol in the target
/// - non-extern symbol in the target
/// It is an error if the highest-priority result is ambiguous.
///
/// @param[in] name
/// The name of the symbol to search for.
///
/// @param[out] error
/// An error that will be populated with a message if there was an
/// ambiguous result. The error will not be populated if no result
/// was found.
///
/// @return
/// The symbol that was found, or \b nullptr if none was found.
//------------------------------------------------------------------
const Symbol *FindBestGlobalDataSymbol(const ConstString &name, Status &error);
void GetDescription(Stream *s, lldb::DescriptionLevel level,
Target *target) const;

View File

@ -0,0 +1,18 @@
LEVEL := ../../../make
LD_EXTRAS := -L. -l$(LIB_PREFIX)One -l$(LIB_PREFIX)Two
C_SOURCES := main.c
main.o : CFLAGS_EXTRAS += -g -O0
include $(LEVEL)/Makefile.rules
.PHONY:
a.out: lib_One lib_Two
lib_%:
$(MAKE) -f $*.mk
clean::
$(MAKE) -f One.mk clean
$(MAKE) -f Two.mk clean

View File

@ -0,0 +1,12 @@
LEVEL := ../../../make
DYLIB_NAME := One
DYLIB_C_SOURCES := One/One.c One/OneConstant.c
DYLIB_ONLY := YES
include $(LEVEL)/Makefile.rules
CFLAGS_EXTRAS += -fPIC
One/OneConstant.o: One/OneConstant.c
$(CC) $(CFLAGS_NO_DEBUG) -c $< -o $@

View File

@ -0,0 +1,6 @@
#include "One.h"
#include <stdio.h>
void one() {
printf("One\n"); // break here
}

View File

@ -0,0 +1,4 @@
#ifndef ONE_H
#define ONE_H
void one();
#endif

View File

@ -0,0 +1 @@
int __attribute__ ((visibility("hidden"))) conflicting_symbol = 11111;

View File

@ -0,0 +1,90 @@
"""Test that conflicting symbols in different shared libraries work correctly"""
from __future__ import print_function
import os
import time
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class TestConflictingSymbols(TestBase):
mydir = TestBase.compute_mydir(__file__)
NO_DEBUG_INFO_TESTCASE = True
def test_conflicting_symbols(self):
self.build()
exe = os.path.join(os.getcwd(), "a.out")
target = self.dbg.CreateTarget("a.out")
self.assertTrue(target, VALID_TARGET)
# Register our shared libraries for remote targets so they get
# automatically uploaded
environment = self.registerSharedLibrariesWithTarget(
target, ['One', 'Two'])
One_line = line_number('One/One.c', '// break here')
Two_line = line_number('Two/Two.c', '// break here')
main_line = line_number('main.c', '// break here')
lldbutil.run_break_set_command(
self, 'breakpoint set -f One.c -l %s' % (One_line))
lldbutil.run_break_set_command(
self, 'breakpoint set -f Two.c -l %s' % (Two_line))
lldbutil.run_break_set_by_file_and_line(
self, 'main.c', main_line, num_expected_locations=1, loc_exact=True)
process = target.LaunchSimple(
None, environment, self.get_process_working_directory())
self.assertTrue(process, PROCESS_IS_VALID)
# The stop reason of the thread should be breakpoint.
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
substrs=['stopped',
'stop reason = breakpoint'])
self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
substrs=[' resolved, hit count = 1'])
# This should display correctly.
self.expect(
"expr (unsigned long long)conflicting_symbol",
"Symbol from One should be found",
substrs=[
"11111"])
self.runCmd("continue", RUN_SUCCEEDED)
# The stop reason of the thread should be breakpoint.
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
substrs=['stopped',
'stop reason = breakpoint'])
self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
substrs=[' resolved, hit count = 1'])
self.expect(
"expr (unsigned long long)conflicting_symbol",
"Symbol from Two should be found",
substrs=[
"22222"])
self.runCmd("continue", RUN_SUCCEEDED)
# The stop reason of the thread should be breakpoint.
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
substrs=['stopped',
'stop reason = breakpoint'])
self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
substrs=[' resolved, hit count = 1'])
self.expect(
"expr (unsigned long long)conflicting_symbol",
"An error should be printed when symbols can't be ordered",
error=True,
substrs=[
"Multiple internal symbols"])

View File

@ -0,0 +1,12 @@
LEVEL := ../../../make
DYLIB_NAME := Two
DYLIB_C_SOURCES := Two/Two.c Two/TwoConstant.c
DYLIB_ONLY := YES
include $(LEVEL)/Makefile.rules
CFLAGS_EXTRAS += -fPIC
Two/TwoConstant.o: Two/TwoConstant.c
$(CC) $(CFLAGS_NO_DEBUG) -c $< -o $@

View File

@ -0,0 +1,6 @@
#include "Two.h"
#include <stdio.h>
void two() {
printf("Two\n"); // break here
}

View File

@ -0,0 +1,4 @@
#ifndef TWO_H
#define TWO_H
void two();
#endif

View File

@ -0,0 +1 @@
int __attribute__ ((visibility("hidden"))) conflicting_symbol = 22222;

View File

@ -0,0 +1,11 @@
#include "One/One.h"
#include "Two/Two.h"
#include <stdio.h>
int main() {
one();
two();
printf("main\n"); // break here
return(0);
}

View File

@ -1934,7 +1934,7 @@ def registerSharedLibrariesWithTarget(self, target, shlibs):
# "libFoo.dylib" or "libFoo.so", or "Foo.so" for "Foo.so" or "libFoo.so", or just a
# basename like "libFoo.so". So figure out which one it is and resolve the local copy
# of the shared library accordingly
if os.path.exists(name):
if os.path.isfile(name):
local_shlib_path = name # name is the full path to the local shared library
else:
# Check relative names

View File

@ -837,8 +837,8 @@ bool Breakpoint::AddName(llvm::StringRef new_name, Status &error) {
if (new_name.empty())
return false;
if (!BreakpointID::StringIsBreakpointName(new_name, error)) {
error.SetErrorStringWithFormat("input name \"%s\" not a breakpoint name.",
new_name);
error.SetErrorStringWithFormatv("input name \"{0}\" not a breakpoint name.",
new_name);
return false;
}
if (!error.Success())

View File

@ -591,103 +591,6 @@ addr_t ClangExpressionDeclMap::GetSymbolAddress(const ConstString &name,
symbol_type);
}
const Symbol *ClangExpressionDeclMap::FindGlobalDataSymbol(
Target &target, const ConstString &name, lldb_private::Module *module) {
SymbolContextList sc_list;
if (module)
module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list);
else
target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny,
sc_list);
const uint32_t matches = sc_list.GetSize();
for (uint32_t i = 0; i < matches; ++i) {
SymbolContext sym_ctx;
sc_list.GetContextAtIndex(i, sym_ctx);
if (sym_ctx.symbol) {
const Symbol *symbol = sym_ctx.symbol;
const Address sym_address = symbol->GetAddress();
if (sym_address.IsValid()) {
switch (symbol->GetType()) {
case eSymbolTypeData:
case eSymbolTypeRuntime:
case eSymbolTypeAbsolute:
case eSymbolTypeObjCClass:
case eSymbolTypeObjCMetaClass:
case eSymbolTypeObjCIVar:
if (symbol->GetDemangledNameIsSynthesized()) {
// If the demangled name was synthesized, then don't use it
// for expressions. Only let the symbol match if the mangled
// named matches for these symbols.
if (symbol->GetMangled().GetMangledName() != name)
break;
}
return symbol;
case eSymbolTypeReExported: {
ConstString reexport_name = symbol->GetReExportedSymbolName();
if (reexport_name) {
ModuleSP reexport_module_sp;
ModuleSpec reexport_module_spec;
reexport_module_spec.GetPlatformFileSpec() =
symbol->GetReExportedSymbolSharedLibrary();
if (reexport_module_spec.GetPlatformFileSpec()) {
reexport_module_sp =
target.GetImages().FindFirstModule(reexport_module_spec);
if (!reexport_module_sp) {
reexport_module_spec.GetPlatformFileSpec()
.GetDirectory()
.Clear();
reexport_module_sp =
target.GetImages().FindFirstModule(reexport_module_spec);
}
}
// Don't allow us to try and resolve a re-exported symbol if it is
// the same
// as the current symbol
if (name == symbol->GetReExportedSymbolName() &&
module == reexport_module_sp.get())
return NULL;
return FindGlobalDataSymbol(target,
symbol->GetReExportedSymbolName(),
reexport_module_sp.get());
}
} break;
case eSymbolTypeCode: // We already lookup functions elsewhere
case eSymbolTypeVariable:
case eSymbolTypeLocal:
case eSymbolTypeParam:
case eSymbolTypeTrampoline:
case eSymbolTypeInvalid:
case eSymbolTypeException:
case eSymbolTypeSourceFile:
case eSymbolTypeHeaderFile:
case eSymbolTypeObjectFile:
case eSymbolTypeCommonBlock:
case eSymbolTypeBlock:
case eSymbolTypeVariableType:
case eSymbolTypeLineEntry:
case eSymbolTypeLineHeader:
case eSymbolTypeScopeBegin:
case eSymbolTypeScopeEnd:
case eSymbolTypeAdditional:
case eSymbolTypeCompiler:
case eSymbolTypeInstrumentation:
case eSymbolTypeUndefined:
case eSymbolTypeResolver:
break;
}
}
}
}
return NULL;
}
lldb::VariableSP ClangExpressionDeclMap::FindGlobalVariable(
Target &target, ModuleSP &module, const ConstString &name,
CompilerDeclContext *namespace_decl, TypeFromUser *type) {
@ -1526,9 +1429,18 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
// We couldn't find a non-symbol variable for this. Now we'll hunt for
// a generic
// data symbol, and -- if it is found -- treat it as a variable.
const Symbol *data_symbol = FindGlobalDataSymbol(*target, name);
Status error;
const Symbol *data_symbol =
m_parser_vars->m_sym_ctx.FindBestGlobalDataSymbol(name, error);
if (!error.Success()) {
const unsigned diag_id =
m_ast_context->getDiagnostics().getCustomDiagID(
clang::DiagnosticsEngine::Level::Error, "%0");
m_ast_context->getDiagnostics().Report(diag_id) << error.AsCString();
}
if (data_symbol) {
std::string warning("got name from symbols: ");
warning.append(name.AsCString());

View File

@ -447,24 +447,6 @@ class ClangExpressionDeclMap : public ClangASTSource {
//----------------------------------------------------------------------
uint64_t GetParserID() { return (uint64_t) this; }
//------------------------------------------------------------------
/// Given a target, find a data symbol that has the given name.
///
/// @param[in] target
/// The target to use as the basis for the search.
///
/// @param[in] name
/// The name as a plain C string.
///
/// @param[in] module
/// The module to limit the search to. This can be NULL
///
/// @return
/// The LLDB Symbol found, or NULL if none was found.
//------------------------------------------------------------------
const Symbol *FindGlobalDataSymbol(Target &target, const ConstString &name,
Module *module = NULL);
//------------------------------------------------------------------
/// Given a target, find a variable that matches the given name and
/// type.

View File

@ -799,6 +799,163 @@ bool SymbolContext::GetAddressRangeFromHereToEndLine(uint32_t end_line,
return true;
}
const Symbol *
SymbolContext::FindBestGlobalDataSymbol(const ConstString &name, Status &error) {
error.Clear();
if (!target_sp) {
return nullptr;
}
Target &target = *target_sp;
Module *module = module_sp.get();
auto ProcessMatches = [this, &name, &target, module]
(SymbolContextList &sc_list, Status &error) -> const Symbol* {
llvm::SmallVector<const Symbol *, 1> external_symbols;
llvm::SmallVector<const Symbol *, 1> internal_symbols;
const uint32_t matches = sc_list.GetSize();
for (uint32_t i = 0; i < matches; ++i) {
SymbolContext sym_ctx;
sc_list.GetContextAtIndex(i, sym_ctx);
if (sym_ctx.symbol) {
const Symbol *symbol = sym_ctx.symbol;
const Address sym_address = symbol->GetAddress();
if (sym_address.IsValid()) {
switch (symbol->GetType()) {
case eSymbolTypeData:
case eSymbolTypeRuntime:
case eSymbolTypeAbsolute:
case eSymbolTypeObjCClass:
case eSymbolTypeObjCMetaClass:
case eSymbolTypeObjCIVar:
if (symbol->GetDemangledNameIsSynthesized()) {
// If the demangled name was synthesized, then don't use it
// for expressions. Only let the symbol match if the mangled
// named matches for these symbols.
if (symbol->GetMangled().GetMangledName() != name)
break;
}
if (symbol->IsExternal()) {
external_symbols.push_back(symbol);
} else {
internal_symbols.push_back(symbol);
}
break;
case eSymbolTypeReExported: {
ConstString reexport_name = symbol->GetReExportedSymbolName();
if (reexport_name) {
ModuleSP reexport_module_sp;
ModuleSpec reexport_module_spec;
reexport_module_spec.GetPlatformFileSpec() =
symbol->GetReExportedSymbolSharedLibrary();
if (reexport_module_spec.GetPlatformFileSpec()) {
reexport_module_sp =
target.GetImages().FindFirstModule(reexport_module_spec);
if (!reexport_module_sp) {
reexport_module_spec.GetPlatformFileSpec()
.GetDirectory()
.Clear();
reexport_module_sp =
target.GetImages().FindFirstModule(reexport_module_spec);
}
}
// Don't allow us to try and resolve a re-exported symbol if it is
// the same as the current symbol
if (name == symbol->GetReExportedSymbolName() &&
module == reexport_module_sp.get())
return nullptr;
return FindBestGlobalDataSymbol(
symbol->GetReExportedSymbolName(), error);
}
} break;
case eSymbolTypeCode: // We already lookup functions elsewhere
case eSymbolTypeVariable:
case eSymbolTypeLocal:
case eSymbolTypeParam:
case eSymbolTypeTrampoline:
case eSymbolTypeInvalid:
case eSymbolTypeException:
case eSymbolTypeSourceFile:
case eSymbolTypeHeaderFile:
case eSymbolTypeObjectFile:
case eSymbolTypeCommonBlock:
case eSymbolTypeBlock:
case eSymbolTypeVariableType:
case eSymbolTypeLineEntry:
case eSymbolTypeLineHeader:
case eSymbolTypeScopeBegin:
case eSymbolTypeScopeEnd:
case eSymbolTypeAdditional:
case eSymbolTypeCompiler:
case eSymbolTypeInstrumentation:
case eSymbolTypeUndefined:
case eSymbolTypeResolver:
break;
}
}
}
}
if (external_symbols.size() > 1) {
StreamString ss;
ss.Printf("Multiple external symbols found for '%s'\n", name.AsCString());
for (const Symbol *symbol : external_symbols) {
symbol->GetDescription(&ss, eDescriptionLevelFull, &target);
}
ss.PutChar('\n');
error.SetErrorString(ss.GetData());
return nullptr;
} else if (external_symbols.size()) {
return external_symbols[0];
} else if (internal_symbols.size() > 1) {
StreamString ss;
ss.Printf("Multiple internal symbols found for '%s'\n", name.AsCString());
for (const Symbol *symbol : internal_symbols) {
symbol->GetDescription(&ss, eDescriptionLevelVerbose, &target);
ss.PutChar('\n');
}
error.SetErrorString(ss.GetData());
return nullptr;
} else if (internal_symbols.size()) {
return internal_symbols[0];
} else {
return nullptr;
}
};
if (module) {
SymbolContextList sc_list;
module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list);
const Symbol *const module_symbol = ProcessMatches(sc_list, error);
if (!error.Success()) {
return nullptr;
} else if (module_symbol) {
return module_symbol;
}
}
{
SymbolContextList sc_list;
target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny,
sc_list);
const Symbol *const target_symbol = ProcessMatches(sc_list, error);
if (!error.Success()) {
return nullptr;
} else if (target_symbol) {
return target_symbol;
}
}
return nullptr; // no error; we just didn't find anything
}
//----------------------------------------------------------------------
//
// SymbolContextSpecifier