diff options
Diffstat (limited to 'source/Core/Debugger.cpp')
-rw-r--r-- | source/Core/Debugger.cpp | 196 |
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); } |