Skip to content

Commit

Permalink
Revert "Revert "Make it possible for lldb to launch a remote binary w…
Browse files Browse the repository at this point in the history
…ith no local file.""

This reverts commit dd5505a.

I picked the wrong class for the test, should have been GDBRemoteTestBase.
  • Loading branch information
jimingham committed Nov 18, 2021
1 parent 02eca53 commit 92eaad2
Show file tree
Hide file tree
Showing 4 changed files with 328 additions and 220 deletions.
40 changes: 30 additions & 10 deletions lldb/source/Commands/CommandObjectProcess.cpp
Expand Up @@ -159,7 +159,12 @@ class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {
// If our listener is nullptr, users aren't allows to launch
ModuleSP exe_module_sp = target->GetExecutableModule();

if (exe_module_sp == nullptr) {
// If the target already has an executable module, then use that. If it
// doesn't then someone must be trying to launch using a path that will
// make sense to the remote stub, but doesn't exist on the local host.
// In that case use the ExecutableFile that was set in the target's
// ProcessLaunchInfo.
if (exe_module_sp == nullptr && !target->GetProcessLaunchInfo().GetExecutableFile()) {
result.AppendError("no file in target, create a debug target using the "
"'target create' command");
return false;
Expand Down Expand Up @@ -219,11 +224,17 @@ class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {
if (!target_settings_argv0.empty()) {
m_options.launch_info.GetArguments().AppendArgument(
target_settings_argv0);
m_options.launch_info.SetExecutableFile(
exe_module_sp->GetPlatformFileSpec(), false);
if (exe_module_sp)
m_options.launch_info.SetExecutableFile(
exe_module_sp->GetPlatformFileSpec(), false);
else
m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), false);
} else {
m_options.launch_info.SetExecutableFile(
exe_module_sp->GetPlatformFileSpec(), true);
if (exe_module_sp)
m_options.launch_info.SetExecutableFile(
exe_module_sp->GetPlatformFileSpec(), true);
else
m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), true);
}

if (launch_args.GetArgumentCount() == 0) {
Expand All @@ -250,11 +261,20 @@ class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {
llvm::StringRef data = stream.GetString();
if (!data.empty())
result.AppendMessage(data);
const char *archname =
exe_module_sp->GetArchitecture().GetArchitectureName();
result.AppendMessageWithFormat(
"Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(),
exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
// If we didn't have a local executable, then we wouldn't have had an
// executable module before launch.
if (!exe_module_sp)
exe_module_sp = target->GetExecutableModule();
if (!exe_module_sp) {
result.AppendWarning("Could not get executable module after launch.");
} else {

const char *archname =
exe_module_sp->GetArchitecture().GetArchitectureName();
result.AppendMessageWithFormat(
"Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(),
exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
}
result.SetStatus(eReturnStatusSuccessFinishResult);
result.SetDidChangeProcessState(true);
} else {
Expand Down
224 changes: 107 additions & 117 deletions lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
Expand Up @@ -677,143 +677,133 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module,
// LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
// ::LogSetLogFile ("/dev/stdout");

ObjectFile *object_file = exe_module->GetObjectFile();
if (object_file) {
error = EstablishConnectionIfNeeded(launch_info);
if (error.Success()) {
PseudoTerminal pty;
const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;

PlatformSP platform_sp(GetTarget().GetPlatform());
if (disable_stdio) {
// set to /dev/null unless redirected to a file above
if (!stdin_file_spec)
stdin_file_spec.SetFile(FileSystem::DEV_NULL,
FileSpec::Style::native);
if (!stdout_file_spec)
stdout_file_spec.SetFile(FileSystem::DEV_NULL,
FileSpec::Style::native);
if (!stderr_file_spec)
stderr_file_spec.SetFile(FileSystem::DEV_NULL,
FileSpec::Style::native);
} else if (platform_sp && platform_sp->IsHost()) {
// If the debugserver is local and we aren't disabling STDIO, lets use
// a pseudo terminal to instead of relying on the 'O' packets for stdio
// since 'O' packets can really slow down debugging if the inferior
// does a lot of output.
if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) &&
!errorToBool(pty.OpenFirstAvailablePrimary(O_RDWR | O_NOCTTY))) {
FileSpec secondary_name(pty.GetSecondaryName());

if (!stdin_file_spec)
stdin_file_spec = secondary_name;

if (!stdout_file_spec)
stdout_file_spec = secondary_name;

if (!stderr_file_spec)
stderr_file_spec = secondary_name;
}
LLDB_LOGF(
log,
"ProcessGDBRemote::%s adjusted STDIO paths for local platform "
"(IsHost() is true) using secondary: stdin=%s, stdout=%s, "
"stderr=%s",
__FUNCTION__,
stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
}
error = EstablishConnectionIfNeeded(launch_info);
if (error.Success()) {
PseudoTerminal pty;
const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;

LLDB_LOGF(log,
"ProcessGDBRemote::%s final STDIO paths after all "
"adjustments: stdin=%s, stdout=%s, stderr=%s",
__FUNCTION__,
stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");

if (stdin_file_spec)
m_gdb_comm.SetSTDIN(stdin_file_spec);
if (stdout_file_spec)
m_gdb_comm.SetSTDOUT(stdout_file_spec);
if (stderr_file_spec)
m_gdb_comm.SetSTDERR(stderr_file_spec);

m_gdb_comm.SetDisableASLR(launch_flags & eLaunchFlagDisableASLR);
m_gdb_comm.SetDetachOnError(launch_flags & eLaunchFlagDetachOnError);
PlatformSP platform_sp(GetTarget().GetPlatform());
if (disable_stdio) {
// set to /dev/null unless redirected to a file above
if (!stdin_file_spec)
stdin_file_spec.SetFile(FileSystem::DEV_NULL,
FileSpec::Style::native);
if (!stdout_file_spec)
stdout_file_spec.SetFile(FileSystem::DEV_NULL,
FileSpec::Style::native);
if (!stderr_file_spec)
stderr_file_spec.SetFile(FileSystem::DEV_NULL,
FileSpec::Style::native);
} else if (platform_sp && platform_sp->IsHost()) {
// If the debugserver is local and we aren't disabling STDIO, lets use
// a pseudo terminal to instead of relying on the 'O' packets for stdio
// since 'O' packets can really slow down debugging if the inferior
// does a lot of output.
if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) &&
!errorToBool(pty.OpenFirstAvailablePrimary(O_RDWR | O_NOCTTY))) {
FileSpec secondary_name(pty.GetSecondaryName());

m_gdb_comm.SendLaunchArchPacket(
GetTarget().GetArchitecture().GetArchitectureName());
if (!stdin_file_spec)
stdin_file_spec = secondary_name;

const char *launch_event_data = launch_info.GetLaunchEventData();
if (launch_event_data != nullptr && *launch_event_data != '\0')
m_gdb_comm.SendLaunchEventDataPacket(launch_event_data);
if (!stdout_file_spec)
stdout_file_spec = secondary_name;

if (working_dir) {
m_gdb_comm.SetWorkingDir(working_dir);
if (!stderr_file_spec)
stderr_file_spec = secondary_name;
}
LLDB_LOGF(
log,
"ProcessGDBRemote::%s adjusted STDIO paths for local platform "
"(IsHost() is true) using secondary: stdin=%s, stdout=%s, "
"stderr=%s",
__FUNCTION__,
stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
}

// Send the environment and the program + arguments after we connect
m_gdb_comm.SendEnvironment(launch_info.GetEnvironment());
LLDB_LOGF(log,
"ProcessGDBRemote::%s final STDIO paths after all "
"adjustments: stdin=%s, stdout=%s, stderr=%s",
__FUNCTION__,
stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");

if (stdin_file_spec)
m_gdb_comm.SetSTDIN(stdin_file_spec);
if (stdout_file_spec)
m_gdb_comm.SetSTDOUT(stdout_file_spec);
if (stderr_file_spec)
m_gdb_comm.SetSTDERR(stderr_file_spec);

m_gdb_comm.SetDisableASLR(launch_flags & eLaunchFlagDisableASLR);
m_gdb_comm.SetDetachOnError(launch_flags & eLaunchFlagDetachOnError);

m_gdb_comm.SendLaunchArchPacket(
GetTarget().GetArchitecture().GetArchitectureName());

const char *launch_event_data = launch_info.GetLaunchEventData();
if (launch_event_data != nullptr && *launch_event_data != '\0')
m_gdb_comm.SendLaunchEventDataPacket(launch_event_data);

if (working_dir) {
m_gdb_comm.SetWorkingDir(working_dir);
}

{
// Scope for the scoped timeout object
GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm,
std::chrono::seconds(10));
// Send the environment and the program + arguments after we connect
m_gdb_comm.SendEnvironment(launch_info.GetEnvironment());

int arg_packet_err = m_gdb_comm.SendArgumentsPacket(launch_info);
if (arg_packet_err == 0) {
std::string error_str;
if (m_gdb_comm.GetLaunchSuccess(error_str)) {
SetID(m_gdb_comm.GetCurrentProcessID());
} else {
error.SetErrorString(error_str.c_str());
}
{
// Scope for the scoped timeout object
GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm,
std::chrono::seconds(10));

int arg_packet_err = m_gdb_comm.SendArgumentsPacket(launch_info);
if (arg_packet_err == 0) {
std::string error_str;
if (m_gdb_comm.GetLaunchSuccess(error_str)) {
SetID(m_gdb_comm.GetCurrentProcessID());
} else {
error.SetErrorStringWithFormat("'A' packet returned an error: %i",
arg_packet_err);
error.SetErrorString(error_str.c_str());
}
} else {
error.SetErrorStringWithFormat("'A' packet returned an error: %i",
arg_packet_err);
}
}

if (GetID() == LLDB_INVALID_PROCESS_ID) {
LLDB_LOGF(log, "failed to connect to debugserver: %s",
error.AsCString());
KillDebugserverProcess();
return error;
}
if (GetID() == LLDB_INVALID_PROCESS_ID) {
LLDB_LOGF(log, "failed to connect to debugserver: %s",
error.AsCString());
KillDebugserverProcess();
return error;
}

StringExtractorGDBRemote response;
if (m_gdb_comm.GetStopReply(response)) {
SetLastStopPacket(response);
StringExtractorGDBRemote response;
if (m_gdb_comm.GetStopReply(response)) {
SetLastStopPacket(response);

const ArchSpec &process_arch = m_gdb_comm.GetProcessArchitecture();
const ArchSpec &process_arch = m_gdb_comm.GetProcessArchitecture();

if (process_arch.IsValid()) {
GetTarget().MergeArchitecture(process_arch);
} else {
const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture();
if (host_arch.IsValid())
GetTarget().MergeArchitecture(host_arch);
}
if (process_arch.IsValid()) {
GetTarget().MergeArchitecture(process_arch);
} else {
const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture();
if (host_arch.IsValid())
GetTarget().MergeArchitecture(host_arch);
}

SetPrivateState(SetThreadStopInfo(response));
SetPrivateState(SetThreadStopInfo(response));

if (!disable_stdio) {
if (pty.GetPrimaryFileDescriptor() != PseudoTerminal::invalid_fd)
SetSTDIOFileDescriptor(pty.ReleasePrimaryFileDescriptor());
}
if (!disable_stdio) {
if (pty.GetPrimaryFileDescriptor() != PseudoTerminal::invalid_fd)
SetSTDIOFileDescriptor(pty.ReleasePrimaryFileDescriptor());
}
} else {
LLDB_LOGF(log, "failed to connect to debugserver: %s", error.AsCString());
}
} else {
// Set our user ID to an invalid process ID.
SetID(LLDB_INVALID_PROCESS_ID);
error.SetErrorStringWithFormat(
"failed to get object file from '%s' for arch %s",
exe_module->GetFileSpec().GetFilename().AsCString(),
exe_module->GetArchitecture().GetArchitectureName());
LLDB_LOGF(log, "failed to connect to debugserver: %s", error.AsCString());
}
return error;
}
Expand Down

0 comments on commit 92eaad2

Please sign in to comment.