130fdc8d8SChris Lattner //===-- Driver.cpp ----------------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner
930fdc8d8SChris Lattner #include "Driver.h"
1030fdc8d8SChris Lattner
11a382d474SEli Friedman #include "lldb/API/SBCommandInterpreter.h"
124b354039SJonas Devlieghere #include "lldb/API/SBCommandInterpreterRunOptions.h"
13a382d474SEli Friedman #include "lldb/API/SBCommandReturnObject.h"
14a382d474SEli Friedman #include "lldb/API/SBDebugger.h"
159eb13719SLawrence D'Anna #include "lldb/API/SBFile.h"
16a382d474SEli Friedman #include "lldb/API/SBHostOS.h"
173e7e915dSSean Callanan #include "lldb/API/SBLanguageRuntime.h"
18936c6242SJonas Devlieghere #include "lldb/API/SBReproducer.h"
1985e8b814SJim Ingham #include "lldb/API/SBStream.h"
20878ae018SJason Molenda #include "lldb/API/SBStringList.h"
21bbef51ebSLawrence D'Anna #include "lldb/API/SBStructuredData.h"
2200eae5eaSJonas Devlieghere
232ad6e0a6SJonas Devlieghere #include "llvm/ADT/StringRef.h"
24b02baf0aSJonas Devlieghere #include "llvm/Support/Format.h"
254778f40fSMartin Storsjo #include "llvm/Support/InitLLVM.h"
2600eae5eaSJonas Devlieghere #include "llvm/Support/Path.h"
272ad6e0a6SJonas Devlieghere #include "llvm/Support/Signals.h"
28b02baf0aSJonas Devlieghere #include "llvm/Support/WithColor.h"
2900eae5eaSJonas Devlieghere #include "llvm/Support/raw_ostream.h"
3000eae5eaSJonas Devlieghere
3100eae5eaSJonas Devlieghere #include <algorithm>
3200eae5eaSJonas Devlieghere #include <atomic>
3300eae5eaSJonas Devlieghere #include <bitset>
3472748488SJan Kratochvil #include <clocale>
3500eae5eaSJonas Devlieghere #include <csignal>
3600eae5eaSJonas Devlieghere #include <string>
37190fadcdSZachary Turner #include <thread>
385ce9dc61STatyana Krasnukha #include <utility>
3930fdc8d8SChris Lattner
4076e47d48SRaphael Isemann #include <climits>
4176e47d48SRaphael Isemann #include <cstdio>
4276e47d48SRaphael Isemann #include <cstdlib>
4376e47d48SRaphael Isemann #include <cstring>
4400eae5eaSJonas Devlieghere #include <fcntl.h>
4500eae5eaSJonas Devlieghere
46b82ad2a8STodd Fiala #if !defined(__APPLE__)
4740a069adSZachary Turner #include "llvm/Support/DataTypes.h"
48b82ad2a8STodd Fiala #endif
4940a069adSZachary Turner
5030fdc8d8SChris Lattner using namespace lldb;
5100eae5eaSJonas Devlieghere using namespace llvm;
5200eae5eaSJonas Devlieghere
5300eae5eaSJonas Devlieghere namespace {
5400eae5eaSJonas Devlieghere enum ID {
5500eae5eaSJonas Devlieghere OPT_INVALID = 0, // This is not an option ID.
5600eae5eaSJonas Devlieghere #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
5700eae5eaSJonas Devlieghere HELPTEXT, METAVAR, VALUES) \
5800eae5eaSJonas Devlieghere OPT_##ID,
5900eae5eaSJonas Devlieghere #include "Options.inc"
6000eae5eaSJonas Devlieghere #undef OPTION
6100eae5eaSJonas Devlieghere };
6200eae5eaSJonas Devlieghere
6300eae5eaSJonas Devlieghere #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
6400eae5eaSJonas Devlieghere #include "Options.inc"
6500eae5eaSJonas Devlieghere #undef PREFIX
6600eae5eaSJonas Devlieghere
67e6366a85SJonas Devlieghere const opt::OptTable::Info InfoTable[] = {
6800eae5eaSJonas Devlieghere #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
6900eae5eaSJonas Devlieghere HELPTEXT, METAVAR, VALUES) \
7000eae5eaSJonas Devlieghere { \
7100eae5eaSJonas Devlieghere PREFIX, NAME, HELPTEXT, \
7200eae5eaSJonas Devlieghere METAVAR, OPT_##ID, opt::Option::KIND##Class, \
7300eae5eaSJonas Devlieghere PARAM, FLAGS, OPT_##GROUP, \
7400eae5eaSJonas Devlieghere OPT_##ALIAS, ALIASARGS, VALUES},
7500eae5eaSJonas Devlieghere #include "Options.inc"
7600eae5eaSJonas Devlieghere #undef OPTION
7700eae5eaSJonas Devlieghere };
7800eae5eaSJonas Devlieghere
7900eae5eaSJonas Devlieghere class LLDBOptTable : public opt::OptTable {
8000eae5eaSJonas Devlieghere public:
LLDBOptTable()8100eae5eaSJonas Devlieghere LLDBOptTable() : OptTable(InfoTable) {}
8200eae5eaSJonas Devlieghere };
8300eae5eaSJonas Devlieghere } // namespace
8430fdc8d8SChris Lattner
8530fdc8d8SChris Lattner static void reset_stdin_termios();
86f571b890SGreg Clayton static bool g_old_stdin_termios_is_valid = false;
8730fdc8d8SChris Lattner static struct termios g_old_stdin_termios;
8830fdc8d8SChris Lattner
disable_color(const raw_ostream & OS)894429cf14SJonas Devlieghere static bool disable_color(const raw_ostream &OS) { return false; }
904429cf14SJonas Devlieghere
91e6366a85SJonas Devlieghere static Driver *g_driver = nullptr;
92dd759857SCaroline Tice
9330fdc8d8SChris Lattner // In the Driver::MainLoop, we change the terminal settings. This function is
9430fdc8d8SChris Lattner // added as an atexit handler to make sure we clean them up.
reset_stdin_termios()95b9c1b51eSKate Stone static void reset_stdin_termios() {
96b9c1b51eSKate Stone if (g_old_stdin_termios_is_valid) {
97f571b890SGreg Clayton g_old_stdin_termios_is_valid = false;
9830fdc8d8SChris Lattner ::tcsetattr(STDIN_FILENO, TCSANOW, &g_old_stdin_termios);
9930fdc8d8SChris Lattner }
100f571b890SGreg Clayton }
10130fdc8d8SChris Lattner
Driver()102b9c1b51eSKate Stone Driver::Driver()
103e6366a85SJonas Devlieghere : SBBroadcaster("Driver"), m_debugger(SBDebugger::Create(false)) {
104fc3f027dSGreg Clayton // We want to be able to handle CTRL+D in the terminal to have it terminate
105fc3f027dSGreg Clayton // certain input
106fc3f027dSGreg Clayton m_debugger.SetCloseInputOnEOF(false);
107efed6131SCaroline Tice g_driver = this;
10830fdc8d8SChris Lattner }
10930fdc8d8SChris Lattner
~Driver()1106ac12b5bSJonas Devlieghere Driver::~Driver() {
1116ac12b5bSJonas Devlieghere SBDebugger::Destroy(m_debugger);
1126ac12b5bSJonas Devlieghere g_driver = nullptr;
1136ac12b5bSJonas Devlieghere }
11430fdc8d8SChris Lattner
AddInitialCommand(std::string command,CommandPlacement placement,bool is_file,SBError & error)11500eae5eaSJonas Devlieghere void Driver::OptionData::AddInitialCommand(std::string command,
116b9c1b51eSKate Stone CommandPlacement placement,
117b9c1b51eSKate Stone bool is_file, SBError &error) {
1180f17c557SJim Ingham std::vector<InitialCmdEntry> *command_set;
119b9c1b51eSKate Stone switch (placement) {
1204add3b13SJim Ingham case eCommandPlacementBeforeFile:
121ed3252fbSJim Ingham command_set = &(m_initial_commands);
1224add3b13SJim Ingham break;
1234add3b13SJim Ingham case eCommandPlacementAfterFile:
124ed3252fbSJim Ingham command_set = &(m_after_file_commands);
1254add3b13SJim Ingham break;
1264add3b13SJim Ingham case eCommandPlacementAfterCrash:
1274add3b13SJim Ingham command_set = &(m_after_crash_commands);
1284add3b13SJim Ingham break;
1294add3b13SJim Ingham }
130ed3252fbSJim Ingham
131b9c1b51eSKate Stone if (is_file) {
13200eae5eaSJonas Devlieghere SBFileSpec file(command.c_str());
133ed3252fbSJim Ingham if (file.Exists())
1342edcad7bSJonas Devlieghere command_set->push_back(InitialCmdEntry(command, is_file));
135b9c1b51eSKate Stone else if (file.ResolveExecutableLocation()) {
136ed3252fbSJim Ingham char final_path[PATH_MAX];
137ed3252fbSJim Ingham file.GetPath(final_path, sizeof(final_path));
1382edcad7bSJonas Devlieghere command_set->push_back(InitialCmdEntry(final_path, is_file));
139b9c1b51eSKate Stone } else
140b9c1b51eSKate Stone error.SetErrorStringWithFormat(
14100eae5eaSJonas Devlieghere "file specified in --source (-s) option doesn't exist: '%s'",
14200eae5eaSJonas Devlieghere command.c_str());
143b9c1b51eSKate Stone } else
1442edcad7bSJonas Devlieghere command_set->push_back(InitialCmdEntry(command, is_file));
145ed3252fbSJim Ingham }
146ed3252fbSJim Ingham
WriteCommandsForSourcing(CommandPlacement placement,SBStream & strm)147b9c1b51eSKate Stone void Driver::WriteCommandsForSourcing(CommandPlacement placement,
148b9c1b51eSKate Stone SBStream &strm) {
1490f17c557SJim Ingham std::vector<OptionData::InitialCmdEntry> *command_set;
150b9c1b51eSKate Stone switch (placement) {
1514add3b13SJim Ingham case eCommandPlacementBeforeFile:
1524add3b13SJim Ingham command_set = &m_option_data.m_initial_commands;
1534add3b13SJim Ingham break;
1544add3b13SJim Ingham case eCommandPlacementAfterFile:
1554add3b13SJim Ingham command_set = &m_option_data.m_after_file_commands;
1564add3b13SJim Ingham break;
1574add3b13SJim Ingham case eCommandPlacementAfterCrash:
1584add3b13SJim Ingham command_set = &m_option_data.m_after_crash_commands;
1594add3b13SJim Ingham break;
1604add3b13SJim Ingham }
16106357c93SGreg Clayton
162b9c1b51eSKate Stone for (const auto &command_entry : *command_set) {
1630f17c557SJim Ingham const char *command = command_entry.contents.c_str();
164b9c1b51eSKate Stone if (command_entry.is_file) {
165b9c1b51eSKate Stone bool source_quietly =
166b9c1b51eSKate Stone m_option_data.m_source_quietly || command_entry.source_quietly;
167e6366a85SJonas Devlieghere strm.Printf("command source -s %i '%s'\n",
168e6366a85SJonas Devlieghere static_cast<int>(source_quietly), command);
169b9c1b51eSKate Stone } else
17006357c93SGreg Clayton strm.Printf("%s\n", command);
1716611103cSGreg Clayton }
1726611103cSGreg Clayton }
1736611103cSGreg Clayton
174b9c1b51eSKate Stone // Check the arguments that were passed to this program to make sure they are
17500eae5eaSJonas Devlieghere // valid and to get their argument values (if any). Return a boolean value
17600eae5eaSJonas Devlieghere // indicating whether or not to start up the full debugger (i.e. the Command
17700eae5eaSJonas Devlieghere // Interpreter) or not. Return FALSE if the arguments were invalid OR if the
17800eae5eaSJonas Devlieghere // user only wanted help or version information.
ProcessArgs(const opt::InputArgList & args,bool & exiting)179b02baf0aSJonas Devlieghere SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) {
18000eae5eaSJonas Devlieghere SBError error;
1816611103cSGreg Clayton
182b9c1b51eSKate Stone // This is kind of a pain, but since we make the debugger in the Driver's
18300eae5eaSJonas Devlieghere // constructor, we can't know at that point whether we should read in init
18400eae5eaSJonas Devlieghere // files yet. So we don't read them in in the Driver constructor, then set
18500eae5eaSJonas Devlieghere // the flags back to "read them in" here, and then if we see the "-n" flag,
18600eae5eaSJonas Devlieghere // we'll turn it off again. Finally we have to read them in by hand later in
18700eae5eaSJonas Devlieghere // the main loop.
18806942690SJim Ingham m_debugger.SkipLLDBInitFiles(false);
18906942690SJim Ingham m_debugger.SkipAppInitFiles(false);
19006942690SJim Ingham
1914429cf14SJonas Devlieghere if (args.hasArg(OPT_no_use_colors)) {
1924429cf14SJonas Devlieghere m_debugger.SetUseColor(false);
1934429cf14SJonas Devlieghere WithColor::setAutoDetectFunction(disable_color);
1944429cf14SJonas Devlieghere m_option_data.m_debug_mode = true;
1954429cf14SJonas Devlieghere }
1964429cf14SJonas Devlieghere
19700eae5eaSJonas Devlieghere if (args.hasArg(OPT_version)) {
19800eae5eaSJonas Devlieghere m_option_data.m_print_version = true;
19930fdc8d8SChris Lattner }
20030fdc8d8SChris Lattner
20100eae5eaSJonas Devlieghere if (args.hasArg(OPT_python_path)) {
202e2231ac7SJim Ingham m_option_data.m_print_python_path = true;
20300eae5eaSJonas Devlieghere }
204bbef51ebSLawrence D'Anna if (args.hasArg(OPT_print_script_interpreter_info)) {
205bbef51ebSLawrence D'Anna m_option_data.m_print_script_interpreter_info = true;
206bbef51ebSLawrence D'Anna }
207e2231ac7SJim Ingham
20800eae5eaSJonas Devlieghere if (args.hasArg(OPT_batch)) {
209ffc9f1deSJim Ingham m_option_data.m_batch = true;
21000eae5eaSJonas Devlieghere }
211ffc9f1deSJim Ingham
212cef2af0fSJonas Devlieghere if (auto *arg = args.getLastArg(OPT_core)) {
213cef2af0fSJonas Devlieghere auto arg_value = arg->getValue();
214cef2af0fSJonas Devlieghere SBFileSpec file(arg_value);
215cef2af0fSJonas Devlieghere if (!file.Exists()) {
216b9c1b51eSKate Stone error.SetErrorStringWithFormat(
217cef2af0fSJonas Devlieghere "file specified in --core (-c) option doesn't exist: '%s'",
218cef2af0fSJonas Devlieghere arg_value);
21900eae5eaSJonas Devlieghere return error;
22000eae5eaSJonas Devlieghere }
221cef2af0fSJonas Devlieghere m_option_data.m_core_file = arg_value;
22200eae5eaSJonas Devlieghere }
2236eee5aa0SGreg Clayton
22400eae5eaSJonas Devlieghere if (args.hasArg(OPT_editor)) {
225e40e4218SJim Ingham m_option_data.m_use_external_editor = true;
22600eae5eaSJonas Devlieghere }
2276611103cSGreg Clayton
22800eae5eaSJonas Devlieghere if (args.hasArg(OPT_no_lldbinit)) {
2296eee5aa0SGreg Clayton m_debugger.SkipLLDBInitFiles(true);
23006942690SJim Ingham m_debugger.SkipAppInitFiles(true);
23100eae5eaSJonas Devlieghere }
2326eee5aa0SGreg Clayton
2337ffd9638SJonas Devlieghere if (args.hasArg(OPT_local_lldbinit)) {
2347ffd9638SJonas Devlieghere lldb::SBDebugger::SetInternalVariable("target.load-cwd-lldbinit", "true",
2357ffd9638SJonas Devlieghere m_debugger.GetInstanceName());
2367ffd9638SJonas Devlieghere }
2377ffd9638SJonas Devlieghere
23800eae5eaSJonas Devlieghere if (auto *arg = args.getLastArg(OPT_file)) {
239cef2af0fSJonas Devlieghere auto arg_value = arg->getValue();
240cef2af0fSJonas Devlieghere SBFileSpec file(arg_value);
241b9c1b51eSKate Stone if (file.Exists()) {
242e6366a85SJonas Devlieghere m_option_data.m_args.emplace_back(arg_value);
243b9c1b51eSKate Stone } else if (file.ResolveExecutableLocation()) {
244428a9a58SCaroline Tice char path[PATH_MAX];
24525f3a3cdSJohnny Chen file.GetPath(path, sizeof(path));
246e6366a85SJonas Devlieghere m_option_data.m_args.emplace_back(path);
24700eae5eaSJonas Devlieghere } else {
248b9c1b51eSKate Stone error.SetErrorStringWithFormat(
249cef2af0fSJonas Devlieghere "file specified in --file (-f) option doesn't exist: '%s'",
250cef2af0fSJonas Devlieghere arg_value);
25100eae5eaSJonas Devlieghere return error;
25200eae5eaSJonas Devlieghere }
25300eae5eaSJonas Devlieghere }
2546611103cSGreg Clayton
25500eae5eaSJonas Devlieghere if (auto *arg = args.getLastArg(OPT_arch)) {
256cef2af0fSJonas Devlieghere auto arg_value = arg->getValue();
257e6366a85SJonas Devlieghere if (!lldb::SBDebugger::SetDefaultArchitecture(arg_value)) {
258b9c1b51eSKate Stone error.SetErrorStringWithFormat(
259cef2af0fSJonas Devlieghere "invalid architecture in the -a or --arch option: '%s'", arg_value);
26000eae5eaSJonas Devlieghere return error;
26100eae5eaSJonas Devlieghere }
26200eae5eaSJonas Devlieghere }
2636611103cSGreg Clayton
26400eae5eaSJonas Devlieghere if (auto *arg = args.getLastArg(OPT_script_language)) {
265cef2af0fSJonas Devlieghere auto arg_value = arg->getValue();
266de3d12f9SJonas Devlieghere m_debugger.SetScriptLanguage(m_debugger.GetScriptingLanguage(arg_value));
26700eae5eaSJonas Devlieghere }
2686611103cSGreg Clayton
26900eae5eaSJonas Devlieghere if (args.hasArg(OPT_source_quietly)) {
270ed3252fbSJim Ingham m_option_data.m_source_quietly = true;
27100eae5eaSJonas Devlieghere }
272ed3252fbSJim Ingham
27300eae5eaSJonas Devlieghere if (auto *arg = args.getLastArg(OPT_attach_name)) {
274cef2af0fSJonas Devlieghere auto arg_value = arg->getValue();
275cef2af0fSJonas Devlieghere m_option_data.m_process_name = arg_value;
27600eae5eaSJonas Devlieghere }
277e64f0dc7SJim Ingham
27800eae5eaSJonas Devlieghere if (args.hasArg(OPT_wait_for)) {
279e64f0dc7SJim Ingham m_option_data.m_wait_for = true;
28000eae5eaSJonas Devlieghere }
281e64f0dc7SJim Ingham
28200eae5eaSJonas Devlieghere if (auto *arg = args.getLastArg(OPT_attach_pid)) {
283cef2af0fSJonas Devlieghere auto arg_value = arg->getValue();
284e64f0dc7SJim Ingham char *remainder;
285cef2af0fSJonas Devlieghere m_option_data.m_process_pid = strtol(arg_value, &remainder, 0);
286cef2af0fSJonas Devlieghere if (remainder == arg_value || *remainder != '\0') {
287b9c1b51eSKate Stone error.SetErrorStringWithFormat(
288cef2af0fSJonas Devlieghere "Could not convert process PID: \"%s\" into a pid.", arg_value);
28900eae5eaSJonas Devlieghere return error;
29000eae5eaSJonas Devlieghere }
29100eae5eaSJonas Devlieghere }
2923e7e915dSSean Callanan
29300eae5eaSJonas Devlieghere if (auto *arg = args.getLastArg(OPT_repl_language)) {
294cef2af0fSJonas Devlieghere auto arg_value = arg->getValue();
295b9c1b51eSKate Stone m_option_data.m_repl_lang =
296cef2af0fSJonas Devlieghere SBLanguageRuntime::GetLanguageTypeFromString(arg_value);
297b9c1b51eSKate Stone if (m_option_data.m_repl_lang == eLanguageTypeUnknown) {
298b9c1b51eSKate Stone error.SetErrorStringWithFormat("Unrecognized language name: \"%s\"",
299cef2af0fSJonas Devlieghere arg_value);
30030fdc8d8SChris Lattner return error;
30130fdc8d8SChris Lattner }
30246a28a95SJonas Devlieghere m_debugger.SetREPLLanguage(m_option_data.m_repl_lang);
30330fdc8d8SChris Lattner }
30400eae5eaSJonas Devlieghere
3057e896277SJonas Devlieghere if (args.hasArg(OPT_repl)) {
30600eae5eaSJonas Devlieghere m_option_data.m_repl = true;
3077e896277SJonas Devlieghere }
3087e896277SJonas Devlieghere
3097e896277SJonas Devlieghere if (auto *arg = args.getLastArg(OPT_repl_)) {
3107e896277SJonas Devlieghere m_option_data.m_repl = true;
3117e896277SJonas Devlieghere if (auto arg_value = arg->getValue())
312cef2af0fSJonas Devlieghere m_option_data.m_repl_options = arg_value;
3134ab31c98SCaroline Tice }
31430fdc8d8SChris Lattner
31500eae5eaSJonas Devlieghere // We need to process the options below together as their relative order
31600eae5eaSJonas Devlieghere // matters.
31700eae5eaSJonas Devlieghere for (auto *arg : args.filtered(OPT_source_on_crash, OPT_one_line_on_crash,
31800eae5eaSJonas Devlieghere OPT_source, OPT_source_before_file,
31900eae5eaSJonas Devlieghere OPT_one_line, OPT_one_line_before_file)) {
320cef2af0fSJonas Devlieghere auto arg_value = arg->getValue();
32100eae5eaSJonas Devlieghere if (arg->getOption().matches(OPT_source_on_crash)) {
322cef2af0fSJonas Devlieghere m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash,
323cef2af0fSJonas Devlieghere true, error);
32400eae5eaSJonas Devlieghere if (error.Fail())
32500eae5eaSJonas Devlieghere return error;
32600eae5eaSJonas Devlieghere }
32700eae5eaSJonas Devlieghere
32800eae5eaSJonas Devlieghere if (arg->getOption().matches(OPT_one_line_on_crash)) {
329cef2af0fSJonas Devlieghere m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash,
33000eae5eaSJonas Devlieghere false, error);
33100eae5eaSJonas Devlieghere if (error.Fail())
33200eae5eaSJonas Devlieghere return error;
33300eae5eaSJonas Devlieghere }
33400eae5eaSJonas Devlieghere
33500eae5eaSJonas Devlieghere if (arg->getOption().matches(OPT_source)) {
336cef2af0fSJonas Devlieghere m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile,
337cef2af0fSJonas Devlieghere true, error);
33800eae5eaSJonas Devlieghere if (error.Fail())
33900eae5eaSJonas Devlieghere return error;
34000eae5eaSJonas Devlieghere }
34100eae5eaSJonas Devlieghere
34200eae5eaSJonas Devlieghere if (arg->getOption().matches(OPT_source_before_file)) {
343cef2af0fSJonas Devlieghere m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile,
344cef2af0fSJonas Devlieghere true, error);
34500eae5eaSJonas Devlieghere if (error.Fail())
34600eae5eaSJonas Devlieghere return error;
34700eae5eaSJonas Devlieghere }
34800eae5eaSJonas Devlieghere
34900eae5eaSJonas Devlieghere if (arg->getOption().matches(OPT_one_line)) {
350cef2af0fSJonas Devlieghere m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile,
351cef2af0fSJonas Devlieghere false, error);
35200eae5eaSJonas Devlieghere if (error.Fail())
35300eae5eaSJonas Devlieghere return error;
35400eae5eaSJonas Devlieghere }
35500eae5eaSJonas Devlieghere
35600eae5eaSJonas Devlieghere if (arg->getOption().matches(OPT_one_line_before_file)) {
357cef2af0fSJonas Devlieghere m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile,
35800eae5eaSJonas Devlieghere false, error);
35900eae5eaSJonas Devlieghere if (error.Fail())
36000eae5eaSJonas Devlieghere return error;
36100eae5eaSJonas Devlieghere }
36200eae5eaSJonas Devlieghere }
36300eae5eaSJonas Devlieghere
36400eae5eaSJonas Devlieghere if (m_option_data.m_process_name.empty() &&
36500eae5eaSJonas Devlieghere m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) {
36600eae5eaSJonas Devlieghere
36782093e8fSJonas Devlieghere for (auto *arg : args.filtered(OPT_INPUT))
36800eae5eaSJonas Devlieghere m_option_data.m_args.push_back(arg->getAsString((args)));
36900eae5eaSJonas Devlieghere
37000eae5eaSJonas Devlieghere // Any argument following -- is an argument for the inferior.
37100eae5eaSJonas Devlieghere if (auto *arg = args.getLastArgNoClaim(OPT_REM)) {
37200eae5eaSJonas Devlieghere for (auto value : arg->getValues())
373e6366a85SJonas Devlieghere m_option_data.m_args.emplace_back(value);
37400eae5eaSJonas Devlieghere }
375e6366a85SJonas Devlieghere } else if (args.getLastArgNoClaim() != nullptr) {
376b02baf0aSJonas Devlieghere WithColor::warning() << "program arguments are ignored when attaching.\n";
37700eae5eaSJonas Devlieghere }
37800eae5eaSJonas Devlieghere
37900eae5eaSJonas Devlieghere if (m_option_data.m_print_version) {
380e6366a85SJonas Devlieghere llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n';
381429222c1SDeepak Panickal exiting = true;
38200eae5eaSJonas Devlieghere return error;
38300eae5eaSJonas Devlieghere }
38400eae5eaSJonas Devlieghere
38500eae5eaSJonas Devlieghere if (m_option_data.m_print_python_path) {
386e2231ac7SJim Ingham SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath();
387b9c1b51eSKate Stone if (python_file_spec.IsValid()) {
388e2231ac7SJim Ingham char python_path[PATH_MAX];
389e2231ac7SJim Ingham size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX);
390b9c1b51eSKate Stone if (num_chars < PATH_MAX) {
391b02baf0aSJonas Devlieghere llvm::outs() << python_path << '\n';
392b9c1b51eSKate Stone } else
393b02baf0aSJonas Devlieghere llvm::outs() << "<PATH TOO LONG>\n";
394b9c1b51eSKate Stone } else
395b02baf0aSJonas Devlieghere llvm::outs() << "<COULD NOT FIND PATH>\n";
396429222c1SDeepak Panickal exiting = true;
39700eae5eaSJonas Devlieghere return error;
398e64f0dc7SJim Ingham }
39930fdc8d8SChris Lattner
400bbef51ebSLawrence D'Anna if (m_option_data.m_print_script_interpreter_info) {
401bbef51ebSLawrence D'Anna SBStructuredData info =
402bbef51ebSLawrence D'Anna m_debugger.GetScriptInterpreterInfo(m_debugger.GetScriptLanguage());
403bbef51ebSLawrence D'Anna if (!info) {
404bbef51ebSLawrence D'Anna error.SetErrorString("no script interpreter.");
405bbef51ebSLawrence D'Anna } else {
406bbef51ebSLawrence D'Anna SBStream stream;
407bbef51ebSLawrence D'Anna error = info.GetAsJSON(stream);
408bbef51ebSLawrence D'Anna if (error.Success()) {
409bbef51ebSLawrence D'Anna llvm::outs() << stream.GetData() << '\n';
410bbef51ebSLawrence D'Anna }
411bbef51ebSLawrence D'Anna }
412bbef51ebSLawrence D'Anna exiting = true;
413bbef51ebSLawrence D'Anna return error;
414bbef51ebSLawrence D'Anna }
415bbef51ebSLawrence D'Anna
4166611103cSGreg Clayton return error;
41730fdc8d8SChris Lattner }
41830fdc8d8SChris Lattner
EscapeString(std::string arg)419b9c1b51eSKate Stone std::string EscapeString(std::string arg) {
420aa1ae6f6SPavel Labath std::string::size_type pos = 0;
421b9c1b51eSKate Stone while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) {
422aa1ae6f6SPavel Labath arg.insert(pos, 1, '\\');
423aa1ae6f6SPavel Labath pos += 2;
424aa1ae6f6SPavel Labath }
425aa1ae6f6SPavel Labath return '"' + arg + '"';
426aa1ae6f6SPavel Labath }
427aa1ae6f6SPavel Labath
MainLoop()428c094d23fSRaphael Isemann int Driver::MainLoop() {
429b9c1b51eSKate Stone if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) {
430f571b890SGreg Clayton g_old_stdin_termios_is_valid = true;
43130fdc8d8SChris Lattner atexit(reset_stdin_termios);
432f571b890SGreg Clayton }
43330fdc8d8SChris Lattner
434f6034c4fSAdrian McCarthy #ifndef _MSC_VER
435f6034c4fSAdrian McCarthy // Disabling stdin buffering with MSVC's 2015 CRT exposes a bug in fgets
436f6034c4fSAdrian McCarthy // which causes it to miss newlines depending on whether there have been an
437f6034c4fSAdrian McCarthy // odd or even number of characters. Bug has been reported to MS via Connect.
438e6366a85SJonas Devlieghere ::setbuf(stdin, nullptr);
439f6034c4fSAdrian McCarthy #endif
440e6366a85SJonas Devlieghere ::setbuf(stdout, nullptr);
44130fdc8d8SChris Lattner
4426611103cSGreg Clayton m_debugger.SetErrorFileHandle(stderr, false);
4436611103cSGreg Clayton m_debugger.SetOutputFileHandle(stdout, false);
444de3d12f9SJonas Devlieghere // Don't take ownership of STDIN yet...
445de3d12f9SJonas Devlieghere m_debugger.SetInputFileHandle(stdin, false);
44630fdc8d8SChris Lattner
447e40e4218SJim Ingham m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
448e40e4218SJim Ingham
44930fdc8d8SChris Lattner struct winsize window_size;
450e6366a85SJonas Devlieghere if ((isatty(STDIN_FILENO) != 0) &&
451b9c1b51eSKate Stone ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) {
4523df9a8dfSCaroline Tice if (window_size.ws_col > 0)
453a7015092SGreg Clayton m_debugger.SetTerminalWidth(window_size.ws_col);
454f7c0fd8dSGreg Clayton }
45530fdc8d8SChris Lattner
45644d93782SGreg Clayton SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
45730fdc8d8SChris Lattner
4586c99a346SPavel Labath // Process lldbinit files before handling any options from the command line.
45930fdc8d8SChris Lattner SBCommandReturnObject result;
4606c99a346SPavel Labath sb_interpreter.SourceInitFileInGlobalDirectory(result);
4616c99a346SPavel Labath if (m_option_data.m_debug_mode) {
4626c99a346SPavel Labath result.PutError(m_debugger.GetErrorFile());
4636c99a346SPavel Labath result.PutOutput(m_debugger.GetOutputFile());
4646c99a346SPavel Labath }
4656c99a346SPavel Labath
466868b45b5SMed Ismail Bennani sb_interpreter.SourceInitFileInHomeDirectory(result, m_option_data.m_repl);
467de3d12f9SJonas Devlieghere if (m_option_data.m_debug_mode) {
4689eb13719SLawrence D'Anna result.PutError(m_debugger.GetErrorFile());
4699eb13719SLawrence D'Anna result.PutOutput(m_debugger.GetOutputFile());
47030fdc8d8SChris Lattner }
47130fdc8d8SChris Lattner
4722edcad7bSJonas Devlieghere // Source the local .lldbinit file if it exists and we're allowed to source.
4732edcad7bSJonas Devlieghere // Here we want to always print the return object because it contains the
4742edcad7bSJonas Devlieghere // warning and instructions to load local lldbinit files.
4752edcad7bSJonas Devlieghere sb_interpreter.SourceInitFileInCurrentWorkingDirectory(result);
4769eb13719SLawrence D'Anna result.PutError(m_debugger.GetErrorFile());
4779eb13719SLawrence D'Anna result.PutOutput(m_debugger.GetOutputFile());
4782edcad7bSJonas Devlieghere
479c094d23fSRaphael Isemann // We allow the user to specify an exit code when calling quit which we will
480c094d23fSRaphael Isemann // return when exiting.
481c094d23fSRaphael Isemann m_debugger.GetCommandInterpreter().AllowExitCodeOnQuit(true);
482c094d23fSRaphael Isemann
48330fdc8d8SChris Lattner // Now we handle options we got from the command line
484f8314536SEd Maste SBStream commands_stream;
48506357c93SGreg Clayton
486b9c1b51eSKate Stone // First source in the commands specified to be run before the file arguments
487b9c1b51eSKate Stone // are processed.
4884add3b13SJim Ingham WriteCommandsForSourcing(eCommandPlacementBeforeFile, commands_stream);
48930fdc8d8SChris Lattner
490040f94ccSAdrian Prantl // If we're not in --repl mode, add the commands to process the file
491040f94ccSAdrian Prantl // arguments, and the commands specified to run afterwards.
492040f94ccSAdrian Prantl if (!m_option_data.m_repl) {
4938d846daaSGreg Clayton const size_t num_args = m_option_data.m_args.size();
494b9c1b51eSKate Stone if (num_args > 0) {
4955b1fe95dSJim Ingham char arch_name[64];
496de3d12f9SJonas Devlieghere if (lldb::SBDebugger::GetDefaultArchitecture(arch_name,
497de3d12f9SJonas Devlieghere sizeof(arch_name)))
498b9c1b51eSKate Stone commands_stream.Printf("target create --arch=%s %s", arch_name,
499b9c1b51eSKate Stone EscapeString(m_option_data.m_args[0]).c_str());
5005b1fe95dSJim Ingham else
501b9c1b51eSKate Stone commands_stream.Printf("target create %s",
502b9c1b51eSKate Stone EscapeString(m_option_data.m_args[0]).c_str());
5035b1fe95dSJim Ingham
504b9c1b51eSKate Stone if (!m_option_data.m_core_file.empty()) {
505b9c1b51eSKate Stone commands_stream.Printf(" --core %s",
506b9c1b51eSKate Stone EscapeString(m_option_data.m_core_file).c_str());
50706357c93SGreg Clayton }
50806357c93SGreg Clayton commands_stream.Printf("\n");
5098d846daaSGreg Clayton
510b9c1b51eSKate Stone if (num_args > 1) {
51106357c93SGreg Clayton commands_stream.Printf("settings set -- target.run-args ");
5128d846daaSGreg Clayton for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
513b9c1b51eSKate Stone commands_stream.Printf(
514b9c1b51eSKate Stone " %s", EscapeString(m_option_data.m_args[arg_idx]).c_str());
51506357c93SGreg Clayton commands_stream.Printf("\n");
5168d846daaSGreg Clayton }
517b9c1b51eSKate Stone } else if (!m_option_data.m_core_file.empty()) {
518b9c1b51eSKate Stone commands_stream.Printf("target create --core %s\n",
519b9c1b51eSKate Stone EscapeString(m_option_data.m_core_file).c_str());
520b9c1b51eSKate Stone } else if (!m_option_data.m_process_name.empty()) {
521de3d12f9SJonas Devlieghere commands_stream.Printf(
522de3d12f9SJonas Devlieghere "process attach --name %s",
523b9c1b51eSKate Stone EscapeString(m_option_data.m_process_name).c_str());
52406357c93SGreg Clayton
52506357c93SGreg Clayton if (m_option_data.m_wait_for)
52606357c93SGreg Clayton commands_stream.Printf(" --waitfor");
52706357c93SGreg Clayton
52806357c93SGreg Clayton commands_stream.Printf("\n");
52906357c93SGreg Clayton
530b9c1b51eSKate Stone } else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid) {
531b9c1b51eSKate Stone commands_stream.Printf("process attach --pid %" PRIu64 "\n",
532b9c1b51eSKate Stone m_option_data.m_process_pid);
5339c0b64c9SGreg Clayton }
53430fdc8d8SChris Lattner
5354add3b13SJim Ingham WriteCommandsForSourcing(eCommandPlacementAfterFile, commands_stream);
536040f94ccSAdrian Prantl } else if (!m_option_data.m_after_file_commands.empty()) {
537040f94ccSAdrian Prantl // We're in repl mode and after-file-load commands were specified.
538040f94ccSAdrian Prantl WithColor::warning() << "commands specified to run after file load (via -o "
539040f94ccSAdrian Prantl "or -s) are ignored in REPL mode.\n";
540040f94ccSAdrian Prantl }
54144d93782SGreg Clayton
542de3d12f9SJonas Devlieghere if (m_option_data.m_debug_mode) {
5439eb13719SLawrence D'Anna result.PutError(m_debugger.GetErrorFile());
5449eb13719SLawrence D'Anna result.PutOutput(m_debugger.GetOutputFile());
54530fdc8d8SChris Lattner }
54630fdc8d8SChris Lattner
547de3d12f9SJonas Devlieghere const bool handle_events = true;
548de3d12f9SJonas Devlieghere const bool spawn_thread = false;
54906357c93SGreg Clayton
550b9c1b51eSKate Stone // Check if we have any data in the commands stream, and if so, save it to a
551b9c1b51eSKate Stone // temp file
55206357c93SGreg Clayton // so we can then run the command interpreter using the file contents.
5534c67b119SJonas Devlieghere bool go_interactive = true;
554f23b829aSLevon Ter-Grigoryan if ((commands_stream.GetData() != nullptr) &&
555f23b829aSLevon Ter-Grigoryan (commands_stream.GetSize() != 0u)) {
556f23b829aSLevon Ter-Grigoryan SBError error = m_debugger.SetInputString(commands_stream.GetData());
557f23b829aSLevon Ter-Grigoryan if (error.Fail()) {
558f23b829aSLevon Ter-Grigoryan WithColor::error() << error.GetCString() << '\n';
5590ca90eb3SJonas Devlieghere return 1;
5600d671dbcSJonas Devlieghere }
5610d671dbcSJonas Devlieghere
5624c67b119SJonas Devlieghere // Set the debugger into Sync mode when running the command file. Otherwise
5634c67b119SJonas Devlieghere // command files that run the target won't run in a sensible way.
56426c7bf93SJim Ingham bool old_async = m_debugger.GetAsync();
56526c7bf93SJim Ingham m_debugger.SetAsync(false);
56626c7bf93SJim Ingham
56726c7bf93SJim Ingham SBCommandInterpreterRunOptions options;
5684c67b119SJonas Devlieghere options.SetAutoHandleEvents(true);
5694c67b119SJonas Devlieghere options.SetSpawnThread(false);
57026c7bf93SJim Ingham options.SetStopOnError(true);
5714c67b119SJonas Devlieghere options.SetStopOnCrash(m_option_data.m_batch);
572e2a6c08bSLawrence D'Anna options.SetEchoCommands(!m_option_data.m_source_quietly);
57326c7bf93SJim Ingham
5744c67b119SJonas Devlieghere SBCommandInterpreterRunResult results =
5754c67b119SJonas Devlieghere m_debugger.RunCommandInterpreter(options);
5764c67b119SJonas Devlieghere if (results.GetResult() == lldb::eCommandInterpreterResultQuitRequested)
5774c67b119SJonas Devlieghere go_interactive = false;
5784c67b119SJonas Devlieghere if (m_option_data.m_batch &&
5794c67b119SJonas Devlieghere results.GetResult() != lldb::eCommandInterpreterResultInferiorCrash)
5804c67b119SJonas Devlieghere go_interactive = false;
5814add3b13SJim Ingham
58261d5b0e6SJonas Devlieghere // When running in batch mode and stopped because of an error, exit with a
58361d5b0e6SJonas Devlieghere // non-zero exit status.
58461d5b0e6SJonas Devlieghere if (m_option_data.m_batch &&
58561d5b0e6SJonas Devlieghere results.GetResult() == lldb::eCommandInterpreterResultCommandError)
5860ca90eb3SJonas Devlieghere return 1;
58761d5b0e6SJonas Devlieghere
5884c67b119SJonas Devlieghere if (m_option_data.m_batch &&
5894c67b119SJonas Devlieghere results.GetResult() == lldb::eCommandInterpreterResultInferiorCrash &&
590b9c1b51eSKate Stone !m_option_data.m_after_crash_commands.empty()) {
5914add3b13SJim Ingham SBStream crash_commands_stream;
592b9c1b51eSKate Stone WriteCommandsForSourcing(eCommandPlacementAfterCrash,
593b9c1b51eSKate Stone crash_commands_stream);
594f23b829aSLevon Ter-Grigoryan SBError error =
595f23b829aSLevon Ter-Grigoryan m_debugger.SetInputString(crash_commands_stream.GetData());
596f23b829aSLevon Ter-Grigoryan if (error.Success()) {
5974c67b119SJonas Devlieghere SBCommandInterpreterRunResult local_results =
5984c67b119SJonas Devlieghere m_debugger.RunCommandInterpreter(options);
5994c67b119SJonas Devlieghere if (local_results.GetResult() ==
6004c67b119SJonas Devlieghere lldb::eCommandInterpreterResultQuitRequested)
6014c67b119SJonas Devlieghere go_interactive = false;
60261d5b0e6SJonas Devlieghere
60361d5b0e6SJonas Devlieghere // When running in batch mode and an error occurred while sourcing
60461d5b0e6SJonas Devlieghere // the crash commands, exit with a non-zero exit status.
60561d5b0e6SJonas Devlieghere if (m_option_data.m_batch &&
60661d5b0e6SJonas Devlieghere local_results.GetResult() ==
60761d5b0e6SJonas Devlieghere lldb::eCommandInterpreterResultCommandError)
6080ca90eb3SJonas Devlieghere return 1;
6094add3b13SJim Ingham }
6104add3b13SJim Ingham }
61126c7bf93SJim Ingham m_debugger.SetAsync(old_async);
61249668765SGreg Clayton }
61306357c93SGreg Clayton
6144c67b119SJonas Devlieghere // Now set the input file handle to STDIN and run the command interpreter
6154c67b119SJonas Devlieghere // again in interactive mode or repl mode and let the debugger take ownership
6164c67b119SJonas Devlieghere // of stdin.
617b9c1b51eSKate Stone if (go_interactive) {
61806357c93SGreg Clayton m_debugger.SetInputFileHandle(stdin, true);
619040f94ccSAdrian Prantl
620040f94ccSAdrian Prantl if (m_option_data.m_repl) {
621040f94ccSAdrian Prantl const char *repl_options = nullptr;
622040f94ccSAdrian Prantl if (!m_option_data.m_repl_options.empty())
623040f94ccSAdrian Prantl repl_options = m_option_data.m_repl_options.c_str();
624de3d12f9SJonas Devlieghere SBError error(
625de3d12f9SJonas Devlieghere m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options));
626040f94ccSAdrian Prantl if (error.Fail()) {
627040f94ccSAdrian Prantl const char *error_cstr = error.GetCString();
628040f94ccSAdrian Prantl if ((error_cstr != nullptr) && (error_cstr[0] != 0))
629040f94ccSAdrian Prantl WithColor::error() << error_cstr << '\n';
630040f94ccSAdrian Prantl else
631040f94ccSAdrian Prantl WithColor::error() << error.GetError() << '\n';
632040f94ccSAdrian Prantl }
633040f94ccSAdrian Prantl } else {
63444d93782SGreg Clayton m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
63526c7bf93SJim Ingham }
6363e7e915dSSean Callanan }
637ed3252fbSJim Ingham
63830fdc8d8SChris Lattner reset_stdin_termios();
639f571b890SGreg Clayton fclose(stdin);
64030fdc8d8SChris Lattner
6416ac12b5bSJonas Devlieghere return sb_interpreter.GetQuitStatus();
64230fdc8d8SChris Lattner }
64330fdc8d8SChris Lattner
ResizeWindow(unsigned short col)644b9c1b51eSKate Stone void Driver::ResizeWindow(unsigned short col) {
645c46fe7c0SJim Ingham GetDebugger().SetTerminalWidth(col);
646c46fe7c0SJim Ingham }
64730fdc8d8SChris Lattner
sigwinch_handler(int signo)648b9c1b51eSKate Stone void sigwinch_handler(int signo) {
649dd759857SCaroline Tice struct winsize window_size;
650e6366a85SJonas Devlieghere if ((isatty(STDIN_FILENO) != 0) &&
651b9c1b51eSKate Stone ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) {
652e6366a85SJonas Devlieghere if ((window_size.ws_col > 0) && g_driver != nullptr) {
653c46fe7c0SJim Ingham g_driver->ResizeWindow(window_size.ws_col);
654dd759857SCaroline Tice }
655dd759857SCaroline Tice }
656dd759857SCaroline Tice }
657dd759857SCaroline Tice
sigint_handler(int signo)658b9c1b51eSKate Stone void sigint_handler(int signo) {
659320d6795SNathan Lanza #ifdef _WIN32 // Restore handler as it is not persistent on Windows
660320d6795SNathan Lanza signal(SIGINT, sigint_handler);
661320d6795SNathan Lanza #endif
6626c84ffbfSAdrian McCarthy static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT;
663e6366a85SJonas Devlieghere if (g_driver != nullptr) {
6646c84ffbfSAdrian McCarthy if (!g_interrupt_sent.test_and_set()) {
665efed6131SCaroline Tice g_driver->GetDebugger().DispatchInputInterrupt();
6666c84ffbfSAdrian McCarthy g_interrupt_sent.clear();
667efed6131SCaroline Tice return;
668efed6131SCaroline Tice }
669efed6131SCaroline Tice }
670efed6131SCaroline Tice
6716c84ffbfSAdrian McCarthy _exit(signo);
672efed6131SCaroline Tice }
673efed6131SCaroline Tice
6744bcadd66SPavel Labath #ifndef _WIN32
sigtstp_handler(int signo)6754bcadd66SPavel Labath static void sigtstp_handler(int signo) {
676e6366a85SJonas Devlieghere if (g_driver != nullptr)
677c5917d9aSJim Ingham g_driver->GetDebugger().SaveInputTerminalState();
678bb5c39d7SPavel Labath
6794bcadd66SPavel Labath // Unblock the signal and remove our handler.
6804bcadd66SPavel Labath sigset_t set;
6814bcadd66SPavel Labath sigemptyset(&set);
6824bcadd66SPavel Labath sigaddset(&set, signo);
6834bcadd66SPavel Labath pthread_sigmask(SIG_UNBLOCK, &set, nullptr);
684c5917d9aSJim Ingham signal(signo, SIG_DFL);
685c5917d9aSJim Ingham
6864bcadd66SPavel Labath // Now re-raise the signal. We will immediately suspend...
6874bcadd66SPavel Labath raise(signo);
6884bcadd66SPavel Labath // ... and resume after a SIGCONT.
6894bcadd66SPavel Labath
6904bcadd66SPavel Labath // Now undo the modifications.
6914bcadd66SPavel Labath pthread_sigmask(SIG_BLOCK, &set, nullptr);
6924bcadd66SPavel Labath signal(signo, sigtstp_handler);
6934bcadd66SPavel Labath
694e6366a85SJonas Devlieghere if (g_driver != nullptr)
695c5917d9aSJim Ingham g_driver->GetDebugger().RestoreInputTerminalState();
696c5917d9aSJim Ingham }
6974bcadd66SPavel Labath #endif
698c5917d9aSJim Ingham
printHelp(LLDBOptTable & table,llvm::StringRef tool_name)69900eae5eaSJonas Devlieghere static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) {
700b0337458SJonas Devlieghere std::string usage_str = tool_name.str() + " [options]";
701f1e2d585SFangrui Song table.printHelp(llvm::outs(), usage_str.c_str(), "LLDB", false);
70200eae5eaSJonas Devlieghere
70300eae5eaSJonas Devlieghere std::string examples = R"___(
70400eae5eaSJonas Devlieghere EXAMPLES:
70500eae5eaSJonas Devlieghere The debugger can be started in several modes.
70600eae5eaSJonas Devlieghere
70700eae5eaSJonas Devlieghere Passing an executable as a positional argument prepares lldb to debug the
70882093e8fSJonas Devlieghere given executable. To disambiguate between arguments passed to lldb and
70982093e8fSJonas Devlieghere arguments passed to the debugged executable, arguments starting with a - must
71082093e8fSJonas Devlieghere be passed after --.
71100eae5eaSJonas Devlieghere
7123a62d4fdSBrad Smith lldb --arch x86_64 /path/to/program program argument -- --arch armv7
71382093e8fSJonas Devlieghere
71482093e8fSJonas Devlieghere For convenience, passing the executable after -- is also supported.
71582093e8fSJonas Devlieghere
7163a62d4fdSBrad Smith lldb --arch x86_64 -- /path/to/program program argument --arch armv7
71700eae5eaSJonas Devlieghere
71800eae5eaSJonas Devlieghere Passing one of the attach options causes lldb to immediately attach to the
71900eae5eaSJonas Devlieghere given process.
72000eae5eaSJonas Devlieghere
72100eae5eaSJonas Devlieghere lldb -p <pid>
72200eae5eaSJonas Devlieghere lldb -n <process-name>
72300eae5eaSJonas Devlieghere
72400eae5eaSJonas Devlieghere Passing --repl starts lldb in REPL mode.
72500eae5eaSJonas Devlieghere
72600eae5eaSJonas Devlieghere lldb -r
72700eae5eaSJonas Devlieghere
72800eae5eaSJonas Devlieghere Passing --core causes lldb to debug the core file.
72900eae5eaSJonas Devlieghere
73000eae5eaSJonas Devlieghere lldb -c /path/to/core
73100eae5eaSJonas Devlieghere
732040f94ccSAdrian Prantl Command options can be combined with these modes and cause lldb to run the
73300eae5eaSJonas Devlieghere specified commands before or after events, like loading the file or crashing,
73400eae5eaSJonas Devlieghere in the order provided on the command line.
73500eae5eaSJonas Devlieghere
73600eae5eaSJonas Devlieghere lldb -O 'settings set stop-disassembly-count 20' -o 'run' -o 'bt'
73700eae5eaSJonas Devlieghere lldb -S /source/before/file -s /source/after/file
73800eae5eaSJonas Devlieghere lldb -K /source/before/crash -k /source/after/crash
739040f94ccSAdrian Prantl
740040f94ccSAdrian Prantl Note: In REPL mode no file is loaded, so commands specified to run after
7416c2e4e88SJonas Devlieghere loading the file (via -o or -s) will be ignored.)___";
7426c2e4e88SJonas Devlieghere llvm::outs() << examples << '\n';
74300eae5eaSJonas Devlieghere }
74400eae5eaSJonas Devlieghere
InitializeReproducer(llvm::StringRef argv0,opt::InputArgList & input_args)745cdae6d77SFangrui Song static llvm::Optional<int> InitializeReproducer(llvm::StringRef argv0,
74610aa9e19SJonas Devlieghere opt::InputArgList &input_args) {
74713ecae2fSJonas Devlieghere bool capture = input_args.hasArg(OPT_capture);
74884557c18SJonas Devlieghere bool generate_on_exit = input_args.hasArg(OPT_generate_on_exit);
74913ecae2fSJonas Devlieghere auto *capture_path = input_args.getLastArg(OPT_capture_path);
75013ecae2fSJonas Devlieghere
75184557c18SJonas Devlieghere if (generate_on_exit && !capture) {
752066e817bSJonas Devlieghere WithColor::warning()
75384557c18SJonas Devlieghere << "-reproducer-generate-on-exit specified without -capture\n";
754066e817bSJonas Devlieghere }
755066e817bSJonas Devlieghere
75613ecae2fSJonas Devlieghere if (capture || capture_path) {
75713ecae2fSJonas Devlieghere if (capture_path) {
75813ecae2fSJonas Devlieghere if (!capture)
75913ecae2fSJonas Devlieghere WithColor::warning() << "-capture-path specified without -capture\n";
76013ecae2fSJonas Devlieghere if (const char *error = SBReproducer::Capture(capture_path->getValue())) {
76113ecae2fSJonas Devlieghere WithColor::error() << "reproducer capture failed: " << error << '\n';
76213ecae2fSJonas Devlieghere return 1;
76313ecae2fSJonas Devlieghere }
76413ecae2fSJonas Devlieghere } else {
76513ecae2fSJonas Devlieghere const char *error = SBReproducer::Capture();
76613ecae2fSJonas Devlieghere if (error) {
76713ecae2fSJonas Devlieghere WithColor::error() << "reproducer capture failed: " << error << '\n';
76813ecae2fSJonas Devlieghere return 1;
76913ecae2fSJonas Devlieghere }
77013ecae2fSJonas Devlieghere }
77184557c18SJonas Devlieghere if (generate_on_exit)
772066e817bSJonas Devlieghere SBReproducer::SetAutoGenerate(true);
77313ecae2fSJonas Devlieghere }
77413ecae2fSJonas Devlieghere
77513ecae2fSJonas Devlieghere return llvm::None;
77613ecae2fSJonas Devlieghere }
77713ecae2fSJonas Devlieghere
main(int argc,char const * argv[])778b117ec8bSJonas Devlieghere int main(int argc, char const *argv[]) {
77972748488SJan Kratochvil // Editline uses for example iswprint which is dependent on LC_CTYPE.
78072748488SJan Kratochvil std::setlocale(LC_ALL, "");
78172748488SJan Kratochvil std::setlocale(LC_CTYPE, "");
78272748488SJan Kratochvil
783fa6984a3SJonas Devlieghere // Setup LLVM signal handlers and make sure we call llvm_shutdown() on
784fa6984a3SJonas Devlieghere // destruction.
7854624e83cSVedant Kumar llvm::InitLLVM IL(argc, argv, /*InstallPipeSignalExitHandler=*/false);
786190fadcdSZachary Turner
78700eae5eaSJonas Devlieghere // Parse arguments.
78800eae5eaSJonas Devlieghere LLDBOptTable T;
78977d5a63cSLuboš Luňák unsigned MissingArgIndex;
79077d5a63cSLuboš Luňák unsigned MissingArgCount;
79100eae5eaSJonas Devlieghere ArrayRef<const char *> arg_arr = makeArrayRef(argv + 1, argc - 1);
79277d5a63cSLuboš Luňák opt::InputArgList input_args =
79377d5a63cSLuboš Luňák T.ParseArgs(arg_arr, MissingArgIndex, MissingArgCount);
794ce19664dSJonas Devlieghere llvm::StringRef argv0 = llvm::sys::path::filename(argv[0]);
79530fdc8d8SChris Lattner
79600eae5eaSJonas Devlieghere if (input_args.hasArg(OPT_help)) {
797ce19664dSJonas Devlieghere printHelp(T, argv0);
79800eae5eaSJonas Devlieghere return 0;
79900eae5eaSJonas Devlieghere }
80000eae5eaSJonas Devlieghere
80177d5a63cSLuboš Luňák // Check for missing argument error.
80277d5a63cSLuboš Luňák if (MissingArgCount) {
80377d5a63cSLuboš Luňák WithColor::error() << "argument to '"
80477d5a63cSLuboš Luňák << input_args.getArgString(MissingArgIndex)
80577d5a63cSLuboš Luňák << "' is missing\n";
80677d5a63cSLuboš Luňák }
8075b5b81bcSJonas Devlieghere // Error out on unknown options.
8085b5b81bcSJonas Devlieghere if (input_args.hasArg(OPT_UNKNOWN)) {
809b02baf0aSJonas Devlieghere for (auto *arg : input_args.filtered(OPT_UNKNOWN)) {
8105b5b81bcSJonas Devlieghere WithColor::error() << "unknown option: " << arg->getSpelling() << '\n';
8115b5b81bcSJonas Devlieghere }
81277d5a63cSLuboš Luňák }
81377d5a63cSLuboš Luňák if (MissingArgCount || input_args.hasArg(OPT_UNKNOWN)) {
814ce19664dSJonas Devlieghere llvm::errs() << "Use '" << argv0
815ce19664dSJonas Devlieghere << " --help' for a complete list of options.\n";
8165b5b81bcSJonas Devlieghere return 1;
817b02baf0aSJonas Devlieghere }
818b02baf0aSJonas Devlieghere
81910aa9e19SJonas Devlieghere if (auto exit_code = InitializeReproducer(argv[0], input_args)) {
82013ecae2fSJonas Devlieghere return *exit_code;
82115eacd74SJonas Devlieghere }
82215eacd74SJonas Devlieghere
823936c6242SJonas Devlieghere SBError error = SBDebugger::InitializeWithErrorHandling();
82415eacd74SJonas Devlieghere if (error.Fail()) {
82515eacd74SJonas Devlieghere WithColor::error() << "initialization failed: " << error.GetCString()
82615eacd74SJonas Devlieghere << '\n';
82715eacd74SJonas Devlieghere return 1;
82815eacd74SJonas Devlieghere }
8292ccf8cfcSGreg Clayton SBHostOS::ThreadCreated("<lldb.driver.main-thread>");
83030fdc8d8SChris Lattner
83129365da0SZachary Turner signal(SIGINT, sigint_handler);
832*bc13101cSMartin Storsjö #if !defined(_WIN32)
8333fcbed6bSGreg Clayton signal(SIGPIPE, SIG_IGN);
834dd759857SCaroline Tice signal(SIGWINCH, sigwinch_handler);
835c5917d9aSJim Ingham signal(SIGTSTP, sigtstp_handler);
83629365da0SZachary Turner #endif
837dd759857SCaroline Tice
838c094d23fSRaphael Isemann int exit_code = 0;
8396611103cSGreg Clayton // Create a scope for driver so that the driver object will destroy itself
8406611103cSGreg Clayton // before SBDebugger::Terminate() is called.
8416611103cSGreg Clayton {
84230fdc8d8SChris Lattner Driver driver;
84330fdc8d8SChris Lattner
844429222c1SDeepak Panickal bool exiting = false;
845b02baf0aSJonas Devlieghere SBError error(driver.ProcessArgs(input_args, exiting));
846b9c1b51eSKate Stone if (error.Fail()) {
847c094d23fSRaphael Isemann exit_code = 1;
848b02baf0aSJonas Devlieghere if (const char *error_cstr = error.GetCString())
849b02baf0aSJonas Devlieghere WithColor::error() << error_cstr << '\n';
850b9c1b51eSKate Stone } else if (!exiting) {
851c094d23fSRaphael Isemann exit_code = driver.MainLoop();
85230fdc8d8SChris Lattner }
8536611103cSGreg Clayton }
85430fdc8d8SChris Lattner
85530fdc8d8SChris Lattner SBDebugger::Terminate();
856c094d23fSRaphael Isemann return exit_code;
85730fdc8d8SChris Lattner }
858