summaryrefslogtreecommitdiff
path: root/source/Core/Debugger.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Core/Debugger.cpp')
-rw-r--r--source/Core/Debugger.cpp196
1 files changed, 65 insertions, 131 deletions
diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp
index a4d78151c75f..972d0bc0a6d7 100644
--- a/source/Core/Debugger.cpp
+++ b/source/Core/Debugger.cpp
@@ -14,6 +14,7 @@
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Listener.h" // for Listener
#include "lldb/Core/Mangled.h" // for Mangled
+#include "lldb/Core/ModuleList.h" // for Mangled
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamAsynchronousIO.h"
@@ -47,7 +48,7 @@
#include "lldb/Utility/StreamCallback.h"
#include "lldb/Utility/StreamString.h"
-#if defined(LLVM_ON_WIN32)
+#if defined(_WIN32)
#include "lldb/Host/windows/PosixApi.h" // for PATH_MAX
#endif
@@ -166,13 +167,15 @@ OptionEnumValueElement g_language_enumerators[] = {
"}${addr-file-or-load}{ " \
"<${function.concrete-only-addr-offset-no-padding}>}: "
-// gdb's disassembly format can be emulated with
-// ${current-pc-arrow}${addr-file-or-load}{
-// <${function.name-without-args}${function.concrete-only-addr-offset-no-padding}>}:
+// gdb's disassembly format can be emulated with ${current-pc-arrow}${addr-
+// file-or-load}{ <${function.name-without-args}${function.concrete-only-addr-
+// offset-no-padding}>}:
// lldb's original format for disassembly would look like this format string -
-// {${function.initial-function}{${module.file.basename}`}{${function.name-without-args}}:\n}{${function.changed}\n{${module.file.basename}`}{${function.name-without-args}}:\n}{${current-pc-arrow}
-// }{${addr-file-or-load}}:
+// {${function.initial-function}{${module.file.basename}`}{${function.name-
+// without-
+// args}}:\n}{${function.changed}\n{${module.file.basename}`}{${function.name-
+// without-args}}:\n}{${current-pc-arrow} }{${addr-file-or-load}}:
#define DEFAULT_STOP_SHOW_COLUMN_ANSI_PREFIX "${ansi.underline}"
#define DEFAULT_STOP_SHOW_COLUMN_ANSI_SUFFIX "${ansi.normal}"
@@ -589,9 +592,9 @@ bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) {
return true;
}
} else {
- // The g_load_plugin_callback is registered in SBDebugger::Initialize()
- // and if the public API layer isn't available (code is linking against
- // all of the internal LLDB static libraries), then we can't load plugins
+ // The g_load_plugin_callback is registered in SBDebugger::Initialize() and
+ // if the public API layer isn't available (code is linking against all of
+ // the internal LLDB static libraries), then we can't load plugins
error.SetErrorString("Public API layer is not available");
}
return false;
@@ -602,8 +605,8 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
const FileSpec &file_spec) {
Status error;
- static ConstString g_dylibext("dylib");
- static ConstString g_solibext("so");
+ static ConstString g_dylibext(".dylib");
+ static ConstString g_solibext(".so");
if (!baton)
return FileSpec::eEnumerateDirectoryResultQuit;
@@ -611,8 +614,8 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
Debugger *debugger = (Debugger *)baton;
namespace fs = llvm::sys::fs;
- // If we have a regular file, a symbolic link or unknown file type, try
- // and process the file. We must handle unknown as sometimes the directory
+ // If we have a regular file, a symbolic link or unknown file type, try and
+ // process the file. We must handle unknown as sometimes the directory
// enumeration might be enumerating a file system that doesn't have correct
// file type information.
if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
@@ -632,9 +635,9 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
} else if (ft == fs::file_type::directory_file ||
ft == fs::file_type::symlink_file ||
ft == fs::file_type::type_unknown) {
- // Try and recurse into anything that a directory or symbolic link.
- // We must also do this for unknown as sometimes the directory enumeration
- // might be enumerating a file system that doesn't have correct file type
+ // Try and recurse into anything that a directory or symbolic link. We must
+ // also do this for unknown as sometimes the directory enumeration might be
+ // enumerating a file system that doesn't have correct file type
// information.
return FileSpec::eEnumerateDirectoryResultEnter;
}
@@ -643,19 +646,18 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
}
void Debugger::InstanceInitialize() {
- FileSpec dir_spec;
const bool find_directories = true;
const bool find_files = true;
const bool find_other = true;
char dir_path[PATH_MAX];
- if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec)) {
+ if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) {
if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
find_other, LoadPluginCallback, this);
}
}
- if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec)) {
+ if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) {
if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
find_other, LoadPluginCallback, this);
@@ -774,6 +776,9 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
m_collection_sp->AppendProperty(
ConstString("platform"), ConstString("Platform settings."), true,
Platform::GetGlobalPlatformProperties()->GetValueProperties());
+ m_collection_sp->AppendProperty(
+ ConstString("symbols"), ConstString("Symbol lookup and cache settings."),
+ true, ModuleList::GetGlobalModuleListProperties().GetValueProperties());
if (m_command_interpreter_ap) {
m_collection_sp->AppendProperty(
ConstString("interpreter"),
@@ -796,10 +801,9 @@ Debugger::~Debugger() { Clear(); }
void Debugger::Clear() {
//----------------------------------------------------------------------
- // Make sure we call this function only once. With the C++ global
- // destructor chain having a list of debuggers and with code that can be
- // running on other threads, we need to ensure this doesn't happen
- // multiple times.
+ // Make sure we call this function only once. With the C++ global destructor
+ // chain having a list of debuggers and with code that can be running on
+ // other threads, we need to ensure this doesn't happen multiple times.
//
// The following functions call Debugger::Clear():
// Debugger::~Debugger();
@@ -824,8 +828,7 @@ void Debugger::Clear() {
m_broadcaster_manager_sp->Clear();
// Close the input file _before_ we close the input read communications
- // class
- // as it does NOT own the input file, our m_input_file does.
+ // class as it does NOT own the input file, our m_input_file does.
m_terminal_state.Clear();
if (m_input_file_sp)
m_input_file_sp->GetFile().Close();
@@ -861,8 +864,8 @@ void Debugger::SetInputFileHandle(FILE *fh, bool tranfer_ownership) {
if (!in_file.IsValid())
in_file.SetStream(stdin, true);
- // Save away the terminal state if that is relevant, so that we can restore it
- // in RestoreInputState.
+ // Save away the terminal state if that is relevant, so that we can restore
+ // it in RestoreInputState.
SaveInputTerminalState();
}
@@ -876,8 +879,8 @@ void Debugger::SetOutputFileHandle(FILE *fh, bool tranfer_ownership) {
if (!out_file.IsValid())
out_file.SetStream(stdout, false);
- // do not create the ScriptInterpreter just for setting the output file handle
- // as the constructor will know how to do the right thing on its own
+ // do not create the ScriptInterpreter just for setting the output file
+ // handle as the constructor will know how to do the right thing on its own
const bool can_create = false;
ScriptInterpreter *script_interpreter =
GetCommandInterpreter().GetScriptInterpreter(can_create);
@@ -1023,11 +1026,10 @@ void Debugger::RunIOHandler(const IOHandlerSP &reader_sp) {
void Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in,
StreamFileSP &out,
StreamFileSP &err) {
- // Before an IOHandler runs, it must have in/out/err streams.
- // This function is called when one ore more of the streams
- // are nullptr. We use the top input reader's in/out/err streams,
- // or fall back to the debugger file handles, or we fall back
- // onto stdin/stdout/stderr as a last resort.
+ // Before an IOHandler runs, it must have in/out/err streams. This function
+ // is called when one ore more of the streams are nullptr. We use the top
+ // input reader's in/out/err streams, or fall back to the debugger file
+ // handles, or we fall back onto stdin/stdout/stderr as a last resort.
std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
IOHandlerSP top_reader_sp(m_input_reader_stack.Top());
@@ -1083,8 +1085,8 @@ void Debugger::PushIOHandler(const IOHandlerSP &reader_sp) {
m_input_reader_stack.Push(reader_sp);
reader_sp->Activate();
- // Interrupt the top input reader to it will exit its Run() function
- // and let this new input reader take over
+ // Interrupt the top input reader to it will exit its Run() function and let
+ // this new input reader take over
if (top_reader_sp) {
top_reader_sp->Deactivate();
top_reader_sp->Cancel();
@@ -1097,8 +1099,8 @@ bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) {
std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
- // The reader on the stop of the stack is done, so let the next
- // read on the stack refresh its prompt and if there is one...
+ // The reader on the stop of the stack is done, so let the next read on the
+ // stack refresh its prompt and if there is one...
if (m_input_reader_stack.IsEmpty())
return false;
@@ -1162,75 +1164,6 @@ DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) {
return debugger_sp;
}
-#if 0
-static void
-TestPromptFormats (StackFrame *frame)
-{
- if (frame == nullptr)
- return;
-
- StreamString s;
- const char *prompt_format =
- "{addr = '${addr}'\n}"
- "{addr-file-or-load = '${addr-file-or-load}'\n}"
- "{current-pc-arrow = '${current-pc-arrow}'\n}"
- "{process.id = '${process.id}'\n}"
- "{process.name = '${process.name}'\n}"
- "{process.file.basename = '${process.file.basename}'\n}"
- "{process.file.fullpath = '${process.file.fullpath}'\n}"
- "{thread.id = '${thread.id}'\n}"
- "{thread.index = '${thread.index}'\n}"
- "{thread.name = '${thread.name}'\n}"
- "{thread.queue = '${thread.queue}'\n}"
- "{thread.stop-reason = '${thread.stop-reason}'\n}"
- "{target.arch = '${target.arch}'\n}"
- "{module.file.basename = '${module.file.basename}'\n}"
- "{module.file.fullpath = '${module.file.fullpath}'\n}"
- "{file.basename = '${file.basename}'\n}"
- "{file.fullpath = '${file.fullpath}'\n}"
- "{frame.index = '${frame.index}'\n}"
- "{frame.pc = '${frame.pc}'\n}"
- "{frame.sp = '${frame.sp}'\n}"
- "{frame.fp = '${frame.fp}'\n}"
- "{frame.flags = '${frame.flags}'\n}"
- "{frame.reg.rdi = '${frame.reg.rdi}'\n}"
- "{frame.reg.rip = '${frame.reg.rip}'\n}"
- "{frame.reg.rsp = '${frame.reg.rsp}'\n}"
- "{frame.reg.rbp = '${frame.reg.rbp}'\n}"
- "{frame.reg.rflags = '${frame.reg.rflags}'\n}"
- "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}"
- "{frame.reg.carp = '${frame.reg.carp}'\n}"
- "{function.id = '${function.id}'\n}"
- "{function.changed = '${function.changed}'\n}"
- "{function.initial-function = '${function.initial-function}'\n}"
- "{function.name = '${function.name}'\n}"
- "{function.name-without-args = '${function.name-without-args}'\n}"
- "{function.name-with-args = '${function.name-with-args}'\n}"
- "{function.addr-offset = '${function.addr-offset}'\n}"
- "{function.concrete-only-addr-offset-no-padding = '${function.concrete-only-addr-offset-no-padding}'\n}"
- "{function.line-offset = '${function.line-offset}'\n}"
- "{function.pc-offset = '${function.pc-offset}'\n}"
- "{line.file.basename = '${line.file.basename}'\n}"
- "{line.file.fullpath = '${line.file.fullpath}'\n}"
- "{line.number = '${line.number}'\n}"
- "{line.start-addr = '${line.start-addr}'\n}"
- "{line.end-addr = '${line.end-addr}'\n}"
-;
-
- SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything));
- ExecutionContext exe_ctx;
- frame->CalculateExecutionContext(exe_ctx);
- if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s))
- {
- printf("%s\n", s.GetData());
- }
- else
- {
- printf ("what we got: %s\n", s.GetData());
- }
-}
-#endif
-
bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format,
const SymbolContext *sc,
const SymbolContext *prev_sc,
@@ -1262,8 +1195,8 @@ bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format,
}
}
}
- // The first context on a list of instructions will have a prev_sc that
- // has no Function or Symbol -- if SymbolContext had an IsValid() method, it
+ // The first context on a list of instructions will have a prev_sc that has
+ // no Function or Symbol -- if SymbolContext had an IsValid() method, it
// would return false. But we do get a prev_sc pointer.
if ((sc && (sc->function || sc->symbol)) && prev_sc &&
(prev_sc->function == nullptr && prev_sc->symbol == nullptr)) {
@@ -1307,8 +1240,8 @@ bool Debugger::EnableLog(llvm::StringRef channel,
if (log_options & LLDB_LOG_OPTION_APPEND)
flags |= llvm::sys::fs::F_Append;
int FD;
- if (std::error_code ec =
- llvm::sys::fs::openFileForWrite(log_file, FD, flags)) {
+ if (std::error_code ec = llvm::sys::fs::openFileForWrite(
+ log_file, FD, llvm::sys::fs::CD_CreateAlways, flags)) {
error_stream << "Unable to open log file: " << ec.message();
return false;
}
@@ -1529,8 +1462,8 @@ void Debugger::HandleProcessEvent(const EventSP &event_sp) {
}
void Debugger::HandleThreadEvent(const EventSP &event_sp) {
- // At present the only thread event we handle is the Frame Changed event,
- // and all we do for that is just reprint the thread status for that thread.
+ // At present the only thread event we handle is the Frame Changed event, and
+ // all we do for that is just reprint the thread status for that thread.
using namespace lldb;
const uint32_t event_type = event_sp->GetType();
const bool stop_format = true;
@@ -1583,8 +1516,8 @@ void Debugger::DefaultEventHandler() {
CommandInterpreter::eBroadcastBitAsynchronousOutputData |
CommandInterpreter::eBroadcastBitAsynchronousErrorData);
- // Let the thread that spawned us know that we have started up and
- // that we are now listening to all required events so no events get missed
+ // Let the thread that spawned us know that we have started up and that we
+ // are now listening to all required events so no events get missed
m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);
bool done = false;
@@ -1649,27 +1582,28 @@ lldb::thread_result_t Debugger::EventHandlerThread(lldb::thread_arg_t arg) {
bool Debugger::StartEventHandlerThread() {
if (!m_event_handler_thread.IsJoinable()) {
- // We must synchronize with the DefaultEventHandler() thread to ensure
- // it is up and running and listening to events before we return from
- // this function. We do this by listening to events for the
+ // We must synchronize with the DefaultEventHandler() thread to ensure it
+ // is up and running and listening to events before we return from this
+ // function. We do this by listening to events for the
// eBroadcastBitEventThreadIsListening from the m_sync_broadcaster
- ListenerSP listener_sp(
- Listener::MakeListener("lldb.debugger.event-handler"));
+ ConstString full_name("lldb.debugger.event-handler");
+ ListenerSP listener_sp(Listener::MakeListener(full_name.AsCString()));
listener_sp->StartListeningForEvents(&m_sync_broadcaster,
eBroadcastBitEventThreadIsListening);
+ auto thread_name =
+ full_name.GetLength() < llvm::get_max_thread_name_length() ?
+ full_name.AsCString() : "dbg.evt-handler";
+
// Use larger 8MB stack for this thread
- m_event_handler_thread = ThreadLauncher::LaunchThread(
- "lldb.debugger.event-handler", EventHandlerThread, this, nullptr,
- g_debugger_event_thread_stack_bytes);
-
- // Make sure DefaultEventHandler() is running and listening to events before
- // we return
- // from this function. We are only listening for events of type
- // eBroadcastBitEventThreadIsListening so we don't need to check the event,
- // we just need
- // to wait an infinite amount of time for it (nullptr timeout as the first
- // parameter)
+ m_event_handler_thread = ThreadLauncher::LaunchThread(thread_name,
+ EventHandlerThread, this, nullptr, g_debugger_event_thread_stack_bytes);
+
+ // Make sure DefaultEventHandler() is running and listening to events
+ // before we return from this function. We are only listening for events of
+ // type eBroadcastBitEventThreadIsListening so we don't need to check the
+ // event, we just need to wait an infinite amount of time for it (nullptr
+ // timeout as the first parameter)
lldb::EventSP event_sp;
listener_sp->GetEvent(event_sp, llvm::None);
}