aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Core
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Core')
-rw-r--r--lldb/source/Core/Communication.cpp18
-rw-r--r--lldb/source/Core/CoreProperties.td4
-rw-r--r--lldb/source/Core/Debugger.cpp38
-rw-r--r--lldb/source/Core/Disassembler.cpp92
-rw-r--r--lldb/source/Core/DynamicLoader.cpp2
-rw-r--r--lldb/source/Core/IOHandler.cpp27
-rw-r--r--lldb/source/Core/IOHandlerCursesGUI.cpp630
-rw-r--r--lldb/source/Core/Mangled.cpp12
-rw-r--r--lldb/source/Core/Module.cpp43
-rw-r--r--lldb/source/Core/ModuleList.cpp78
-rw-r--r--lldb/source/Core/PluginManager.cpp65
-rw-r--r--lldb/source/Core/SearchFilter.cpp41
-rw-r--r--lldb/source/Core/SourceManager.cpp9
-rw-r--r--lldb/source/Core/Value.cpp53
-rw-r--r--lldb/source/Core/ValueObject.cpp32
-rw-r--r--lldb/source/Core/ValueObjectCast.cpp2
-rw-r--r--lldb/source/Core/ValueObjectChild.cpp154
-rw-r--r--lldb/source/Core/ValueObjectConstResult.cpp21
-rw-r--r--lldb/source/Core/ValueObjectDynamicValue.cpp2
-rw-r--r--lldb/source/Core/ValueObjectMemory.cpp10
-rw-r--r--lldb/source/Core/ValueObjectRegister.cpp6
-rw-r--r--lldb/source/Core/ValueObjectSyntheticFilter.cpp6
-rw-r--r--lldb/source/Core/ValueObjectVariable.cpp14
23 files changed, 800 insertions, 559 deletions
diff --git a/lldb/source/Core/Communication.cpp b/lldb/source/Core/Communication.cpp
index b358e70b1a91..b50cd0ecab5c 100644
--- a/lldb/source/Core/Communication.cpp
+++ b/lldb/source/Core/Communication.cpp
@@ -199,9 +199,8 @@ bool Communication::StartReadThread(Status *error_ptr) {
LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMUNICATION),
"{0} Communication::StartReadThread ()", this);
- char thread_name[1024];
- snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>",
- GetBroadcasterName().AsCString());
+ const std::string thread_name =
+ llvm::formatv("<lldb.comm.{0}>", GetBroadcasterName());
m_read_thread_enabled = true;
m_read_thread_did_exit = false;
@@ -340,7 +339,7 @@ lldb::thread_result_t Communication::ReadThread(lldb::thread_arg_t p) {
}
if (error.Fail())
LLDB_LOG(log, "error: {0}, status = {1}", error,
- Communication::ConnectionStatusAsCString(status));
+ Communication::ConnectionStatusAsString(status));
break;
case eConnectionStatusInterrupted: // Synchronization signal from
// SynchronizeWithReadThread()
@@ -356,7 +355,7 @@ lldb::thread_result_t Communication::ReadThread(lldb::thread_arg_t p) {
case eConnectionStatusTimedOut: // Request timed out
if (error.Fail())
LLDB_LOG(log, "error: {0}, status = {1}", error,
- Communication::ConnectionStatusAsCString(status));
+ Communication::ConnectionStatusAsString(status));
break;
}
}
@@ -417,8 +416,8 @@ void Communication::SetConnection(std::unique_ptr<Connection> connection) {
m_connection_sp = std::move(connection);
}
-const char *
-Communication::ConnectionStatusAsCString(lldb::ConnectionStatus status) {
+std::string
+Communication::ConnectionStatusAsString(lldb::ConnectionStatus status) {
switch (status) {
case eConnectionStatusSuccess:
return "success";
@@ -436,8 +435,5 @@ Communication::ConnectionStatusAsCString(lldb::ConnectionStatus status) {
return "interrupted";
}
- static char unknown_state_string[64];
- snprintf(unknown_state_string, sizeof(unknown_state_string),
- "ConnectionStatus = %i", status);
- return unknown_state_string;
+ return "@" + std::to_string(status);
}
diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td
index b04738175f34..96f67801553b 100644
--- a/lldb/source/Core/CoreProperties.td
+++ b/lldb/source/Core/CoreProperties.td
@@ -131,4 +131,8 @@ let Definition = "debugger" in {
Global,
DefaultStringValue<"frame #${frame.index}: ${ansi.fg.yellow}${frame.pc}${ansi.normal}{ ${module.file.basename}{`${function.name-without-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}{${function.is-optimized} [opt]}{${frame.is-artificial} [artificial]}\\\\n">,
Desc<"The default frame format string to use when displaying stack frameinformation for threads from thread backtrace unique.">;
+ def ShowAutosuggestion: Property<"show-autosuggestion", "Boolean">,
+ Global,
+ DefaultFalse,
+ Desc<"If true, LLDB will show suggestions to complete the command the user typed.">;
}
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 5f4f1e266d81..b16ce68c2fd2 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -346,6 +346,12 @@ bool Debugger::SetUseColor(bool b) {
return ret;
}
+bool Debugger::GetUseAutosuggestion() const {
+ const uint32_t idx = ePropertyShowAutosuggestion;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_debugger_properties[idx].default_uint_value != 0);
+}
+
bool Debugger::GetUseSourceCache() const {
const uint32_t idx = ePropertyUseSourceCache;
return m_collection_sp->GetPropertyAtIndexAsBoolean(
@@ -666,9 +672,7 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
m_event_handler_thread(), m_io_handler_thread(),
m_sync_broadcaster(nullptr, "lldb.debugger.sync"),
m_forward_listener_sp(), m_clear_once() {
- char instance_cstr[256];
- snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID());
- m_instance_name.SetCString(instance_cstr);
+ m_instance_name.SetString(llvm::formatv("debugger_{0}", GetID()).str());
if (log_callback)
m_log_callback_stream_sp =
std::make_shared<StreamCallback>(log_callback, baton);
@@ -678,7 +682,16 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
assert(default_platform_sp);
m_platform_list.Append(default_platform_sp, true);
- m_dummy_target_sp = m_target_list.GetDummyTarget(*this);
+ // Create the dummy target.
+ {
+ ArchSpec arch(Target::GetDefaultArchitecture());
+ if (!arch.IsValid())
+ arch = HostInfo::GetArchitecture();
+ assert(arch.IsValid() && "No valid default or host archspec");
+ const bool is_dummy_target = true;
+ m_dummy_target_sp.reset(
+ new Target(*this, arch, default_platform_sp, is_dummy_target));
+ }
assert(m_dummy_target_sp.get() && "Couldn't construct dummy target?");
m_collection_sp->Initialize(g_debugger_properties);
@@ -778,7 +791,7 @@ repro::DataRecorder *Debugger::GetInputRecorder() { return m_input_recorder; }
void Debugger::SetInputFile(FileSP file_sp, repro::DataRecorder *recorder) {
assert(file_sp && file_sp->IsValid());
m_input_recorder = recorder;
- m_input_file_sp = file_sp;
+ m_input_file_sp = std::move(file_sp);
// Save away the terminal state if that is relevant, so that we can restore
// it in RestoreInputState.
SaveInputTerminalState();
@@ -1160,11 +1173,11 @@ bool Debugger::EnableLog(llvm::StringRef channel,
flags |= File::eOpenOptionAppend;
else
flags |= File::eOpenOptionTruncate;
- auto file = FileSystem::Instance().Open(
+ llvm::Expected<FileUP> file = FileSystem::Instance().Open(
FileSpec(log_file), flags, lldb::eFilePermissionsFileDefault, false);
if (!file) {
- // FIXME: This gets garbled when called from the log command.
- error_stream << "Unable to open log file: " << log_file;
+ error_stream << "Unable to open log file '" << log_file
+ << "': " << llvm::toString(file.takeError()) << "\n";
return false;
}
@@ -1565,14 +1578,11 @@ void Debugger::JoinIOHandlerThread() {
}
}
-Target *Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) {
- Target *target = nullptr;
+Target &Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) {
if (!prefer_dummy) {
- target = m_target_list.GetSelectedTarget().get();
- if (target)
- return target;
+ if (TargetSP target = m_target_list.GetSelectedTarget())
+ return *target;
}
-
return GetDummyTarget();
}
diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp
index 4da823c7a243..3a975d9296f4 100644
--- a/lldb/source/Core/Disassembler.cpp
+++ b/lldb/source/Core/Disassembler.cpp
@@ -58,9 +58,7 @@ using namespace lldb_private;
DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch,
const char *flavor,
const char *plugin_name) {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat,
- "Disassembler::FindPlugin (arch = %s, plugin_name = %s)",
+ LLDB_SCOPED_TIMERF("Disassembler::FindPlugin (arch = %s, plugin_name = %s)",
arch.GetArchitectureName(), plugin_name);
DisassemblerCreateInstance create_callback = nullptr;
@@ -540,34 +538,29 @@ void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch,
}
bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
- const char *plugin_name, const char *flavor,
- const ExecutionContext &exe_ctx,
- uint32_t num_instructions,
- bool mixed_source_and_assembly,
- uint32_t num_mixed_context_lines,
- uint32_t options, Stream &strm) {
+ StackFrame &frame, Stream &strm) {
AddressRange range;
- StackFrame *frame = exe_ctx.GetFramePtr();
- if (frame) {
- SymbolContext sc(
- frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
- if (sc.function) {
- range = sc.function->GetAddressRange();
- } else if (sc.symbol && sc.symbol->ValueIsAddress()) {
- range.GetBaseAddress() = sc.symbol->GetAddressRef();
- range.SetByteSize(sc.symbol->GetByteSize());
- } else {
- range.GetBaseAddress() = frame->GetFrameCodeAddress();
- }
+ SymbolContext sc(
+ frame.GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
+ if (sc.function) {
+ range = sc.function->GetAddressRange();
+ } else if (sc.symbol && sc.symbol->ValueIsAddress()) {
+ range.GetBaseAddress() = sc.symbol->GetAddressRef();
+ range.SetByteSize(sc.symbol->GetByteSize());
+ } else {
+ range.GetBaseAddress() = frame.GetFrameCodeAddress();
+ }
if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
- }
- return Disassemble(
- debugger, arch, plugin_name, flavor, exe_ctx, range.GetBaseAddress(),
- {Limit::Instructions, num_instructions}, mixed_source_and_assembly,
- num_mixed_context_lines, options, strm);
+ Disassembler::Limit limit = {Disassembler::Limit::Bytes,
+ range.GetByteSize()};
+ if (limit.value == 0)
+ limit.value = DEFAULT_DISASM_BYTE_SIZE;
+
+ return Disassemble(debugger, arch, nullptr, nullptr, frame,
+ range.GetBaseAddress(), limit, false, 0, 0, strm);
}
Instruction::Instruction(const Address &address, AddressClass addr_class)
@@ -957,6 +950,13 @@ InstructionSP InstructionList::GetInstructionAtIndex(size_t idx) const {
return inst_sp;
}
+InstructionSP InstructionList::GetInstructionAtAddress(const Address &address) {
+ uint32_t index = GetIndexOfInstructionAtAddress(address);
+ if (index != UINT32_MAX)
+ return GetInstructionAtIndex(index);
+ return nullptr;
+}
+
void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes,
const ExecutionContext *exe_ctx) {
const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize();
@@ -990,17 +990,15 @@ void InstructionList::Append(lldb::InstructionSP &inst_sp) {
uint32_t
InstructionList::GetIndexOfNextBranchInstruction(uint32_t start,
- Target &target,
bool ignore_calls,
bool *found_calls) const {
size_t num_instructions = m_instructions.size();
uint32_t next_branch = UINT32_MAX;
- size_t i;
if (found_calls)
*found_calls = false;
- for (i = start; i < num_instructions; i++) {
+ for (size_t i = start; i < num_instructions; i++) {
if (m_instructions[i]->DoesBranch()) {
if (ignore_calls && m_instructions[i]->IsCall()) {
if (found_calls)
@@ -1012,42 +1010,6 @@ InstructionList::GetIndexOfNextBranchInstruction(uint32_t start,
}
}
- // Hexagon needs the first instruction of the packet with the branch. Go
- // backwards until we find an instruction marked end-of-packet, or until we
- // hit start.
- if (target.GetArchitecture().GetTriple().getArch() == llvm::Triple::hexagon) {
- // If we didn't find a branch, find the last packet start.
- if (next_branch == UINT32_MAX) {
- i = num_instructions - 1;
- }
-
- while (i > start) {
- --i;
-
- Status error;
- uint32_t inst_bytes;
- bool prefer_file_cache = false; // Read from process if process is running
- lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
- target.ReadMemory(m_instructions[i]->GetAddress(), prefer_file_cache,
- &inst_bytes, sizeof(inst_bytes), error, &load_addr);
- // If we have an error reading memory, return start
- if (!error.Success())
- return start;
- // check if this is the last instruction in a packet bits 15:14 will be
- // 11b or 00b for a duplex
- if (((inst_bytes & 0xC000) == 0xC000) ||
- ((inst_bytes & 0xC000) == 0x0000)) {
- // instruction after this should be the start of next packet
- next_branch = i + 1;
- break;
- }
- }
-
- if (next_branch == UINT32_MAX) {
- // We couldn't find the previous packet, so return start
- next_branch = start;
- }
- }
return next_branch;
}
diff --git a/lldb/source/Core/DynamicLoader.cpp b/lldb/source/Core/DynamicLoader.cpp
index ceccbe437e1d..22cb9f18147a 100644
--- a/lldb/source/Core/DynamicLoader.cpp
+++ b/lldb/source/Core/DynamicLoader.cpp
@@ -60,8 +60,6 @@ DynamicLoader *DynamicLoader::FindPlugin(Process *process,
DynamicLoader::DynamicLoader(Process *process) : m_process(process) {}
-DynamicLoader::~DynamicLoader() = default;
-
// Accessosors to the global setting as to whether to stop at image (shared
// library) loading/unloading.
diff --git a/lldb/source/Core/IOHandler.cpp b/lldb/source/Core/IOHandler.cpp
index 6cf09aaa7f9d..8c654d9d8a98 100644
--- a/lldb/source/Core/IOHandler.cpp
+++ b/lldb/source/Core/IOHandler.cpp
@@ -18,6 +18,7 @@
#include "lldb/Host/Config.h"
#include "lldb/Host/File.h"
#include "lldb/Utility/Predicate.h"
+#include "lldb/Utility/ReproducerProvider.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StringList.h"
@@ -102,11 +103,11 @@ FILE *IOHandler::GetErrorFILE() {
return (m_error_sp ? m_error_sp->GetFile().GetStream() : nullptr);
}
-FileSP &IOHandler::GetInputFileSP() { return m_input_sp; }
+FileSP IOHandler::GetInputFileSP() { return m_input_sp; }
-StreamFileSP &IOHandler::GetOutputStreamFileSP() { return m_output_sp; }
+StreamFileSP IOHandler::GetOutputStreamFileSP() { return m_output_sp; }
-StreamFileSP &IOHandler::GetErrorStreamFileSP() { return m_error_sp; }
+StreamFileSP IOHandler::GetErrorStreamFileSP() { return m_error_sp; }
bool IOHandler::GetIsInteractive() {
return GetInputFileSP() ? GetInputFileSP()->GetIsInteractive() : false;
@@ -195,6 +196,14 @@ void IOHandlerConfirm::IOHandlerInputComplete(IOHandler &io_handler,
}
}
+llvm::Optional<std::string>
+IOHandlerDelegate::IOHandlerSuggestion(IOHandler &io_handler,
+ llvm::StringRef line) {
+ return io_handler.GetDebugger()
+ .GetCommandInterpreter()
+ .GetAutoSuggestionForCommand(line);
+}
+
void IOHandlerDelegate::IOHandlerComplete(IOHandler &io_handler,
CompletionRequest &request) {
switch (m_completion) {
@@ -258,6 +267,8 @@ IOHandlerEditline::IOHandlerEditline(
m_color_prompts);
m_editline_up->SetIsInputCompleteCallback(IsInputCompleteCallback, this);
m_editline_up->SetAutoCompleteCallback(AutoCompleteCallback, this);
+ if (debugger.GetUseAutosuggestion() && debugger.GetUseColor())
+ m_editline_up->SetSuggestionCallback(SuggestionCallback, this);
// See if the delegate supports fixing indentation
const char *indent_chars = delegate.IOHandlerGetFixIndentationCharacters();
if (indent_chars) {
@@ -430,6 +441,16 @@ int IOHandlerEditline::FixIndentationCallback(Editline *editline,
*editline_reader, lines, cursor_position);
}
+llvm::Optional<std::string>
+IOHandlerEditline::SuggestionCallback(llvm::StringRef line, void *baton) {
+ IOHandlerEditline *editline_reader = static_cast<IOHandlerEditline *>(baton);
+ if (editline_reader)
+ return editline_reader->m_delegate.IOHandlerSuggestion(*editline_reader,
+ line);
+
+ return llvm::None;
+}
+
void IOHandlerEditline::AutoCompleteCallback(CompletionRequest &request,
void *baton) {
IOHandlerEditline *editline_reader = (IOHandlerEditline *)baton;
diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp
index f8fc91772198..19066e6be623 100644
--- a/lldb/source/Core/IOHandlerCursesGUI.cpp
+++ b/lldb/source/Core/IOHandlerCursesGUI.cpp
@@ -10,9 +10,14 @@
#include "lldb/Host/Config.h"
#if LLDB_ENABLE_CURSES
+#if CURSES_HAVE_NCURSES_CURSES_H
+#include <ncurses/curses.h>
+#include <ncurses/panel.h>
+#else
#include <curses.h>
#include <panel.h>
#endif
+#endif
#if defined(__APPLE__)
#include <deque>
@@ -268,6 +273,32 @@ struct KeyHelp {
const char *description;
};
+// COLOR_PAIR index names
+enum {
+ // First 16 colors are 8 black background and 8 blue background colors,
+ // needed by OutputColoredStringTruncated().
+ BlackOnBlack = 1,
+ RedOnBlack,
+ GreenOnBlack,
+ YellowOnBlack,
+ BlueOnBlack,
+ MagentaOnBlack,
+ CyanOnBlack,
+ WhiteOnBlack,
+ BlackOnBlue,
+ RedOnBlue,
+ GreenOnBlue,
+ YellowOnBlue,
+ BlueOnBlue,
+ MagentaOnBlue,
+ CyanOnBlue,
+ WhiteOnBlue,
+ // Other colors, as needed.
+ BlackOnWhite,
+ MagentaOnWhite,
+ LastColorPairIndex = MagentaOnWhite
+};
+
class WindowDelegate {
public:
virtual ~WindowDelegate() = default;
@@ -362,23 +393,23 @@ public:
}
void Clear() { ::wclear(m_window); }
void Erase() { ::werase(m_window); }
- Rect GetBounds() {
+ Rect GetBounds() const {
return Rect(GetParentOrigin(), GetSize());
} // Get the rectangle in our parent window
int GetChar() { return ::wgetch(m_window); }
- int GetCursorX() { return getcurx(m_window); }
- int GetCursorY() { return getcury(m_window); }
- Rect GetFrame() {
+ int GetCursorX() const { return getcurx(m_window); }
+ int GetCursorY() const { return getcury(m_window); }
+ Rect GetFrame() const {
return Rect(Point(), GetSize());
} // Get our rectangle in our own coordinate system
- Point GetParentOrigin() { return Point(GetParentX(), GetParentY()); }
- Size GetSize() { return Size(GetWidth(), GetHeight()); }
- int GetParentX() { return getparx(m_window); }
- int GetParentY() { return getpary(m_window); }
- int GetMaxX() { return getmaxx(m_window); }
- int GetMaxY() { return getmaxy(m_window); }
- int GetWidth() { return GetMaxX(); }
- int GetHeight() { return GetMaxY(); }
+ Point GetParentOrigin() const { return Point(GetParentX(), GetParentY()); }
+ Size GetSize() const { return Size(GetWidth(), GetHeight()); }
+ int GetParentX() const { return getparx(m_window); }
+ int GetParentY() const { return getpary(m_window); }
+ int GetMaxX() const { return getmaxx(m_window); }
+ int GetMaxY() const { return getmaxy(m_window); }
+ int GetWidth() const { return GetMaxX(); }
+ int GetHeight() const { return GetMaxY(); }
void MoveCursor(int x, int y) { ::wmove(m_window, y, x); }
void MoveWindow(int x, int y) { MoveWindow(Point(x, y)); }
void Resize(int w, int h) { ::wresize(m_window, h, w); }
@@ -391,11 +422,11 @@ public:
::wbkgd(m_window, COLOR_PAIR(color_pair_idx));
}
- void PutCStringTruncated(const char *s, int right_pad) {
+ void PutCStringTruncated(int right_pad, const char *s, int len = -1) {
int bytes_left = GetWidth() - GetCursorX();
if (bytes_left > right_pad) {
bytes_left -= right_pad;
- ::waddnstr(m_window, s, bytes_left);
+ ::waddnstr(m_window, s, len < 0 ? bytes_left : std::min(bytes_left, len));
}
}
@@ -433,6 +464,93 @@ public:
va_end(args);
}
+ void PrintfTruncated(int right_pad, const char *format, ...)
+ __attribute__((format(printf, 3, 4))) {
+ va_list args;
+ va_start(args, format);
+ StreamString strm;
+ strm.PrintfVarArg(format, args);
+ va_end(args);
+ PutCStringTruncated(right_pad, strm.GetData());
+ }
+
+ size_t LimitLengthToRestOfLine(size_t length) const {
+ return std::min<size_t>(length, std::max(0, GetWidth() - GetCursorX() - 1));
+ }
+
+ // Curses doesn't allow direct output of color escape sequences, but that's
+ // how we get source lines from the Highligher class. Read the line and
+ // convert color escape sequences to curses color attributes. Use
+ // first_skip_count to skip leading visible characters. Returns false if all
+ // visible characters were skipped due to first_skip_count.
+ bool OutputColoredStringTruncated(int right_pad, StringRef string,
+ size_t skip_first_count,
+ bool use_blue_background) {
+ attr_t saved_attr;
+ short saved_pair;
+ bool result = false;
+ wattr_get(m_window, &saved_attr, &saved_pair, nullptr);
+ if (use_blue_background)
+ ::wattron(m_window, COLOR_PAIR(WhiteOnBlue));
+ while (!string.empty()) {
+ size_t esc_pos = string.find('\x1b');
+ if (esc_pos == StringRef::npos) {
+ string = string.substr(skip_first_count);
+ if (!string.empty()) {
+ PutCStringTruncated(right_pad, string.data(), string.size());
+ result = true;
+ }
+ break;
+ }
+ if (esc_pos > 0) {
+ if (skip_first_count > 0) {
+ int skip = std::min(esc_pos, skip_first_count);
+ string = string.substr(skip);
+ skip_first_count -= skip;
+ esc_pos -= skip;
+ }
+ if (esc_pos > 0) {
+ PutCStringTruncated(right_pad, string.data(), esc_pos);
+ result = true;
+ string = string.drop_front(esc_pos);
+ }
+ }
+ bool consumed = string.consume_front("\x1b");
+ assert(consumed);
+ UNUSED_IF_ASSERT_DISABLED(consumed);
+ // This is written to match our Highlighter classes, which seem to
+ // generate only foreground color escape sequences. If necessary, this
+ // will need to be extended.
+ if (!string.consume_front("[")) {
+ llvm::errs() << "Missing '[' in color escape sequence.\n";
+ continue;
+ }
+ // Only 8 basic foreground colors and reset, our Highlighter doesn't use
+ // anything else.
+ int value;
+ if (!!string.consumeInteger(10, value) || // Returns false on success.
+ !(value == 0 || (value >= 30 && value <= 37))) {
+ llvm::errs() << "No valid color code in color escape sequence.\n";
+ continue;
+ }
+ if (!string.consume_front("m")) {
+ llvm::errs() << "Missing 'm' in color escape sequence.\n";
+ continue;
+ }
+ if (value == 0) { // Reset.
+ wattr_set(m_window, saved_attr, saved_pair, nullptr);
+ if (use_blue_background)
+ ::wattron(m_window, COLOR_PAIR(WhiteOnBlue));
+ } else {
+ // Mapped directly to first 16 color pairs (black/blue background).
+ ::wattron(m_window,
+ COLOR_PAIR(value - 30 + 1 + (use_blue_background ? 8 : 0)));
+ }
+ }
+ wattr_set(m_window, saved_attr, saved_pair, nullptr);
+ return result;
+ }
+
void Touch() {
::touchwin(m_window);
if (m_parent)
@@ -521,7 +639,7 @@ public:
void DrawTitleBox(const char *title, const char *bottom_message = nullptr) {
attr_t attr = 0;
if (IsActive())
- attr = A_BOLD | COLOR_PAIR(2);
+ attr = A_BOLD | COLOR_PAIR(BlackOnWhite);
else
attr = 0;
if (attr)
@@ -548,7 +666,7 @@ public:
} else {
MoveCursor(1, GetHeight() - 1);
PutChar('[');
- PutCStringTruncated(bottom_message, 1);
+ PutCStringTruncated(1, bottom_message);
}
}
if (attr)
@@ -687,42 +805,44 @@ public:
void SelectNextWindowAsActive() {
// Move active focus to next window
- const size_t num_subwindows = m_subwindows.size();
- if (m_curr_active_window_idx == UINT32_MAX) {
- uint32_t idx = 0;
- for (auto subwindow_sp : m_subwindows) {
- if (subwindow_sp->GetCanBeActive()) {
- m_curr_active_window_idx = idx;
- break;
- }
- ++idx;
- }
- } else if (m_curr_active_window_idx + 1 < num_subwindows) {
- bool handled = false;
+ const int num_subwindows = m_subwindows.size();
+ int start_idx = 0;
+ if (m_curr_active_window_idx != UINT32_MAX) {
m_prev_active_window_idx = m_curr_active_window_idx;
- for (size_t idx = m_curr_active_window_idx + 1; idx < num_subwindows;
- ++idx) {
- if (m_subwindows[idx]->GetCanBeActive()) {
- m_curr_active_window_idx = idx;
- handled = true;
- break;
- }
+ start_idx = m_curr_active_window_idx + 1;
+ }
+ for (int idx = start_idx; idx < num_subwindows; ++idx) {
+ if (m_subwindows[idx]->GetCanBeActive()) {
+ m_curr_active_window_idx = idx;
+ return;
}
- if (!handled) {
- for (size_t idx = 0; idx <= m_prev_active_window_idx; ++idx) {
- if (m_subwindows[idx]->GetCanBeActive()) {
- m_curr_active_window_idx = idx;
- break;
- }
- }
+ }
+ for (int idx = 0; idx < start_idx; ++idx) {
+ if (m_subwindows[idx]->GetCanBeActive()) {
+ m_curr_active_window_idx = idx;
+ break;
}
- } else {
+ }
+ }
+
+ void SelectPreviousWindowAsActive() {
+ // Move active focus to previous window
+ const int num_subwindows = m_subwindows.size();
+ int start_idx = num_subwindows - 1;
+ if (m_curr_active_window_idx != UINT32_MAX) {
m_prev_active_window_idx = m_curr_active_window_idx;
- for (size_t idx = 0; idx < num_subwindows; ++idx) {
- if (m_subwindows[idx]->GetCanBeActive()) {
- m_curr_active_window_idx = idx;
- break;
- }
+ start_idx = m_curr_active_window_idx - 1;
+ }
+ for (int idx = start_idx; idx >= 0; --idx) {
+ if (m_subwindows[idx]->GetCanBeActive()) {
+ m_curr_active_window_idx = idx;
+ return;
+ }
+ }
+ for (int idx = num_subwindows - 1; idx > start_idx; --idx) {
+ if (m_subwindows[idx]->GetCanBeActive()) {
+ m_curr_active_window_idx = idx;
+ break;
}
}
}
@@ -916,9 +1036,9 @@ void Menu::DrawMenuTitle(Window &window, bool highlight) {
} else {
const int shortcut_key = m_key_value;
bool underlined_shortcut = false;
- const attr_t hilgight_attr = A_REVERSE;
+ const attr_t highlight_attr = A_REVERSE;
if (highlight)
- window.AttributeOn(hilgight_attr);
+ window.AttributeOn(highlight_attr);
if (llvm::isPrint(shortcut_key)) {
size_t lower_pos = m_name.find(tolower(shortcut_key));
size_t upper_pos = m_name.find(toupper(shortcut_key));
@@ -945,18 +1065,18 @@ void Menu::DrawMenuTitle(Window &window, bool highlight) {
}
if (highlight)
- window.AttributeOff(hilgight_attr);
+ window.AttributeOff(highlight_attr);
if (m_key_name.empty()) {
if (!underlined_shortcut && llvm::isPrint(m_key_value)) {
- window.AttributeOn(COLOR_PAIR(3));
+ window.AttributeOn(COLOR_PAIR(MagentaOnWhite));
window.Printf(" (%c)", m_key_value);
- window.AttributeOff(COLOR_PAIR(3));
+ window.AttributeOff(COLOR_PAIR(MagentaOnWhite));
}
} else {
- window.AttributeOn(COLOR_PAIR(3));
+ window.AttributeOn(COLOR_PAIR(MagentaOnWhite));
window.Printf(" (%s)", m_key_name.c_str());
- window.AttributeOff(COLOR_PAIR(3));
+ window.AttributeOff(COLOR_PAIR(MagentaOnWhite));
}
}
}
@@ -968,7 +1088,7 @@ bool Menu::WindowDelegateDraw(Window &window, bool force) {
Menu::Type menu_type = GetType();
switch (menu_type) {
case Menu::Type::Bar: {
- window.SetBackground(2);
+ window.SetBackground(BlackOnWhite);
window.MoveCursor(0, 0);
for (size_t i = 0; i < num_submenus; ++i) {
Menu *menu = submenus[i].get();
@@ -988,7 +1108,7 @@ bool Menu::WindowDelegateDraw(Window &window, bool force) {
int cursor_x = 0;
int cursor_y = 0;
window.Erase();
- window.SetBackground(2);
+ window.SetBackground(BlackOnWhite);
window.Box();
for (size_t i = 0; i < num_submenus; ++i) {
const bool is_selected = (i == static_cast<size_t>(selected_idx));
@@ -1189,18 +1309,16 @@ public:
ListenerSP listener_sp(
Listener::MakeListener("lldb.IOHandler.curses.Application"));
- ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
- ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
debugger.EnableForwardEvents(listener_sp);
- bool update = true;
+ m_update_screen = true;
#if defined(__APPLE__)
std::deque<int> escape_chars;
#endif
while (!done) {
- if (update) {
+ if (m_update_screen) {
m_window_sp->Draw(false);
// All windows should be calling Window::DeferredRefresh() instead of
// Window::Refresh() so we can do a single update and avoid any screen
@@ -1212,7 +1330,7 @@ public:
m_window_sp->MoveCursor(0, 0);
doupdate();
- update = false;
+ m_update_screen = false;
}
#if defined(__APPLE__)
@@ -1274,7 +1392,7 @@ public:
if (broadcaster_class == broadcaster_class_process) {
debugger.GetCommandInterpreter().UpdateExecutionContext(
nullptr);
- update = true;
+ m_update_screen = true;
continue; // Don't get any key, just update our view
}
}
@@ -1286,9 +1404,13 @@ public:
switch (key_result) {
case eKeyHandled:
debugger.GetCommandInterpreter().UpdateExecutionContext(nullptr);
- update = true;
+ m_update_screen = true;
break;
case eKeyNotHandled:
+ if (ch == 12) { // Ctrl+L, force full redraw
+ redrawwin(m_window_sp->get());
+ m_update_screen = true;
+ }
break;
case eQuitApplication:
done = true;
@@ -1306,12 +1428,65 @@ public:
return m_window_sp;
}
+ void TerminalSizeChanged() {
+ ::endwin();
+ ::refresh();
+ Rect content_bounds = m_window_sp->GetFrame();
+ m_window_sp->SetBounds(content_bounds);
+ if (WindowSP menubar_window_sp = m_window_sp->FindSubWindow("Menubar"))
+ menubar_window_sp->SetBounds(content_bounds.MakeMenuBar());
+ if (WindowSP status_window_sp = m_window_sp->FindSubWindow("Status"))
+ status_window_sp->SetBounds(content_bounds.MakeStatusBar());
+
+ WindowSP source_window_sp = m_window_sp->FindSubWindow("Source");
+ WindowSP variables_window_sp = m_window_sp->FindSubWindow("Variables");
+ WindowSP registers_window_sp = m_window_sp->FindSubWindow("Registers");
+ WindowSP threads_window_sp = m_window_sp->FindSubWindow("Threads");
+
+ Rect threads_bounds;
+ Rect source_variables_bounds;
+ content_bounds.VerticalSplitPercentage(0.80, source_variables_bounds,
+ threads_bounds);
+ if (threads_window_sp)
+ threads_window_sp->SetBounds(threads_bounds);
+ else
+ source_variables_bounds = content_bounds;
+
+ Rect source_bounds;
+ Rect variables_registers_bounds;
+ source_variables_bounds.HorizontalSplitPercentage(
+ 0.70, source_bounds, variables_registers_bounds);
+ if (variables_window_sp || registers_window_sp) {
+ if (variables_window_sp && registers_window_sp) {
+ Rect variables_bounds;
+ Rect registers_bounds;
+ variables_registers_bounds.VerticalSplitPercentage(
+ 0.50, variables_bounds, registers_bounds);
+ variables_window_sp->SetBounds(variables_bounds);
+ registers_window_sp->SetBounds(registers_bounds);
+ } else if (variables_window_sp) {
+ variables_window_sp->SetBounds(variables_registers_bounds);
+ } else {
+ registers_window_sp->SetBounds(variables_registers_bounds);
+ }
+ } else {
+ source_bounds = source_variables_bounds;
+ }
+
+ source_window_sp->SetBounds(source_bounds);
+
+ touchwin(stdscr);
+ redrawwin(m_window_sp->get());
+ m_update_screen = true;
+ }
+
protected:
WindowSP m_window_sp;
WindowDelegates m_window_delegates;
SCREEN *m_screen;
FILE *m_in;
FILE *m_out;
+ bool m_update_screen = false;
};
} // namespace curses
@@ -1322,19 +1497,18 @@ struct Row {
ValueObjectManager value;
Row *parent;
// The process stop ID when the children were calculated.
- uint32_t children_stop_id;
- int row_idx;
- int x;
- int y;
+ uint32_t children_stop_id = 0;
+ int row_idx = 0;
+ int x = 1;
+ int y = 1;
bool might_have_children;
- bool expanded;
- bool calculated_children;
+ bool expanded = false;
+ bool calculated_children = false;
std::vector<Row> children;
Row(const ValueObjectSP &v, Row *p)
- : value(v, lldb::eDynamicDontRunTarget, true), parent(p), row_idx(0),
- x(1), y(1), might_have_children(v ? v->MightHaveChildren() : false),
- expanded(false), calculated_children(false), children() {}
+ : value(v, lldb::eDynamicDontRunTarget, true), parent(p),
+ might_have_children(v ? v->MightHaveChildren() : false) {}
size_t GetDepth() const {
if (parent)
@@ -1849,7 +2023,7 @@ public:
if (FormatEntity::Format(m_format, strm, &sc, &exe_ctx, nullptr,
nullptr, false, false)) {
int right_pad = 1;
- window.PutCStringTruncated(strm.GetString().str().c_str(), right_pad);
+ window.PutCStringTruncated(right_pad, strm.GetString().str().c_str());
}
}
}
@@ -1908,7 +2082,7 @@ public:
if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr,
nullptr, false, false)) {
int right_pad = 1;
- window.PutCStringTruncated(strm.GetString().str().c_str(), right_pad);
+ window.PutCStringTruncated(right_pad, strm.GetString().str().c_str());
}
}
}
@@ -1998,7 +2172,7 @@ public:
if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr,
nullptr, false, false)) {
int right_pad = 1;
- window.PutCStringTruncated(strm.GetString().str().c_str(), right_pad);
+ window.PutCStringTruncated(right_pad, strm.GetString().str().c_str());
}
}
}
@@ -2301,29 +2475,29 @@ protected:
window.AttributeOn(A_REVERSE);
if (type_name && type_name[0])
- window.Printf("(%s) ", type_name);
+ window.PrintfTruncated(1, "(%s) ", type_name);
if (name && name[0])
- window.PutCString(name);
+ window.PutCStringTruncated(1, name);
attr_t changd_attr = 0;
if (valobj->GetValueDidChange())
- changd_attr = COLOR_PAIR(5) | A_BOLD;
+ changd_attr = COLOR_PAIR(RedOnBlack) | A_BOLD;
if (value && value[0]) {
- window.PutCString(" = ");
+ window.PutCStringTruncated(1, " = ");
if (changd_attr)
window.AttributeOn(changd_attr);
- window.PutCString(value);
+ window.PutCStringTruncated(1, value);
if (changd_attr)
window.AttributeOff(changd_attr);
}
if (summary && summary[0]) {
- window.PutChar(' ');
+ window.PutCStringTruncated(1, " ");
if (changd_attr)
window.AttributeOn(changd_attr);
- window.PutCString(summary);
+ window.PutCStringTruncated(1, summary);
if (changd_attr)
window.AttributeOff(changd_attr);
}
@@ -2761,7 +2935,7 @@ bool HelpDialogDelegate::WindowDelegateDraw(Window &window, bool force) {
while (y <= max_y) {
window.MoveCursor(x, y);
window.PutCStringTruncated(
- m_text.GetStringAtIndex(m_first_visible_line + y - min_y), 1);
+ 1, m_text.GetStringAtIndex(m_first_visible_line + y - min_y));
++y;
}
return true;
@@ -2831,7 +3005,8 @@ public:
eMenuID_Process,
eMenuID_ProcessAttach,
- eMenuID_ProcessDetach,
+ eMenuID_ProcessDetachResume,
+ eMenuID_ProcessDetachSuspended,
eMenuID_ProcessLaunch,
eMenuID_ProcessContinue,
eMenuID_ProcessHalt,
@@ -2867,6 +3042,10 @@ public:
window.SelectNextWindowAsActive();
return eKeyHandled;
+ case KEY_BTAB:
+ window.SelectPreviousWindowAsActive();
+ return eKeyHandled;
+
case 'h':
window.CreateHelpSubwindow();
return eKeyHandled;
@@ -2891,6 +3070,7 @@ public:
KeyHelp *WindowDelegateGetKeyHelp() override {
static curses::KeyHelp g_source_view_key_help[] = {
{'\t', "Select next view"},
+ {KEY_BTAB, "Select previous view"},
{'h', "Show help dialog with view specific key bindings"},
{',', "Page up"},
{'.', "Page down"},
@@ -2976,13 +3156,15 @@ public:
}
return MenuActionResult::Handled;
- case eMenuID_ProcessDetach: {
+ case eMenuID_ProcessDetachResume:
+ case eMenuID_ProcessDetachSuspended: {
ExecutionContext exe_ctx =
m_debugger.GetCommandInterpreter().GetExecutionContext();
if (exe_ctx.HasProcessScope()) {
Process *process = exe_ctx.GetProcessPtr();
if (process && process->IsAlive())
- process->Detach(false);
+ process->Detach(menu.GetIdentifier() ==
+ eMenuID_ProcessDetachSuspended);
}
}
return MenuActionResult::Handled;
@@ -3072,7 +3254,7 @@ public:
new_registers_rect);
registers_window_sp->SetBounds(new_registers_rect);
} else {
- // No variables window, grab the bottom part of the source window
+ // No registers window, grab the bottom part of the source window
Rect new_source_rect;
source_bounds.HorizontalSplitPercentage(0.70, new_source_rect,
new_variables_rect);
@@ -3123,7 +3305,7 @@ public:
new_regs_rect);
variables_window_sp->SetBounds(new_vars_rect);
} else {
- // No registers window, grab the bottom part of the source window
+ // No variables window, grab the bottom part of the source window
Rect new_source_rect;
source_bounds.HorizontalSplitPercentage(0.70, new_source_rect,
new_regs_rect);
@@ -3169,7 +3351,7 @@ public:
Thread *thread = exe_ctx.GetThreadPtr();
StackFrame *frame = exe_ctx.GetFramePtr();
window.Erase();
- window.SetBackground(2);
+ window.SetBackground(BlackOnWhite);
window.MoveCursor(0, 0);
if (process) {
const StateType state = process->GetState();
@@ -3181,7 +3363,7 @@ public:
if (thread && FormatEntity::Format(m_format, strm, nullptr, &exe_ctx,
nullptr, nullptr, false, false)) {
window.MoveCursor(40, 0);
- window.PutCStringTruncated(strm.GetString().str().c_str(), 1);
+ window.PutCStringTruncated(1, strm.GetString().str().c_str());
}
window.MoveCursor(60, 0);
@@ -3214,7 +3396,8 @@ public:
m_disassembly_scope(nullptr), m_disassembly_sp(), m_disassembly_range(),
m_title(), m_line_width(4), m_selected_line(0), m_pc_line(0),
m_stop_id(0), m_frame_idx(UINT32_MAX), m_first_visible_line(0),
- m_min_x(0), m_min_y(0), m_max_x(0), m_max_y(0) {}
+ m_first_visible_column(0), m_min_x(0), m_min_y(0), m_max_x(0),
+ m_max_y(0) {}
~SourceFileWindowDelegate() override = default;
@@ -3231,19 +3414,21 @@ public:
{KEY_RETURN, "Run to selected line with one shot breakpoint"},
{KEY_UP, "Select previous source line"},
{KEY_DOWN, "Select next source line"},
+ {KEY_LEFT, "Scroll to the left"},
+ {KEY_RIGHT, "Scroll to the right"},
{KEY_PPAGE, "Page up"},
{KEY_NPAGE, "Page down"},
{'b', "Set breakpoint on selected source/disassembly line"},
{'c', "Continue process"},
- {'d', "Detach and resume process"},
{'D', "Detach with process suspended"},
{'h', "Show help dialog"},
- {'k', "Kill process"},
{'n', "Step over (source line)"},
{'N', "Step over (single instruction)"},
- {'o', "Step out"},
+ {'f', "Step out (finish)"},
{'s', "Step in (source line)"},
{'S', "Step in (single instruction)"},
+ {'u', "Frame up"},
+ {'d', "Frame down"},
{',', "Page up"},
{'.', "Page down"},
{'\0', nullptr}};
@@ -3407,7 +3592,7 @@ public:
window.AttributeOn(A_REVERSE);
window.MoveCursor(1, 1);
window.PutChar(' ');
- window.PutCStringTruncated(m_title.GetString().str().c_str(), 1);
+ window.PutCStringTruncated(1, m_title.GetString().str().c_str());
int x = window.GetCursorX();
if (x < window_width - 1) {
window.Printf("%*s", window_width - x - 1, "");
@@ -3441,7 +3626,7 @@ public:
}
const attr_t selected_highlight_attr = A_REVERSE;
- const attr_t pc_highlight_attr = COLOR_PAIR(1);
+ const attr_t pc_highlight_attr = COLOR_PAIR(BlackOnBlue);
for (size_t i = 0; i < num_visible_lines; ++i) {
const uint32_t curr_line = m_first_visible_line + i;
@@ -3460,7 +3645,7 @@ public:
highlight_attr = selected_highlight_attr;
if (bp_lines.find(curr_line + 1) != bp_lines.end())
- bp_attr = COLOR_PAIR(2);
+ bp_attr = COLOR_PAIR(BlackOnWhite);
if (bp_attr)
window.AttributeOn(bp_attr);
@@ -3479,10 +3664,21 @@ public:
if (highlight_attr)
window.AttributeOn(highlight_attr);
- const uint32_t line_len =
- m_file_sp->GetLineLength(curr_line + 1, false);
- if (line_len > 0)
- window.PutCString(m_file_sp->PeekLineData(curr_line + 1), line_len);
+
+ StreamString lineStream;
+ m_file_sp->DisplaySourceLines(curr_line + 1, {}, 0, 0, &lineStream);
+ StringRef line = lineStream.GetString();
+ if (line.endswith("\n"))
+ line = line.drop_back();
+ bool wasWritten = window.OutputColoredStringTruncated(
+ 1, line, m_first_visible_column, line_is_selected);
+ if (line_is_selected && !wasWritten) {
+ // Draw an empty space to show the selected line if empty,
+ // or draw '<' if nothing is visible because of scrolling too much
+ // to the right.
+ window.PutCStringTruncated(
+ 1, line.empty() && m_first_visible_column == 0 ? " " : "<");
+ }
if (is_pc_line && frame_sp &&
frame_sp->GetConcreteFrameIndex() == 0) {
@@ -3494,11 +3690,15 @@ public:
if (stop_description && stop_description[0]) {
size_t stop_description_len = strlen(stop_description);
int desc_x = window_width - stop_description_len - 16;
- window.Printf("%*s", desc_x - window.GetCursorX(), "");
- // window.MoveCursor(window_width - stop_description_len - 15,
- // line_y);
- window.Printf("<<< Thread %u: %s ", thread->GetIndexID(),
- stop_description);
+ if (desc_x - window.GetCursorX() > 0)
+ window.Printf("%*s", desc_x - window.GetCursorX(), "");
+ window.MoveCursor(window_width - stop_description_len - 16,
+ line_y);
+ const attr_t stop_reason_attr = COLOR_PAIR(WhiteOnBlue);
+ window.AttributeOn(stop_reason_attr);
+ window.PrintfTruncated(1, " <<< Thread %u: %s ",
+ thread->GetIndexID(), stop_description);
+ window.AttributeOff(stop_reason_attr);
}
} else {
window.Printf("%*s", window_width - window.GetCursorX() - 1, "");
@@ -3538,7 +3738,7 @@ public:
}
const attr_t selected_highlight_attr = A_REVERSE;
- const attr_t pc_highlight_attr = COLOR_PAIR(1);
+ const attr_t pc_highlight_attr = COLOR_PAIR(WhiteOnBlue);
StreamString strm;
@@ -3586,7 +3786,7 @@ public:
if (bp_file_addrs.find(inst->GetAddress().GetFileAddress()) !=
bp_file_addrs.end())
- bp_attr = COLOR_PAIR(2);
+ bp_attr = COLOR_PAIR(BlackOnWhite);
if (bp_attr)
window.AttributeOn(bp_attr);
@@ -3629,7 +3829,9 @@ public:
strm.Printf("%s", mnemonic);
int right_pad = 1;
- window.PutCStringTruncated(strm.GetData(), right_pad);
+ window.PutCStringTruncated(
+ right_pad,
+ strm.GetString().substr(m_first_visible_column).data());
if (is_pc_line && frame_sp &&
frame_sp->GetConcreteFrameIndex() == 0) {
@@ -3641,11 +3843,12 @@ public:
if (stop_description && stop_description[0]) {
size_t stop_description_len = strlen(stop_description);
int desc_x = window_width - stop_description_len - 16;
- window.Printf("%*s", desc_x - window.GetCursorX(), "");
- // window.MoveCursor(window_width - stop_description_len - 15,
- // line_y);
- window.Printf("<<< Thread %u: %s ", thread->GetIndexID(),
- stop_description);
+ if (desc_x - window.GetCursorX() > 0)
+ window.Printf("%*s", desc_x - window.GetCursorX(), "");
+ window.MoveCursor(window_width - stop_description_len - 15,
+ line_y);
+ window.PrintfTruncated(1, "<<< Thread %u: %s ",
+ thread->GetIndexID(), stop_description);
}
} else {
window.Printf("%*s", window_width - window.GetCursorX() - 1, "");
@@ -3723,6 +3926,15 @@ public:
}
return eKeyHandled;
+ case KEY_LEFT:
+ if (m_first_visible_column > 0)
+ --m_first_visible_column;
+ return eKeyHandled;
+
+ case KEY_RIGHT:
+ ++m_first_visible_column;
+ return eKeyHandled;
+
case '\r':
case '\n':
case KEY_ENTER:
@@ -3767,59 +3979,18 @@ public:
return eKeyHandled;
case 'b': // 'b' == toggle breakpoint on currently selected line
- if (m_selected_line < GetNumSourceLines()) {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasTargetScope()) {
- BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
- nullptr, // Don't limit the breakpoint to certain modules
- m_file_sp->GetFileSpec(), // Source file
- m_selected_line +
- 1, // Source line number (m_selected_line is zero based)
- 0, // No column specified.
- 0, // No offset
- eLazyBoolCalculate, // Check inlines using global setting
- eLazyBoolCalculate, // Skip prologue using global setting,
- false, // internal
- false, // request_hardware
- eLazyBoolCalculate); // move_to_nearest_code
- }
- } else if (m_selected_line < GetNumDisassemblyLines()) {
- const Instruction *inst = m_disassembly_sp->GetInstructionList()
- .GetInstructionAtIndex(m_selected_line)
- .get();
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasTargetScope()) {
- Address addr = inst->GetAddress();
- BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
- addr, // lldb_private::Address
- false, // internal
- false); // request_hardware
- }
- }
+ ToggleBreakpointOnSelectedLine();
return eKeyHandled;
- case 'd': // 'd' == detach and let run
case 'D': // 'D' == detach and keep stopped
{
ExecutionContext exe_ctx =
m_debugger.GetCommandInterpreter().GetExecutionContext();
if (exe_ctx.HasProcessScope())
- exe_ctx.GetProcessRef().Detach(c == 'D');
+ exe_ctx.GetProcessRef().Detach(true);
}
return eKeyHandled;
- case 'k':
- // 'k' == kill
- {
- ExecutionContext exe_ctx =
- m_debugger.GetCommandInterpreter().GetExecutionContext();
- if (exe_ctx.HasProcessScope())
- exe_ctx.GetProcessRef().Destroy(false);
- }
- return eKeyHandled;
-
case 'c':
// 'c' == continue
{
@@ -3830,8 +4001,8 @@ public:
}
return eKeyHandled;
- case 'o':
- // 'o' == step out
+ case 'f':
+ // 'f' == step out (finish)
{
ExecutionContext exe_ctx =
m_debugger.GetCommandInterpreter().GetExecutionContext();
@@ -3868,6 +4039,26 @@ public:
}
return eKeyHandled;
+ case 'u': // 'u' == frame up
+ case 'd': // 'd' == frame down
+ {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (exe_ctx.HasThreadScope()) {
+ Thread *thread = exe_ctx.GetThreadPtr();
+ uint32_t frame_idx = thread->GetSelectedFrameIndex();
+ if (frame_idx == UINT32_MAX)
+ frame_idx = 0;
+ if (c == 'u' && frame_idx + 1 < thread->GetStackFrameCount())
+ ++frame_idx;
+ else if (c == 'd' && frame_idx > 0)
+ --frame_idx;
+ if (thread->SetSelectedFrameByIndex(frame_idx, true))
+ exe_ctx.SetFrameSP(thread->GetSelectedFrame());
+ }
+ }
+ return eKeyHandled;
+
case 'h':
window.CreateHelpSubwindow();
return eKeyHandled;
@@ -3878,6 +4069,85 @@ public:
return eKeyNotHandled;
}
+ void ToggleBreakpointOnSelectedLine() {
+ ExecutionContext exe_ctx =
+ m_debugger.GetCommandInterpreter().GetExecutionContext();
+ if (!exe_ctx.HasTargetScope())
+ return;
+ if (GetNumSourceLines() > 0) {
+ // Source file breakpoint.
+ BreakpointList &bp_list = exe_ctx.GetTargetRef().GetBreakpointList();
+ const size_t num_bps = bp_list.GetSize();
+ for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) {
+ BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
+ const size_t num_bps_locs = bp_sp->GetNumLocations();
+ for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs; ++bp_loc_idx) {
+ BreakpointLocationSP bp_loc_sp =
+ bp_sp->GetLocationAtIndex(bp_loc_idx);
+ LineEntry bp_loc_line_entry;
+ if (bp_loc_sp->GetAddress().CalculateSymbolContextLineEntry(
+ bp_loc_line_entry)) {
+ if (m_file_sp->GetFileSpec() == bp_loc_line_entry.file &&
+ m_selected_line + 1 == bp_loc_line_entry.line) {
+ bool removed =
+ exe_ctx.GetTargetRef().RemoveBreakpointByID(bp_sp->GetID());
+ assert(removed);
+ UNUSED_IF_ASSERT_DISABLED(removed);
+ return; // Existing breakpoint removed.
+ }
+ }
+ }
+ }
+ // No breakpoint found on the location, add it.
+ BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
+ nullptr, // Don't limit the breakpoint to certain modules
+ m_file_sp->GetFileSpec(), // Source file
+ m_selected_line +
+ 1, // Source line number (m_selected_line is zero based)
+ 0, // No column specified.
+ 0, // No offset
+ eLazyBoolCalculate, // Check inlines using global setting
+ eLazyBoolCalculate, // Skip prologue using global setting,
+ false, // internal
+ false, // request_hardware
+ eLazyBoolCalculate); // move_to_nearest_code
+ } else {
+ // Disassembly breakpoint.
+ assert(GetNumDisassemblyLines() > 0);
+ assert(m_selected_line < GetNumDisassemblyLines());
+ const Instruction *inst = m_disassembly_sp->GetInstructionList()
+ .GetInstructionAtIndex(m_selected_line)
+ .get();
+ Address addr = inst->GetAddress();
+ // Try to find it.
+ BreakpointList &bp_list = exe_ctx.GetTargetRef().GetBreakpointList();
+ const size_t num_bps = bp_list.GetSize();
+ for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) {
+ BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
+ const size_t num_bps_locs = bp_sp->GetNumLocations();
+ for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs; ++bp_loc_idx) {
+ BreakpointLocationSP bp_loc_sp =
+ bp_sp->GetLocationAtIndex(bp_loc_idx);
+ LineEntry bp_loc_line_entry;
+ const lldb::addr_t file_addr =
+ bp_loc_sp->GetAddress().GetFileAddress();
+ if (file_addr == addr.GetFileAddress()) {
+ bool removed =
+ exe_ctx.GetTargetRef().RemoveBreakpointByID(bp_sp->GetID());
+ assert(removed);
+ UNUSED_IF_ASSERT_DISABLED(removed);
+ return; // Existing breakpoint removed.
+ }
+ }
+ }
+ // No breakpoint found on the address, add it.
+ BreakpointSP bp_sp =
+ exe_ctx.GetTargetRef().CreateBreakpoint(addr, // lldb_private::Address
+ false, // internal
+ false); // request_hardware
+ }
+ }
+
protected:
typedef std::set<uint32_t> BreakpointLines;
typedef std::set<lldb::addr_t> BreakpointAddrs;
@@ -3896,6 +4166,7 @@ protected:
uint32_t m_stop_id;
uint32_t m_frame_idx;
int m_first_visible_line;
+ int m_first_visible_column;
int m_min_x;
int m_min_y;
int m_max_x;
@@ -3939,8 +4210,12 @@ void IOHandlerCursesGUI::Activate() {
ApplicationDelegate::eMenuID_Process));
process_menu_sp->AddSubmenu(MenuSP(new Menu(
"Attach", nullptr, 'a', ApplicationDelegate::eMenuID_ProcessAttach)));
- process_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Detach", nullptr, 'd', ApplicationDelegate::eMenuID_ProcessDetach)));
+ process_menu_sp->AddSubmenu(
+ MenuSP(new Menu("Detach and resume", nullptr, 'd',
+ ApplicationDelegate::eMenuID_ProcessDetachResume)));
+ process_menu_sp->AddSubmenu(
+ MenuSP(new Menu("Detach suspended", nullptr, 's',
+ ApplicationDelegate::eMenuID_ProcessDetachSuspended)));
process_menu_sp->AddSubmenu(MenuSP(new Menu(
"Launch", nullptr, 'l', ApplicationDelegate::eMenuID_ProcessLaunch)));
process_menu_sp->AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
@@ -4042,11 +4317,28 @@ void IOHandlerCursesGUI::Activate() {
main_window_sp->CreateHelpSubwindow();
}
- init_pair(1, COLOR_WHITE, COLOR_BLUE);
- init_pair(2, COLOR_BLACK, COLOR_WHITE);
- init_pair(3, COLOR_MAGENTA, COLOR_WHITE);
- init_pair(4, COLOR_MAGENTA, COLOR_BLACK);
- init_pair(5, COLOR_RED, COLOR_BLACK);
+ // All colors with black background.
+ init_pair(1, COLOR_BLACK, COLOR_BLACK);
+ init_pair(2, COLOR_RED, COLOR_BLACK);
+ init_pair(3, COLOR_GREEN, COLOR_BLACK);
+ init_pair(4, COLOR_YELLOW, COLOR_BLACK);
+ init_pair(5, COLOR_BLUE, COLOR_BLACK);
+ init_pair(6, COLOR_MAGENTA, COLOR_BLACK);
+ init_pair(7, COLOR_CYAN, COLOR_BLACK);
+ init_pair(8, COLOR_WHITE, COLOR_BLACK);
+ // All colors with blue background.
+ init_pair(9, COLOR_BLACK, COLOR_BLUE);
+ init_pair(10, COLOR_RED, COLOR_BLUE);
+ init_pair(11, COLOR_GREEN, COLOR_BLUE);
+ init_pair(12, COLOR_YELLOW, COLOR_BLUE);
+ init_pair(13, COLOR_BLUE, COLOR_BLUE);
+ init_pair(14, COLOR_MAGENTA, COLOR_BLUE);
+ init_pair(15, COLOR_CYAN, COLOR_BLUE);
+ init_pair(16, COLOR_WHITE, COLOR_BLUE);
+ // These must match the order in the color indexes enum.
+ init_pair(17, COLOR_BLACK, COLOR_WHITE);
+ init_pair(18, COLOR_MAGENTA, COLOR_WHITE);
+ static_assert(LastColorPairIndex == 18, "Color indexes do not match.");
}
}
@@ -4065,4 +4357,8 @@ bool IOHandlerCursesGUI::Interrupt() { return false; }
void IOHandlerCursesGUI::GotEOF() {}
+void IOHandlerCursesGUI::TerminalSizeChanged() {
+ m_app_ap->TerminalSizeChanged();
+}
+
#endif // LLDB_ENABLE_CURSES
diff --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp
index 143ec8770bf4..627be94a303c 100644
--- a/lldb/source/Core/Mangled.cpp
+++ b/lldb/source/Core/Mangled.cpp
@@ -14,7 +14,6 @@
#include "lldb/Utility/Logging.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Stream.h"
-#include "lldb/Utility/Timer.h"
#include "lldb/lldb-enumerations.h"
#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
@@ -227,12 +226,6 @@ static char *GetItaniumDemangledStr(const char *M) {
// makes use of ItaniumPartialDemangler's rich demangle info
bool Mangled::DemangleWithRichManglingInfo(
RichManglingContext &context, SkipMangledNameFn *skip_mangled_name) {
- // We need to generate and cache the demangled name.
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat,
- "Mangled::DemangleWithRichNameIndexInfo (m_mangled = %s)",
- m_mangled.GetCString());
-
// Others are not meant to arrive here. ObjC names or C's main() for example
// have their names stored in m_demangled, while m_mangled is empty.
assert(m_mangled);
@@ -298,11 +291,6 @@ ConstString Mangled::GetDemangledName() const {
// Check to make sure we have a valid mangled name and that we haven't
// already decoded our mangled name.
if (m_mangled && m_demangled.IsNull()) {
- // We need to generate and cache the demangled name.
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat, "Mangled::GetDemangledName (m_mangled = %s)",
- m_mangled.GetCString());
-
// Don't bother running anything that isn't mangled
const char *mangled_name = m_mangled.GetCString();
ManglingScheme mangling_scheme = GetManglingScheme(m_mangled.GetStringRef());
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index b76659ee3e07..1f9987c21658 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -419,8 +419,7 @@ void Module::DumpSymbolContext(Stream *s) {
size_t Module::GetNumCompileUnits() {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat, "Module::GetNumCompileUnits (module = %p)",
+ LLDB_SCOPED_TIMERF("Module::GetNumCompileUnits (module = %p)",
static_cast<void *>(this));
if (SymbolFile *symbols = GetSymbolFile())
return symbols->GetNumCompileUnits();
@@ -441,9 +440,7 @@ CompUnitSP Module::GetCompileUnitAtIndex(size_t index) {
bool Module::ResolveFileAddress(lldb::addr_t vm_addr, Address &so_addr) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat,
- "Module::ResolveFileAddress (vm_addr = 0x%" PRIx64 ")",
+ LLDB_SCOPED_TIMERF("Module::ResolveFileAddress (vm_addr = 0x%" PRIx64 ")",
vm_addr);
SectionList *section_list = GetSectionList();
if (section_list)
@@ -594,9 +591,7 @@ uint32_t Module::ResolveSymbolContextsForFileSpec(
const FileSpec &file_spec, uint32_t line, bool check_inlines,
lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat,
- "Module::ResolveSymbolContextForFilePath (%s:%u, "
+ LLDB_SCOPED_TIMERF("Module::ResolveSymbolContextForFilePath (%s:%u, "
"check_inlines = %s, resolve_scope = 0x%8.8x)",
file_spec.GetPath().c_str(), line,
check_inlines ? "yes" : "no", resolve_scope);
@@ -940,8 +935,7 @@ void Module::FindTypes_Impl(
size_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types) {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
+ LLDB_SCOPED_TIMER();
if (SymbolFile *symbols = GetSymbolFile())
symbols->FindTypes(name, parent_decl_ctx, max_matches,
searched_symbol_files, types);
@@ -1028,8 +1022,7 @@ void Module::FindTypes(
llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types) {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
+ LLDB_SCOPED_TIMER();
if (SymbolFile *symbols = GetSymbolFile())
symbols->FindTypes(pattern, languages, searched_symbol_files, types);
}
@@ -1040,8 +1033,7 @@ SymbolFile *Module::GetSymbolFile(bool can_create, Stream *feedback_strm) {
if (!m_did_load_symfile.load() && can_create) {
ObjectFile *obj_file = GetObjectFile();
if (obj_file != nullptr) {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
+ LLDB_SCOPED_TIMER();
m_symfile_up.reset(
SymbolVendor::FindPlugin(shared_from_this(), feedback_strm));
m_did_load_symfile = true;
@@ -1244,8 +1236,7 @@ ObjectFile *Module::GetObjectFile() {
if (!m_did_load_objfile.load()) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
if (!m_did_load_objfile.load()) {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat, "Module::GetObjectFile () module = %s",
+ LLDB_SCOPED_TIMERF("Module::GetObjectFile () module = %s",
GetFileSpec().GetFilename().AsCString(""));
lldb::offset_t data_offset = 0;
lldb::offset_t file_size = 0;
@@ -1312,9 +1303,8 @@ SectionList *Module::GetUnifiedSectionList() {
const Symbol *Module::FindFirstSymbolWithNameAndType(ConstString name,
SymbolType symbol_type) {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(
- func_cat, "Module::FindFirstSymbolWithNameAndType (name = %s, type = %i)",
+ LLDB_SCOPED_TIMERF(
+ "Module::FindFirstSymbolWithNameAndType (name = %s, type = %i)",
name.AsCString(), symbol_type);
if (Symtab *symtab = GetSymtab())
return symtab->FindFirstSymbolWithNameAndType(
@@ -1342,9 +1332,7 @@ void Module::SymbolIndicesToSymbolContextList(
void Module::FindFunctionSymbols(ConstString name,
uint32_t name_type_mask,
SymbolContextList &sc_list) {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat,
- "Module::FindSymbolsFunctions (name = %s, mask = 0x%8.8x)",
+ LLDB_SCOPED_TIMERF("Module::FindSymbolsFunctions (name = %s, mask = 0x%8.8x)",
name.AsCString(), name_type_mask);
if (Symtab *symtab = GetSymtab())
symtab->FindFunctionSymbols(name, name_type_mask, sc_list);
@@ -1355,10 +1343,8 @@ void Module::FindSymbolsWithNameAndType(ConstString name,
SymbolContextList &sc_list) {
// No need to protect this call using m_mutex all other method calls are
// already thread safe.
-
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(
- func_cat, "Module::FindSymbolsWithNameAndType (name = %s, type = %i)",
+ LLDB_SCOPED_TIMERF(
+ "Module::FindSymbolsWithNameAndType (name = %s, type = %i)",
name.AsCString(), symbol_type);
if (Symtab *symtab = GetSymtab()) {
std::vector<uint32_t> symbol_indexes;
@@ -1372,10 +1358,7 @@ void Module::FindSymbolsMatchingRegExAndType(const RegularExpression &regex,
SymbolContextList &sc_list) {
// No need to protect this call using m_mutex all other method calls are
// already thread safe.
-
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(
- func_cat,
+ LLDB_SCOPED_TIMERF(
"Module::FindSymbolsMatchingRegExAndType (regex = %s, type = %i)",
regex.GetText().str().c_str(), symbol_type);
if (Symtab *symtab = GetSymtab()) {
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index 0345678ddaff..98f6ae2c62b0 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -82,8 +82,9 @@ ModuleListProperties::ModuleListProperties() {
[this] { UpdateSymlinkMappings(); });
llvm::SmallString<128> path;
- clang::driver::Driver::getDefaultModuleCachePath(path);
- SetClangModulesCachePath(path);
+ if (clang::driver::Driver::getDefaultModuleCachePath(path)) {
+ lldbassert(SetClangModulesCachePath(FileSpec(path)));
+ }
}
bool ModuleListProperties::GetEnableExternalLookup() const {
@@ -104,8 +105,8 @@ FileSpec ModuleListProperties::GetClangModulesCachePath() const {
->GetCurrentValue();
}
-bool ModuleListProperties::SetClangModulesCachePath(llvm::StringRef path) {
- return m_collection_sp->SetPropertyAtIndexAsString(
+bool ModuleListProperties::SetClangModulesCachePath(const FileSpec &path) {
+ return m_collection_sp->SetPropertyAtIndexAsFileSpec(
nullptr, ePropertyClangModulesCachePath, path);
}
@@ -171,7 +172,9 @@ void ModuleList::Append(const ModuleSP &module_sp, bool notify) {
AppendImpl(module_sp, notify);
}
-void ModuleList::ReplaceEquivalent(const ModuleSP &module_sp) {
+void ModuleList::ReplaceEquivalent(
+ const ModuleSP &module_sp,
+ llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules) {
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
@@ -184,11 +187,14 @@ void ModuleList::ReplaceEquivalent(const ModuleSP &module_sp) {
size_t idx = 0;
while (idx < m_modules.size()) {
- ModuleSP module_sp(m_modules[idx]);
- if (module_sp->MatchesModuleSpec(equivalent_module_spec))
+ ModuleSP test_module_sp(m_modules[idx]);
+ if (test_module_sp->MatchesModuleSpec(equivalent_module_spec)) {
+ if (old_modules)
+ old_modules->push_back(test_module_sp);
RemoveImpl(m_modules.begin() + idx);
- else
+ } else {
++idx;
+ }
}
// Now add the new module to the list
Append(module_sp);
@@ -291,14 +297,24 @@ size_t ModuleList::RemoveOrphans(bool mandatory) {
if (!lock.try_lock())
return 0;
}
- collection::iterator pos = m_modules.begin();
size_t remove_count = 0;
- while (pos != m_modules.end()) {
- if (pos->unique()) {
- pos = RemoveImpl(pos);
- ++remove_count;
- } else {
- ++pos;
+ // Modules might hold shared pointers to other modules, so removing one
+ // module might make other other modules orphans. Keep removing modules until
+ // there are no further modules that can be removed.
+ bool made_progress = true;
+ while (made_progress) {
+ // Keep track if we make progress this iteration.
+ made_progress = false;
+ collection::iterator pos = m_modules.begin();
+ while (pos != m_modules.end()) {
+ if (pos->unique()) {
+ pos = RemoveImpl(pos);
+ ++remove_count;
+ // We did make progress.
+ made_progress = true;
+ } else {
+ ++pos;
+ }
}
}
return remove_count;
@@ -330,10 +346,6 @@ void ModuleList::ClearImpl(bool use_notifier) {
Module *ModuleList::GetModulePointerAtIndex(size_t idx) const {
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
- return GetModulePointerAtIndexUnlocked(idx);
-}
-
-Module *ModuleList::GetModulePointerAtIndexUnlocked(size_t idx) const {
if (idx < m_modules.size())
return m_modules[idx].get();
return nullptr;
@@ -731,11 +743,11 @@ size_t ModuleList::RemoveOrphanSharedModules(bool mandatory) {
return GetSharedModuleList().RemoveOrphans(mandatory);
}
-Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
- ModuleSP &module_sp,
- const FileSpecList *module_search_paths_ptr,
- ModuleSP *old_module_sp_ptr,
- bool *did_create_ptr, bool always_create) {
+Status
+ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules,
+ bool *did_create_ptr, bool always_create) {
ModuleList &shared_module_list = GetSharedModuleList();
std::lock_guard<std::recursive_mutex> guard(
shared_module_list.m_modules_mutex);
@@ -747,8 +759,6 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
if (did_create_ptr)
*did_create_ptr = false;
- if (old_module_sp_ptr)
- old_module_sp_ptr->reset();
const UUID *uuid_ptr = module_spec.GetUUIDPtr();
const FileSpec &module_file_spec = module_spec.GetFileSpec();
@@ -769,8 +779,8 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
// Make sure the file for the module hasn't been modified
if (module_sp->FileHasChanged()) {
- if (old_module_sp_ptr && !*old_module_sp_ptr)
- *old_module_sp_ptr = module_sp;
+ if (old_modules)
+ old_modules->push_back(module_sp);
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_MODULES));
if (log != nullptr)
@@ -812,7 +822,7 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
*did_create_ptr = true;
}
- shared_module_list.ReplaceEquivalent(module_sp);
+ shared_module_list.ReplaceEquivalent(module_sp, old_modules);
return error;
}
}
@@ -849,7 +859,7 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
if (did_create_ptr)
*did_create_ptr = true;
- shared_module_list.ReplaceEquivalent(module_sp);
+ shared_module_list.ReplaceEquivalent(module_sp, old_modules);
return Status();
}
}
@@ -924,8 +934,8 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
located_binary_modulespec.GetFileSpec());
if (file_spec_mod_time != llvm::sys::TimePoint<>()) {
if (file_spec_mod_time != module_sp->GetModificationTime()) {
- if (old_module_sp_ptr)
- *old_module_sp_ptr = module_sp;
+ if (old_modules)
+ old_modules->push_back(module_sp);
shared_module_list.Remove(module_sp);
module_sp.reset();
}
@@ -947,7 +957,7 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
if (did_create_ptr)
*did_create_ptr = true;
- shared_module_list.ReplaceEquivalent(module_sp);
+ shared_module_list.ReplaceEquivalent(module_sp, old_modules);
}
} else {
located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path));
@@ -968,7 +978,7 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
error.SetErrorStringWithFormat(
"cannot locate a module for UUID '%s'", uuid_str.c_str());
else
- error.SetErrorStringWithFormat("cannot locate a module");
+ error.SetErrorString("cannot locate a module");
}
}
}
diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp
index 3545ef66cc38..97e1e8d14039 100644
--- a/lldb/source/Core/PluginManager.cpp
+++ b/lldb/source/Core/PluginManager.cpp
@@ -264,12 +264,13 @@ public:
const std::vector<Instance> &GetInstances() const { return m_instances; }
std::vector<Instance> &GetInstances() { return m_instances; }
-private:
Instance *GetInstanceAtIndex(uint32_t idx) {
if (idx < m_instances.size())
return &m_instances[idx];
return nullptr;
}
+
+private:
std::vector<Instance> m_instances;
};
@@ -1005,6 +1006,67 @@ PluginManager::GetSymbolVendorCreateCallbackAtIndex(uint32_t idx) {
return GetSymbolVendorInstances().GetCallbackAtIndex(idx);
}
+#pragma mark Trace
+
+struct TraceInstance : public PluginInstance<TraceCreateInstance> {
+ TraceInstance(ConstString name, std::string description,
+ CallbackType create_callback, llvm::StringRef schema,
+ TraceGetStartCommand get_start_command)
+ : PluginInstance<TraceCreateInstance>(name, std::move(description),
+ create_callback),
+ schema(schema), get_start_command(get_start_command) {}
+
+ llvm::StringRef schema;
+ TraceGetStartCommand get_start_command;
+};
+
+typedef PluginInstances<TraceInstance> TraceInstances;
+
+static TraceInstances &GetTracePluginInstances() {
+ static TraceInstances g_instances;
+ return g_instances;
+}
+
+bool PluginManager::RegisterPlugin(ConstString name, const char *description,
+ TraceCreateInstance create_callback,
+ llvm::StringRef schema,
+ TraceGetStartCommand get_start_command) {
+ return GetTracePluginInstances().RegisterPlugin(
+ name, description, create_callback, schema, get_start_command);
+}
+
+bool PluginManager::UnregisterPlugin(TraceCreateInstance create_callback) {
+ return GetTracePluginInstances().UnregisterPlugin(create_callback);
+}
+
+TraceCreateInstance
+PluginManager::GetTraceCreateCallback(ConstString plugin_name) {
+ return GetTracePluginInstances().GetCallbackForName(plugin_name);
+}
+
+llvm::StringRef PluginManager::GetTraceSchema(ConstString plugin_name) {
+ for (const TraceInstance &instance : GetTracePluginInstances().GetInstances())
+ if (instance.name == plugin_name)
+ return instance.schema;
+ return llvm::StringRef();
+}
+
+CommandObjectSP
+PluginManager::GetTraceStartCommand(llvm::StringRef plugin_name,
+ CommandInterpreter &interpreter) {
+ for (const TraceInstance &instance : GetTracePluginInstances().GetInstances())
+ if (instance.name.GetStringRef() == plugin_name)
+ return instance.get_start_command(interpreter);
+ return CommandObjectSP();
+}
+
+llvm::StringRef PluginManager::GetTraceSchema(size_t index) {
+ if (TraceInstance *instance =
+ GetTracePluginInstances().GetInstanceAtIndex(index))
+ return instance->schema;
+ return llvm::StringRef();
+}
+
#pragma mark UnwindAssembly
typedef PluginInstance<UnwindAssemblyCreateInstance> UnwindAssemblyInstance;
@@ -1218,6 +1280,7 @@ void PluginManager::DebuggerInitialize(Debugger &debugger) {
GetSymbolFileInstances().PerformDebuggerCallback(debugger);
GetOperatingSystemInstances().PerformDebuggerCallback(debugger);
GetStructuredDataPluginInstances().PerformDebuggerCallback(debugger);
+ GetTracePluginInstances().PerformDebuggerCallback(debugger);
}
// This is the preferred new way to register plugin specific settings. e.g.
diff --git a/lldb/source/Core/SearchFilter.cpp b/lldb/source/Core/SearchFilter.cpp
index ea51fb379181..e3327ff5e750 100644
--- a/lldb/source/Core/SearchFilter.cpp
+++ b/lldb/source/Core/SearchFilter.cpp
@@ -89,7 +89,7 @@ SearchFilterSP SearchFilter::CreateFromStructuredData(
bool success = filter_dict.GetValueForKeyAsString(
GetSerializationSubclassKey(), subclass_name);
if (!success) {
- error.SetErrorStringWithFormat("Filter data missing subclass key");
+ error.SetErrorString("Filter data missing subclass key");
return result_sp;
}
@@ -228,11 +228,7 @@ void SearchFilter::SearchInModuleList(Searcher &searcher, ModuleList &modules) {
return;
}
- std::lock_guard<std::recursive_mutex> guard(modules.GetMutex());
- const size_t numModules = modules.GetSize();
-
- for (size_t i = 0; i < numModules; i++) {
- ModuleSP module_sp(modules.GetModuleAtIndexUnlocked(i));
+ for (ModuleSP module_sp : modules.Modules()) {
if (!ModulePasses(module_sp))
continue;
if (DoModuleIteration(module_sp, searcher) == Searcher::eCallbackReturnStop)
@@ -262,14 +258,9 @@ SearchFilter::DoModuleIteration(const SymbolContext &context,
return Searcher::eCallbackReturnContinue;
}
- const ModuleList &target_images = m_target_sp->GetImages();
- std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex());
-
- size_t n_modules = target_images.GetSize();
- for (size_t i = 0; i < n_modules; i++) {
+ for (ModuleSP module_sp : m_target_sp->GetImages().Modules()) {
// If this is the last level supplied, then call the callback directly,
// otherwise descend.
- ModuleSP module_sp(target_images.GetModuleAtIndexUnlocked(i));
if (!ModulePasses(module_sp))
continue;
@@ -434,11 +425,9 @@ void SearchFilterByModule::Search(Searcher &searcher) {
const ModuleList &target_modules = m_target_sp->GetImages();
std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
- const size_t num_modules = target_modules.GetSize();
- for (size_t i = 0; i < num_modules; i++) {
- Module *module = target_modules.GetModulePointerAtIndexUnlocked(i);
- if (FileSpec::Match(m_module_spec, module->GetFileSpec())) {
- SymbolContext matchingContext(m_target_sp, module->shared_from_this());
+ for (ModuleSP module_sp : m_target_sp->GetImages().Modules()) {
+ if (FileSpec::Match(m_module_spec, module_sp->GetFileSpec())) {
+ SymbolContext matchingContext(m_target_sp, module_sp);
Searcher::CallbackReturn shouldContinue;
shouldContinue = DoModuleIteration(matchingContext, searcher);
@@ -550,17 +539,11 @@ void SearchFilterByModuleList::Search(Searcher &searcher) {
// If the module file spec is a full path, then we can just find the one
// filespec that passes. Otherwise, we need to go through all modules and
// find the ones that match the file name.
-
- const ModuleList &target_modules = m_target_sp->GetImages();
- std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
-
- const size_t num_modules = target_modules.GetSize();
- for (size_t i = 0; i < num_modules; i++) {
- Module *module = target_modules.GetModulePointerAtIndexUnlocked(i);
- if (m_module_spec_list.FindFileIndex(0, module->GetFileSpec(), false) ==
+ for (ModuleSP module_sp : m_target_sp->GetImages().Modules()) {
+ if (m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) ==
UINT32_MAX)
continue;
- SymbolContext matchingContext(m_target_sp, module->shared_from_this());
+ SymbolContext matchingContext(m_target_sp, module_sp);
Searcher::CallbackReturn shouldContinue;
shouldContinue = DoModuleIteration(matchingContext, searcher);
@@ -752,13 +735,9 @@ void SearchFilterByModuleListAndCU::Search(Searcher &searcher) {
// find the ones that match the file name.
ModuleList matching_modules;
- const ModuleList &target_images = m_target_sp->GetImages();
- std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex());
- const size_t num_modules = target_images.GetSize();
bool no_modules_in_filter = m_module_spec_list.GetSize() == 0;
- for (size_t i = 0; i < num_modules; i++) {
- lldb::ModuleSP module_sp = target_images.GetModuleAtIndexUnlocked(i);
+ for (ModuleSP module_sp : m_target_sp->GetImages().Modules()) {
if (!no_modules_in_filter &&
m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) ==
UINT32_MAX)
diff --git a/lldb/source/Core/SourceManager.cpp b/lldb/source/Core/SourceManager.cpp
index 7414dd281d43..e79fcb48742d 100644
--- a/lldb/source/Core/SourceManager.cpp
+++ b/lldb/source/Core/SourceManager.cpp
@@ -183,14 +183,14 @@ size_t SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile(
break;
}
- char prefix[32] = "";
+ std::string prefix;
if (bp_locs) {
uint32_t bp_count = bp_locs->NumLineEntriesWithLine(line);
if (bp_count > 0)
- ::snprintf(prefix, sizeof(prefix), "[%u] ", bp_count);
+ prefix = llvm::formatv("[{0}]", bp_count);
else
- ::snprintf(prefix, sizeof(prefix), " ");
+ prefix = " ";
}
char buffer[3];
@@ -206,7 +206,8 @@ size_t SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile(
.str());
}
- s->Printf("%s%s %-4u\t", prefix, current_line_highlight.c_str(), line);
+ s->Printf("%s%s %-4u\t", prefix.c_str(), current_line_highlight.c_str(),
+ line);
// So far we treated column 0 as a special 'no column value', but
// DisplaySourceLines starts counting columns from 0 (and no column is
diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp
index 63467644cdef..cc8f3f4e2615 100644
--- a/lldb/source/Core/Value.cpp
+++ b/lldb/source/Core/Value.cpp
@@ -39,27 +39,26 @@ using namespace lldb;
using namespace lldb_private;
Value::Value()
- : m_value(), m_vector(), m_compiler_type(), m_context(nullptr),
+ : m_value(), m_compiler_type(), m_context(nullptr),
m_value_type(eValueTypeScalar), m_context_type(eContextTypeInvalid),
m_data_buffer() {}
Value::Value(const Scalar &scalar)
- : m_value(scalar), m_vector(), m_compiler_type(), m_context(nullptr),
+ : m_value(scalar), m_compiler_type(), m_context(nullptr),
m_value_type(eValueTypeScalar), m_context_type(eContextTypeInvalid),
m_data_buffer() {}
Value::Value(const void *bytes, int len)
- : m_value(), m_vector(), m_compiler_type(), m_context(nullptr),
+ : m_value(), m_compiler_type(), m_context(nullptr),
m_value_type(eValueTypeHostAddress), m_context_type(eContextTypeInvalid),
m_data_buffer() {
SetBytes(bytes, len);
}
Value::Value(const Value &v)
- : m_value(v.m_value), m_vector(v.m_vector),
- m_compiler_type(v.m_compiler_type), m_context(v.m_context),
- m_value_type(v.m_value_type), m_context_type(v.m_context_type),
- m_data_buffer() {
+ : m_value(v.m_value), m_compiler_type(v.m_compiler_type),
+ m_context(v.m_context), m_value_type(v.m_value_type),
+ m_context_type(v.m_context_type), m_data_buffer() {
const uintptr_t rhs_value =
(uintptr_t)v.m_value.ULongLong(LLDB_INVALID_ADDRESS);
if ((rhs_value != 0) &&
@@ -74,7 +73,6 @@ Value::Value(const Value &v)
Value &Value::operator=(const Value &rhs) {
if (this != &rhs) {
m_value = rhs.m_value;
- m_vector = rhs.m_vector;
m_compiler_type = rhs.m_compiler_type;
m_context = rhs.m_context;
m_value_type = rhs.m_value_type;
@@ -115,7 +113,6 @@ Value::ValueType Value::GetValueType() const { return m_value_type; }
AddressType Value::GetValueAddressType() const {
switch (m_value_type) {
- default:
case eValueTypeScalar:
break;
case eValueTypeLoadAddress:
@@ -159,17 +156,6 @@ size_t Value::AppendDataToHostBuffer(const Value &rhs) {
}
}
} break;
- case eValueTypeVector: {
- const size_t vector_size = rhs.m_vector.length;
- if (vector_size > 0) {
- const size_t new_size = curr_size + vector_size;
- if (ResizeData(new_size) == new_size) {
- ::memcpy(m_data_buffer.GetBytes() + curr_size, rhs.m_vector.bytes,
- vector_size);
- return vector_size;
- }
- }
- } break;
case eValueTypeFileAddress:
case eValueTypeLoadAddress:
case eValueTypeHostAddress: {
@@ -291,9 +277,6 @@ lldb::Format Value::GetValueDefaultFormat() {
bool Value::GetData(DataExtractor &data) {
switch (m_value_type) {
- default:
- break;
-
case eValueTypeScalar:
if (m_value.GetData(data))
return true;
@@ -329,14 +312,6 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
return error;
switch (m_value_type) {
- case eValueTypeVector:
- if (ast_type.IsValid())
- data.SetAddressByteSize(ast_type.GetPointerByteSize());
- else
- data.SetAddressByteSize(sizeof(void *));
- data.SetData(m_vector.bytes, m_vector.length, m_vector.byte_order);
- break;
-
case eValueTypeScalar: {
data.SetByteOrder(endian::InlHostByteOrder());
if (ast_type.IsValid())
@@ -354,7 +329,7 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
return error; // Success;
}
- error.SetErrorStringWithFormat("extracting data from value failed");
+ error.SetErrorString("extracting data from value failed");
break;
}
case eValueTypeLoadAddress:
@@ -535,8 +510,7 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
if (address_type == eAddressTypeHost) {
// The address is an address in this process, so just copy it.
if (address == 0) {
- error.SetErrorStringWithFormat(
- "trying to read from host address of 0.");
+ error.SetErrorString("trying to read from host address of 0.");
return error;
}
memcpy(dst, reinterpret_cast<uint8_t *>(address), byte_size);
@@ -580,7 +554,7 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
address_type);
}
} else {
- error.SetErrorStringWithFormat("out of memory");
+ error.SetErrorString("out of memory");
}
return error;
@@ -593,7 +567,6 @@ Scalar &Value::ResolveValue(ExecutionContext *exe_ctx) {
case eValueTypeScalar: // raw scalar value
break;
- default:
case eValueTypeFileAddress:
case eValueTypeLoadAddress: // load address value
case eValueTypeHostAddress: // host address value (for memory in the process
@@ -604,8 +577,9 @@ Scalar &Value::ResolveValue(ExecutionContext *exe_ctx) {
Status error(GetValueAsData(exe_ctx, data, nullptr));
if (error.Success()) {
Scalar scalar;
- if (compiler_type.GetValueAsScalar(data, 0, data.GetByteSize(),
- scalar)) {
+ if (compiler_type.GetValueAsScalar(
+ data, 0, data.GetByteSize(), scalar,
+ exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr)) {
m_value = scalar;
m_value_type = eValueTypeScalar;
} else {
@@ -634,7 +608,6 @@ Variable *Value::GetVariable() {
void Value::Clear() {
m_value.Clear();
- m_vector.Clear();
m_compiler_type.Clear();
m_value_type = eValueTypeScalar;
m_context = nullptr;
@@ -646,8 +619,6 @@ const char *Value::GetValueTypeAsCString(ValueType value_type) {
switch (value_type) {
case eValueTypeScalar:
return "scalar";
- case eValueTypeVector:
- return "vector";
case eValueTypeFileAddress:
return "file address";
case eValueTypeLoadAddress:
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index 3a775b07e5e1..da90092336d6 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -337,7 +337,6 @@ const char *ValueObject::GetLocationAsCStringImpl(const Value &value,
switch (value_type) {
case Value::eValueTypeScalar:
- case Value::eValueTypeVector:
if (value.GetContextType() == Value::eContextTypeRegisterInfo) {
RegisterInfo *reg_info = value.GetRegisterInfo();
if (reg_info) {
@@ -352,8 +351,7 @@ const char *ValueObject::GetLocationAsCStringImpl(const Value &value,
}
}
if (m_location_str.empty())
- m_location_str =
- (value_type == Value::eValueTypeVector) ? "vector" : "scalar";
+ m_location_str = "scalar";
break;
case Value::eValueTypeLoadAddress:
@@ -849,7 +847,7 @@ bool ValueObject::SetData(DataExtractor &data, Status &error) {
uint64_t count = 0;
const Encoding encoding = GetCompilerType().GetEncoding(count);
- const size_t byte_size = GetByteSize();
+ const size_t byte_size = GetByteSize().getValueOr(0);
Value::ValueType value_type = m_value.GetValueType();
@@ -892,7 +890,6 @@ bool ValueObject::SetData(DataExtractor &data, Status &error) {
m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
} break;
case Value::eValueTypeFileAddress:
- case Value::eValueTypeVector:
break;
}
@@ -1459,7 +1456,6 @@ addr_t ValueObject::GetAddressOf(bool scalar_is_load_address,
switch (m_value.GetValueType()) {
case Value::eValueTypeScalar:
- case Value::eValueTypeVector:
if (scalar_is_load_address) {
if (address_type)
*address_type = eAddressTypeLoad;
@@ -1494,7 +1490,6 @@ addr_t ValueObject::GetPointerValue(AddressType *address_type) {
switch (m_value.GetValueType()) {
case Value::eValueTypeScalar:
- case Value::eValueTypeVector:
address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
break;
@@ -1524,7 +1519,7 @@ bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
uint64_t count = 0;
const Encoding encoding = GetCompilerType().GetEncoding(count);
- const size_t byte_size = GetByteSize();
+ const size_t byte_size = GetByteSize().getValueOr(0);
Value::ValueType value_type = m_value.GetValueType();
@@ -1577,7 +1572,6 @@ bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
} break;
case Value::eValueTypeFileAddress:
case Value::eValueTypeScalar:
- case Value::eValueTypeVector:
break;
}
} else {
@@ -1702,8 +1696,7 @@ ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index,
bool can_create) {
ValueObjectSP synthetic_child_sp;
if (IsPointerType() || IsArrayType()) {
- char index_str[64];
- snprintf(index_str, sizeof(index_str), "[%" PRIu64 "]", (uint64_t)index);
+ std::string index_str = llvm::formatv("[{0}]", index);
ConstString index_const_str(index_str);
// Check if we have already created a synthetic array member in this valid
// object. If we have we will re-use it.
@@ -1730,8 +1723,7 @@ ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
bool can_create) {
ValueObjectSP synthetic_child_sp;
if (IsScalarType()) {
- char index_str[64];
- snprintf(index_str, sizeof(index_str), "[%i-%i]", from, to);
+ std::string index_str = llvm::formatv("[{0}-{1}]", from, to);
ConstString index_const_str(index_str);
// Check if we have already created a synthetic array member in this valid
// object. If we have we will re-use it.
@@ -1741,13 +1733,13 @@ ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
uint32_t bit_field_offset = from;
if (GetDataExtractor().GetByteOrder() == eByteOrderBig)
bit_field_offset =
- GetByteSize() * 8 - bit_field_size - bit_field_offset;
+ GetByteSize().getValueOr(0) * 8 - bit_field_size - bit_field_offset;
// We haven't made a synthetic array member for INDEX yet, so lets make
// one and cache it for any future reference.
ValueObjectChild *synthetic_child = new ValueObjectChild(
- *this, GetCompilerType(), index_const_str, GetByteSize(), 0,
- bit_field_size, bit_field_offset, false, false, eAddressTypeInvalid,
- 0);
+ *this, GetCompilerType(), index_const_str,
+ GetByteSize().getValueOr(0), 0, bit_field_size, bit_field_offset,
+ false, false, eAddressTypeInvalid, 0);
// Cache the value if we got one back...
if (synthetic_child) {
@@ -1768,9 +1760,7 @@ ValueObjectSP ValueObject::GetSyntheticChildAtOffset(
ValueObjectSP synthetic_child_sp;
if (name_const_str.IsEmpty()) {
- char name_str[64];
- snprintf(name_str, sizeof(name_str), "@%i", offset);
- name_const_str.SetCString(name_str);
+ name_const_str.SetString("@" + std::to_string(offset));
}
// Check if we have already created a synthetic array member in this valid
@@ -3215,7 +3205,7 @@ bool ValueObject::CanProvideValue() {
// we need to support invalid types as providers of values because some bare-
// board debugging scenarios have no notion of types, but still manage to
// have raw numeric values for things like registers. sigh.
- const CompilerType &type(GetCompilerType());
+ CompilerType type = GetCompilerType();
return (!type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));
}
diff --git a/lldb/source/Core/ValueObjectCast.cpp b/lldb/source/Core/ValueObjectCast.cpp
index 22e856be539b..7b6d3591faf4 100644
--- a/lldb/source/Core/ValueObjectCast.cpp
+++ b/lldb/source/Core/ValueObjectCast.cpp
@@ -47,7 +47,7 @@ size_t ValueObjectCast::CalculateNumChildren(uint32_t max) {
return children_count <= max ? children_count : max;
}
-uint64_t ValueObjectCast::GetByteSize() {
+llvm::Optional<uint64_t> ValueObjectCast::GetByteSize() {
ExecutionContext exe_ctx(GetExecutionContextRef());
return m_value.GetValueByteSize(nullptr, &exe_ctx);
}
diff --git a/lldb/source/Core/ValueObjectChild.cpp b/lldb/source/Core/ValueObjectChild.cpp
index 6205ed32c615..34baa19f0a24 100644
--- a/lldb/source/Core/ValueObjectChild.cpp
+++ b/lldb/source/Core/ValueObjectChild.cpp
@@ -57,15 +57,8 @@ size_t ValueObjectChild::CalculateNumChildren(uint32_t max) {
static void AdjustForBitfieldness(ConstString &name,
uint8_t bitfield_bit_size) {
- if (name && bitfield_bit_size) {
- const char *compiler_type_name = name.AsCString();
- if (compiler_type_name) {
- std::vector<char> bitfield_type_name(strlen(compiler_type_name) + 32, 0);
- ::snprintf(&bitfield_type_name.front(), bitfield_type_name.size(),
- "%s:%u", compiler_type_name, bitfield_bit_size);
- name.SetCString(&bitfield_type_name.front());
- }
- }
+ if (name && bitfield_bit_size)
+ name.SetString(llvm::formatv("{0}:{1}", name, bitfield_bit_size).str());
}
ConstString ValueObjectChild::GetTypeName() {
@@ -118,8 +111,7 @@ bool ValueObjectChild::UpdateValue() {
CompilerType parent_type(parent->GetCompilerType());
// Copy the parent scalar value and the scalar value type
m_value.GetScalar() = parent->GetValue().GetScalar();
- Value::ValueType value_type = parent->GetValue().GetValueType();
- m_value.SetValueType(value_type);
+ m_value.SetValueType(parent->GetValue().GetValueType());
Flags parent_type_flags(parent_type.GetTypeInfo());
const bool is_instance_ptr_base =
@@ -127,97 +119,77 @@ bool ValueObjectChild::UpdateValue() {
(parent_type_flags.AnySet(lldb::eTypeInstanceIsPointer)));
if (parent->GetCompilerType().ShouldTreatScalarValueAsAddress()) {
- lldb::addr_t addr = parent->GetPointerValue();
- m_value.GetScalar() = addr;
+ m_value.GetScalar() = parent->GetPointerValue();
+ switch (parent->GetAddressTypeOfChildren()) {
+ case eAddressTypeFile: {
+ lldb::ProcessSP process_sp(GetProcessSP());
+ if (process_sp && process_sp->IsAlive())
+ m_value.SetValueType(Value::eValueTypeLoadAddress);
+ else
+ m_value.SetValueType(Value::eValueTypeFileAddress);
+ } break;
+ case eAddressTypeLoad:
+ m_value.SetValueType(is_instance_ptr_base
+ ? Value::eValueTypeScalar
+ : Value::eValueTypeLoadAddress);
+ break;
+ case eAddressTypeHost:
+ m_value.SetValueType(Value::eValueTypeHostAddress);
+ break;
+ case eAddressTypeInvalid:
+ // TODO: does this make sense?
+ m_value.SetValueType(Value::eValueTypeScalar);
+ break;
+ }
+ }
+ switch (m_value.GetValueType()) {
+ case Value::eValueTypeLoadAddress:
+ case Value::eValueTypeFileAddress:
+ case Value::eValueTypeHostAddress: {
+ lldb::addr_t addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
if (addr == LLDB_INVALID_ADDRESS) {
m_error.SetErrorString("parent address is invalid.");
} else if (addr == 0) {
m_error.SetErrorString("parent is NULL");
} else {
- m_value.GetScalar() += m_byte_offset;
- AddressType addr_type = parent->GetAddressTypeOfChildren();
-
- switch (addr_type) {
- case eAddressTypeFile: {
- lldb::ProcessSP process_sp(GetProcessSP());
- if (process_sp && process_sp->IsAlive())
- m_value.SetValueType(Value::eValueTypeLoadAddress);
- else
- m_value.SetValueType(Value::eValueTypeFileAddress);
- } break;
- case eAddressTypeLoad:
- m_value.SetValueType(is_instance_ptr_base
- ? Value::eValueTypeScalar
- : Value::eValueTypeLoadAddress);
- break;
- case eAddressTypeHost:
- m_value.SetValueType(Value::eValueTypeHostAddress);
- break;
- case eAddressTypeInvalid:
- // TODO: does this make sense?
- m_value.SetValueType(Value::eValueTypeScalar);
- break;
- }
- }
- } else {
- switch (value_type) {
- case Value::eValueTypeLoadAddress:
- case Value::eValueTypeFileAddress:
- case Value::eValueTypeHostAddress: {
- lldb::addr_t addr =
- m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
- if (addr == LLDB_INVALID_ADDRESS) {
- m_error.SetErrorString("parent address is invalid.");
- } else if (addr == 0) {
- m_error.SetErrorString("parent is NULL");
- } else {
- // Set this object's scalar value to the address of its value by
- // adding its byte offset to the parent address
- m_value.GetScalar() += GetByteOffset();
-
- // If a bitfield doesn't fit into the child_byte_size'd
- // window at child_byte_offset, move the window forward
- // until it fits. The problem here is that Value has no
- // notion of bitfields and thus the Value's DataExtractor
- // is sized like the bitfields CompilerType; a sequence of
- // bitfields, however, can be larger than their underlying
- // type.
- if (m_bitfield_bit_offset) {
- const bool thread_and_frame_only_if_stopped = true;
- ExecutionContext exe_ctx(GetExecutionContextRef().Lock(
- thread_and_frame_only_if_stopped));
- if (auto type_bit_size = GetCompilerType().GetBitSize(
- exe_ctx.GetBestExecutionContextScope())) {
- uint64_t bitfield_end =
- m_bitfield_bit_size + m_bitfield_bit_offset;
- if (bitfield_end > *type_bit_size) {
- uint64_t overhang_bytes =
- (bitfield_end - *type_bit_size + 7) / 8;
- m_value.GetScalar() += overhang_bytes;
- m_bitfield_bit_offset -= overhang_bytes * 8;
- }
+ // If a bitfield doesn't fit into the child_byte_size'd window at
+ // child_byte_offset, move the window forward until it fits. The
+ // problem here is that Value has no notion of bitfields and thus the
+ // Value's DataExtractor is sized like the bitfields CompilerType; a
+ // sequence of bitfields, however, can be larger than their underlying
+ // type.
+ if (m_bitfield_bit_offset) {
+ const bool thread_and_frame_only_if_stopped = true;
+ ExecutionContext exe_ctx(GetExecutionContextRef().Lock(
+ thread_and_frame_only_if_stopped));
+ if (auto type_bit_size = GetCompilerType().GetBitSize(
+ exe_ctx.GetBestExecutionContextScope())) {
+ uint64_t bitfield_end =
+ m_bitfield_bit_size + m_bitfield_bit_offset;
+ if (bitfield_end > *type_bit_size) {
+ uint64_t overhang_bytes =
+ (bitfield_end - *type_bit_size + 7) / 8;
+ m_byte_offset += overhang_bytes;
+ m_bitfield_bit_offset -= overhang_bytes * 8;
}
}
}
- } break;
- case Value::eValueTypeScalar:
- // try to extract the child value from the parent's scalar value
- {
- Scalar scalar(m_value.GetScalar());
- if (m_bitfield_bit_size)
- scalar.ExtractBitfield(m_bitfield_bit_size,
- m_bitfield_bit_offset);
- else
- scalar.ExtractBitfield(8 * m_byte_size, 8 * m_byte_offset);
- m_value.GetScalar() = scalar;
- }
- break;
- default:
- m_error.SetErrorString("parent has invalid value.");
- break;
+ // Set this object's scalar value to the address of its value by
+ // adding its byte offset to the parent address
+ m_value.GetScalar() += m_byte_offset;
+ }
+ } break;
+
+ case Value::eValueTypeScalar:
+ // try to extract the child value from the parent's scalar value
+ {
+ Scalar scalar(m_value.GetScalar());
+ scalar.ExtractBitfield(8 * m_byte_size, 8 * m_byte_offset);
+ m_value.GetScalar() = scalar;
}
+ break;
}
if (m_error.Success()) {
diff --git a/lldb/source/Core/ValueObjectConstResult.cpp b/lldb/source/Core/ValueObjectConstResult.cpp
index 8d84f8e62ccc..ceb4491f8666 100644
--- a/lldb/source/Core/ValueObjectConstResult.cpp
+++ b/lldb/source/Core/ValueObjectConstResult.cpp
@@ -40,8 +40,7 @@ ValueObjectConstResult::ValueObjectConstResult(ExecutionContextScope *exe_scope,
ByteOrder byte_order,
uint32_t addr_byte_size,
lldb::addr_t address)
- : ValueObject(exe_scope, manager), m_type_name(), m_byte_size(0),
- m_impl(this, address) {
+ : ValueObject(exe_scope, manager), m_impl(this, address) {
SetIsConstant();
SetValueIsValid(true);
m_data.SetByteOrder(byte_order);
@@ -64,8 +63,7 @@ ValueObjectConstResult::ValueObjectConstResult(
ExecutionContextScope *exe_scope, ValueObjectManager &manager,
const CompilerType &compiler_type, ConstString name,
const DataExtractor &data, lldb::addr_t address)
- : ValueObject(exe_scope, manager), m_type_name(), m_byte_size(0),
- m_impl(this, address) {
+ : ValueObject(exe_scope, manager), m_impl(this, address) {
m_data = data;
if (!m_data.GetSharedDataBuffer()) {
@@ -112,8 +110,7 @@ ValueObjectConstResult::ValueObjectConstResult(
const CompilerType &compiler_type, ConstString name,
const lldb::DataBufferSP &data_sp, lldb::ByteOrder data_byte_order,
uint32_t data_addr_size, lldb::addr_t address)
- : ValueObject(exe_scope, manager), m_type_name(), m_byte_size(0),
- m_impl(this, address) {
+ : ValueObject(exe_scope, manager), m_impl(this, address) {
m_data.SetByteOrder(data_byte_order);
m_data.SetAddressByteSize(data_addr_size);
m_data.SetData(data_sp);
@@ -143,7 +140,7 @@ ValueObjectConstResult::ValueObjectConstResult(
ExecutionContextScope *exe_scope, ValueObjectManager &manager,
const CompilerType &compiler_type, ConstString name, lldb::addr_t address,
AddressType address_type, uint32_t addr_byte_size)
- : ValueObject(exe_scope, manager), m_type_name(), m_byte_size(0),
+ : ValueObject(exe_scope, manager), m_type_name(),
m_impl(this, address) {
m_value.GetScalar() = address;
m_data.SetAddressByteSize(addr_byte_size);
@@ -179,8 +176,7 @@ ValueObjectSP ValueObjectConstResult::Create(ExecutionContextScope *exe_scope,
ValueObjectConstResult::ValueObjectConstResult(ExecutionContextScope *exe_scope,
ValueObjectManager &manager,
const Status &error)
- : ValueObject(exe_scope, manager), m_type_name(), m_byte_size(0),
- m_impl(this) {
+ : ValueObject(exe_scope, manager), m_impl(this) {
m_error = error;
SetIsConstant();
}
@@ -189,8 +185,7 @@ ValueObjectConstResult::ValueObjectConstResult(ExecutionContextScope *exe_scope,
ValueObjectManager &manager,
const Value &value,
ConstString name, Module *module)
- : ValueObject(exe_scope, manager), m_type_name(), m_byte_size(0),
- m_impl(this) {
+ : ValueObject(exe_scope, manager), m_impl(this) {
m_value = value;
m_name = name;
ExecutionContext exe_ctx;
@@ -208,9 +203,9 @@ lldb::ValueType ValueObjectConstResult::GetValueType() const {
return eValueTypeConstResult;
}
-uint64_t ValueObjectConstResult::GetByteSize() {
+llvm::Optional<uint64_t> ValueObjectConstResult::GetByteSize() {
ExecutionContext exe_ctx(GetExecutionContextRef());
- if (m_byte_size == 0) {
+ if (!m_byte_size) {
if (auto size =
GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope()))
SetByteSize(*size);
diff --git a/lldb/source/Core/ValueObjectDynamicValue.cpp b/lldb/source/Core/ValueObjectDynamicValue.cpp
index ca66740cb55d..1c25b8c85a05 100644
--- a/lldb/source/Core/ValueObjectDynamicValue.cpp
+++ b/lldb/source/Core/ValueObjectDynamicValue.cpp
@@ -98,7 +98,7 @@ size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) {
return m_parent->GetNumChildren(max);
}
-uint64_t ValueObjectDynamicValue::GetByteSize() {
+llvm::Optional<uint64_t> ValueObjectDynamicValue::GetByteSize() {
const bool success = UpdateValueIfNeeded(false);
if (success && m_dynamic_type_info.HasType()) {
ExecutionContext exe_ctx(GetExecutionContextRef());
diff --git a/lldb/source/Core/ValueObjectMemory.cpp b/lldb/source/Core/ValueObjectMemory.cpp
index 91b2c6084928..abf7b38ed89a 100644
--- a/lldb/source/Core/ValueObjectMemory.cpp
+++ b/lldb/source/Core/ValueObjectMemory.cpp
@@ -139,10 +139,11 @@ size_t ValueObjectMemory::CalculateNumChildren(uint32_t max) {
return child_count <= max ? child_count : max;
}
-uint64_t ValueObjectMemory::GetByteSize() {
+llvm::Optional<uint64_t> ValueObjectMemory::GetByteSize() {
+ ExecutionContext exe_ctx(GetExecutionContextRef());
if (m_type_sp)
- return m_type_sp->GetByteSize().getValueOr(0);
- return m_compiler_type.GetByteSize(nullptr).getValueOr(0);
+ return m_type_sp->GetByteSize(exe_ctx.GetBestExecutionContextScope());
+ return m_compiler_type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
}
lldb::ValueType ValueObjectMemory::GetValueType() const {
@@ -167,9 +168,6 @@ bool ValueObjectMemory::UpdateValue() {
Value::ValueType value_type = m_value.GetValueType();
switch (value_type) {
- default:
- llvm_unreachable("Unhandled expression result value kind...");
-
case Value::eValueTypeScalar:
// The variable value is in the Scalar value inside the m_value. We can
// point our m_data right to it.
diff --git a/lldb/source/Core/ValueObjectRegister.cpp b/lldb/source/Core/ValueObjectRegister.cpp
index ec87c38fb367..27461e9cebc4 100644
--- a/lldb/source/Core/ValueObjectRegister.cpp
+++ b/lldb/source/Core/ValueObjectRegister.cpp
@@ -81,7 +81,7 @@ size_t ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) {
return 0;
}
-uint64_t ValueObjectRegisterSet::GetByteSize() { return 0; }
+llvm::Optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }
bool ValueObjectRegisterSet::UpdateValue() {
m_error.Clear();
@@ -229,7 +229,9 @@ size_t ValueObjectRegister::CalculateNumChildren(uint32_t max) {
return children_count <= max ? children_count : max;
}
-uint64_t ValueObjectRegister::GetByteSize() { return m_reg_info.byte_size; }
+llvm::Optional<uint64_t> ValueObjectRegister::GetByteSize() {
+ return m_reg_info.byte_size;
+}
bool ValueObjectRegister::UpdateValue() {
m_error.Clear();
diff --git a/lldb/source/Core/ValueObjectSyntheticFilter.cpp b/lldb/source/Core/ValueObjectSyntheticFilter.cpp
index 32d1e6ab8368..cebf7abfe523 100644
--- a/lldb/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/lldb/source/Core/ValueObjectSyntheticFilter.cpp
@@ -46,7 +46,7 @@ public:
ValueObjectSynthetic::ValueObjectSynthetic(ValueObject &parent,
lldb::SyntheticChildrenSP filter)
- : ValueObject(parent), m_synth_sp(filter), m_children_byindex(),
+ : ValueObject(parent), m_synth_sp(std::move(filter)), m_children_byindex(),
m_name_toindex(), m_synthetic_children_cache(),
m_synthetic_children_count(UINT32_MAX),
m_parent_type_name(parent.GetTypeName()),
@@ -121,7 +121,9 @@ bool ValueObjectSynthetic::MightHaveChildren() {
return (m_might_have_children != eLazyBoolNo);
}
-uint64_t ValueObjectSynthetic::GetByteSize() { return m_parent->GetByteSize(); }
+llvm::Optional<uint64_t> ValueObjectSynthetic::GetByteSize() {
+ return m_parent->GetByteSize();
+}
lldb::ValueType ValueObjectSynthetic::GetValueType() const {
return m_parent->GetValueType();
diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp
index 0d1e7b047a0a..5acb23aaac5b 100644
--- a/lldb/source/Core/ValueObjectVariable.cpp
+++ b/lldb/source/Core/ValueObjectVariable.cpp
@@ -105,15 +105,15 @@ size_t ValueObjectVariable::CalculateNumChildren(uint32_t max) {
return child_count <= max ? child_count : max;
}
-uint64_t ValueObjectVariable::GetByteSize() {
+llvm::Optional<uint64_t> ValueObjectVariable::GetByteSize() {
ExecutionContext exe_ctx(GetExecutionContextRef());
CompilerType type(GetCompilerType());
if (!type.IsValid())
- return 0;
+ return {};
- return type.GetByteSize(exe_ctx.GetBestExecutionContextScope()).getValueOr(0);
+ return type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
}
lldb::ValueType ValueObjectVariable::GetValueType() const {
@@ -132,8 +132,11 @@ bool ValueObjectVariable::UpdateValue() {
if (variable->GetLocationIsConstantValueData()) {
// expr doesn't contain DWARF bytes, it contains the constant variable
// value bytes themselves...
- if (expr.GetExpressionData(m_data))
+ if (expr.GetExpressionData(m_data)) {
+ if (m_data.GetDataStart() && m_data.GetByteSize())
+ m_value.SetBytes(m_data.GetDataStart(), m_data.GetByteSize());
m_value.SetContext(Value::eContextTypeVariable, variable);
+ }
else
m_error.SetErrorString("empty constant data");
// constant bytes can't be edited - sorry
@@ -193,8 +196,6 @@ bool ValueObjectVariable::UpdateValue() {
const bool process_is_alive = process && process->IsAlive();
switch (value_type) {
- case Value::eValueTypeVector:
- // fall through
case Value::eValueTypeScalar:
// The variable value is in the Scalar value inside the m_value. We can
// point our m_data right to it.
@@ -292,7 +293,6 @@ void ValueObjectVariable::DoUpdateChildrenAddressType(ValueObject &valobj) {
break;
case Value::eValueTypeLoadAddress:
case Value::eValueTypeScalar:
- case Value::eValueTypeVector:
valobj.SetAddressTypeOfChildren(eAddressTypeLoad);
break;
}