forked from OSchip/llvm-project
Add a new option to Platform::LoadImage to install the image
This change introduce 3 different working mode for Platform::LoadImage depending on the file specs specified. * If only a remote file is specified then the remote file is loaded on the target (same behavior as before) * If only a local file is specified then the local file is installed to the current working directory and then loaded from there. * If both local and remote file is specified then the local file is installed to the specified location and then loaded from there. The same options are exposed on the SB API with a new method LoadImage method while the old signature presers its meaning. On the command line the installation of the shared library can be specified with the "--install" option of "process load". Differential revision: http://reviews.llvm.org/D15152 llvm-svn: 255014
This commit is contained in:
parent
9cbf7dde88
commit
4fbd67ac11
|
@ -294,8 +294,56 @@ public:
|
|||
uint32_t
|
||||
GetNumSupportedHardwareWatchpoints (lldb::SBError &error) const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Load a shared library into this process.
|
||||
///
|
||||
/// @param[in] remote_image_spec
|
||||
/// The path for the shared library on the target what you want
|
||||
/// to load.
|
||||
///
|
||||
/// @param[out] error
|
||||
/// An error object that gets filled in with any errors that
|
||||
/// might occur when trying to load the shared library.
|
||||
///
|
||||
/// @return
|
||||
/// A token that represents the shared library that can be
|
||||
/// later used to unload the shared library. A value of
|
||||
/// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared
|
||||
/// library can't be opened.
|
||||
//------------------------------------------------------------------
|
||||
uint32_t
|
||||
LoadImage (lldb::SBFileSpec &image_spec, lldb::SBError &error);
|
||||
LoadImage (lldb::SBFileSpec &remote_image_spec, lldb::SBError &error);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Load a shared library into this process.
|
||||
///
|
||||
/// @param[in] local_image_spec
|
||||
/// The file spec that points to the shared library that you
|
||||
/// want to load if the library is located on the host. The
|
||||
/// library will be copied over to the location specified by
|
||||
/// remote_image_spec or into the current working directory with
|
||||
/// the same filename if the remote_image_spec isn't specified.
|
||||
///
|
||||
/// @param[in] remote_image_spec
|
||||
/// If local_image_spec is specified then the location where the
|
||||
/// library should be copied over from the host. If
|
||||
/// local_image_spec isn't specified, then the path for the
|
||||
/// shared library on the target what you want to load.
|
||||
///
|
||||
/// @param[out] error
|
||||
/// An error object that gets filled in with any errors that
|
||||
/// might occur when trying to load the shared library.
|
||||
///
|
||||
/// @return
|
||||
/// A token that represents the shared library that can be
|
||||
/// later used to unload the shared library. A value of
|
||||
/// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared
|
||||
/// library can't be opened.
|
||||
//------------------------------------------------------------------
|
||||
uint32_t
|
||||
LoadImage (const lldb::SBFileSpec &local_image_spec,
|
||||
const lldb::SBFileSpec &remote_image_spec,
|
||||
lldb::SBError &error);
|
||||
|
||||
lldb::SBError
|
||||
UnloadImage (uint32_t image_token);
|
||||
|
|
|
@ -997,9 +997,18 @@ class ModuleCache;
|
|||
/// @param[in] process
|
||||
/// The process to load the image.
|
||||
///
|
||||
/// @param[in] image_spec
|
||||
/// The image file spec that points to the shared library that
|
||||
/// you want to load.
|
||||
/// @param[in] local_file
|
||||
/// The file spec that points to the shared library that you want
|
||||
/// to load if the library is located on the host. The library will
|
||||
/// be copied over to the location specified by remote_file or into
|
||||
/// the current working directory with the same filename if the
|
||||
/// remote_file isn't specified.
|
||||
///
|
||||
/// @param[in] remote_file
|
||||
/// If local_file is specified then the location where the library
|
||||
/// should be copied over from the host. If local_file isn't
|
||||
/// specified, then the path for the shared library on the target
|
||||
/// what you want to load.
|
||||
///
|
||||
/// @param[out] error
|
||||
/// An error object that gets filled in with any errors that
|
||||
|
@ -1011,11 +1020,17 @@ class ModuleCache;
|
|||
/// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared
|
||||
/// library can't be opened.
|
||||
//------------------------------------------------------------------
|
||||
virtual uint32_t
|
||||
uint32_t
|
||||
LoadImage (lldb_private::Process* process,
|
||||
const lldb_private::FileSpec& image_spec,
|
||||
const lldb_private::FileSpec& local_file,
|
||||
const lldb_private::FileSpec& remote_file,
|
||||
lldb_private::Error& error);
|
||||
|
||||
virtual uint32_t
|
||||
DoLoadImage (lldb_private::Process* process,
|
||||
const lldb_private::FileSpec& remote_file,
|
||||
lldb_private::Error& error);
|
||||
|
||||
virtual Error
|
||||
UnloadImage (lldb_private::Process* process, uint32_t image_token);
|
||||
|
||||
|
|
|
@ -210,19 +210,13 @@ class LoadUnloadTestCase(TestBase):
|
|||
else:
|
||||
dylibName = 'libloadunload_a.so'
|
||||
|
||||
if lldb.remote_platform:
|
||||
# Don't use os.path.join as we have to use the path separator for the target
|
||||
dylibPath = shlib_dir + '/' + dylibName
|
||||
else:
|
||||
dylibPath = dylibName
|
||||
|
||||
# Make sure that a_function does not exist at this point.
|
||||
self.expect("image lookup -n a_function", "a_function should not exist yet",
|
||||
error=True, matching=False, patterns = ["1 match found"])
|
||||
|
||||
# Use lldb 'process load' to load the dylib.
|
||||
self.expect("process load %s" % dylibPath, "%s loaded correctly" % dylibPath,
|
||||
patterns = ['Loading "%s".*ok' % dylibPath,
|
||||
self.expect("process load %s --install" % dylibName, "%s loaded correctly" % dylibName,
|
||||
patterns = ['Loading "%s".*ok' % dylibName,
|
||||
'Image [0-9]+ loaded'])
|
||||
|
||||
# Search for and match the "Image ([0-9]+) loaded" pattern.
|
||||
|
|
|
@ -1288,7 +1288,15 @@ SBProcess::GetNumSupportedHardwareWatchpoints (lldb::SBError &sb_error) const
|
|||
}
|
||||
|
||||
uint32_t
|
||||
SBProcess::LoadImage (lldb::SBFileSpec &sb_image_spec, lldb::SBError &sb_error)
|
||||
SBProcess::LoadImage (lldb::SBFileSpec &sb_remote_image_spec, lldb::SBError &sb_error)
|
||||
{
|
||||
return LoadImage(SBFileSpec(), sb_remote_image_spec, sb_error);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SBProcess::LoadImage (const lldb::SBFileSpec &sb_local_image_spec,
|
||||
const lldb::SBFileSpec &sb_remote_image_spec,
|
||||
lldb::SBError &sb_error)
|
||||
{
|
||||
ProcessSP process_sp(GetSP());
|
||||
if (process_sp)
|
||||
|
@ -1298,7 +1306,10 @@ SBProcess::LoadImage (lldb::SBFileSpec &sb_image_spec, lldb::SBError &sb_error)
|
|||
{
|
||||
Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
|
||||
PlatformSP platform_sp = process_sp->GetTarget().GetPlatform();
|
||||
return platform_sp->LoadImage (process_sp.get(), *sb_image_spec, sb_error.ref());
|
||||
return platform_sp->LoadImage (process_sp.get(),
|
||||
*sb_local_image_spec,
|
||||
*sb_remote_image_spec,
|
||||
sb_error.ref());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1174,6 +1174,57 @@ public:
|
|||
class CommandObjectProcessLoad : public CommandObjectParsed
|
||||
{
|
||||
public:
|
||||
class CommandOptions : public Options
|
||||
{
|
||||
public:
|
||||
CommandOptions (CommandInterpreter &interpreter) :
|
||||
Options(interpreter)
|
||||
{
|
||||
// Keep default values of all options in one place: OptionParsingStarting ()
|
||||
OptionParsingStarting ();
|
||||
}
|
||||
|
||||
~CommandOptions () override = default;
|
||||
|
||||
Error
|
||||
SetOptionValue (uint32_t option_idx, const char *option_arg) override
|
||||
{
|
||||
Error error;
|
||||
const int short_option = m_getopt_table[option_idx].val;
|
||||
switch (short_option)
|
||||
{
|
||||
case 'i':
|
||||
do_install = true;
|
||||
if (option_arg && option_arg[0])
|
||||
install_path.SetFile(option_arg, false);
|
||||
break;
|
||||
default:
|
||||
error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
void
|
||||
OptionParsingStarting () override
|
||||
{
|
||||
do_install = false;
|
||||
install_path.Clear();
|
||||
}
|
||||
|
||||
const OptionDefinition*
|
||||
GetDefinitions () override
|
||||
{
|
||||
return g_option_table;
|
||||
}
|
||||
|
||||
// Options table: Required for subclasses of Options.
|
||||
static OptionDefinition g_option_table[];
|
||||
|
||||
// Instance variables to hold the values for command options.
|
||||
bool do_install;
|
||||
FileSpec install_path;
|
||||
};
|
||||
|
||||
CommandObjectProcessLoad (CommandInterpreter &interpreter) :
|
||||
CommandObjectParsed (interpreter,
|
||||
|
@ -1183,12 +1234,17 @@ public:
|
|||
eCommandRequiresProcess |
|
||||
eCommandTryTargetAPILock |
|
||||
eCommandProcessMustBeLaunched |
|
||||
eCommandProcessMustBePaused )
|
||||
eCommandProcessMustBePaused ),
|
||||
m_options (interpreter)
|
||||
{
|
||||
}
|
||||
|
||||
~CommandObjectProcessLoad () override
|
||||
~CommandObjectProcessLoad () override = default;
|
||||
|
||||
Options *
|
||||
GetOptions () override
|
||||
{
|
||||
return &m_options;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -1198,18 +1254,34 @@ protected:
|
|||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
|
||||
const size_t argc = command.GetArgumentCount();
|
||||
|
||||
for (uint32_t i=0; i<argc; ++i)
|
||||
{
|
||||
Error error;
|
||||
const char *image_path = command.GetArgumentAtIndex(i);
|
||||
FileSpec image_spec (image_path, false);
|
||||
PlatformSP platform = process->GetTarget().GetPlatform();
|
||||
platform->ResolveRemotePath(image_spec, image_spec);
|
||||
uint32_t image_token = platform->LoadImage(process, image_spec, error);
|
||||
const char *image_path = command.GetArgumentAtIndex(i);
|
||||
uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN;
|
||||
|
||||
if (!m_options.do_install)
|
||||
{
|
||||
FileSpec image_spec (image_path, false);
|
||||
platform->ResolveRemotePath(image_spec, image_spec);
|
||||
image_token = platform->LoadImage(process, FileSpec(), image_spec, error);
|
||||
}
|
||||
else if (m_options.install_path)
|
||||
{
|
||||
FileSpec image_spec (image_path, true);
|
||||
platform->ResolveRemotePath(m_options.install_path, m_options.install_path);
|
||||
image_token = platform->LoadImage(process, image_spec, m_options.install_path, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileSpec image_spec (image_path, true);
|
||||
image_token = platform->LoadImage(process, image_spec, FileSpec(), error);
|
||||
}
|
||||
|
||||
if (image_token != LLDB_INVALID_IMAGE_TOKEN)
|
||||
{
|
||||
result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
|
||||
result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
}
|
||||
else
|
||||
|
@ -1220,8 +1292,16 @@ protected:
|
|||
}
|
||||
return result.Succeeded();
|
||||
}
|
||||
|
||||
CommandOptions m_options;
|
||||
};
|
||||
|
||||
OptionDefinition
|
||||
CommandObjectProcessLoad::CommandOptions::g_option_table[] =
|
||||
{
|
||||
{ LLDB_OPT_SET_ALL, false, "install", 'i', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypePath, "Install the shared library to the target. If specified without an argument then the library will installed in the current working directory."},
|
||||
{ 0, false, nullptr, 0 , 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectProcessUnload
|
||||
|
|
|
@ -898,10 +898,12 @@ PlatformPOSIX::EvaluateLibdlExpression(lldb_private::Process* process,
|
|||
}
|
||||
|
||||
uint32_t
|
||||
PlatformPOSIX::LoadImage(lldb_private::Process* process, const FileSpec& image_spec, Error& error)
|
||||
PlatformPOSIX::DoLoadImage(lldb_private::Process* process,
|
||||
const lldb_private::FileSpec& remote_file,
|
||||
lldb_private::Error& error)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
image_spec.GetPath(path, sizeof(path));
|
||||
remote_file.GetPath(path, sizeof(path));
|
||||
|
||||
StreamString expr;
|
||||
expr.Printf(R"(
|
||||
|
|
|
@ -174,9 +174,9 @@ public:
|
|||
DisconnectRemote () override;
|
||||
|
||||
uint32_t
|
||||
LoadImage (lldb_private::Process* process,
|
||||
const lldb_private::FileSpec& image_spec,
|
||||
lldb_private::Error& error) override;
|
||||
DoLoadImage (lldb_private::Process* process,
|
||||
const lldb_private::FileSpec& remote_file,
|
||||
lldb_private::Error& error) override;
|
||||
|
||||
lldb_private::Error
|
||||
UnloadImage (lldb_private::Process* process, uint32_t image_token) override;
|
||||
|
|
|
@ -1985,7 +1985,51 @@ Platform::GetUnixSignals()
|
|||
}
|
||||
|
||||
uint32_t
|
||||
Platform::LoadImage(lldb_private::Process* process, const FileSpec& image_spec, Error& error)
|
||||
Platform::LoadImage(lldb_private::Process* process,
|
||||
const lldb_private::FileSpec& local_file,
|
||||
const lldb_private::FileSpec& remote_file,
|
||||
lldb_private::Error& error)
|
||||
{
|
||||
if (local_file && remote_file)
|
||||
{
|
||||
// Both local and remote file was specified. Install the local file to the given location.
|
||||
if (IsRemote() || local_file != remote_file)
|
||||
{
|
||||
error = Install(local_file, remote_file);
|
||||
if (error.Fail())
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
||||
return DoLoadImage(process, remote_file, error);
|
||||
}
|
||||
|
||||
if (local_file)
|
||||
{
|
||||
// Only local file was specified. Install it to the current working directory.
|
||||
FileSpec target_file = GetWorkingDirectory();
|
||||
target_file.AppendPathComponent(local_file.GetFilename().AsCString());
|
||||
if (IsRemote() || local_file != target_file)
|
||||
{
|
||||
error = Install(local_file, target_file);
|
||||
if (error.Fail())
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
||||
return DoLoadImage(process, target_file, error);
|
||||
}
|
||||
|
||||
if (remote_file)
|
||||
{
|
||||
// Only remote file was specified so we don't have to do any copying
|
||||
return DoLoadImage(process, remote_file, error);
|
||||
}
|
||||
|
||||
error.SetErrorString("Neither local nor remote file was specified");
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Platform::DoLoadImage (lldb_private::Process* process,
|
||||
const lldb_private::FileSpec& remote_file,
|
||||
lldb_private::Error& error)
|
||||
{
|
||||
error.SetErrorString("LoadImage is not supported on the current platform");
|
||||
return LLDB_INVALID_IMAGE_TOKEN;
|
||||
|
@ -1994,5 +2038,5 @@ Platform::LoadImage(lldb_private::Process* process, const FileSpec& image_spec,
|
|||
Error
|
||||
Platform::UnloadImage(lldb_private::Process* process, uint32_t image_token)
|
||||
{
|
||||
return Error("UnLoadImage is not supported on the current platform");
|
||||
return Error("UnloadImage is not supported on the current platform");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue