Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1490,12 +1490,17 @@ def __init__(
init_commands: list[str] = [],
log_file: Optional[TextIO] = None,
env: Optional[dict[str, str]] = None,
additional_args: list[str] = [],
):
self.process = None
self.connection = None
if executable is not None:
process, connection = DebugAdapterServer.launch(
executable=executable, connection=connection, env=env, log_file=log_file
executable=executable,
connection=connection,
env=env,
log_file=log_file,
additional_args=additional_args,
)
self.process = process
self.connection = connection
Expand Down Expand Up @@ -1528,6 +1533,7 @@ def launch(
env: Optional[dict[str, str]] = None,
log_file: Optional[TextIO] = None,
connection: Optional[str] = None,
additional_args: list[str] = [],
) -> tuple[subprocess.Popen, Optional[str]]:
adapter_env = os.environ.copy()
if env is not None:
Expand All @@ -1537,6 +1543,9 @@ def launch(
adapter_env["LLDBDAP_LOG"] = log_file
args = [executable]

# Add additional arguments first (like --no-lldbinit)
args.extend(additional_args)

if connection is not None:
args.append("--connection")
args.append(connection)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def create_debug_adapter(
self,
lldbDAPEnv: Optional[dict[str, str]] = None,
connection: Optional[str] = None,
additional_args: Optional[list[str]] = None,
):
"""Create the Visual Studio Code debug adapter"""
self.assertTrue(
Expand All @@ -33,15 +34,17 @@ def create_debug_adapter(
init_commands=self.setUpCommands(),
log_file=log_file_path,
env=lldbDAPEnv,
additional_args=additional_args or [],
)

def build_and_create_debug_adapter(
self,
lldbDAPEnv: Optional[dict[str, str]] = None,
dictionary: Optional[dict] = None,
additional_args: Optional[list[str]] = None,
):
self.build(dictionary=dictionary)
self.create_debug_adapter(lldbDAPEnv)
self.create_debug_adapter(lldbDAPEnv, additional_args=additional_args)

def build_and_create_debug_adapter_for_attach(self):
"""Variant of build_and_create_debug_adapter that builds a uniquely
Expand Down
40 changes: 40 additions & 0 deletions lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import lldbdap_testcase
import os
import re
import tempfile

# Many tests are skipped on Windows because get_stdout() returns None there.
# Despite the test program printing correctly. See
Expand Down Expand Up @@ -582,3 +583,42 @@ def test_version(self):
version_string.splitlines(),
"version string does not match",
)

def test_no_lldbinit_flag(self):
"""
Test that the --no-lldbinit flag prevents sourcing .lldbinit files.
"""
# Create a temporary .lldbinit file in the home directory
with tempfile.TemporaryDirectory() as temp_home:
lldbinit_path = os.path.join(temp_home, ".lldbinit")

# Write a command to the .lldbinit file that would set a unique setting
with open(lldbinit_path, "w") as f:
f.write("settings set stop-disassembly-display never\n")
f.write("settings set target.x86-disassembly-flavor intel\n")

# Test with --no-lldbinit flag (should NOT source .lldbinit)
self.build_and_create_debug_adapter(
lldbDAPEnv={"HOME": temp_home}, additional_args=["--no-lldbinit"]
)
program = self.getBuildArtifact("a.out")

# Use initCommands to check if .lldbinit was sourced
initCommands = ["settings show stop-disassembly-display"]

# Launch with initCommands to check the setting
self.launch(program, initCommands=initCommands, stopOnEntry=True)

# Get console output to verify the setting was NOT set from .lldbinit
output = self.get_console()
self.assertTrue(output and len(output) > 0, "expect console output")

# Verify the setting has default value, not "never" from .lldbinit
self.assertNotIn(
"never",
output,
"Setting should have default value when --no-lldbinit is used",
)

# Verify the initCommands were executed
self.verify_commands("initCommands", output, initCommands)
5 changes: 3 additions & 2 deletions lldb/tools/lldb-dap/DAP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,13 @@ static std::string capitalize(llvm::StringRef str) {
llvm::StringRef DAP::debug_adapter_path = "";

DAP::DAP(Log *log, const ReplMode default_repl_mode,
std::vector<std::string> pre_init_commands,
std::vector<std::string> pre_init_commands, bool no_lldbinit,
llvm::StringRef client_name, DAPTransport &transport, MainLoop &loop)
: log(log), transport(transport), broadcaster("lldb-dap"),
progress_event_reporter(
[&](const ProgressEvent &event) { SendJSON(event.ToJSON()); }),
repl_mode(default_repl_mode), m_client_name(client_name), m_loop(loop) {
repl_mode(default_repl_mode), no_lldbinit(no_lldbinit),
m_client_name(client_name), m_loop(loop) {
configuration.preInitCommands = std::move(pre_init_commands);
RegisterRequests();
}
Expand Down
10 changes: 8 additions & 2 deletions lldb/tools/lldb-dap/DAP.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ struct DAP final : private DAPTransport::MessageHandler {
/// The set of features supported by the connected client.
llvm::DenseSet<ClientFeature> clientFeatures;

/// Whether to disable sourcing .lldbinit files.
bool no_lldbinit;

/// The initial thread list upon attaching.
std::vector<protocol::Thread> initial_thread_list;

Expand All @@ -178,13 +181,16 @@ struct DAP final : private DAPTransport::MessageHandler {
/// \param[in] pre_init_commands
/// LLDB commands to execute as soon as the debugger instance is
/// allocated.
/// \param[in] no_lldbinit
/// Whether to disable sourcing .lldbinit files.
/// \param[in] transport
/// Transport for this debug session.
/// \param[in] loop
/// Main loop associated with this instance.
DAP(Log *log, const ReplMode default_repl_mode,
std::vector<std::string> pre_init_commands, llvm::StringRef client_name,
DAPTransport &transport, lldb_private::MainLoop &loop);
std::vector<std::string> pre_init_commands, bool no_lldbinit,
llvm::StringRef client_name, DAPTransport &transport,
lldb_private::MainLoop &loop);

~DAP();

Expand Down
7 changes: 5 additions & 2 deletions lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@ llvm::Expected<InitializeResponse> InitializeRequestHandler::Run(

// The sourceInitFile option is not part of the DAP specification. It is an
// extension used by the test suite to prevent sourcing `.lldbinit` and
// changing its behavior.
if (arguments.lldbExtSourceInitFile.value_or(true)) {
// changing its behavior. The CLI flag --no-lldbinit takes precedence over
// the DAP parameter.
bool should_source_init_files =
!dap.no_lldbinit && arguments.lldbExtSourceInitFile.value_or(true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we have this flag now, we could remove our custom $__lldb_sourceInitFile field and just pass this flag instead.

I can also do that in a follow up patch once this is in.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good

if (should_source_init_files) {
dap.debugger.SkipLLDBInitFiles(false);
dap.debugger.SkipAppInitFiles(false);
lldb::SBCommandReturnObject init;
Expand Down
6 changes: 6 additions & 0 deletions lldb/tools/lldb-dap/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,9 @@ def pre_init_command: S<"pre-init-command">,
def: Separate<["-"], "c">,
Alias<pre_init_command>,
HelpText<"Alias for --pre-init-command">;

def no_lldbinit: F<"no-lldbinit">,
HelpText<"Do not automatically parse any '.lldbinit' files.">;
def: Flag<["-"], "x">,
Alias<no_lldbinit>,
HelpText<"Alias for --no-lldbinit">;
15 changes: 9 additions & 6 deletions lldb/tools/lldb-dap/tool/lldb-dap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,8 @@ validateConnection(llvm::StringRef conn) {
static llvm::Error
serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
Log *log, const ReplMode default_repl_mode,
const std::vector<std::string> &pre_init_commands) {
const std::vector<std::string> &pre_init_commands,
bool no_lldbinit) {
Status status;
static std::unique_ptr<Socket> listener = Socket::Create(protocol, status);
if (status.Fail()) {
Expand Down Expand Up @@ -303,8 +304,8 @@ serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
llvm::set_thread_name(client_name + ".runloop");
MainLoop loop;
Transport transport(client_name, log, io, io);
DAP dap(log, default_repl_mode, pre_init_commands, client_name, transport,
loop);
DAP dap(log, default_repl_mode, pre_init_commands, no_lldbinit,
client_name, transport, loop);

if (auto Err = dap.ConfigureIO()) {
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
Expand Down Expand Up @@ -508,6 +509,8 @@ int main(int argc, char *argv[]) {
pre_init_commands.push_back(arg);
}

bool no_lldbinit = input_args.hasArg(OPT_no_lldbinit);

if (!connection.empty()) {
auto maybeProtoclAndName = validateConnection(connection);
if (auto Err = maybeProtoclAndName.takeError()) {
Expand All @@ -520,7 +523,7 @@ int main(int argc, char *argv[]) {
std::string name;
std::tie(protocol, name) = *maybeProtoclAndName;
if (auto Err = serveConnection(protocol, name, log.get(), default_repl_mode,
pre_init_commands)) {
pre_init_commands, no_lldbinit)) {
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
"Connection failed: ");
return EXIT_FAILURE;
Expand Down Expand Up @@ -556,8 +559,8 @@ int main(int argc, char *argv[]) {
constexpr llvm::StringLiteral client_name = "stdio";
MainLoop loop;
Transport transport(client_name, log.get(), input, output);
DAP dap(log.get(), default_repl_mode, pre_init_commands, client_name,
transport, loop);
DAP dap(log.get(), default_repl_mode, pre_init_commands, no_lldbinit,
client_name, transport, loop);

// stdout/stderr redirection to the IDE's console
if (auto Err = dap.ConfigureIO(stdout, stderr)) {
Expand Down
1 change: 1 addition & 0 deletions lldb/unittests/DAP/DAPTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ TEST_F(DAPTest, SendProtocolMessages) {
/*log=*/nullptr,
/*default_repl_mode=*/ReplMode::Auto,
/*pre_init_commands=*/{},
/*no_lldbinit=*/false,
/*client_name=*/"test_client",
/*transport=*/*transport,
/*loop=*/loop,
Expand Down
1 change: 1 addition & 0 deletions lldb/unittests/DAP/TestBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ void DAPTestBase::SetUp() {
/*log=*/log.get(),
/*default_repl_mode=*/ReplMode::Auto,
/*pre_init_commands=*/std::vector<std::string>(),
/*no_lldbinit=*/false,
/*client_name=*/"test_client",
/*transport=*/*transport, /*loop=*/loop);
}
Expand Down
Loading