|
76 | 76 | using namespace lldb;
|
77 | 77 | using namespace lldb_private;
|
78 | 78 |
|
| 79 | +namespace { |
| 80 | + |
| 81 | +struct ExecutableInstaller { |
| 82 | + |
| 83 | + ExecutableInstaller(PlatformSP platform, ModuleSP module) |
| 84 | + : m_platform{platform}, m_module{module}, |
| 85 | + m_local_file{m_module->GetFileSpec()}, |
| 86 | + m_remote_file{m_module->GetRemoteInstallFileSpec()} {} |
| 87 | + |
| 88 | + void setRemoteFile() const { m_module->SetPlatformFileSpec(m_remote_file); } |
| 89 | + |
| 90 | + PlatformSP m_platform; |
| 91 | + ModuleSP m_module; |
| 92 | + const FileSpec m_local_file; |
| 93 | + const FileSpec m_remote_file; |
| 94 | +}; |
| 95 | + |
| 96 | +struct MainExecutableInstaller { |
| 97 | + |
| 98 | + MainExecutableInstaller(PlatformSP platform, TargetSP target, ModuleSP module, |
| 99 | + ProcessLaunchInfo *launch_info) |
| 100 | + : m_platform{platform}, m_target{target}, m_module{module}, |
| 101 | + m_local_file{m_module->GetFileSpec()}, |
| 102 | + m_remote_file{ |
| 103 | + getRemoteFileSpec(m_platform, m_target, m_module, m_local_file)}, |
| 104 | + m_launch_info{launch_info} {} |
| 105 | + |
| 106 | + void setRemoteFile() const { |
| 107 | + m_module->SetPlatformFileSpec(m_remote_file); |
| 108 | + m_launch_info->SetExecutableFile(m_remote_file, |
| 109 | + false /*add_exe_file_as_first_arg*/); |
| 110 | + m_platform->SetFilePermissions(m_remote_file, 0700 /*-rwx------*/); |
| 111 | + } |
| 112 | + |
| 113 | + PlatformSP m_platform; |
| 114 | + TargetSP m_target; |
| 115 | + ModuleSP m_module; |
| 116 | + const FileSpec m_local_file; |
| 117 | + const FileSpec m_remote_file; |
| 118 | + ProcessLaunchInfo *m_launch_info; |
| 119 | + |
| 120 | +private: |
| 121 | + // Creates a filename "<local_file_name>_<local_file_md5_hash>" for a file |
| 122 | + // on a remote target. This is needed to check existance of the file on a |
| 123 | + // remote machine and then install it if the file is missing. |
| 124 | + static std::optional<std::string> |
| 125 | + getRemoteFileName(const FileSpec &local_file) { |
| 126 | + auto local_md5 = llvm::sys::fs::md5_contents(local_file.GetPath()); |
| 127 | + if (!local_md5) |
| 128 | + return std::nullopt; |
| 129 | + |
| 130 | + auto [high, low] = local_md5->words(); |
| 131 | + |
| 132 | + std::stringstream ss; |
| 133 | + ss << local_file.GetFilename().GetCString() << "_" << high << low; |
| 134 | + return ss.str(); |
| 135 | + } |
| 136 | + |
| 137 | + static FileSpec getRemoteFileSpec(PlatformSP platform, TargetSP target, |
| 138 | + ModuleSP module, |
| 139 | + const FileSpec &local_file) { |
| 140 | + FileSpec remote_file = module->GetRemoteInstallFileSpec(); |
| 141 | + if (remote_file || !target->GetAutoInstallMainExecutable()) |
| 142 | + return remote_file; |
| 143 | + |
| 144 | + if (!local_file) |
| 145 | + return {}; |
| 146 | + |
| 147 | + auto remote_filename = getRemoteFileName(local_file); |
| 148 | + if (!remote_filename) |
| 149 | + return {}; |
| 150 | + |
| 151 | + remote_file = platform->GetRemoteWorkingDirectory(); |
| 152 | + remote_file.AppendPathComponent(remote_filename.value()); |
| 153 | + |
| 154 | + return remote_file; |
| 155 | + } |
| 156 | +}; |
| 157 | +} // namespace |
| 158 | + |
| 159 | +template <typename Installer> |
| 160 | +static Status installExecutable(const Installer &installer) { |
| 161 | + // Firstly check is the file already exists on a remote machine |
| 162 | + if (installer.m_platform->GetFileExists(installer.m_remote_file)) { |
| 163 | + installer.setRemoteFile(); |
| 164 | + return Status(); |
| 165 | + } |
| 166 | + |
| 167 | + if (!installer.m_local_file) |
| 168 | + return Status(); |
| 169 | + |
| 170 | + Status error = installer.m_platform->Install(installer.m_local_file, |
| 171 | + installer.m_remote_file); |
| 172 | + if (error.Fail()) |
| 173 | + return error; |
| 174 | + |
| 175 | + installer.setRemoteFile(); |
| 176 | + return Status(); |
| 177 | +} |
| 178 | + |
79 | 179 | constexpr std::chrono::milliseconds EvaluateExpressionOptions::default_timeout;
|
80 | 180 |
|
81 | 181 | Target::Arch::Arch(const ArchSpec &spec)
|
@@ -3076,48 +3176,33 @@ TargetProperties &Target::GetGlobalProperties() {
|
3076 | 3176 | Status Target::Install(ProcessLaunchInfo *launch_info) {
|
3077 | 3177 | Status error;
|
3078 | 3178 | PlatformSP platform_sp(GetPlatform());
|
3079 |
| - if (platform_sp) { |
3080 |
| - if (platform_sp->IsRemote()) { |
3081 |
| - if (platform_sp->IsConnected()) { |
3082 |
| - // Install all files that have an install path when connected to a |
3083 |
| - // remote platform. If target.auto-install-main-executable is set then |
3084 |
| - // also install the main executable even if it does not have an explicit |
3085 |
| - // install path specified. |
3086 |
| - const ModuleList &modules = GetImages(); |
3087 |
| - const size_t num_images = modules.GetSize(); |
3088 |
| - for (size_t idx = 0; idx < num_images; ++idx) { |
3089 |
| - ModuleSP module_sp(modules.GetModuleAtIndex(idx)); |
3090 |
| - if (module_sp) { |
3091 |
| - const bool is_main_executable = module_sp == GetExecutableModule(); |
3092 |
| - FileSpec local_file(module_sp->GetFileSpec()); |
3093 |
| - if (local_file) { |
3094 |
| - FileSpec remote_file(module_sp->GetRemoteInstallFileSpec()); |
3095 |
| - if (!remote_file) { |
3096 |
| - if (is_main_executable && GetAutoInstallMainExecutable()) { |
3097 |
| - // Automatically install the main executable. |
3098 |
| - remote_file = platform_sp->GetRemoteWorkingDirectory(); |
3099 |
| - remote_file.AppendPathComponent( |
3100 |
| - module_sp->GetFileSpec().GetFilename().GetCString()); |
3101 |
| - } |
3102 |
| - } |
3103 |
| - if (remote_file) { |
3104 |
| - error = platform_sp->Install(local_file, remote_file); |
3105 |
| - if (error.Success()) { |
3106 |
| - module_sp->SetPlatformFileSpec(remote_file); |
3107 |
| - if (is_main_executable) { |
3108 |
| - platform_sp->SetFilePermissions(remote_file, 0700); |
3109 |
| - if (launch_info) |
3110 |
| - launch_info->SetExecutableFile(remote_file, false); |
3111 |
| - } |
3112 |
| - } else |
3113 |
| - break; |
3114 |
| - } |
3115 |
| - } |
3116 |
| - } |
3117 |
| - } |
3118 |
| - } |
| 3179 | + if (!platform_sp || !platform_sp->IsRemote() || !platform_sp->IsConnected()) |
| 3180 | + return error; |
| 3181 | + |
| 3182 | + // Install all files that have an install path when connected to a |
| 3183 | + // remote platform. If target.auto-install-main-executable is set then |
| 3184 | + // also install the main executable even if it does not have an explicit |
| 3185 | + // install path specified. |
| 3186 | + |
| 3187 | + for (auto module_sp : GetImages().Modules()) { |
| 3188 | + if (module_sp == GetExecutableModule()) { |
| 3189 | + MainExecutableInstaller installer{platform_sp, shared_from_this(), |
| 3190 | + module_sp, launch_info}; |
| 3191 | + if (installer.m_remote_file) |
| 3192 | + error = installExecutable(installer); |
| 3193 | + else if (GetAutoInstallMainExecutable()) |
| 3194 | + error.SetErrorStringWithFormatv("Target::{0}() can't get a remote file", |
| 3195 | + __FUNCTION__); |
| 3196 | + } else { |
| 3197 | + ExecutableInstaller installer{platform_sp, module_sp}; |
| 3198 | + if (installer.m_remote_file) |
| 3199 | + error = installExecutable(installer); |
3119 | 3200 | }
|
| 3201 | + |
| 3202 | + if (error.Fail()) |
| 3203 | + return error; |
3120 | 3204 | }
|
| 3205 | + |
3121 | 3206 | return error;
|
3122 | 3207 | }
|
3123 | 3208 |
|
|
0 commit comments