Vendor import of lldb trunk r303291:
https://llvm.org/svn/llvm-project/lldb/trunk@303291
This commit is contained in:
parent
b76161e41b
commit
5a5de6ea39
@ -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;
|
||||
|
@ -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
|
@ -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 $@
|
@ -0,0 +1,6 @@
|
||||
#include "One.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void one() {
|
||||
printf("One\n"); // break here
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
#ifndef ONE_H
|
||||
#define ONE_H
|
||||
void one();
|
||||
#endif
|
@ -0,0 +1 @@
|
||||
int __attribute__ ((visibility("hidden"))) conflicting_symbol = 11111;
|
@ -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"])
|
@ -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 $@
|
@ -0,0 +1,6 @@
|
||||
#include "Two.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void two() {
|
||||
printf("Two\n"); // break here
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
#ifndef TWO_H
|
||||
#define TWO_H
|
||||
void two();
|
||||
#endif
|
@ -0,0 +1 @@
|
||||
int __attribute__ ((visibility("hidden"))) conflicting_symbol = 22222;
|
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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())
|
||||
|
@ -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());
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user