aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Core
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-12-09 13:28:42 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-12-09 13:28:42 +0000
commitb1c73532ee8997fe5dfbeb7d223027bdf99758a0 (patch)
tree7d6e51c294ab6719475d660217aa0c0ad0526292 /lldb/source/Core
parent7fa27ce4a07f19b07799a767fc29416f3b625afb (diff)
Diffstat (limited to 'lldb/source/Core')
-rw-r--r--lldb/source/Core/Address.cpp32
-rw-r--r--lldb/source/Core/CoreProperties.td26
-rw-r--r--lldb/source/Core/DataFileCache.cpp2
-rw-r--r--lldb/source/Core/Debugger.cpp62
-rw-r--r--lldb/source/Core/Disassembler.cpp17
-rw-r--r--lldb/source/Core/DumpDataExtractor.cpp15
-rw-r--r--lldb/source/Core/DynamicLoader.cpp54
-rw-r--r--lldb/source/Core/EmulateInstruction.cpp2
-rw-r--r--lldb/source/Core/FormatEntity.cpp27
-rw-r--r--lldb/source/Core/IOHandler.cpp52
-rw-r--r--lldb/source/Core/IOHandlerCursesGUI.cpp105
-rw-r--r--lldb/source/Core/Mangled.cpp23
-rw-r--r--lldb/source/Core/Module.cpp18
-rw-r--r--lldb/source/Core/ModuleList.cpp17
-rw-r--r--lldb/source/Core/PluginManager.cpp129
-rw-r--r--lldb/source/Core/Progress.cpp5
-rw-r--r--lldb/source/Core/SearchFilter.cpp32
-rw-r--r--lldb/source/Core/Section.cpp3
-rw-r--r--lldb/source/Core/StreamFile.cpp54
-rw-r--r--lldb/source/Core/ThreadedCommunication.cpp9
-rw-r--r--lldb/source/Core/UserSettingsController.cpp7
-rw-r--r--lldb/source/Core/Value.cpp8
-rw-r--r--lldb/source/Core/ValueObject.cpp76
-rw-r--r--lldb/source/Core/ValueObjectSyntheticFilter.cpp8
-rw-r--r--lldb/source/Core/ValueObjectVTable.cpp274
25 files changed, 787 insertions, 270 deletions
diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp
index 189d50fe962a..19d34db44ea5 100644
--- a/lldb/source/Core/Address.cpp
+++ b/lldb/source/Core/Address.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/Core/Address.h"
+#include "lldb/Core/Debugger.h"
#include "lldb/Core/Declaration.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Module.h"
@@ -28,6 +29,7 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
+#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
@@ -405,7 +407,7 @@ bool Address::GetDescription(Stream &s, Target &target,
bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
DumpStyle fallback_style, uint32_t addr_size,
- bool all_ranges) const {
+ bool all_ranges, llvm::StringRef pattern) const {
// If the section was nullptr, only load address is going to work unless we
// are trying to deref a pointer
SectionSP section_sp(GetSection());
@@ -501,7 +503,6 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
pointer_size = target->GetArchitecture().GetAddressByteSize();
else if (module_sp)
pointer_size = module_sp->GetArchitecture().GetAddressByteSize();
-
bool showed_info = false;
if (section_sp) {
SectionType sect_type = section_sp->GetType();
@@ -515,7 +516,16 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
if (symbol) {
const char *symbol_name = symbol->GetName().AsCString();
if (symbol_name) {
- s->PutCString(symbol_name);
+ llvm::StringRef ansi_prefix;
+ llvm::StringRef ansi_suffix;
+ if (target) {
+ ansi_prefix =
+ target->GetDebugger().GetRegexMatchAnsiPrefix();
+ ansi_suffix =
+ target->GetDebugger().GetRegexMatchAnsiSuffix();
+ }
+ s->PutCStringColorHighlighted(symbol_name, pattern,
+ ansi_prefix, ansi_suffix);
addr_t delta =
file_Addr - symbol->GetAddressRef().GetFileAddress();
if (delta)
@@ -643,7 +653,7 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
pointer_sc.symbol != nullptr) {
s->PutCString(": ");
pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false,
- false, true, true);
+ false, true, true, pattern);
}
}
}
@@ -682,19 +692,22 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
// address.
sc.DumpStopContext(s, exe_scope, *this, show_fullpaths,
show_module, show_inlined_frames,
- show_function_arguments, show_function_name);
+ show_function_arguments, show_function_name,
+ pattern);
} else {
// We found a symbol but it was in a different section so it
// isn't the symbol we should be showing, just show the section
// name + offset
- Dump(s, exe_scope, DumpStyleSectionNameOffset);
+ Dump(s, exe_scope, DumpStyleSectionNameOffset, DumpStyleInvalid,
+ UINT32_MAX, false, pattern);
}
}
}
}
} else {
if (fallback_style != DumpStyleInvalid)
- return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
+ return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size,
+ false, pattern);
return false;
}
break;
@@ -715,7 +728,7 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
sc.symbol->GetAddressRef().GetSection() != GetSection())
sc.symbol = nullptr;
}
- sc.GetDescription(s, eDescriptionLevelBrief, target);
+ sc.GetDescription(s, eDescriptionLevelBrief, target, pattern);
if (sc.block) {
bool can_create = true;
@@ -763,7 +776,8 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
}
} else {
if (fallback_style != DumpStyleInvalid)
- return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
+ return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size,
+ false, pattern);
return false;
}
break;
diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td
index 4287cb1fff02..8d81967bdb50 100644
--- a/lldb/source/Core/CoreProperties.td
+++ b/lldb/source/Core/CoreProperties.td
@@ -4,7 +4,7 @@ let Definition = "modulelist" in {
def EnableExternalLookup: Property<"enable-external-lookup", "Boolean">,
Global,
DefaultTrue,
- Desc<"Control the use of external tools and repositories to locate symbol files. Directories listed in target.debug-file-search-paths and directory of the executable are always checked first for separate debug info files. Then depending on this setting: On macOS, Spotlight would be also used to locate a matching .dSYM bundle based on the UUID of the executable. On NetBSD, directory /usr/libdata/debug would be also searched. On platforms other than NetBSD directory /usr/lib/debug would be also searched.">;
+ Desc<"Control the use of external tools and repositories to locate symbol files. Directories listed in target.debug-file-search-paths and directory of the executable are always checked first for separate debug info files. Then depending on this setting: On macOS, Spotlight would be also used to locate a matching .dSYM bundle based on the UUID of the executable. On NetBSD, directory /usr/libdata/debug would be also searched. On platforms other than NetBSD directory /usr/lib/debug would be also searched. If all other methods fail there may be symbol-locator plugins that, if configured properly, will also attempt to acquire symbols. The debuginfod plugin defaults to the DEGUFINFOD_URLS environment variable which is configurable through the 'plugin.symbol-locator.debuginfod.server_urls' setting.">;
def EnableBackgroundLookup: Property<"enable-background-lookup", "Boolean">,
Global,
DefaultFalse,
@@ -65,6 +65,14 @@ let Definition = "debugger" in {
DefaultEnumValue<"OptionValueString::eOptionEncodeCharacterEscapeSequences">,
DefaultStringValue<"(lldb) ">,
Desc<"The debugger command line prompt displayed for the user.">;
+ def PromptAnsiPrefix: Property<"prompt-ansi-prefix", "String">,
+ Global,
+ DefaultStringValue<"${ansi.faint}">,
+ Desc<"When in a color-enabled terminal, use the ANSI terminal code specified in this format immediately before the prompt.">;
+ def PromptAnsiSuffix: Property<"prompt-ansi-suffix", "String">,
+ Global,
+ DefaultStringValue<"${ansi.normal}">,
+ Desc<"When in a color-enabled terminal, use the ANSI terminal code specified in this format immediately after the prompt.">;
def ScriptLanguage: Property<"script-lang", "Enum">,
Global,
DefaultEnumValue<"eScriptLanguagePython">,
@@ -173,8 +181,8 @@ let Definition = "debugger" in {
Desc<"If true, LLDB will print the values of variables declared in an expression. Currently only supported in the REPL (default: true).">;
def TabSize: Property<"tab-size", "UInt64">,
Global,
- DefaultUnsignedValue<4>,
- Desc<"The tab size to use when indenting code in multi-line input mode (default: 4).">;
+ DefaultUnsignedValue<2>,
+ Desc<"The tab size to use when indenting code in multi-line input mode (default: 2).">;
def EscapeNonPrintables: Property<"escape-non-printables", "Boolean">,
Global,
DefaultTrue,
@@ -195,6 +203,18 @@ let Definition = "debugger" in {
Global,
DefaultStringValue<"${ansi.normal}">,
Desc<"When displaying suggestion in a color-enabled terminal, use the ANSI terminal code specified in this format immediately after the suggestion.">;
+ def ShowRegexMatchAnsiPrefix: Property<"show-regex-match-ansi-prefix", "String">,
+ Global,
+ DefaultStringValue<"${ansi.fg.red}">,
+ Desc<"When displaying a regex match in a color-enabled terminal, use the ANSI terminal code specified in this format immediately before the match.">;
+ def ShowRegexMatchAnsiSuffix: Property<"show-regex-match-ansi-suffix", "String">,
+ Global,
+ DefaultStringValue<"${ansi.normal}">,
+ Desc<"When displaying a regex match in a color-enabled terminal, use the ANSI terminal code specified in this format immediately after the match.">;
+ def ShowDontUsePoHint: Property<"show-dont-use-po-hint", "Boolean">,
+ Global,
+ DefaultTrue,
+ Desc<"If true, and object description was requested for a type that does not implement it, LLDB will print a hint telling the user to consider using p instead.">;
def DWIMPrintVerbosity: Property<"dwim-print-verbosity", "Enum">,
Global,
DefaultEnumValue<"eDWIMPrintVerbosityNone">,
diff --git a/lldb/source/Core/DataFileCache.cpp b/lldb/source/Core/DataFileCache.cpp
index b29327db5ca3..a8127efc1df0 100644
--- a/lldb/source/Core/DataFileCache.cpp
+++ b/lldb/source/Core/DataFileCache.cpp
@@ -285,7 +285,7 @@ bool ConstStringTable::Encode(DataEncoder &encoder) {
size_t length_offset = encoder.GetByteSize();
encoder.AppendU32(0); // Total length of all strings which will be fixed up.
size_t strtab_offset = encoder.GetByteSize();
- encoder.AppendU8(0); // Start the string table with with an empty string.
+ encoder.AppendU8(0); // Start the string table with an empty string.
for (auto s: m_strings) {
// Make sure all of the offsets match up with what we handed out!
assert(m_string_to_offset.find(s)->second ==
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index f54108629185..97311b4716ac 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -16,12 +16,12 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamAsynchronousIO.h"
-#include "lldb/Core/StreamFile.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Expression/REPL.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/StreamFile.h"
#include "lldb/Host/Terminal.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -236,6 +236,13 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
// codes.
SetPrompt(GetPrompt());
} else if (property_path ==
+ g_debugger_properties[ePropertyPromptAnsiPrefix].name ||
+ property_path ==
+ g_debugger_properties[ePropertyPromptAnsiSuffix].name) {
+ // Prompt colors changed. Ping the prompt so it can reset the ansi
+ // terminal codes.
+ SetPrompt(GetPrompt());
+ } else if (property_path ==
g_debugger_properties[ePropertyUseSourceCache].name) {
// use-source-cache changed. Wipe out the cache contents if it was
// disabled.
@@ -301,6 +308,18 @@ llvm::StringRef Debugger::GetPrompt() const {
idx, g_debugger_properties[idx].default_cstr_value);
}
+llvm::StringRef Debugger::GetPromptAnsiPrefix() const {
+ const uint32_t idx = ePropertyPromptAnsiPrefix;
+ return GetPropertyAtIndexAs<llvm::StringRef>(
+ idx, g_debugger_properties[idx].default_cstr_value);
+}
+
+llvm::StringRef Debugger::GetPromptAnsiSuffix() const {
+ const uint32_t idx = ePropertyPromptAnsiSuffix;
+ return GetPropertyAtIndexAs<llvm::StringRef>(
+ idx, g_debugger_properties[idx].default_cstr_value);
+}
+
void Debugger::SetPrompt(llvm::StringRef p) {
constexpr uint32_t idx = ePropertyPrompt;
SetPropertyAtIndex(idx, p);
@@ -434,6 +453,24 @@ llvm::StringRef Debugger::GetAutosuggestionAnsiSuffix() const {
idx, g_debugger_properties[idx].default_cstr_value);
}
+llvm::StringRef Debugger::GetRegexMatchAnsiPrefix() const {
+ const uint32_t idx = ePropertyShowRegexMatchAnsiPrefix;
+ return GetPropertyAtIndexAs<llvm::StringRef>(
+ idx, g_debugger_properties[idx].default_cstr_value);
+}
+
+llvm::StringRef Debugger::GetRegexMatchAnsiSuffix() const {
+ const uint32_t idx = ePropertyShowRegexMatchAnsiSuffix;
+ return GetPropertyAtIndexAs<llvm::StringRef>(
+ idx, g_debugger_properties[idx].default_cstr_value);
+}
+
+bool Debugger::GetShowDontUsePoHint() const {
+ const uint32_t idx = ePropertyShowDontUsePoHint;
+ return GetPropertyAtIndexAs<bool>(
+ idx, g_debugger_properties[idx].default_uint_value != 0);
+}
+
bool Debugger::GetUseSourceCache() const {
const uint32_t idx = ePropertyUseSourceCache;
return GetPropertyAtIndexAs<bool>(
@@ -905,7 +942,7 @@ void Debugger::Clear() {
for (TargetSP target_sp : m_target_list.Targets()) {
if (target_sp) {
if (ProcessSP process_sp = target_sp->GetProcessSP())
- process_sp->Finalize();
+ process_sp->Finalize(false /* not destructing */);
target_sp->Destroy();
}
}
@@ -923,15 +960,6 @@ void Debugger::Clear() {
});
}
-bool Debugger::GetCloseInputOnEOF() const {
- // return m_input_comm.GetCloseOnEOF();
- return false;
-}
-
-void Debugger::SetCloseInputOnEOF(bool b) {
- // m_input_comm.SetCloseOnEOF(b);
-}
-
bool Debugger::GetAsyncExecution() {
return !m_command_interpreter_up->GetSynchronous();
}
@@ -1275,17 +1303,17 @@ bool Debugger::InterruptRequested() {
return GetCommandInterpreter().WasInterrupted();
}
-Debugger::InterruptionReport::InterruptionReport(std::string function_name,
- const llvm::formatv_object_base &payload) :
- m_function_name(std::move(function_name)),
- m_interrupt_time(std::chrono::system_clock::now()),
- m_thread_id(llvm::get_threadid()) {
+Debugger::InterruptionReport::InterruptionReport(
+ std::string function_name, const llvm::formatv_object_base &payload)
+ : m_function_name(std::move(function_name)),
+ m_interrupt_time(std::chrono::system_clock::now()),
+ m_thread_id(llvm::get_threadid()) {
llvm::raw_string_ostream desc(m_description);
desc << payload << "\n";
}
void Debugger::ReportInterruption(const InterruptionReport &report) {
- // For now, just log the description:
+ // For now, just log the description:
Log *log = GetLog(LLDBLog::Host);
LLDB_LOG(log, "Interruption: {0}", report.m_description);
}
diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp
index 104e9100e388..166b5fdf22f0 100644
--- a/lldb/source/Core/Disassembler.cpp
+++ b/lldb/source/Core/Disassembler.cpp
@@ -645,18 +645,29 @@ void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size,
instruction_control_flow_kind));
}
+ bool show_color = false;
+ if (exe_ctx) {
+ if (TargetSP target_sp = exe_ctx->GetTargetSP()) {
+ show_color = target_sp->GetDebugger().GetUseColor();
+ }
+ }
const size_t opcode_pos = ss.GetSizeOfLastLine();
+ const std::string &opcode_name =
+ show_color ? m_markup_opcode_name : m_opcode_name;
+ const std::string &mnemonics = show_color ? m_markup_mnemonics : m_mnemonics;
// The default opcode size of 7 characters is plenty for most architectures
// but some like arm can pull out the occasional vqrshrun.s16. We won't get
- // consistent column spacing in these cases, unfortunately.
+ // consistent column spacing in these cases, unfortunately. Also note that we
+ // need to directly use m_opcode_name here (instead of opcode_name) so we
+ // don't include color codes as characters.
if (m_opcode_name.length() >= opcode_column_width) {
opcode_column_width = m_opcode_name.length() + 1;
}
- ss.PutCString(m_opcode_name);
+ ss.PutCString(opcode_name);
ss.FillLastLineToColumn(opcode_pos + opcode_column_width, ' ');
- ss.PutCString(m_mnemonics);
+ ss.PutCString(mnemonics);
if (!m_comment.empty()) {
ss.FillLastLineToColumn(
diff --git a/lldb/source/Core/DumpDataExtractor.cpp b/lldb/source/Core/DumpDataExtractor.cpp
index cb76b118325b..986c9a181919 100644
--- a/lldb/source/Core/DumpDataExtractor.cpp
+++ b/lldb/source/Core/DumpDataExtractor.cpp
@@ -620,10 +620,17 @@ lldb::offset_t lldb_private::DumpDataExtractor(
case 2:
case 4:
case 8:
- s->Printf(wantsuppercase ? "0x%*.*" PRIX64 : "0x%*.*" PRIx64,
- (int)(2 * item_byte_size), (int)(2 * item_byte_size),
- DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
- item_bit_offset));
+ if (Target::GetGlobalProperties()
+ .ShowHexVariableValuesWithLeadingZeroes()) {
+ s->Printf(wantsuppercase ? "0x%*.*" PRIX64 : "0x%*.*" PRIx64,
+ (int)(2 * item_byte_size), (int)(2 * item_byte_size),
+ DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
+ item_bit_offset));
+ } else {
+ s->Printf(wantsuppercase ? "0x%" PRIX64 : "0x%" PRIx64,
+ DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
+ item_bit_offset));
+ }
break;
default: {
assert(item_bit_size == 0 && item_bit_offset == 0);
diff --git a/lldb/source/Core/DynamicLoader.cpp b/lldb/source/Core/DynamicLoader.cpp
index 2e5378f654a5..7871be6fc451 100644
--- a/lldb/source/Core/DynamicLoader.cpp
+++ b/lldb/source/Core/DynamicLoader.cpp
@@ -8,12 +8,12 @@
#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
-#include "lldb/Symbol/LocateSymbolFile.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Platform.h"
@@ -188,7 +188,7 @@ static ModuleSP ReadUnnamedMemoryModule(Process *process, addr_t addr,
ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
Process *process, llvm::StringRef name, UUID uuid, addr_t value,
bool value_is_offset, bool force_symbol_search, bool notify,
- bool set_address_in_target) {
+ bool set_address_in_target, bool allow_memory_image_last_resort) {
ModuleSP memory_module_sp;
ModuleSP module_sp;
PlatformSP platform_sp = process->GetTarget().GetPlatform();
@@ -218,9 +218,9 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
if (!module_sp) {
FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
module_spec.GetSymbolFileSpec() =
- Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
+ PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
ModuleSpec objfile_module_spec =
- Symbols::LocateExecutableObjectFile(module_spec);
+ PluginManager::LocateExecutableObjectFile(module_spec);
module_spec.GetFileSpec() = objfile_module_spec.GetFileSpec();
if (FileSystem::Instance().Exists(module_spec.GetFileSpec()) &&
FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec())) {
@@ -231,10 +231,13 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
// If we haven't found a binary, or we don't have a SymbolFile, see
// if there is an external search tool that can find it.
if (!module_sp || !module_sp->GetSymbolFileFileSpec()) {
- Symbols::DownloadObjectAndSymbolFile(module_spec, error,
- force_symbol_search);
+ PluginManager::DownloadObjectAndSymbolFile(module_spec, error,
+ force_symbol_search);
if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
module_sp = std::make_shared<Module>(module_spec);
+ } else if (force_symbol_search && error.AsCString("") &&
+ error.AsCString("")[0] != '\0') {
+ target.GetDebugger().GetErrorStream() << error.AsCString();
}
}
@@ -245,7 +248,8 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
// If we couldn't find the binary anywhere else, as a last resort,
// read it out of memory.
- if (!module_sp.get() && value != LLDB_INVALID_ADDRESS && !value_is_offset) {
+ if (allow_memory_image_last_resort && !module_sp.get() &&
+ value != LLDB_INVALID_ADDRESS && !value_is_offset) {
if (!memory_module_sp)
memory_module_sp = ReadUnnamedMemoryModule(process, value, name);
if (memory_module_sp)
@@ -266,8 +270,8 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
if (value != LLDB_INVALID_ADDRESS) {
LLDB_LOGF(log,
"DynamicLoader::LoadBinaryWithUUIDAndAddress Loading "
- "binary UUID %s at %s 0x%" PRIx64,
- uuid.GetAsString().c_str(),
+ "binary %s UUID %s at %s 0x%" PRIx64,
+ name.str().c_str(), uuid.GetAsString().c_str(),
value_is_offset ? "offset" : "address", value);
module_sp->SetLoadAddress(target, value, value_is_offset, changed);
} else {
@@ -275,8 +279,8 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
// offset 0.
LLDB_LOGF(log,
"DynamicLoader::LoadBinaryWithUUIDAndAddress Loading "
- "binary UUID %s at file address",
- uuid.GetAsString().c_str());
+ "binary %s UUID %s at file address",
+ name.str().c_str(), uuid.GetAsString().c_str());
module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
changed);
}
@@ -284,8 +288,8 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
// In-memory image, load at its true address, offset 0.
LLDB_LOGF(log,
"DynamicLoader::LoadBinaryWithUUIDAndAddress Loading binary "
- "UUID %s from memory at address 0x%" PRIx64,
- uuid.GetAsString().c_str(), value);
+ "%s UUID %s from memory at address 0x%" PRIx64,
+ name.str().c_str(), uuid.GetAsString().c_str(), value);
module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
changed);
}
@@ -297,10 +301,26 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
target.ModulesDidLoad(added_module);
}
} else {
- LLDB_LOGF(log, "Unable to find binary with UUID %s and load it at "
- "%s 0x%" PRIx64,
- uuid.GetAsString().c_str(),
- value_is_offset ? "offset" : "address", value);
+ if (force_symbol_search) {
+ Stream &s = target.GetDebugger().GetErrorStream();
+ s.Printf("Unable to find file");
+ if (!name.empty())
+ s.Printf(" %s", name.str().c_str());
+ if (uuid.IsValid())
+ s.Printf(" with UUID %s", uuid.GetAsString().c_str());
+ if (value != LLDB_INVALID_ADDRESS) {
+ if (value_is_offset)
+ s.Printf(" with slide 0x%" PRIx64, value);
+ else
+ s.Printf(" at address 0x%" PRIx64, value);
+ }
+ s.Printf("\n");
+ }
+ LLDB_LOGF(log,
+ "Unable to find binary %s with UUID %s and load it at "
+ "%s 0x%" PRIx64,
+ name.str().c_str(), uuid.GetAsString().c_str(),
+ value_is_offset ? "offset" : "address", value);
}
return module_sp;
diff --git a/lldb/source/Core/EmulateInstruction.cpp b/lldb/source/Core/EmulateInstruction.cpp
index 753bee25de6d..d240b4d3b331 100644
--- a/lldb/source/Core/EmulateInstruction.cpp
+++ b/lldb/source/Core/EmulateInstruction.cpp
@@ -11,7 +11,7 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/DumpRegisterValue.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/StreamFile.h"
+#include "lldb/Host/StreamFile.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
diff --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp
index 00ab20243855..94986457552d 100644
--- a/lldb/source/Core/FormatEntity.cpp
+++ b/lldb/source/Core/FormatEntity.cpp
@@ -286,13 +286,6 @@ void FormatEntity::Entry::AppendText(const char *cstr) {
return AppendText(llvm::StringRef(cstr));
}
-Status FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) {
- entry.Clear();
- entry.type = Entry::Type::Root;
- llvm::StringRef modifiable_format(format_str);
- return ParseInternal(modifiable_format, entry, 0);
-}
-
#define ENUM_TO_CSTR(eee) \
case FormatEntity::Entry::Type::eee: \
return #eee
@@ -1252,9 +1245,10 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
llvm::Triple::OSType ostype = arch.IsValid()
? arch.GetTriple().getOS()
: llvm::Triple::UnknownOS;
- if ((ostype == llvm::Triple::FreeBSD) ||
- (ostype == llvm::Triple::Linux) ||
- (ostype == llvm::Triple::NetBSD)) {
+ if (ostype == llvm::Triple::FreeBSD ||
+ ostype == llvm::Triple::Linux ||
+ ostype == llvm::Triple::NetBSD ||
+ ostype == llvm::Triple::OpenBSD) {
format = "%" PRIu64;
}
} else {
@@ -1991,8 +1985,8 @@ static const Definition *FindEntry(const llvm::StringRef &format_str,
return parent;
}
-Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry,
- uint32_t depth) {
+static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
+ uint32_t depth) {
Status error;
while (!format.empty() && error.Success()) {
const size_t non_special_chars = format.find_first_of("${}\\");
@@ -2017,7 +2011,7 @@ Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry,
case '{': {
format = format.drop_front(); // Skip the '{'
Entry scope_entry(Entry::Type::Scope);
- error = FormatEntity::ParseInternal(format, scope_entry, depth + 1);
+ error = ParseInternal(format, scope_entry, depth + 1);
if (error.Fail())
return error;
parent_entry.AppendEntry(std::move(scope_entry));
@@ -2467,3 +2461,10 @@ void FormatEntity::PrettyPrintFunctionArguments(
out_stream.Printf("%s=<unavailable>", var_name);
}
}
+
+Status FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) {
+ entry.Clear();
+ entry.type = Entry::Type::Root;
+ llvm::StringRef modifiable_format(format_str);
+ return ParseInternal(modifiable_format, entry, 0);
+}
diff --git a/lldb/source/Core/IOHandler.cpp b/lldb/source/Core/IOHandler.cpp
index 49f39f2ce492..695c2481e353 100644
--- a/lldb/source/Core/IOHandler.cpp
+++ b/lldb/source/Core/IOHandler.cpp
@@ -14,9 +14,9 @@
#include <string>
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/StreamFile.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/File.h"
+#include "lldb/Host/StreamFile.h"
#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/Predicate.h"
#include "lldb/Utility/Status.h"
@@ -226,7 +226,7 @@ IOHandlerEditline::IOHandlerEditline(
Debugger &debugger, IOHandler::Type type,
const char *editline_name, // Used for saving history files
llvm::StringRef prompt, llvm::StringRef continuation_prompt,
- bool multi_line, bool color_prompts, uint32_t line_number_start,
+ bool multi_line, bool color, uint32_t line_number_start,
IOHandlerDelegate &delegate)
: IOHandlerEditline(debugger, type,
FileSP(), // Inherit input from top input reader
@@ -234,7 +234,7 @@ IOHandlerEditline::IOHandlerEditline(
StreamFileSP(), // Inherit error from top input reader
0, // Flags
editline_name, // Used for saving history files
- prompt, continuation_prompt, multi_line, color_prompts,
+ prompt, continuation_prompt, multi_line, color,
line_number_start, delegate) {}
IOHandlerEditline::IOHandlerEditline(
@@ -243,7 +243,7 @@ IOHandlerEditline::IOHandlerEditline(
uint32_t flags,
const char *editline_name, // Used for saving history files
llvm::StringRef prompt, llvm::StringRef continuation_prompt,
- bool multi_line, bool color_prompts, uint32_t line_number_start,
+ bool multi_line, bool color, uint32_t line_number_start,
IOHandlerDelegate &delegate)
: IOHandler(debugger, type, input_sp, output_sp, error_sp, flags),
#if LLDB_ENABLE_LIBEDIT
@@ -251,8 +251,8 @@ IOHandlerEditline::IOHandlerEditline(
#endif
m_delegate(delegate), m_prompt(), m_continuation_prompt(),
m_current_lines_ptr(nullptr), m_base_line_number(line_number_start),
- m_curr_line_idx(UINT32_MAX), m_multi_line(multi_line),
- m_color_prompts(color_prompts), m_interrupt_exits(true) {
+ m_curr_line_idx(UINT32_MAX), m_multi_line(multi_line), m_color(color),
+ m_interrupt_exits(true) {
SetPrompt(prompt);
#if LLDB_ENABLE_LIBEDIT
@@ -262,9 +262,9 @@ IOHandlerEditline::IOHandlerEditline(
m_input_sp && m_input_sp->GetIsRealTerminal();
if (use_editline) {
- m_editline_up = std::make_unique<Editline>(
- editline_name, GetInputFILE(), GetOutputFILE(), GetErrorFILE(),
- GetOutputMutex(), m_color_prompts);
+ m_editline_up = std::make_unique<Editline>(editline_name, GetInputFILE(),
+ GetOutputFILE(), GetErrorFILE(),
+ GetOutputMutex());
m_editline_up->SetIsInputCompleteCallback(
[this](Editline *editline, StringList &lines) {
return this->IsInputCompleteCallback(editline, lines);
@@ -278,10 +278,12 @@ IOHandlerEditline::IOHandlerEditline(
m_editline_up->SetSuggestionCallback([this](llvm::StringRef line) {
return this->SuggestionCallback(line);
});
- m_editline_up->SetSuggestionAnsiPrefix(ansi::FormatAnsiTerminalCodes(
- debugger.GetAutosuggestionAnsiPrefix()));
- m_editline_up->SetSuggestionAnsiSuffix(ansi::FormatAnsiTerminalCodes(
- debugger.GetAutosuggestionAnsiSuffix()));
+ if (m_color) {
+ m_editline_up->SetSuggestionAnsiPrefix(ansi::FormatAnsiTerminalCodes(
+ debugger.GetAutosuggestionAnsiPrefix()));
+ m_editline_up->SetSuggestionAnsiSuffix(ansi::FormatAnsiTerminalCodes(
+ debugger.GetAutosuggestionAnsiSuffix()));
+ }
}
// See if the delegate supports fixing indentation
const char *indent_chars = delegate.IOHandlerGetFixIndentationCharacters();
@@ -474,8 +476,15 @@ bool IOHandlerEditline::SetPrompt(llvm::StringRef prompt) {
m_prompt = std::string(prompt);
#if LLDB_ENABLE_LIBEDIT
- if (m_editline_up)
+ if (m_editline_up) {
m_editline_up->SetPrompt(m_prompt.empty() ? nullptr : m_prompt.c_str());
+ if (m_color) {
+ m_editline_up->SetPromptAnsiPrefix(
+ ansi::FormatAnsiTerminalCodes(m_debugger.GetPromptAnsiPrefix()));
+ m_editline_up->SetPromptAnsiSuffix(
+ ansi::FormatAnsiTerminalCodes(m_debugger.GetPromptAnsiSuffix()));
+ }
+ }
#endif
return true;
}
@@ -508,6 +517,21 @@ uint32_t IOHandlerEditline::GetCurrentLineIndex() const {
return m_curr_line_idx;
}
+StringList IOHandlerEditline::GetCurrentLines() const {
+#if LLDB_ENABLE_LIBEDIT
+ if (m_editline_up)
+ return m_editline_up->GetInputAsStringList();
+#endif
+ // When libedit is not used, the current lines can be gotten from
+ // `m_current_lines_ptr`, which is updated whenever a new line is processed.
+ // This doesn't happen when libedit is used, in which case
+ // `m_current_lines_ptr` is only updated when the full input is terminated.
+
+ if (m_current_lines_ptr)
+ return *m_current_lines_ptr;
+ return StringList();
+}
+
bool IOHandlerEditline::GetLines(StringList &lines, bool &interrupted) {
m_current_lines_ptr = &lines;
diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp
index 79d3da63059c..abf0b6b801f3 100644
--- a/lldb/source/Core/IOHandlerCursesGUI.cpp
+++ b/lldb/source/Core/IOHandlerCursesGUI.cpp
@@ -25,7 +25,6 @@
#include <string>
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/StreamFile.h"
#include "lldb/Core/ValueObjectUpdater.h"
#include "lldb/Host/File.h"
#include "lldb/Utility/AnsiTerminal.h"
@@ -3179,13 +3178,13 @@ public:
m_debugger.GetListener(), llvm::StringRef(), &core_file_spec, false));
if (!process_sp) {
- SetError("Unable to find process plug-in for core file!");
+ SetError("Unknown core file format!");
return;
}
Status status = process_sp->LoadCore();
if (status.Fail()) {
- SetError("Can't find plug-in for core file!");
+ SetError("Unknown core file format!");
return;
}
}
@@ -4615,30 +4614,48 @@ public:
typedef std::shared_ptr<TreeDelegate> TreeDelegateSP;
-class TreeItem {
+struct TreeItemData {
+ TreeItemData(TreeItem *parent, TreeDelegate &delegate,
+ bool might_have_children, bool is_expanded)
+ : m_parent(parent), m_delegate(&delegate),
+ m_might_have_children(might_have_children), m_is_expanded(is_expanded) {
+ }
+
+protected:
+ TreeItem *m_parent;
+ TreeDelegate *m_delegate;
+ void *m_user_data = nullptr;
+ uint64_t m_identifier = 0;
+ std::string m_text;
+ int m_row_idx = -1; // Zero based visible row index, -1 if not visible or for
+ // the root item
+ bool m_might_have_children;
+ bool m_is_expanded = false;
+};
+
+class TreeItem : public TreeItemData {
public:
TreeItem(TreeItem *parent, TreeDelegate &delegate, bool might_have_children)
- : m_parent(parent), m_delegate(delegate), m_children(),
- m_might_have_children(might_have_children) {
- if (m_parent == nullptr)
- m_is_expanded = m_delegate.TreeDelegateExpandRootByDefault();
- }
+ : TreeItemData(parent, delegate, might_have_children,
+ parent == nullptr
+ ? delegate.TreeDelegateExpandRootByDefault()
+ : false),
+ m_children() {}
+
+ TreeItem(const TreeItem &) = delete;
+ TreeItem &operator=(const TreeItem &rhs) = delete;
- TreeItem &operator=(const TreeItem &rhs) {
+ TreeItem &operator=(TreeItem &&rhs) {
if (this != &rhs) {
- m_parent = rhs.m_parent;
- m_delegate = rhs.m_delegate;
- m_user_data = rhs.m_user_data;
- m_identifier = rhs.m_identifier;
- m_row_idx = rhs.m_row_idx;
- m_children = rhs.m_children;
- m_might_have_children = rhs.m_might_have_children;
- m_is_expanded = rhs.m_is_expanded;
+ TreeItemData::operator=(std::move(rhs));
+ AdoptChildren(rhs.m_children);
}
return *this;
}
- TreeItem(const TreeItem &) = default;
+ TreeItem(TreeItem &&rhs) : TreeItemData(std::move(rhs)) {
+ AdoptChildren(rhs.m_children);
+ }
size_t GetDepth() const {
if (m_parent)
@@ -4650,18 +4667,28 @@ public:
void ClearChildren() { m_children.clear(); }
- void Resize(size_t n, const TreeItem &t) { m_children.resize(n, t); }
+ void Resize(size_t n, TreeDelegate &delegate, bool might_have_children) {
+ if (m_children.size() >= n) {
+ m_children.erase(m_children.begin() + n, m_children.end());
+ return;
+ }
+ m_children.reserve(n);
+ std::generate_n(std::back_inserter(m_children), n - m_children.size(),
+ [&, parent = this]() {
+ return TreeItem(parent, delegate, might_have_children);
+ });
+ }
TreeItem &operator[](size_t i) { return m_children[i]; }
void SetRowIndex(int row_idx) { m_row_idx = row_idx; }
size_t GetNumChildren() {
- m_delegate.TreeDelegateGenerateChildren(*this);
+ m_delegate->TreeDelegateGenerateChildren(*this);
return m_children.size();
}
- void ItemWasSelected() { m_delegate.TreeDelegateItemSelected(*this); }
+ void ItemWasSelected() { m_delegate->TreeDelegateItemSelected(*this); }
void CalculateRowIndexes(int &row_idx) {
SetRowIndex(row_idx);
@@ -4728,7 +4755,7 @@ public:
if (highlight)
window.AttributeOn(A_REVERSE);
- m_delegate.TreeDelegateDrawTreeItem(*this, window);
+ m_delegate->TreeDelegateDrawTreeItem(*this, window);
if (highlight)
window.AttributeOff(A_REVERSE);
@@ -4812,16 +4839,13 @@ public:
void SetMightHaveChildren(bool b) { m_might_have_children = b; }
protected:
- TreeItem *m_parent;
- TreeDelegate &m_delegate;
- void *m_user_data = nullptr;
- uint64_t m_identifier = 0;
- std::string m_text;
- int m_row_idx = -1; // Zero based visible row index, -1 if not visible or for
- // the root item
+ void AdoptChildren(std::vector<TreeItem> &children) {
+ m_children = std::move(children);
+ for (auto &child : m_children)
+ child.m_parent = this;
+ }
+
std::vector<TreeItem> m_children;
- bool m_might_have_children;
- bool m_is_expanded = false;
};
class TreeWindowDelegate : public WindowDelegate {
@@ -5118,9 +5142,8 @@ public:
m_stop_id = process_sp->GetStopID();
m_tid = thread_sp->GetID();
- TreeItem t(&item, *m_frame_delegate_sp, false);
size_t num_frames = thread_sp->GetStackFrameCount();
- item.Resize(num_frames, t);
+ item.Resize(num_frames, *m_frame_delegate_sp, false);
for (size_t i = 0; i < num_frames; ++i) {
item[i].SetUserData(thread_sp.get());
item[i].SetIdentifier(i);
@@ -5220,12 +5243,11 @@ public:
std::make_shared<ThreadTreeDelegate>(m_debugger);
}
- TreeItem t(&item, *m_thread_delegate_sp, false);
ThreadList &threads = process_sp->GetThreadList();
std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
ThreadSP selected_thread = threads.GetSelectedThread();
size_t num_threads = threads.GetSize();
- item.Resize(num_threads, t);
+ item.Resize(num_threads, *m_thread_delegate_sp, false);
for (size_t i = 0; i < num_threads; ++i) {
ThreadSP thread = threads.GetThreadAtIndex(i);
item[i].SetIdentifier(thread->GetID());
@@ -5405,9 +5427,8 @@ public:
if (!m_string_delegate_sp)
m_string_delegate_sp = std::make_shared<TextTreeDelegate>();
- TreeItem details_tree_item(&item, *m_string_delegate_sp, false);
- item.Resize(details.GetSize(), details_tree_item);
+ item.Resize(details.GetSize(), *m_string_delegate_sp, false);
for (size_t i = 0; i < details.GetSize(); i++) {
item[i].SetText(details.GetStringAtIndex(i));
}
@@ -5449,10 +5470,9 @@ public:
if (!m_breakpoint_location_delegate_sp)
m_breakpoint_location_delegate_sp =
std::make_shared<BreakpointLocationTreeDelegate>(m_debugger);
- TreeItem breakpoint_location_tree_item(
- &item, *m_breakpoint_location_delegate_sp, true);
- item.Resize(breakpoint->GetNumLocations(), breakpoint_location_tree_item);
+ item.Resize(breakpoint->GetNumLocations(),
+ *m_breakpoint_location_delegate_sp, true);
for (size_t i = 0; i < breakpoint->GetNumLocations(); i++) {
item[i].SetIdentifier(i);
item[i].SetUserData(breakpoint.get());
@@ -5496,9 +5516,8 @@ public:
if (!m_breakpoint_delegate_sp)
m_breakpoint_delegate_sp =
std::make_shared<BreakpointTreeDelegate>(m_debugger);
- TreeItem breakpoint_tree_item(&item, *m_breakpoint_delegate_sp, true);
- item.Resize(breakpoints.GetSize(), breakpoint_tree_item);
+ item.Resize(breakpoints.GetSize(), *m_breakpoint_delegate_sp, true);
for (size_t i = 0; i < breakpoints.GetSize(); i++) {
item[i].SetIdentifier(i);
}
diff --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp
index d1973a9a8f7f..4587119519e9 100644
--- a/lldb/source/Core/Mangled.cpp
+++ b/lldb/source/Core/Mangled.cpp
@@ -58,6 +58,24 @@ Mangled::ManglingScheme Mangled::GetManglingScheme(llvm::StringRef const name) {
if (name.startswith("___Z"))
return Mangled::eManglingSchemeItanium;
+ // Swift's older style of mangling used "_T" as a mangling prefix. This can
+ // lead to false positives with other symbols that just so happen to start
+ // with "_T". To minimize the chance of that happening, we only return true
+ // for select old-style swift mangled names. The known cases are ObjC classes
+ // and protocols. Classes are either prefixed with "_TtC" or "_TtGC".
+ // Protocols are prefixed with "_TtP".
+ if (name.startswith("_TtC") || name.startswith("_TtGC") ||
+ name.startswith("_TtP"))
+ return Mangled::eManglingSchemeSwift;
+
+ // Swift 4.2 used "$S" and "_$S".
+ // Swift 5 and onward uses "$s" and "_$s".
+ // Swift also uses "@__swiftmacro_" as a prefix for mangling filenames.
+ if (name.startswith("$S") || name.startswith("_$S") ||
+ name.startswith("$s") || name.startswith("_$s") ||
+ name.startswith("@__swiftmacro_"))
+ return Mangled::eManglingSchemeSwift;
+
return Mangled::eManglingSchemeNone;
}
@@ -228,6 +246,7 @@ bool Mangled::GetRichManglingInfo(RichManglingContext &context,
case eManglingSchemeRustV0:
case eManglingSchemeD:
+ case eManglingSchemeSwift:
// Rich demangling scheme is not supported
return false;
}
@@ -265,6 +284,10 @@ ConstString Mangled::GetDemangledName() const {
case eManglingSchemeD:
demangled_name = GetDLangDemangledStr(m_mangled);
break;
+ case eManglingSchemeSwift:
+ // Demangling a swift name requires the swift compiler. This is
+ // explicitly unsupported on llvm.org.
+ break;
case eManglingSchemeNone:
llvm_unreachable("eManglingSchemeNone was handled already");
}
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index 672d86496bde..e6279a0feda8 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -23,11 +23,11 @@
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
-#include "lldb/Symbol/LocateSymbolFile.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/SymbolLocator.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Symtab.h"
#include "lldb/Symbol/Type.h"
@@ -233,12 +233,12 @@ Module::Module(const ModuleSpec &module_spec)
}
Module::Module(const FileSpec &file_spec, const ArchSpec &arch,
- const ConstString *object_name, lldb::offset_t object_offset,
+ ConstString object_name, lldb::offset_t object_offset,
const llvm::sys::TimePoint<> &object_mod_time)
: m_mod_time(FileSystem::Instance().GetModificationTime(file_spec)),
- m_arch(arch), m_file(file_spec), m_object_offset(object_offset),
- m_object_mod_time(object_mod_time), m_file_has_changed(false),
- m_first_file_changed_log(false) {
+ m_arch(arch), m_file(file_spec), m_object_name(object_name),
+ m_object_offset(object_offset), m_object_mod_time(object_mod_time),
+ m_file_has_changed(false), m_first_file_changed_log(false) {
// Scope for locker below...
{
std::lock_guard<std::recursive_mutex> guard(
@@ -246,9 +246,6 @@ Module::Module(const FileSpec &file_spec, const ArchSpec &arch,
GetModuleCollection().push_back(this);
}
- if (object_name)
- m_object_name = *object_name;
-
Log *log(GetLog(LLDBLog::Object | LLDBLog::Modules));
if (log != nullptr)
LLDB_LOGF(log, "%p Module::Module((%s) '%s%s%s%s')",
@@ -1285,7 +1282,8 @@ ObjectFile *Module::GetObjectFile() {
// those values that overwrite unspecified unknown values.
m_arch.MergeFrom(m_objfile_sp->GetArchitecture());
} else {
- ReportError("failed to load objfile for {0}",
+ ReportError("failed to load objfile for {0}\nDebugging will be "
+ "degraded for this module.",
GetFileSpec().GetPath().c_str());
}
}
@@ -1316,7 +1314,7 @@ UnwindTable &Module::GetUnwindTable() {
if (!m_unwind_table) {
m_unwind_table.emplace(*this);
if (!m_symfile_spec)
- Symbols::DownloadSymbolFileAsync(GetUUID());
+ SymbolLocator::DownloadSymbolFileAsync(GetUUID());
}
return *m_unwind_table;
}
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index d0d0b2050e18..04a9df7dd63b 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -9,12 +9,12 @@
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Interpreter/OptionValueFileSpec.h"
#include "lldb/Interpreter/OptionValueFileSpecList.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/Property.h"
-#include "lldb/Symbol/LocateSymbolFile.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/TypeList.h"
@@ -75,8 +75,7 @@ enum {
} // namespace
ModuleListProperties::ModuleListProperties() {
- m_collection_sp =
- std::make_shared<OptionValueProperties>(ConstString("symbols"));
+ m_collection_sp = std::make_shared<OptionValueProperties>("symbols");
m_collection_sp->Initialize(g_modulelist_properties);
m_collection_sp->SetValueChangedCallback(ePropertySymLinkPaths,
[this] { UpdateSymlinkMappings(); });
@@ -348,7 +347,7 @@ size_t ModuleList::RemoveOrphans(bool mandatory) {
}
size_t remove_count = 0;
// Modules might hold shared pointers to other modules, so removing one
- // module might make other other modules orphans. Keep removing modules until
+ // module might make other modules orphans. Keep removing modules until
// there are no further modules that can be removed.
bool made_progress = true;
while (made_progress) {
@@ -907,7 +906,7 @@ ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp,
// Fixup the incoming path in case the path points to a valid file, yet the
// arch or UUID (if one was passed in) don't match.
ModuleSpec located_binary_modulespec =
- Symbols::LocateExecutableObjectFile(module_spec);
+ PluginManager::LocateExecutableObjectFile(module_spec);
// Don't look for the file if it appears to be the same one we already
// checked for above...
@@ -1079,3 +1078,11 @@ bool ModuleList::AnyOf(
return false;
}
+
+
+void ModuleList::Swap(ModuleList &other) {
+ // scoped_lock locks both mutexes at once.
+ std::scoped_lock<std::recursive_mutex, std::recursive_mutex> lock(
+ m_modules_mutex, other.m_modules_mutex);
+ m_modules.swap(other.m_modules);
+}
diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp
index ac274112e53d..dea380e47f4e 100644
--- a/lldb/source/Core/PluginManager.cpp
+++ b/lldb/source/Core/PluginManager.cpp
@@ -1081,6 +1081,119 @@ PluginManager::GetSymbolVendorCreateCallbackAtIndex(uint32_t idx) {
return GetSymbolVendorInstances().GetCallbackAtIndex(idx);
}
+#pragma mark SymbolLocator
+
+struct SymbolLocatorInstance
+ : public PluginInstance<SymbolLocatorCreateInstance> {
+ SymbolLocatorInstance(
+ llvm::StringRef name, llvm::StringRef description,
+ CallbackType create_callback,
+ SymbolLocatorLocateExecutableObjectFile locate_executable_object_file,
+ SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file,
+ SymbolLocatorDownloadObjectAndSymbolFile download_object_symbol_file,
+ SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle,
+ DebuggerInitializeCallback debugger_init_callback)
+ : PluginInstance<SymbolLocatorCreateInstance>(
+ name, description, create_callback, debugger_init_callback),
+ locate_executable_object_file(locate_executable_object_file),
+ locate_executable_symbol_file(locate_executable_symbol_file),
+ download_object_symbol_file(download_object_symbol_file),
+ find_symbol_file_in_bundle(find_symbol_file_in_bundle) {}
+
+ SymbolLocatorLocateExecutableObjectFile locate_executable_object_file;
+ SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file;
+ SymbolLocatorDownloadObjectAndSymbolFile download_object_symbol_file;
+ SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle;
+};
+typedef PluginInstances<SymbolLocatorInstance> SymbolLocatorInstances;
+
+static SymbolLocatorInstances &GetSymbolLocatorInstances() {
+ static SymbolLocatorInstances g_instances;
+ return g_instances;
+}
+
+bool PluginManager::RegisterPlugin(
+ llvm::StringRef name, llvm::StringRef description,
+ SymbolLocatorCreateInstance create_callback,
+ SymbolLocatorLocateExecutableObjectFile locate_executable_object_file,
+ SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file,
+ SymbolLocatorDownloadObjectAndSymbolFile download_object_symbol_file,
+ SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle,
+ DebuggerInitializeCallback debugger_init_callback) {
+ return GetSymbolLocatorInstances().RegisterPlugin(
+ name, description, create_callback, locate_executable_object_file,
+ locate_executable_symbol_file, download_object_symbol_file,
+ find_symbol_file_in_bundle, debugger_init_callback);
+}
+
+bool PluginManager::UnregisterPlugin(
+ SymbolLocatorCreateInstance create_callback) {
+ return GetSymbolLocatorInstances().UnregisterPlugin(create_callback);
+}
+
+SymbolLocatorCreateInstance
+PluginManager::GetSymbolLocatorCreateCallbackAtIndex(uint32_t idx) {
+ return GetSymbolLocatorInstances().GetCallbackAtIndex(idx);
+}
+
+ModuleSpec
+PluginManager::LocateExecutableObjectFile(const ModuleSpec &module_spec) {
+ auto &instances = GetSymbolLocatorInstances().GetInstances();
+ for (auto &instance : instances) {
+ if (instance.locate_executable_object_file) {
+ std::optional<ModuleSpec> result =
+ instance.locate_executable_object_file(module_spec);
+ if (result)
+ return *result;
+ }
+ }
+ return {};
+}
+
+FileSpec PluginManager::LocateExecutableSymbolFile(
+ const ModuleSpec &module_spec, const FileSpecList &default_search_paths) {
+ auto &instances = GetSymbolLocatorInstances().GetInstances();
+ for (auto &instance : instances) {
+ if (instance.locate_executable_symbol_file) {
+ std::optional<FileSpec> result = instance.locate_executable_symbol_file(
+ module_spec, default_search_paths);
+ if (result)
+ return *result;
+ }
+ }
+ return {};
+}
+
+bool PluginManager::DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
+ Status &error,
+ bool force_lookup,
+ bool copy_executable) {
+ auto &instances = GetSymbolLocatorInstances().GetInstances();
+ for (auto &instance : instances) {
+ if (instance.download_object_symbol_file) {
+ if (instance.download_object_symbol_file(module_spec, error, force_lookup,
+ copy_executable))
+ return true;
+ }
+ }
+ return false;
+}
+
+FileSpec PluginManager::FindSymbolFileInBundle(const FileSpec &symfile_bundle,
+ const UUID *uuid,
+ const ArchSpec *arch) {
+ auto &instances = GetSymbolLocatorInstances().GetInstances();
+ for (auto &instance : instances) {
+ if (instance.find_symbol_file_in_bundle) {
+ std::optional<FileSpec> result =
+ instance.find_symbol_file_in_bundle(symfile_bundle, uuid, arch);
+ if (result)
+ return *result;
+ }
+ }
+ return {};
+}
+
#pragma mark Trace
struct TraceInstance
@@ -1422,6 +1535,7 @@ void PluginManager::DebuggerInitialize(Debugger &debugger) {
GetPlatformInstances().PerformDebuggerCallback(debugger);
GetProcessInstances().PerformDebuggerCallback(debugger);
GetSymbolFileInstances().PerformDebuggerCallback(debugger);
+ GetSymbolLocatorInstances().PerformDebuggerCallback(debugger);
GetOperatingSystemInstances().PerformDebuggerCallback(debugger);
GetStructuredDataPluginInstances().PerformDebuggerCallback(debugger);
GetTracePluginInstances().PerformDebuggerCallback(debugger);
@@ -1549,6 +1663,7 @@ static constexpr llvm::StringLiteral kProcessPluginName("process");
static constexpr llvm::StringLiteral kTracePluginName("trace");
static constexpr llvm::StringLiteral kObjectFilePluginName("object-file");
static constexpr llvm::StringLiteral kSymbolFilePluginName("symbol-file");
+static constexpr llvm::StringLiteral kSymbolLocatorPluginName("symbol-locator");
static constexpr llvm::StringLiteral kJITLoaderPluginName("jit-loader");
static constexpr llvm::StringLiteral
kStructuredDataPluginName("structured-data");
@@ -1597,6 +1712,20 @@ bool PluginManager::CreateSettingForProcessPlugin(
description, is_global_property);
}
+lldb::OptionValuePropertiesSP
+PluginManager::GetSettingForSymbolLocatorPlugin(Debugger &debugger,
+ llvm::StringRef setting_name) {
+ return GetSettingForPlugin(debugger, setting_name, kSymbolLocatorPluginName);
+}
+
+bool PluginManager::CreateSettingForSymbolLocatorPlugin(
+ Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
+ llvm::StringRef description, bool is_global_property) {
+ return CreateSettingForPlugin(debugger, kSymbolLocatorPluginName,
+ "Settings for symbol locator plug-ins",
+ properties_sp, description, is_global_property);
+}
+
bool PluginManager::CreateSettingForTracePlugin(
Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
llvm::StringRef description, bool is_global_property) {
diff --git a/lldb/source/Core/Progress.cpp b/lldb/source/Core/Progress.cpp
index 08be73f1470f..ea3f874916a9 100644
--- a/lldb/source/Core/Progress.cpp
+++ b/lldb/source/Core/Progress.cpp
@@ -30,10 +30,9 @@ Progress::~Progress() {
// Make sure to always report progress completed when this object is
// destructed so it indicates the progress dialog/activity should go away.
std::lock_guard<std::mutex> guard(m_mutex);
- if (!m_completed) {
+ if (!m_completed)
m_completed = m_total;
- ReportProgress();
- }
+ ReportProgress();
}
void Progress::Increment(uint64_t amount, std::string update) {
diff --git a/lldb/source/Core/SearchFilter.cpp b/lldb/source/Core/SearchFilter.cpp
index 4f9519b5cc9a..b3ff73bbf58f 100644
--- a/lldb/source/Core/SearchFilter.cpp
+++ b/lldb/source/Core/SearchFilter.cpp
@@ -471,13 +471,13 @@ SearchFilterSP SearchFilterByModule::CreateFromStructuredData(
return nullptr;
}
- llvm::StringRef module;
- success = modules_array->GetItemAtIndexAsString(0, module);
- if (!success) {
+ std::optional<llvm::StringRef> maybe_module =
+ modules_array->GetItemAtIndexAsString(0);
+ if (!maybe_module) {
error.SetErrorString("SFBM::CFSD: filter module item not a string.");
return nullptr;
}
- FileSpec module_spec(module);
+ FileSpec module_spec(*maybe_module);
return std::make_shared<SearchFilterByModule>(target_sp, module_spec);
}
@@ -596,14 +596,14 @@ SearchFilterSP SearchFilterByModuleList::CreateFromStructuredData(
FileSpecList modules;
size_t num_modules = modules_array->GetSize();
for (size_t i = 0; i < num_modules; i++) {
- llvm::StringRef module;
- success = modules_array->GetItemAtIndexAsString(i, module);
- if (!success) {
+ std::optional<llvm::StringRef> maybe_module =
+ modules_array->GetItemAtIndexAsString(i);
+ if (!maybe_module) {
error.SetErrorStringWithFormat(
"SFBM::CFSD: filter module item %zu not a string.", i);
return nullptr;
}
- modules.EmplaceBack(module);
+ modules.EmplaceBack(*maybe_module);
}
return std::make_shared<SearchFilterByModuleList>(target_sp, modules);
}
@@ -644,14 +644,14 @@ lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData(
if (success) {
size_t num_modules = modules_array->GetSize();
for (size_t i = 0; i < num_modules; i++) {
- llvm::StringRef module;
- success = modules_array->GetItemAtIndexAsString(i, module);
- if (!success) {
+ std::optional<llvm::StringRef> maybe_module =
+ modules_array->GetItemAtIndexAsString(i);
+ if (!maybe_module) {
error.SetErrorStringWithFormat(
"SFBM::CFSD: filter module item %zu not a string.", i);
return result_sp;
}
- modules.EmplaceBack(module);
+ modules.EmplaceBack(*maybe_module);
}
}
@@ -666,14 +666,14 @@ lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData(
size_t num_cus = cus_array->GetSize();
FileSpecList cus;
for (size_t i = 0; i < num_cus; i++) {
- llvm::StringRef cu;
- success = cus_array->GetItemAtIndexAsString(i, cu);
- if (!success) {
+ std::optional<llvm::StringRef> maybe_cu =
+ cus_array->GetItemAtIndexAsString(i);
+ if (!maybe_cu) {
error.SetErrorStringWithFormat(
"SFBM::CFSD: filter CU item %zu not a string.", i);
return nullptr;
}
- cus.EmplaceBack(cu);
+ cus.EmplaceBack(*maybe_cu);
}
return std::make_shared<SearchFilterByModuleListAndCU>(
diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp
index 212b3119894f..9e98b59deb03 100644
--- a/lldb/source/Core/Section.cpp
+++ b/lldb/source/Core/Section.cpp
@@ -149,6 +149,8 @@ const char *Section::GetTypeAsCString() const {
return "ctf";
case eSectionTypeOther:
return "regular";
+ case eSectionTypeSwiftModules:
+ return "swift-modules";
}
return "unknown";
}
@@ -455,6 +457,7 @@ bool Section::ContainsOnlyDebugInfo() const {
case eSectionTypeDWARFAppleObjC:
case eSectionTypeDWARFGNUDebugAltLink:
case eSectionTypeCTF:
+ case eSectionTypeSwiftModules:
return true;
}
return false;
diff --git a/lldb/source/Core/StreamFile.cpp b/lldb/source/Core/StreamFile.cpp
deleted file mode 100644
index 8aac0b6d6306..000000000000
--- a/lldb/source/Core/StreamFile.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//===-- StreamFile.cpp ----------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Host/FileSystem.h"
-#include "lldb/Utility/LLDBLog.h"
-#include "lldb/Utility/Log.h"
-
-#include <cstdio>
-
-using namespace lldb;
-using namespace lldb_private;
-
-StreamFile::StreamFile(uint32_t flags, uint32_t addr_size, ByteOrder byte_order)
- : Stream(flags, addr_size, byte_order) {
- m_file_sp = std::make_shared<File>();
-}
-
-StreamFile::StreamFile(int fd, bool transfer_ownership) : Stream() {
- m_file_sp = std::make_shared<NativeFile>(fd, File::eOpenOptionWriteOnly,
- transfer_ownership);
-}
-
-StreamFile::StreamFile(FILE *fh, bool transfer_ownership) : Stream() {
- m_file_sp = std::make_shared<NativeFile>(fh, transfer_ownership);
-}
-
-StreamFile::StreamFile(const char *path, File::OpenOptions options,
- uint32_t permissions)
- : Stream() {
- auto file = FileSystem::Instance().Open(FileSpec(path), options, permissions);
- if (file)
- m_file_sp = std::move(file.get());
- else {
- // TODO refactor this so the error gets popagated up instead of logged here.
- LLDB_LOG_ERROR(GetLog(LLDBLog::Host), file.takeError(),
- "Cannot open {1}: {0}", path);
- m_file_sp = std::make_shared<File>();
- }
-}
-
-StreamFile::~StreamFile() = default;
-
-void StreamFile::Flush() { m_file_sp->Flush(); }
-
-size_t StreamFile::WriteImpl(const void *s, size_t length) {
- m_file_sp->Write(s, length);
- return length;
-}
diff --git a/lldb/source/Core/ThreadedCommunication.cpp b/lldb/source/Core/ThreadedCommunication.cpp
index 755a158a5359..7d8aae5d8ff6 100644
--- a/lldb/source/Core/ThreadedCommunication.cpp
+++ b/lldb/source/Core/ThreadedCommunication.cpp
@@ -23,6 +23,7 @@
#include <chrono>
#include <cstring>
#include <memory>
+#include <shared_mutex>
#include <cerrno>
#include <cinttypes>
@@ -155,6 +156,8 @@ size_t ThreadedCommunication::Read(void *dst, size_t dst_len,
}
bool ThreadedCommunication::StartReadThread(Status *error_ptr) {
+ std::lock_guard<std::mutex> lock(m_read_thread_mutex);
+
if (error_ptr)
error_ptr->Clear();
@@ -189,6 +192,8 @@ bool ThreadedCommunication::StartReadThread(Status *error_ptr) {
}
bool ThreadedCommunication::StopReadThread(Status *error_ptr) {
+ std::lock_guard<std::mutex> lock(m_read_thread_mutex);
+
if (!m_read_thread.IsJoinable())
return true;
@@ -199,13 +204,13 @@ bool ThreadedCommunication::StopReadThread(Status *error_ptr) {
BroadcastEvent(eBroadcastBitReadThreadShouldExit, nullptr);
- // error = m_read_thread.Cancel();
-
Status error = m_read_thread.Join(nullptr);
return error.Success();
}
bool ThreadedCommunication::JoinReadThread(Status *error_ptr) {
+ std::lock_guard<std::mutex> lock(m_read_thread_mutex);
+
if (!m_read_thread.IsJoinable())
return true;
diff --git a/lldb/source/Core/UserSettingsController.cpp b/lldb/source/Core/UserSettingsController.cpp
index f5dd926cf050..72217117557f 100644
--- a/lldb/source/Core/UserSettingsController.cpp
+++ b/lldb/source/Core/UserSettingsController.cpp
@@ -30,6 +30,13 @@ class Property;
using namespace lldb;
using namespace lldb_private;
+Properties::Properties() = default;
+
+Properties::Properties(const lldb::OptionValuePropertiesSP &collection_sp)
+ : m_collection_sp(collection_sp) {}
+
+Properties::~Properties() = default;
+
lldb::OptionValueSP
Properties::GetPropertyValue(const ExecutionContext *exe_ctx,
llvm::StringRef path, Status &error) const {
diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp
index 5a2631ca501f..995cc934c820 100644
--- a/lldb/source/Core/Value.cpp
+++ b/lldb/source/Core/Value.cpp
@@ -98,7 +98,9 @@ void Value::AppendBytes(const void *bytes, int len) {
}
void Value::Dump(Stream *strm) {
- m_value.GetValue(strm, true);
+ if (!strm)
+ return;
+ m_value.GetValue(*strm, true);
strm->Printf(", value_type = %s, context = %p, context_type = %s",
Value::GetValueTypeAsCString(m_value_type), m_context,
Value::GetContextTypeAsCString(m_context_type));
@@ -572,7 +574,7 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
return error;
}
-Scalar &Value::ResolveValue(ExecutionContext *exe_ctx) {
+Scalar &Value::ResolveValue(ExecutionContext *exe_ctx, Module *module) {
const CompilerType &compiler_type = GetCompilerType();
if (compiler_type.IsValid()) {
switch (m_value_type) {
@@ -587,7 +589,7 @@ Scalar &Value::ResolveValue(ExecutionContext *exe_ctx) {
{
DataExtractor data;
lldb::addr_t addr = m_value.ULongLong(LLDB_INVALID_ADDRESS);
- Status error(GetValueAsData(exe_ctx, data, nullptr));
+ Status error(GetValueAsData(exe_ctx, data, module));
if (error.Success()) {
Scalar scalar;
if (compiler_type.GetValueAsScalar(
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index d60a1d6f7a10..a7f7ee64282d 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -17,6 +17,7 @@
#include "lldb/Core/ValueObjectDynamicValue.h"
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/Core/ValueObjectSyntheticFilter.h"
+#include "lldb/Core/ValueObjectVTable.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/DataFormatters/DumpValueObjectOptions.h"
#include "lldb/DataFormatters/FormatManager.h"
@@ -218,10 +219,8 @@ bool ValueObject::UpdateFormatsIfNeeded() {
SetValueFormat(DataVisualization::GetFormat(*this, eNoDynamicValues));
SetSummaryFormat(
DataVisualization::GetSummaryFormat(*this, GetDynamicValueType()));
-#if LLDB_ENABLE_PYTHON
SetSyntheticChildren(
DataVisualization::GetSyntheticChildren(*this, GetDynamicValueType()));
-#endif
}
return any_change;
@@ -336,7 +335,7 @@ bool ValueObject::ResolveValue(Scalar &scalar) {
{
ExecutionContext exe_ctx(GetExecutionContextRef());
Value tmp_value(m_value);
- scalar = tmp_value.ResolveValue(&exe_ctx);
+ scalar = tmp_value.ResolveValue(&exe_ctx, GetModule().get());
if (scalar.IsValid()) {
const uint32_t bitfield_bit_size = GetBitfieldBitSize();
if (bitfield_bit_size)
@@ -440,23 +439,6 @@ ValueObject::GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names) {
return root;
}
-lldb::ValueObjectSP ValueObject::GetChildAtNamePath(
- llvm::ArrayRef<std::pair<ConstString, bool>> names,
- ConstString *name_of_error) {
- if (names.size() == 0)
- return GetSP();
- ValueObjectSP root(GetSP());
- for (std::pair<ConstString, bool> name : names) {
- root = root->GetChildMemberWithName(name.first, name.second);
- if (!root) {
- if (name_of_error)
- *name_of_error = name.first;
- return root;
- }
- }
- return root;
-}
-
size_t ValueObject::GetIndexOfChildWithName(llvm::StringRef name) {
bool omit_empty_base_classes = true;
return GetCompilerType().GetIndexOfChildWithName(name,
@@ -1170,7 +1152,7 @@ bool ValueObject::DumpPrintableRepresentation(
Stream &s, ValueObjectRepresentationStyle val_obj_display,
Format custom_format, PrintableRepresentationSpecialCases special,
bool do_dump_error) {
-
+
// If the ValueObject has an error, we might end up dumping the type, which
// is useful, but if we don't even have a type, then don't examine the object
// further as that's not meaningful, only the error is.
@@ -2148,11 +2130,10 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
temp_expression = temp_expression.drop_front(); // skip . or >
size_t next_sep_pos = temp_expression.find_first_of("-.[", 1);
- ConstString child_name;
if (next_sep_pos == llvm::StringRef::npos) // if no other separator just
// expand this last layer
{
- child_name.SetString(temp_expression);
+ llvm::StringRef child_name = temp_expression;
ValueObjectSP child_valobj_sp =
root->GetChildMemberWithName(child_name);
@@ -2220,8 +2201,7 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
} else // other layers do expand
{
llvm::StringRef next_separator = temp_expression.substr(next_sep_pos);
-
- child_name.SetString(temp_expression.slice(0, next_sep_pos));
+ llvm::StringRef child_name = temp_expression.slice(0, next_sep_pos);
ValueObjectSP child_valobj_sp =
root->GetChildMemberWithName(child_name);
@@ -2614,34 +2594,30 @@ ValueObjectSP ValueObject::CreateConstantValue(ConstString name) {
ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable(
lldb::DynamicValueType dynValue, bool synthValue) {
- ValueObjectSP result_sp(GetSP());
-
+ ValueObjectSP result_sp;
switch (dynValue) {
case lldb::eDynamicCanRunTarget:
case lldb::eDynamicDontRunTarget: {
- if (!result_sp->IsDynamic()) {
- if (result_sp->GetDynamicValue(dynValue))
- result_sp = result_sp->GetDynamicValue(dynValue);
- }
+ if (!IsDynamic())
+ result_sp = GetDynamicValue(dynValue);
} break;
case lldb::eNoDynamicValues: {
- if (result_sp->IsDynamic()) {
- if (result_sp->GetStaticValue())
- result_sp = result_sp->GetStaticValue();
- }
+ if (IsDynamic())
+ result_sp = GetStaticValue();
} break;
}
+ if (!result_sp)
+ result_sp = GetSP();
+ assert(result_sp);
- if (synthValue) {
- if (!result_sp->IsSynthetic()) {
- if (result_sp->GetSyntheticValue())
- result_sp = result_sp->GetSyntheticValue();
- }
- } else {
- if (result_sp->IsSynthetic()) {
- if (result_sp->GetNonSyntheticValue())
- result_sp = result_sp->GetNonSyntheticValue();
- }
+ bool is_synthetic = result_sp->IsSynthetic();
+ if (synthValue && !is_synthetic) {
+ if (auto synth_sp = result_sp->GetSyntheticValue())
+ return synth_sp;
+ }
+ if (!synthValue && is_synthetic) {
+ if (auto non_synth_sp = result_sp->GetNonSyntheticValue())
+ return non_synth_sp;
}
return result_sp;
@@ -2785,15 +2761,15 @@ ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) {
ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) {
// Only allow casts if the original type is equal or larger than the cast
- // type. We don't know how to fetch more data for all the ConstResult types,
+ // type. We don't know how to fetch more data for all the ConstResult types,
// so we can't guarantee this will work:
Status error;
CompilerType my_type = GetCompilerType();
- ExecutionContextScope *exe_scope
+ ExecutionContextScope *exe_scope
= ExecutionContext(GetExecutionContextRef())
.GetBestExecutionContextScope();
- if (compiler_type.GetByteSize(exe_scope)
+ if (compiler_type.GetByteSize(exe_scope)
<= GetCompilerType().GetByteSize(exe_scope)) {
return DoCast(compiler_type);
}
@@ -3176,3 +3152,7 @@ ValueObjectSP ValueObject::Persist() {
return persistent_var_sp->GetValueObject();
}
+
+lldb::ValueObjectSP ValueObject::GetVTable() {
+ return ValueObjectVTable::Create(*this);
+}
diff --git a/lldb/source/Core/ValueObjectSyntheticFilter.cpp b/lldb/source/Core/ValueObjectSyntheticFilter.cpp
index ad29d36ae08a..43bc532c4a04 100644
--- a/lldb/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/lldb/source/Core/ValueObjectSyntheticFilter.cpp
@@ -41,7 +41,7 @@ public:
return m_backend.GetIndexOfChildWithName(name);
}
- bool MightHaveChildren() override { return true; }
+ bool MightHaveChildren() override { return m_backend.MightHaveChildren(); }
bool Update() override { return false; }
};
@@ -163,8 +163,8 @@ bool ValueObjectSynthetic::UpdateValue() {
return false;
}
- // regenerate the synthetic filter if our typename changes
- // <rdar://problem/12424824>
+ // Regenerate the synthetic filter if our typename changes. When the (dynamic)
+ // type of an object changes, so does their synthetic filter of choice.
ConstString new_parent_type_name = m_parent->GetTypeName();
if (new_parent_type_name != m_parent_type_name) {
LLDB_LOGF(log,
@@ -311,7 +311,7 @@ ValueObjectSynthetic::GetChildMemberWithName(llvm::StringRef name,
bool can_create) {
UpdateValueIfNeeded();
- uint32_t index = GetIndexOfChildWithName(ConstString(name));
+ uint32_t index = GetIndexOfChildWithName(name);
if (index == UINT32_MAX)
return lldb::ValueObjectSP();
diff --git a/lldb/source/Core/ValueObjectVTable.cpp b/lldb/source/Core/ValueObjectVTable.cpp
new file mode 100644
index 000000000000..177ae4167a1d
--- /dev/null
+++ b/lldb/source/Core/ValueObjectVTable.cpp
@@ -0,0 +1,274 @@
+//===-- ValueObjectVTable.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/ValueObjectVTable.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ValueObjectChild.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Target/Language.h"
+#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+class ValueObjectVTableChild : public ValueObject {
+public:
+ ValueObjectVTableChild(ValueObject &parent, uint32_t func_idx,
+ uint64_t addr_size)
+ : ValueObject(parent), m_func_idx(func_idx), m_addr_size(addr_size) {
+ SetFormat(eFormatPointer);
+ SetName(ConstString(llvm::formatv("[{0}]", func_idx).str()));
+ }
+
+ ~ValueObjectVTableChild() override = default;
+
+ std::optional<uint64_t> GetByteSize() override { return m_addr_size; };
+
+ size_t CalculateNumChildren(uint32_t max) override { return 0; };
+
+ ValueType GetValueType() const override { return eValueTypeVTableEntry; };
+
+ bool IsInScope() override {
+ if (ValueObject *parent = GetParent())
+ return parent->IsInScope();
+ return false;
+ };
+
+protected:
+ bool UpdateValue() override {
+ SetValueIsValid(false);
+ m_value.Clear();
+ ValueObject *parent = GetParent();
+ if (!parent) {
+ m_error.SetErrorString("owning vtable object not valid");
+ return false;
+ }
+
+ addr_t parent_addr = parent->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ if (parent_addr == LLDB_INVALID_ADDRESS) {
+ m_error.SetErrorString("invalid vtable address");
+ return false;
+ }
+
+ ProcessSP process_sp = GetProcessSP();
+ if (!process_sp) {
+ m_error.SetErrorString("no process");
+ return false;
+ }
+
+ TargetSP target_sp = GetTargetSP();
+ if (!target_sp) {
+ m_error.SetErrorString("no target");
+ return false;
+ }
+
+ // Each `vtable_entry_addr` points to the function pointer.
+ addr_t vtable_entry_addr = parent_addr + m_func_idx * m_addr_size;
+ addr_t vfunc_ptr =
+ process_sp->ReadPointerFromMemory(vtable_entry_addr, m_error);
+ if (m_error.Fail()) {
+ m_error.SetErrorStringWithFormat(
+ "failed to read virtual function entry 0x%16.16" PRIx64,
+ vtable_entry_addr);
+ return false;
+ }
+
+
+ // Set our value to be the load address of the function pointer in memory
+ // and our type to be the function pointer type.
+ m_value.SetValueType(Value::ValueType::LoadAddress);
+ m_value.GetScalar() = vtable_entry_addr;
+
+ // See if our resolved address points to a function in the debug info. If
+ // it does, then we can report the type as a function prototype for this
+ // function.
+ Function *function = nullptr;
+ Address resolved_vfunc_ptr_address;
+ target_sp->ResolveLoadAddress(vfunc_ptr, resolved_vfunc_ptr_address);
+ if (resolved_vfunc_ptr_address.IsValid())
+ function = resolved_vfunc_ptr_address.CalculateSymbolContextFunction();
+ if (function) {
+ m_value.SetCompilerType(function->GetCompilerType().GetPointerType());
+ } else {
+ // Set our value's compiler type to a generic function protoype so that
+ // it displays as a hex function pointer for the value and the summary
+ // will display the address description.
+
+ // Get the original type that this vtable is based off of so we can get
+ // the language from it correctly.
+ ValueObject *val = parent->GetParent();
+ auto type_system = target_sp->GetScratchTypeSystemForLanguage(
+ val ? val->GetObjectRuntimeLanguage() : eLanguageTypeC_plus_plus);
+ if (type_system) {
+ m_value.SetCompilerType(
+ (*type_system)->CreateGenericFunctionPrototype().GetPointerType());
+ } else {
+ consumeError(type_system.takeError());
+ }
+ }
+
+ // Now read our value into m_data so that our we can use the default
+ // summary provider for C++ for function pointers which will get the
+ // address description for our function pointer.
+ if (m_error.Success()) {
+ const bool thread_and_frame_only_if_stopped = true;
+ ExecutionContext exe_ctx(
+ GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped));
+ m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
+ }
+ SetValueDidChange(true);
+ SetValueIsValid(true);
+ return true;
+ };
+
+ CompilerType GetCompilerTypeImpl() override {
+ return m_value.GetCompilerType();
+ };
+
+ const uint32_t m_func_idx;
+ const uint64_t m_addr_size;
+
+private:
+ // For ValueObject only
+ ValueObjectVTableChild(const ValueObjectVTableChild &) = delete;
+ const ValueObjectVTableChild &
+ operator=(const ValueObjectVTableChild &) = delete;
+};
+
+ValueObjectSP ValueObjectVTable::Create(ValueObject &parent) {
+ return (new ValueObjectVTable(parent))->GetSP();
+}
+
+ValueObjectVTable::ValueObjectVTable(ValueObject &parent)
+ : ValueObject(parent) {
+ SetFormat(eFormatPointer);
+}
+
+std::optional<uint64_t> ValueObjectVTable::GetByteSize() {
+ if (m_vtable_symbol)
+ return m_vtable_symbol->GetByteSize();
+ return std::nullopt;
+}
+
+size_t ValueObjectVTable::CalculateNumChildren(uint32_t max) {
+ if (UpdateValueIfNeeded(false))
+ return m_num_vtable_entries <= max ? m_num_vtable_entries : max;
+ return 0;
+}
+
+ValueType ValueObjectVTable::GetValueType() const { return eValueTypeVTable; }
+
+ConstString ValueObjectVTable::GetTypeName() {
+ if (m_vtable_symbol)
+ return m_vtable_symbol->GetName();
+ return ConstString();
+}
+
+ConstString ValueObjectVTable::GetQualifiedTypeName() { return GetTypeName(); }
+
+ConstString ValueObjectVTable::GetDisplayTypeName() {
+ if (m_vtable_symbol)
+ return m_vtable_symbol->GetDisplayName();
+ return ConstString();
+}
+
+bool ValueObjectVTable::IsInScope() { return GetParent()->IsInScope(); }
+
+ValueObject *ValueObjectVTable::CreateChildAtIndex(size_t idx,
+ bool synthetic_array_member,
+ int32_t synthetic_index) {
+ if (synthetic_array_member)
+ return nullptr;
+ return new ValueObjectVTableChild(*this, idx, m_addr_size);
+}
+
+bool ValueObjectVTable::UpdateValue() {
+ m_error.Clear();
+ m_flags.m_children_count_valid = false;
+ SetValueIsValid(false);
+ m_num_vtable_entries = 0;
+ ValueObject *parent = GetParent();
+ if (!parent) {
+ m_error.SetErrorString("no parent object");
+ return false;
+ }
+
+ ProcessSP process_sp = GetProcessSP();
+ if (!process_sp) {
+ m_error.SetErrorString("no process");
+ return false;
+ }
+
+ const LanguageType language = parent->GetObjectRuntimeLanguage();
+ LanguageRuntime *language_runtime = process_sp->GetLanguageRuntime(language);
+
+ if (language_runtime == nullptr) {
+ m_error.SetErrorStringWithFormat(
+ "no language runtime support for the language \"%s\"",
+ Language::GetNameForLanguageType(language));
+ return false;
+ }
+
+ // Get the vtable information from the language runtime.
+ llvm::Expected<LanguageRuntime::VTableInfo> vtable_info_or_err =
+ language_runtime->GetVTableInfo(*parent, /*check_type=*/true);
+ if (!vtable_info_or_err) {
+ m_error = vtable_info_or_err.takeError();
+ return false;
+ }
+
+ TargetSP target_sp = GetTargetSP();
+ const addr_t vtable_start_addr =
+ vtable_info_or_err->addr.GetLoadAddress(target_sp.get());
+
+ m_vtable_symbol = vtable_info_or_err->symbol;
+ if (!m_vtable_symbol) {
+ m_error.SetErrorStringWithFormat(
+ "no vtable symbol found containing 0x%" PRIx64, vtable_start_addr);
+ return false;
+ }
+
+ // Now that we know it's a vtable, we update the object's state.
+ SetName(GetTypeName());
+
+ // Calculate the number of entries
+ if (!m_vtable_symbol->GetByteSizeIsValid()) {
+ m_error.SetErrorStringWithFormat(
+ "vtable symbol \"%s\" doesn't have a valid size",
+ m_vtable_symbol->GetMangled().GetDemangledName().GetCString());
+ return false;
+ }
+
+ m_addr_size = process_sp->GetAddressByteSize();
+ const addr_t vtable_end_addr =
+ m_vtable_symbol->GetLoadAddress(target_sp.get()) +
+ m_vtable_symbol->GetByteSize();
+ m_num_vtable_entries = (vtable_end_addr - vtable_start_addr) / m_addr_size;
+
+ m_value.SetValueType(Value::ValueType::LoadAddress);
+ m_value.GetScalar() = parent->GetAddressOf();
+ auto type_system_or_err =
+ target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC_plus_plus);
+ if (type_system_or_err) {
+ m_value.SetCompilerType(
+ (*type_system_or_err)->GetBasicTypeFromAST(eBasicTypeUnsignedLong));
+ } else {
+ consumeError(type_system_or_err.takeError());
+ }
+ SetValueDidChange(true);
+ SetValueIsValid(true);
+ return true;
+}
+
+CompilerType ValueObjectVTable::GetCompilerTypeImpl() { return CompilerType(); }
+
+ValueObjectVTable::~ValueObjectVTable() = default;