1e0f8f574SDaniel Malea //===-- PlatformPOSIX.cpp ---------------------------------------*- C++ -*-===// 2e0f8f574SDaniel Malea // 3e0f8f574SDaniel Malea // The LLVM Compiler Infrastructure 4e0f8f574SDaniel Malea // 5e0f8f574SDaniel Malea // This file is distributed under the University of Illinois Open Source 6e0f8f574SDaniel Malea // License. See LICENSE.TXT for details. 7e0f8f574SDaniel Malea // 8e0f8f574SDaniel Malea //===----------------------------------------------------------------------===// 9e0f8f574SDaniel Malea 10e0f8f574SDaniel Malea #include "PlatformPOSIX.h" 11e0f8f574SDaniel Malea 12e0f8f574SDaniel Malea // C Includes 13e0f8f574SDaniel Malea // C++ Includes 14e0f8f574SDaniel Malea // Other libraries and framework includes 15e0f8f574SDaniel Malea // Project includes 16e0f8f574SDaniel Malea 17e0f8f574SDaniel Malea #include "lldb/Core/DataBufferHeap.h" 18348fb385STodd Fiala #include "lldb/Core/Debugger.h" 19e0f8f574SDaniel Malea #include "lldb/Core/Log.h" 20348fb385STodd Fiala #include "lldb/Core/Module.h" 21e0f8f574SDaniel Malea #include "lldb/Core/StreamString.h" 223cb132a0STamas Berghammer #include "lldb/Core/ValueObject.h" 233cb132a0STamas Berghammer #include "lldb/Expression/UserExpression.h" 24e0f8f574SDaniel Malea #include "lldb/Host/File.h" 25c00cf4a0SZachary Turner #include "lldb/Host/FileCache.h" 26e0f8f574SDaniel Malea #include "lldb/Host/FileSpec.h" 27c00cf4a0SZachary Turner #include "lldb/Host/FileSystem.h" 28e0f8f574SDaniel Malea #include "lldb/Host/Host.h" 293cb132a0STamas Berghammer #include "lldb/Target/DynamicLoader.h" 303cb132a0STamas Berghammer #include "lldb/Target/ExecutionContext.h" 31a78bd7ffSZachary Turner #include "lldb/Target/Process.h" 32015d818bSTodd Fiala #include "lldb/Target/ProcessLaunchInfo.h" 333cb132a0STamas Berghammer #include "lldb/Target/Thread.h" 34e0f8f574SDaniel Malea 35e0f8f574SDaniel Malea using namespace lldb; 36e0f8f574SDaniel Malea using namespace lldb_private; 37e0f8f574SDaniel Malea 38e0f8f574SDaniel Malea 39e0f8f574SDaniel Malea //------------------------------------------------------------------ 40e0f8f574SDaniel Malea /// Default Constructor 41e0f8f574SDaniel Malea //------------------------------------------------------------------ 42e0f8f574SDaniel Malea PlatformPOSIX::PlatformPOSIX (bool is_host) : 43e0f8f574SDaniel Malea Platform(is_host), // This is the local host platform 440a66e2f1SEnrico Granata m_option_group_platform_rsync(new OptionGroupPlatformRSync()), 450a66e2f1SEnrico Granata m_option_group_platform_ssh(new OptionGroupPlatformSSH()), 460a66e2f1SEnrico Granata m_option_group_platform_caching(new OptionGroupPlatformCaching()), 47e0f8f574SDaniel Malea m_remote_platform_sp () 48e0f8f574SDaniel Malea { 49e0f8f574SDaniel Malea } 50e0f8f574SDaniel Malea 51e0f8f574SDaniel Malea //------------------------------------------------------------------ 52e0f8f574SDaniel Malea /// Destructor. 53e0f8f574SDaniel Malea /// 54e0f8f574SDaniel Malea /// The destructor is virtual since this class is designed to be 55e0f8f574SDaniel Malea /// inherited from by the plug-in instance. 56e0f8f574SDaniel Malea //------------------------------------------------------------------ 57e0f8f574SDaniel Malea PlatformPOSIX::~PlatformPOSIX() 58e0f8f574SDaniel Malea { 59e0f8f574SDaniel Malea } 60e0f8f574SDaniel Malea 6163acdfdeSOleksiy Vyalov bool 6263acdfdeSOleksiy Vyalov PlatformPOSIX::GetModuleSpec (const FileSpec& module_file_spec, 6363acdfdeSOleksiy Vyalov const ArchSpec& arch, 6463acdfdeSOleksiy Vyalov ModuleSpec &module_spec) 6563acdfdeSOleksiy Vyalov { 6663acdfdeSOleksiy Vyalov if (m_remote_platform_sp) 6763acdfdeSOleksiy Vyalov return m_remote_platform_sp->GetModuleSpec (module_file_spec, arch, module_spec); 6863acdfdeSOleksiy Vyalov 6963acdfdeSOleksiy Vyalov return Platform::GetModuleSpec (module_file_spec, arch, module_spec); 7063acdfdeSOleksiy Vyalov } 7163acdfdeSOleksiy Vyalov 72e0f8f574SDaniel Malea lldb_private::OptionGroupOptions* 73e0f8f574SDaniel Malea PlatformPOSIX::GetConnectionOptions (lldb_private::CommandInterpreter& interpreter) 74e0f8f574SDaniel Malea { 750a66e2f1SEnrico Granata auto iter = m_options.find(&interpreter), end = m_options.end(); 760a66e2f1SEnrico Granata if (iter == end) 77e0f8f574SDaniel Malea { 780a66e2f1SEnrico Granata std::unique_ptr<lldb_private::OptionGroupOptions> options(new OptionGroupOptions(interpreter)); 790a66e2f1SEnrico Granata options->Append(m_option_group_platform_rsync.get()); 800a66e2f1SEnrico Granata options->Append(m_option_group_platform_ssh.get()); 810a66e2f1SEnrico Granata options->Append(m_option_group_platform_caching.get()); 820a66e2f1SEnrico Granata m_options[&interpreter] = std::move(options); 83e0f8f574SDaniel Malea } 840a66e2f1SEnrico Granata 850a66e2f1SEnrico Granata return m_options.at(&interpreter).get(); 86e0f8f574SDaniel Malea } 87e0f8f574SDaniel Malea 88015d818bSTodd Fiala bool 89015d818bSTodd Fiala PlatformPOSIX::IsConnected () const 90015d818bSTodd Fiala { 91015d818bSTodd Fiala if (IsHost()) 92015d818bSTodd Fiala return true; 93015d818bSTodd Fiala else if (m_remote_platform_sp) 94015d818bSTodd Fiala return m_remote_platform_sp->IsConnected(); 95015d818bSTodd Fiala return false; 96015d818bSTodd Fiala } 97015d818bSTodd Fiala 98e0f8f574SDaniel Malea lldb_private::Error 99e0f8f574SDaniel Malea PlatformPOSIX::RunShellCommand(const char *command, // Shouldn't be NULL 100d3173f34SChaoren Lin const FileSpec &working_dir, // Pass empty FileSpec to use the current working directory 101e0f8f574SDaniel Malea int *status_ptr, // Pass NULL if you don't want the process exit status 102e0f8f574SDaniel Malea int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit 103e0f8f574SDaniel Malea std::string *command_output, // Pass NULL if you don't want the command output 104e0f8f574SDaniel Malea uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish 105e0f8f574SDaniel Malea { 106e0f8f574SDaniel Malea if (IsHost()) 107e0f8f574SDaniel Malea return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 108e0f8f574SDaniel Malea else 109e0f8f574SDaniel Malea { 110e0f8f574SDaniel Malea if (m_remote_platform_sp) 111e0f8f574SDaniel Malea return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 112e0f8f574SDaniel Malea else 113e0f8f574SDaniel Malea return Error("unable to run a remote command without a platform"); 114e0f8f574SDaniel Malea } 115e0f8f574SDaniel Malea } 116e0f8f574SDaniel Malea 117fbb76349SGreg Clayton Error 118d3173f34SChaoren Lin PlatformPOSIX::MakeDirectory(const FileSpec &file_spec, uint32_t file_permissions) 119e0f8f574SDaniel Malea { 120fbb76349SGreg Clayton if (m_remote_platform_sp) 121d3173f34SChaoren Lin return m_remote_platform_sp->MakeDirectory(file_spec, file_permissions); 122fbb76349SGreg Clayton else 123d3173f34SChaoren Lin return Platform::MakeDirectory(file_spec ,file_permissions); 124e0f8f574SDaniel Malea } 125fbb76349SGreg Clayton 126fbb76349SGreg Clayton Error 127d3173f34SChaoren Lin PlatformPOSIX::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions) 128fbb76349SGreg Clayton { 129fbb76349SGreg Clayton if (m_remote_platform_sp) 130d3173f34SChaoren Lin return m_remote_platform_sp->GetFilePermissions(file_spec, file_permissions); 131fbb76349SGreg Clayton else 132d3173f34SChaoren Lin return Platform::GetFilePermissions(file_spec ,file_permissions); 133fbb76349SGreg Clayton } 134fbb76349SGreg Clayton 135fbb76349SGreg Clayton Error 136d3173f34SChaoren Lin PlatformPOSIX::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions) 137fbb76349SGreg Clayton { 138fbb76349SGreg Clayton if (m_remote_platform_sp) 139d3173f34SChaoren Lin return m_remote_platform_sp->SetFilePermissions(file_spec, file_permissions); 140fbb76349SGreg Clayton else 141d3173f34SChaoren Lin return Platform::SetFilePermissions(file_spec, file_permissions); 142e0f8f574SDaniel Malea } 143e0f8f574SDaniel Malea 144e0f8f574SDaniel Malea lldb::user_id_t 145e0f8f574SDaniel Malea PlatformPOSIX::OpenFile (const FileSpec& file_spec, 146e0f8f574SDaniel Malea uint32_t flags, 147fbb76349SGreg Clayton uint32_t mode, 148e0f8f574SDaniel Malea Error &error) 149e0f8f574SDaniel Malea { 150e0f8f574SDaniel Malea if (IsHost()) 151c00cf4a0SZachary Turner return FileCache::GetInstance().OpenFile(file_spec, flags, mode, error); 152fbb76349SGreg Clayton else if (m_remote_platform_sp) 153e0f8f574SDaniel Malea return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error); 154fbb76349SGreg Clayton else 155e0f8f574SDaniel Malea return Platform::OpenFile(file_spec, flags, mode, error); 156e0f8f574SDaniel Malea } 157e0f8f574SDaniel Malea 158e0f8f574SDaniel Malea bool 159e0f8f574SDaniel Malea PlatformPOSIX::CloseFile (lldb::user_id_t fd, Error &error) 160e0f8f574SDaniel Malea { 161e0f8f574SDaniel Malea if (IsHost()) 162c00cf4a0SZachary Turner return FileCache::GetInstance().CloseFile(fd, error); 163fbb76349SGreg Clayton else if (m_remote_platform_sp) 164e0f8f574SDaniel Malea return m_remote_platform_sp->CloseFile(fd, error); 165fbb76349SGreg Clayton else 166e0f8f574SDaniel Malea return Platform::CloseFile(fd, error); 167e0f8f574SDaniel Malea } 168e0f8f574SDaniel Malea 169e0f8f574SDaniel Malea uint64_t 170e0f8f574SDaniel Malea PlatformPOSIX::ReadFile (lldb::user_id_t fd, 171e0f8f574SDaniel Malea uint64_t offset, 172e0f8f574SDaniel Malea void *dst, 173e0f8f574SDaniel Malea uint64_t dst_len, 174e0f8f574SDaniel Malea Error &error) 175e0f8f574SDaniel Malea { 176e0f8f574SDaniel Malea if (IsHost()) 177c00cf4a0SZachary Turner return FileCache::GetInstance().ReadFile(fd, offset, dst, dst_len, error); 178fbb76349SGreg Clayton else if (m_remote_platform_sp) 179e0f8f574SDaniel Malea return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error); 180fbb76349SGreg Clayton else 181e0f8f574SDaniel Malea return Platform::ReadFile(fd, offset, dst, dst_len, error); 182e0f8f574SDaniel Malea } 183e0f8f574SDaniel Malea 184e0f8f574SDaniel Malea uint64_t 185e0f8f574SDaniel Malea PlatformPOSIX::WriteFile (lldb::user_id_t fd, 186e0f8f574SDaniel Malea uint64_t offset, 187e0f8f574SDaniel Malea const void* src, 188e0f8f574SDaniel Malea uint64_t src_len, 189e0f8f574SDaniel Malea Error &error) 190e0f8f574SDaniel Malea { 191e0f8f574SDaniel Malea if (IsHost()) 192c00cf4a0SZachary Turner return FileCache::GetInstance().WriteFile(fd, offset, src, src_len, error); 193fbb76349SGreg Clayton else if (m_remote_platform_sp) 194e0f8f574SDaniel Malea return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error); 195fbb76349SGreg Clayton else 196e0f8f574SDaniel Malea return Platform::WriteFile(fd, offset, src, src_len, error); 197e0f8f574SDaniel Malea } 198e0f8f574SDaniel Malea 199e0f8f574SDaniel Malea static uint32_t 200e0f8f574SDaniel Malea chown_file(Platform *platform, 201e0f8f574SDaniel Malea const char* path, 202e0f8f574SDaniel Malea uint32_t uid = UINT32_MAX, 203e0f8f574SDaniel Malea uint32_t gid = UINT32_MAX) 204e0f8f574SDaniel Malea { 205e0f8f574SDaniel Malea if (!platform || !path || *path == 0) 206e0f8f574SDaniel Malea return UINT32_MAX; 207e0f8f574SDaniel Malea 208e0f8f574SDaniel Malea if (uid == UINT32_MAX && gid == UINT32_MAX) 209e0f8f574SDaniel Malea return 0; // pretend I did chown correctly - actually I just didn't care 210e0f8f574SDaniel Malea 211e0f8f574SDaniel Malea StreamString command; 212e0f8f574SDaniel Malea command.PutCString("chown "); 213e0f8f574SDaniel Malea if (uid != UINT32_MAX) 214e0f8f574SDaniel Malea command.Printf("%d",uid); 215e0f8f574SDaniel Malea if (gid != UINT32_MAX) 216e0f8f574SDaniel Malea command.Printf(":%d",gid); 217e0f8f574SDaniel Malea command.Printf("%s",path); 218e0f8f574SDaniel Malea int status; 219e0f8f574SDaniel Malea platform->RunShellCommand(command.GetData(), 220e0f8f574SDaniel Malea NULL, 221e0f8f574SDaniel Malea &status, 222e0f8f574SDaniel Malea NULL, 223e0f8f574SDaniel Malea NULL, 224e0f8f574SDaniel Malea 10); 225e0f8f574SDaniel Malea return status; 226e0f8f574SDaniel Malea } 227e0f8f574SDaniel Malea 228e0f8f574SDaniel Malea lldb_private::Error 229e0f8f574SDaniel Malea PlatformPOSIX::PutFile (const lldb_private::FileSpec& source, 230e0f8f574SDaniel Malea const lldb_private::FileSpec& destination, 231e0f8f574SDaniel Malea uint32_t uid, 232e0f8f574SDaniel Malea uint32_t gid) 233e0f8f574SDaniel Malea { 234fbb76349SGreg Clayton Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 235fbb76349SGreg Clayton 236e0f8f574SDaniel Malea if (IsHost()) 237e0f8f574SDaniel Malea { 238e0f8f574SDaniel Malea if (FileSpec::Equal(source, destination, true)) 239e0f8f574SDaniel Malea return Error(); 240e0f8f574SDaniel Malea // cp src dst 241e0f8f574SDaniel Malea // chown uid:gid dst 242e0f8f574SDaniel Malea std::string src_path (source.GetPath()); 243e0f8f574SDaniel Malea if (src_path.empty()) 244e0f8f574SDaniel Malea return Error("unable to get file path for source"); 245e0f8f574SDaniel Malea std::string dst_path (destination.GetPath()); 246e0f8f574SDaniel Malea if (dst_path.empty()) 247e0f8f574SDaniel Malea return Error("unable to get file path for destination"); 248e0f8f574SDaniel Malea StreamString command; 249e0f8f574SDaniel Malea command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); 250e0f8f574SDaniel Malea int status; 251e0f8f574SDaniel Malea RunShellCommand(command.GetData(), 252e0f8f574SDaniel Malea NULL, 253e0f8f574SDaniel Malea &status, 254e0f8f574SDaniel Malea NULL, 255e0f8f574SDaniel Malea NULL, 256e0f8f574SDaniel Malea 10); 257e0f8f574SDaniel Malea if (status != 0) 258e0f8f574SDaniel Malea return Error("unable to perform copy"); 259e0f8f574SDaniel Malea if (uid == UINT32_MAX && gid == UINT32_MAX) 260e0f8f574SDaniel Malea return Error(); 261e0f8f574SDaniel Malea if (chown_file(this,dst_path.c_str(),uid,gid) != 0) 262e0f8f574SDaniel Malea return Error("unable to perform chown"); 263e0f8f574SDaniel Malea return Error(); 264e0f8f574SDaniel Malea } 265fbb76349SGreg Clayton else if (m_remote_platform_sp) 266e0f8f574SDaniel Malea { 267e0f8f574SDaniel Malea if (GetSupportsRSync()) 268e0f8f574SDaniel Malea { 269e0f8f574SDaniel Malea std::string src_path (source.GetPath()); 270e0f8f574SDaniel Malea if (src_path.empty()) 271e0f8f574SDaniel Malea return Error("unable to get file path for source"); 272e0f8f574SDaniel Malea std::string dst_path (destination.GetPath()); 273e0f8f574SDaniel Malea if (dst_path.empty()) 274e0f8f574SDaniel Malea return Error("unable to get file path for destination"); 275e0f8f574SDaniel Malea StreamString command; 276e0f8f574SDaniel Malea if (GetIgnoresRemoteHostname()) 277e0f8f574SDaniel Malea { 278e0f8f574SDaniel Malea if (!GetRSyncPrefix()) 279e0f8f574SDaniel Malea command.Printf("rsync %s %s %s", 280e0f8f574SDaniel Malea GetRSyncOpts(), 281e0f8f574SDaniel Malea src_path.c_str(), 282e0f8f574SDaniel Malea dst_path.c_str()); 283e0f8f574SDaniel Malea else 284e0f8f574SDaniel Malea command.Printf("rsync %s %s %s%s", 285e0f8f574SDaniel Malea GetRSyncOpts(), 286e0f8f574SDaniel Malea src_path.c_str(), 287e0f8f574SDaniel Malea GetRSyncPrefix(), 288e0f8f574SDaniel Malea dst_path.c_str()); 289e0f8f574SDaniel Malea } 290e0f8f574SDaniel Malea else 291e0f8f574SDaniel Malea command.Printf("rsync %s %s %s:%s", 292e0f8f574SDaniel Malea GetRSyncOpts(), 293e0f8f574SDaniel Malea src_path.c_str(), 294e0f8f574SDaniel Malea GetHostname(), 295e0f8f574SDaniel Malea dst_path.c_str()); 296e0f8f574SDaniel Malea if (log) 297e0f8f574SDaniel Malea log->Printf("[PutFile] Running command: %s\n", command.GetData()); 298e0f8f574SDaniel Malea int retcode; 299e0f8f574SDaniel Malea Host::RunShellCommand(command.GetData(), 300e0f8f574SDaniel Malea NULL, 301e0f8f574SDaniel Malea &retcode, 302e0f8f574SDaniel Malea NULL, 303e0f8f574SDaniel Malea NULL, 304e0f8f574SDaniel Malea 60); 305e0f8f574SDaniel Malea if (retcode == 0) 306e0f8f574SDaniel Malea { 307e0f8f574SDaniel Malea // Don't chown a local file for a remote system 308e0f8f574SDaniel Malea // if (chown_file(this,dst_path.c_str(),uid,gid) != 0) 309e0f8f574SDaniel Malea // return Error("unable to perform chown"); 310e0f8f574SDaniel Malea return Error(); 311e0f8f574SDaniel Malea } 312e0f8f574SDaniel Malea // if we are still here rsync has failed - let's try the slow way before giving up 313e0f8f574SDaniel Malea } 314e0f8f574SDaniel Malea } 315e0f8f574SDaniel Malea return Platform::PutFile(source,destination,uid,gid); 316e0f8f574SDaniel Malea } 317e0f8f574SDaniel Malea 318e0f8f574SDaniel Malea lldb::user_id_t 319e0f8f574SDaniel Malea PlatformPOSIX::GetFileSize (const FileSpec& file_spec) 320e0f8f574SDaniel Malea { 321e0f8f574SDaniel Malea if (IsHost()) 322c00cf4a0SZachary Turner return FileSystem::GetFileSize(file_spec); 323fbb76349SGreg Clayton else if (m_remote_platform_sp) 324e0f8f574SDaniel Malea return m_remote_platform_sp->GetFileSize(file_spec); 325fbb76349SGreg Clayton else 326e0f8f574SDaniel Malea return Platform::GetFileSize(file_spec); 327e0f8f574SDaniel Malea } 328e0f8f574SDaniel Malea 329fbb76349SGreg Clayton Error 330d3173f34SChaoren Lin PlatformPOSIX::CreateSymlink(const FileSpec &src, const FileSpec &dst) 331fbb76349SGreg Clayton { 332fbb76349SGreg Clayton if (IsHost()) 333c00cf4a0SZachary Turner return FileSystem::Symlink(src, dst); 334fbb76349SGreg Clayton else if (m_remote_platform_sp) 335fbb76349SGreg Clayton return m_remote_platform_sp->CreateSymlink(src, dst); 336fbb76349SGreg Clayton else 337fbb76349SGreg Clayton return Platform::CreateSymlink(src, dst); 338fbb76349SGreg Clayton } 339fbb76349SGreg Clayton 340e0f8f574SDaniel Malea bool 341e0f8f574SDaniel Malea PlatformPOSIX::GetFileExists (const FileSpec& file_spec) 342e0f8f574SDaniel Malea { 343e0f8f574SDaniel Malea if (IsHost()) 344e0f8f574SDaniel Malea return file_spec.Exists(); 345fbb76349SGreg Clayton else if (m_remote_platform_sp) 346e0f8f574SDaniel Malea return m_remote_platform_sp->GetFileExists(file_spec); 347fbb76349SGreg Clayton else 348e0f8f574SDaniel Malea return Platform::GetFileExists(file_spec); 349e0f8f574SDaniel Malea } 350e0f8f574SDaniel Malea 351fbb76349SGreg Clayton Error 352d3173f34SChaoren Lin PlatformPOSIX::Unlink(const FileSpec &file_spec) 353e0f8f574SDaniel Malea { 354e0f8f574SDaniel Malea if (IsHost()) 355d3173f34SChaoren Lin return FileSystem::Unlink(file_spec); 356fbb76349SGreg Clayton else if (m_remote_platform_sp) 357d3173f34SChaoren Lin return m_remote_platform_sp->Unlink(file_spec); 358fbb76349SGreg Clayton else 359d3173f34SChaoren Lin return Platform::Unlink(file_spec); 360e0f8f574SDaniel Malea } 361e0f8f574SDaniel Malea 362e0f8f574SDaniel Malea lldb_private::Error 363d3173f34SChaoren Lin PlatformPOSIX::GetFile(const lldb_private::FileSpec &source, // remote file path 364d3173f34SChaoren Lin const lldb_private::FileSpec &destination) // local file path 365e0f8f574SDaniel Malea { 366fbb76349SGreg Clayton Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 367fbb76349SGreg Clayton 368e0f8f574SDaniel Malea // Check the args, first. 369e0f8f574SDaniel Malea std::string src_path (source.GetPath()); 370e0f8f574SDaniel Malea if (src_path.empty()) 371e0f8f574SDaniel Malea return Error("unable to get file path for source"); 372e0f8f574SDaniel Malea std::string dst_path (destination.GetPath()); 373e0f8f574SDaniel Malea if (dst_path.empty()) 374e0f8f574SDaniel Malea return Error("unable to get file path for destination"); 375e0f8f574SDaniel Malea if (IsHost()) 376e0f8f574SDaniel Malea { 377e0f8f574SDaniel Malea if (FileSpec::Equal(source, destination, true)) 378e0f8f574SDaniel Malea return Error("local scenario->source and destination are the same file path: no operation performed"); 379e0f8f574SDaniel Malea // cp src dst 380e0f8f574SDaniel Malea StreamString cp_command; 381e0f8f574SDaniel Malea cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); 382e0f8f574SDaniel Malea int status; 383e0f8f574SDaniel Malea RunShellCommand(cp_command.GetData(), 384e0f8f574SDaniel Malea NULL, 385e0f8f574SDaniel Malea &status, 386e0f8f574SDaniel Malea NULL, 387e0f8f574SDaniel Malea NULL, 388e0f8f574SDaniel Malea 10); 389e0f8f574SDaniel Malea if (status != 0) 390e0f8f574SDaniel Malea return Error("unable to perform copy"); 391e0f8f574SDaniel Malea return Error(); 392e0f8f574SDaniel Malea } 393fbb76349SGreg Clayton else if (m_remote_platform_sp) 394e0f8f574SDaniel Malea { 395e0f8f574SDaniel Malea if (GetSupportsRSync()) 396e0f8f574SDaniel Malea { 397e0f8f574SDaniel Malea StreamString command; 398e0f8f574SDaniel Malea if (GetIgnoresRemoteHostname()) 399e0f8f574SDaniel Malea { 400e0f8f574SDaniel Malea if (!GetRSyncPrefix()) 401e0f8f574SDaniel Malea command.Printf("rsync %s %s %s", 402e0f8f574SDaniel Malea GetRSyncOpts(), 403e0f8f574SDaniel Malea src_path.c_str(), 404e0f8f574SDaniel Malea dst_path.c_str()); 405e0f8f574SDaniel Malea else 406e0f8f574SDaniel Malea command.Printf("rsync %s %s%s %s", 407e0f8f574SDaniel Malea GetRSyncOpts(), 408e0f8f574SDaniel Malea GetRSyncPrefix(), 409e0f8f574SDaniel Malea src_path.c_str(), 410e0f8f574SDaniel Malea dst_path.c_str()); 411e0f8f574SDaniel Malea } 412e0f8f574SDaniel Malea else 413e0f8f574SDaniel Malea command.Printf("rsync %s %s:%s %s", 414e0f8f574SDaniel Malea GetRSyncOpts(), 415e0f8f574SDaniel Malea m_remote_platform_sp->GetHostname(), 416e0f8f574SDaniel Malea src_path.c_str(), 417e0f8f574SDaniel Malea dst_path.c_str()); 418e0f8f574SDaniel Malea if (log) 419e0f8f574SDaniel Malea log->Printf("[GetFile] Running command: %s\n", command.GetData()); 420e0f8f574SDaniel Malea int retcode; 421e0f8f574SDaniel Malea Host::RunShellCommand(command.GetData(), 422e0f8f574SDaniel Malea NULL, 423e0f8f574SDaniel Malea &retcode, 424e0f8f574SDaniel Malea NULL, 425e0f8f574SDaniel Malea NULL, 426e0f8f574SDaniel Malea 60); 427e0f8f574SDaniel Malea if (retcode == 0) 428e0f8f574SDaniel Malea return Error(); 429e0f8f574SDaniel Malea // If we are here, rsync has failed - let's try the slow way before giving up 430e0f8f574SDaniel Malea } 431e0f8f574SDaniel Malea // open src and dst 432e0f8f574SDaniel Malea // read/write, read/write, read/write, ... 433e0f8f574SDaniel Malea // close src 434e0f8f574SDaniel Malea // close dst 435e0f8f574SDaniel Malea if (log) 436e0f8f574SDaniel Malea log->Printf("[GetFile] Using block by block transfer....\n"); 437e0f8f574SDaniel Malea Error error; 438e0f8f574SDaniel Malea user_id_t fd_src = OpenFile (source, 439e0f8f574SDaniel Malea File::eOpenOptionRead, 440fbb76349SGreg Clayton lldb::eFilePermissionsFileDefault, 441e0f8f574SDaniel Malea error); 442e0f8f574SDaniel Malea 443e0f8f574SDaniel Malea if (fd_src == UINT64_MAX) 444e0f8f574SDaniel Malea return Error("unable to open source file"); 445e0f8f574SDaniel Malea 446fbb76349SGreg Clayton uint32_t permissions = 0; 447d3173f34SChaoren Lin error = GetFilePermissions(source, permissions); 448e0f8f574SDaniel Malea 449e0f8f574SDaniel Malea if (permissions == 0) 450fbb76349SGreg Clayton permissions = lldb::eFilePermissionsFileDefault; 451e0f8f574SDaniel Malea 452c00cf4a0SZachary Turner user_id_t fd_dst = FileCache::GetInstance().OpenFile( 453c00cf4a0SZachary Turner destination, File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate, permissions, 454e0f8f574SDaniel Malea error); 455e0f8f574SDaniel Malea 456e0f8f574SDaniel Malea if (fd_dst == UINT64_MAX) 457e0f8f574SDaniel Malea { 458e0f8f574SDaniel Malea if (error.Success()) 459e0f8f574SDaniel Malea error.SetErrorString("unable to open destination file"); 460e0f8f574SDaniel Malea } 461e0f8f574SDaniel Malea 462e0f8f574SDaniel Malea if (error.Success()) 463e0f8f574SDaniel Malea { 464e0f8f574SDaniel Malea lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); 465e0f8f574SDaniel Malea uint64_t offset = 0; 466e0f8f574SDaniel Malea error.Clear(); 467e0f8f574SDaniel Malea while (error.Success()) 468e0f8f574SDaniel Malea { 469e0f8f574SDaniel Malea const uint64_t n_read = ReadFile (fd_src, 470e0f8f574SDaniel Malea offset, 471e0f8f574SDaniel Malea buffer_sp->GetBytes(), 472e0f8f574SDaniel Malea buffer_sp->GetByteSize(), 473e0f8f574SDaniel Malea error); 474e0f8f574SDaniel Malea if (error.Fail()) 475e0f8f574SDaniel Malea break; 476e0f8f574SDaniel Malea if (n_read == 0) 477e0f8f574SDaniel Malea break; 478c00cf4a0SZachary Turner if (FileCache::GetInstance().WriteFile(fd_dst, offset, buffer_sp->GetBytes(), n_read, error) != n_read) 479e0f8f574SDaniel Malea { 480e0f8f574SDaniel Malea if (!error.Fail()) 481e0f8f574SDaniel Malea error.SetErrorString("unable to write to destination file"); 482e0f8f574SDaniel Malea break; 483e0f8f574SDaniel Malea } 484e0f8f574SDaniel Malea offset += n_read; 485e0f8f574SDaniel Malea } 486e0f8f574SDaniel Malea } 487e0f8f574SDaniel Malea // Ignore the close error of src. 488e0f8f574SDaniel Malea if (fd_src != UINT64_MAX) 489e0f8f574SDaniel Malea CloseFile(fd_src, error); 490e0f8f574SDaniel Malea // And close the dst file descriptot. 491c00cf4a0SZachary Turner if (fd_dst != UINT64_MAX && !FileCache::GetInstance().CloseFile(fd_dst, error)) 492e0f8f574SDaniel Malea { 493e0f8f574SDaniel Malea if (!error.Fail()) 494e0f8f574SDaniel Malea error.SetErrorString("unable to close destination file"); 495e0f8f574SDaniel Malea 496e0f8f574SDaniel Malea } 497e0f8f574SDaniel Malea return error; 498e0f8f574SDaniel Malea } 499e0f8f574SDaniel Malea return Platform::GetFile(source,destination); 500e0f8f574SDaniel Malea } 501e0f8f574SDaniel Malea 502e0f8f574SDaniel Malea std::string 503e0f8f574SDaniel Malea PlatformPOSIX::GetPlatformSpecificConnectionInformation() 504e0f8f574SDaniel Malea { 505e0f8f574SDaniel Malea StreamString stream; 506e0f8f574SDaniel Malea if (GetSupportsRSync()) 507e0f8f574SDaniel Malea { 508e0f8f574SDaniel Malea stream.PutCString("rsync"); 509e0f8f574SDaniel Malea if ( (GetRSyncOpts() && *GetRSyncOpts()) || 510e0f8f574SDaniel Malea (GetRSyncPrefix() && *GetRSyncPrefix()) || 511e0f8f574SDaniel Malea GetIgnoresRemoteHostname()) 512e0f8f574SDaniel Malea { 513e0f8f574SDaniel Malea stream.Printf(", options: "); 514e0f8f574SDaniel Malea if (GetRSyncOpts() && *GetRSyncOpts()) 515e0f8f574SDaniel Malea stream.Printf("'%s' ",GetRSyncOpts()); 516e0f8f574SDaniel Malea stream.Printf(", prefix: "); 517e0f8f574SDaniel Malea if (GetRSyncPrefix() && *GetRSyncPrefix()) 518e0f8f574SDaniel Malea stream.Printf("'%s' ",GetRSyncPrefix()); 519e0f8f574SDaniel Malea if (GetIgnoresRemoteHostname()) 520e0f8f574SDaniel Malea stream.Printf("ignore remote-hostname "); 521e0f8f574SDaniel Malea } 522e0f8f574SDaniel Malea } 523e0f8f574SDaniel Malea if (GetSupportsSSH()) 524e0f8f574SDaniel Malea { 525e0f8f574SDaniel Malea stream.PutCString("ssh"); 526e0f8f574SDaniel Malea if (GetSSHOpts() && *GetSSHOpts()) 527e0f8f574SDaniel Malea stream.Printf(", options: '%s' ",GetSSHOpts()); 528e0f8f574SDaniel Malea } 529e0f8f574SDaniel Malea if (GetLocalCacheDirectory() && *GetLocalCacheDirectory()) 530e0f8f574SDaniel Malea stream.Printf("cache dir: %s",GetLocalCacheDirectory()); 531e0f8f574SDaniel Malea if (stream.GetSize()) 532e0f8f574SDaniel Malea return stream.GetData(); 533e0f8f574SDaniel Malea else 534e0f8f574SDaniel Malea return ""; 535e0f8f574SDaniel Malea } 536e0f8f574SDaniel Malea 537e0f8f574SDaniel Malea bool 538e0f8f574SDaniel Malea PlatformPOSIX::CalculateMD5 (const FileSpec& file_spec, 539e0f8f574SDaniel Malea uint64_t &low, 540e0f8f574SDaniel Malea uint64_t &high) 541e0f8f574SDaniel Malea { 542e0f8f574SDaniel Malea if (IsHost()) 543e0f8f574SDaniel Malea return Platform::CalculateMD5 (file_spec, low, high); 544e0f8f574SDaniel Malea if (m_remote_platform_sp) 545e0f8f574SDaniel Malea return m_remote_platform_sp->CalculateMD5(file_spec, low, high); 546e0f8f574SDaniel Malea return false; 547e0f8f574SDaniel Malea } 548fbb76349SGreg Clayton 54998d0a4b3SChaoren Lin const lldb::UnixSignalsSP & 55098d0a4b3SChaoren Lin PlatformPOSIX::GetRemoteUnixSignals() { 55198d0a4b3SChaoren Lin if (IsRemote() && m_remote_platform_sp) 55298d0a4b3SChaoren Lin return m_remote_platform_sp->GetRemoteUnixSignals(); 55398d0a4b3SChaoren Lin return Platform::GetRemoteUnixSignals(); 55498d0a4b3SChaoren Lin } 55598d0a4b3SChaoren Lin 55698d0a4b3SChaoren Lin 557d3173f34SChaoren Lin FileSpec 558fbb76349SGreg Clayton PlatformPOSIX::GetRemoteWorkingDirectory() 559fbb76349SGreg Clayton { 560fbb76349SGreg Clayton if (IsRemote() && m_remote_platform_sp) 561fbb76349SGreg Clayton return m_remote_platform_sp->GetRemoteWorkingDirectory(); 562fbb76349SGreg Clayton else 563fbb76349SGreg Clayton return Platform::GetRemoteWorkingDirectory(); 564fbb76349SGreg Clayton } 565fbb76349SGreg Clayton 566fbb76349SGreg Clayton bool 567d3173f34SChaoren Lin PlatformPOSIX::SetRemoteWorkingDirectory(const FileSpec &working_dir) 568fbb76349SGreg Clayton { 569fbb76349SGreg Clayton if (IsRemote() && m_remote_platform_sp) 570d3173f34SChaoren Lin return m_remote_platform_sp->SetRemoteWorkingDirectory(working_dir); 571fbb76349SGreg Clayton else 572d3173f34SChaoren Lin return Platform::SetRemoteWorkingDirectory(working_dir); 573fbb76349SGreg Clayton } 574fbb76349SGreg Clayton 575015d818bSTodd Fiala bool 576015d818bSTodd Fiala PlatformPOSIX::GetRemoteOSVersion () 577015d818bSTodd Fiala { 578015d818bSTodd Fiala if (m_remote_platform_sp) 579015d818bSTodd Fiala return m_remote_platform_sp->GetOSVersion (m_major_os_version, 580015d818bSTodd Fiala m_minor_os_version, 581015d818bSTodd Fiala m_update_os_version); 582015d818bSTodd Fiala return false; 583015d818bSTodd Fiala } 584015d818bSTodd Fiala 585015d818bSTodd Fiala bool 586015d818bSTodd Fiala PlatformPOSIX::GetRemoteOSBuildString (std::string &s) 587015d818bSTodd Fiala { 588015d818bSTodd Fiala if (m_remote_platform_sp) 589015d818bSTodd Fiala return m_remote_platform_sp->GetRemoteOSBuildString (s); 590015d818bSTodd Fiala s.clear(); 591015d818bSTodd Fiala return false; 592015d818bSTodd Fiala } 593015d818bSTodd Fiala 594e15fcaa2STodd Fiala size_t 595e15fcaa2STodd Fiala PlatformPOSIX::GetEnvironment (StringList &env) 596e15fcaa2STodd Fiala { 597e15fcaa2STodd Fiala if (IsRemote()) 598e15fcaa2STodd Fiala { 599e15fcaa2STodd Fiala if (m_remote_platform_sp) 600e15fcaa2STodd Fiala return m_remote_platform_sp->GetEnvironment(env); 601e15fcaa2STodd Fiala return 0; 602e15fcaa2STodd Fiala } 603e15fcaa2STodd Fiala return Host::GetEnvironment(env); 604e15fcaa2STodd Fiala } 605e15fcaa2STodd Fiala 606015d818bSTodd Fiala bool 607015d818bSTodd Fiala PlatformPOSIX::GetRemoteOSKernelDescription (std::string &s) 608015d818bSTodd Fiala { 609015d818bSTodd Fiala if (m_remote_platform_sp) 610015d818bSTodd Fiala return m_remote_platform_sp->GetRemoteOSKernelDescription (s); 611015d818bSTodd Fiala s.clear(); 612015d818bSTodd Fiala return false; 613015d818bSTodd Fiala } 614015d818bSTodd Fiala 615015d818bSTodd Fiala // Remote Platform subclasses need to override this function 616015d818bSTodd Fiala ArchSpec 617015d818bSTodd Fiala PlatformPOSIX::GetRemoteSystemArchitecture () 618015d818bSTodd Fiala { 619015d818bSTodd Fiala if (m_remote_platform_sp) 620015d818bSTodd Fiala return m_remote_platform_sp->GetRemoteSystemArchitecture (); 621015d818bSTodd Fiala return ArchSpec(); 622015d818bSTodd Fiala } 623015d818bSTodd Fiala 624015d818bSTodd Fiala const char * 625015d818bSTodd Fiala PlatformPOSIX::GetHostname () 626015d818bSTodd Fiala { 627015d818bSTodd Fiala if (IsHost()) 628015d818bSTodd Fiala return Platform::GetHostname(); 629015d818bSTodd Fiala 630015d818bSTodd Fiala if (m_remote_platform_sp) 631015d818bSTodd Fiala return m_remote_platform_sp->GetHostname (); 632015d818bSTodd Fiala return NULL; 633015d818bSTodd Fiala } 634015d818bSTodd Fiala 635015d818bSTodd Fiala const char * 636015d818bSTodd Fiala PlatformPOSIX::GetUserName (uint32_t uid) 637015d818bSTodd Fiala { 638015d818bSTodd Fiala // Check the cache in Platform in case we have already looked this uid up 639015d818bSTodd Fiala const char *user_name = Platform::GetUserName(uid); 640015d818bSTodd Fiala if (user_name) 641015d818bSTodd Fiala return user_name; 642015d818bSTodd Fiala 643015d818bSTodd Fiala if (IsRemote() && m_remote_platform_sp) 644015d818bSTodd Fiala return m_remote_platform_sp->GetUserName(uid); 645015d818bSTodd Fiala return NULL; 646015d818bSTodd Fiala } 647015d818bSTodd Fiala 648015d818bSTodd Fiala const char * 649015d818bSTodd Fiala PlatformPOSIX::GetGroupName (uint32_t gid) 650015d818bSTodd Fiala { 651015d818bSTodd Fiala const char *group_name = Platform::GetGroupName(gid); 652015d818bSTodd Fiala if (group_name) 653015d818bSTodd Fiala return group_name; 654015d818bSTodd Fiala 655015d818bSTodd Fiala if (IsRemote() && m_remote_platform_sp) 656015d818bSTodd Fiala return m_remote_platform_sp->GetGroupName(gid); 657015d818bSTodd Fiala return NULL; 658015d818bSTodd Fiala } 659015d818bSTodd Fiala 660015d818bSTodd Fiala Error 661015d818bSTodd Fiala PlatformPOSIX::ConnectRemote (Args& args) 662015d818bSTodd Fiala { 663015d818bSTodd Fiala Error error; 664015d818bSTodd Fiala if (IsHost()) 665015d818bSTodd Fiala { 666015d818bSTodd Fiala error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString()); 667015d818bSTodd Fiala } 668015d818bSTodd Fiala else 669015d818bSTodd Fiala { 670015d818bSTodd Fiala if (!m_remote_platform_sp) 671615eb7e6SGreg Clayton m_remote_platform_sp = Platform::Create (ConstString("remote-gdb-server"), error); 672015d818bSTodd Fiala 673015d818bSTodd Fiala if (m_remote_platform_sp && error.Success()) 674015d818bSTodd Fiala error = m_remote_platform_sp->ConnectRemote (args); 675015d818bSTodd Fiala else 676015d818bSTodd Fiala error.SetErrorString ("failed to create a 'remote-gdb-server' platform"); 677015d818bSTodd Fiala 678015d818bSTodd Fiala if (error.Fail()) 679015d818bSTodd Fiala m_remote_platform_sp.reset(); 680015d818bSTodd Fiala } 681015d818bSTodd Fiala 682015d818bSTodd Fiala if (error.Success() && m_remote_platform_sp) 683015d818bSTodd Fiala { 6840a66e2f1SEnrico Granata if (m_option_group_platform_rsync.get() && m_option_group_platform_ssh.get() && m_option_group_platform_caching.get()) 685015d818bSTodd Fiala { 6860a66e2f1SEnrico Granata if (m_option_group_platform_rsync->m_rsync) 687015d818bSTodd Fiala { 688015d818bSTodd Fiala SetSupportsRSync(true); 6890a66e2f1SEnrico Granata SetRSyncOpts(m_option_group_platform_rsync->m_rsync_opts.c_str()); 6900a66e2f1SEnrico Granata SetRSyncPrefix(m_option_group_platform_rsync->m_rsync_prefix.c_str()); 6910a66e2f1SEnrico Granata SetIgnoresRemoteHostname(m_option_group_platform_rsync->m_ignores_remote_hostname); 692015d818bSTodd Fiala } 6930a66e2f1SEnrico Granata if (m_option_group_platform_ssh->m_ssh) 694015d818bSTodd Fiala { 695015d818bSTodd Fiala SetSupportsSSH(true); 6960a66e2f1SEnrico Granata SetSSHOpts(m_option_group_platform_ssh->m_ssh_opts.c_str()); 697015d818bSTodd Fiala } 6980a66e2f1SEnrico Granata SetLocalCacheDirectory(m_option_group_platform_caching->m_cache_dir.c_str()); 699015d818bSTodd Fiala } 700015d818bSTodd Fiala } 701015d818bSTodd Fiala 702015d818bSTodd Fiala return error; 703015d818bSTodd Fiala } 704015d818bSTodd Fiala 705015d818bSTodd Fiala Error 706015d818bSTodd Fiala PlatformPOSIX::DisconnectRemote () 707015d818bSTodd Fiala { 708015d818bSTodd Fiala Error error; 709015d818bSTodd Fiala 710015d818bSTodd Fiala if (IsHost()) 711015d818bSTodd Fiala { 712015d818bSTodd Fiala error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString()); 713015d818bSTodd Fiala } 714015d818bSTodd Fiala else 715015d818bSTodd Fiala { 716015d818bSTodd Fiala if (m_remote_platform_sp) 717015d818bSTodd Fiala error = m_remote_platform_sp->DisconnectRemote (); 718015d818bSTodd Fiala else 719015d818bSTodd Fiala error.SetErrorString ("the platform is not currently connected"); 720015d818bSTodd Fiala } 721015d818bSTodd Fiala return error; 722015d818bSTodd Fiala } 723015d818bSTodd Fiala 724348fb385STodd Fiala Error 725348fb385STodd Fiala PlatformPOSIX::LaunchProcess (ProcessLaunchInfo &launch_info) 726348fb385STodd Fiala { 727348fb385STodd Fiala Error error; 728348fb385STodd Fiala 729348fb385STodd Fiala if (IsHost()) 730348fb385STodd Fiala { 731348fb385STodd Fiala error = Platform::LaunchProcess (launch_info); 732348fb385STodd Fiala } 733348fb385STodd Fiala else 734348fb385STodd Fiala { 735348fb385STodd Fiala if (m_remote_platform_sp) 736348fb385STodd Fiala error = m_remote_platform_sp->LaunchProcess (launch_info); 737348fb385STodd Fiala else 738348fb385STodd Fiala error.SetErrorString ("the platform is not currently connected"); 739348fb385STodd Fiala } 740348fb385STodd Fiala return error; 741348fb385STodd Fiala } 742348fb385STodd Fiala 74309daa881SOleksiy Vyalov lldb_private::Error 74409daa881SOleksiy Vyalov PlatformPOSIX::KillProcess (const lldb::pid_t pid) 74509daa881SOleksiy Vyalov { 74609daa881SOleksiy Vyalov if (IsHost()) 74709daa881SOleksiy Vyalov return Platform::KillProcess (pid); 74809daa881SOleksiy Vyalov 74909daa881SOleksiy Vyalov if (m_remote_platform_sp) 75009daa881SOleksiy Vyalov return m_remote_platform_sp->KillProcess (pid); 75109daa881SOleksiy Vyalov 75209daa881SOleksiy Vyalov return Error ("the platform is not currently connected"); 75309daa881SOleksiy Vyalov } 75409daa881SOleksiy Vyalov 755348fb385STodd Fiala lldb::ProcessSP 756348fb385STodd Fiala PlatformPOSIX::Attach (ProcessAttachInfo &attach_info, 757348fb385STodd Fiala Debugger &debugger, 758348fb385STodd Fiala Target *target, 759348fb385STodd Fiala Error &error) 760348fb385STodd Fiala { 761348fb385STodd Fiala lldb::ProcessSP process_sp; 762348fb385STodd Fiala Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 763348fb385STodd Fiala 764348fb385STodd Fiala if (IsHost()) 765348fb385STodd Fiala { 766348fb385STodd Fiala if (target == NULL) 767348fb385STodd Fiala { 768348fb385STodd Fiala TargetSP new_target_sp; 769348fb385STodd Fiala 770348fb385STodd Fiala error = debugger.GetTargetList().CreateTarget (debugger, 771348fb385STodd Fiala NULL, 772348fb385STodd Fiala NULL, 773348fb385STodd Fiala false, 774348fb385STodd Fiala NULL, 775348fb385STodd Fiala new_target_sp); 776348fb385STodd Fiala target = new_target_sp.get(); 777348fb385STodd Fiala if (log) 778348fb385STodd Fiala log->Printf ("PlatformPOSIX::%s created new target", __FUNCTION__); 779348fb385STodd Fiala } 780348fb385STodd Fiala else 781348fb385STodd Fiala { 782348fb385STodd Fiala error.Clear(); 783348fb385STodd Fiala if (log) 784348fb385STodd Fiala log->Printf ("PlatformPOSIX::%s target already existed, setting target", __FUNCTION__); 785348fb385STodd Fiala } 786348fb385STodd Fiala 787348fb385STodd Fiala if (target && error.Success()) 788348fb385STodd Fiala { 789348fb385STodd Fiala debugger.GetTargetList().SetSelectedTarget(target); 790348fb385STodd Fiala if (log) 791348fb385STodd Fiala { 792348fb385STodd Fiala ModuleSP exe_module_sp = target->GetExecutableModule (); 793129b839dSDavid Blaikie log->Printf("PlatformPOSIX::%s set selected target to %p %s", __FUNCTION__, (void *)target, 794348fb385STodd Fiala exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str() : "<null>"); 795348fb385STodd Fiala } 796348fb385STodd Fiala 797348fb385STodd Fiala 7988012cadbSGreg Clayton process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), attach_info.GetProcessPluginName(), NULL); 799348fb385STodd Fiala 800348fb385STodd Fiala if (process_sp) 801348fb385STodd Fiala { 802*583bbb1dSJim Ingham ListenerSP listener_sp = attach_info.GetHijackListener(); 803926af0cdSOleksiy Vyalov if (listener_sp == nullptr) 804926af0cdSOleksiy Vyalov { 805*583bbb1dSJim Ingham listener_sp = Listener::MakeListener("lldb.PlatformPOSIX.attach.hijack"); 806348fb385STodd Fiala attach_info.SetHijackListener(listener_sp); 807926af0cdSOleksiy Vyalov } 808*583bbb1dSJim Ingham process_sp->HijackProcessEvents(listener_sp); 809348fb385STodd Fiala error = process_sp->Attach (attach_info); 810348fb385STodd Fiala } 811348fb385STodd Fiala } 812348fb385STodd Fiala } 813348fb385STodd Fiala else 814348fb385STodd Fiala { 815348fb385STodd Fiala if (m_remote_platform_sp) 8168012cadbSGreg Clayton process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error); 817348fb385STodd Fiala else 818348fb385STodd Fiala error.SetErrorString ("the platform is not currently connected"); 819348fb385STodd Fiala } 820348fb385STodd Fiala return process_sp; 821348fb385STodd Fiala } 822348fb385STodd Fiala 823015d818bSTodd Fiala lldb::ProcessSP 824015d818bSTodd Fiala PlatformPOSIX::DebugProcess (ProcessLaunchInfo &launch_info, 825015d818bSTodd Fiala Debugger &debugger, 826015d818bSTodd Fiala Target *target, // Can be NULL, if NULL create a new target, else use existing one 827015d818bSTodd Fiala Error &error) 828015d818bSTodd Fiala { 829015d818bSTodd Fiala ProcessSP process_sp; 830015d818bSTodd Fiala 831015d818bSTodd Fiala if (IsHost()) 832015d818bSTodd Fiala { 833015d818bSTodd Fiala // We are going to hand this process off to debugserver which will be in charge of setting the exit status. 834015d818bSTodd Fiala // We still need to reap it from lldb but if we let the monitor thread also set the exit status, we set up a 835015d818bSTodd Fiala // race between debugserver & us for who will find out about the debugged process's death. 836015d818bSTodd Fiala launch_info.GetFlags().Set(eLaunchFlagDontSetExitStatus); 8378012cadbSGreg Clayton process_sp = Platform::DebugProcess (launch_info, debugger, target, error); 838015d818bSTodd Fiala } 839015d818bSTodd Fiala else 840015d818bSTodd Fiala { 841015d818bSTodd Fiala if (m_remote_platform_sp) 8428012cadbSGreg Clayton process_sp = m_remote_platform_sp->DebugProcess (launch_info, debugger, target, error); 843015d818bSTodd Fiala else 844015d818bSTodd Fiala error.SetErrorString ("the platform is not currently connected"); 845015d818bSTodd Fiala } 846015d818bSTodd Fiala return process_sp; 847015d818bSTodd Fiala 848015d818bSTodd Fiala } 849015d818bSTodd Fiala 8502094dbf4SJason Molenda void 8512094dbf4SJason Molenda PlatformPOSIX::CalculateTrapHandlerSymbolNames () 8522094dbf4SJason Molenda { 8532094dbf4SJason Molenda m_trap_handlers.push_back (ConstString ("_sigtramp")); 8542094dbf4SJason Molenda } 8553cb132a0STamas Berghammer 8563cb132a0STamas Berghammer Error 8573cb132a0STamas Berghammer PlatformPOSIX::EvaluateLibdlExpression(lldb_private::Process* process, 8583cb132a0STamas Berghammer const char* expr_cstr, 8593cb132a0STamas Berghammer const char* expr_prefix, 8603cb132a0STamas Berghammer lldb::ValueObjectSP& result_valobj_sp) 8613cb132a0STamas Berghammer { 8623cb132a0STamas Berghammer DynamicLoader *loader = process->GetDynamicLoader(); 8633cb132a0STamas Berghammer if (loader) 8643cb132a0STamas Berghammer { 8653cb132a0STamas Berghammer Error error = loader->CanLoadImage(); 8663cb132a0STamas Berghammer if (error.Fail()) 8673cb132a0STamas Berghammer return error; 8683cb132a0STamas Berghammer } 8693cb132a0STamas Berghammer 8703cb132a0STamas Berghammer ThreadSP thread_sp(process->GetThreadList().GetSelectedThread()); 8713cb132a0STamas Berghammer if (!thread_sp) 8723cb132a0STamas Berghammer return Error("Selected thread isn't valid"); 8733cb132a0STamas Berghammer 8743cb132a0STamas Berghammer StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0)); 8753cb132a0STamas Berghammer if (!frame_sp) 8763cb132a0STamas Berghammer return Error("Frame 0 isn't valid"); 8773cb132a0STamas Berghammer 8783cb132a0STamas Berghammer ExecutionContext exe_ctx; 8793cb132a0STamas Berghammer frame_sp->CalculateExecutionContext(exe_ctx); 8803cb132a0STamas Berghammer EvaluateExpressionOptions expr_options; 8813cb132a0STamas Berghammer expr_options.SetUnwindOnError(true); 8823cb132a0STamas Berghammer expr_options.SetIgnoreBreakpoints(true); 8833cb132a0STamas Berghammer expr_options.SetExecutionPolicy(eExecutionPolicyAlways); 8843cb132a0STamas Berghammer expr_options.SetLanguage(eLanguageTypeC_plus_plus); 8853cb132a0STamas Berghammer 8863cb132a0STamas Berghammer Error expr_error; 8873cb132a0STamas Berghammer UserExpression::Evaluate(exe_ctx, 8883cb132a0STamas Berghammer expr_options, 8893cb132a0STamas Berghammer expr_cstr, 8903cb132a0STamas Berghammer expr_prefix, 8913cb132a0STamas Berghammer result_valobj_sp, 8923cb132a0STamas Berghammer expr_error); 8933cb132a0STamas Berghammer if (result_valobj_sp->GetError().Fail()) 8943cb132a0STamas Berghammer return result_valobj_sp->GetError(); 8953cb132a0STamas Berghammer return Error(); 8963cb132a0STamas Berghammer } 8973cb132a0STamas Berghammer 8983cb132a0STamas Berghammer uint32_t 8994fbd67acSTamas Berghammer PlatformPOSIX::DoLoadImage(lldb_private::Process* process, 9004fbd67acSTamas Berghammer const lldb_private::FileSpec& remote_file, 9014fbd67acSTamas Berghammer lldb_private::Error& error) 9023cb132a0STamas Berghammer { 9033cb132a0STamas Berghammer char path[PATH_MAX]; 9044fbd67acSTamas Berghammer remote_file.GetPath(path, sizeof(path)); 9053cb132a0STamas Berghammer 9063cb132a0STamas Berghammer StreamString expr; 9073cb132a0STamas Berghammer expr.Printf(R"( 9083cb132a0STamas Berghammer struct __lldb_dlopen_result { void *image_ptr; const char *error_str; } the_result; 9093cb132a0STamas Berghammer the_result.image_ptr = dlopen ("%s", 2); 9103cb132a0STamas Berghammer if (the_result.image_ptr == (void *) 0x0) 9113cb132a0STamas Berghammer { 9123cb132a0STamas Berghammer the_result.error_str = dlerror(); 9133cb132a0STamas Berghammer } 9143cb132a0STamas Berghammer else 9153cb132a0STamas Berghammer { 9163cb132a0STamas Berghammer the_result.error_str = (const char *) 0x0; 9173cb132a0STamas Berghammer } 9183cb132a0STamas Berghammer the_result; 9193cb132a0STamas Berghammer )", 9203cb132a0STamas Berghammer path); 921fcdde63fSTamas Berghammer const char *prefix = GetLibdlFunctionDeclarations(); 9223cb132a0STamas Berghammer lldb::ValueObjectSP result_valobj_sp; 9233cb132a0STamas Berghammer error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp); 9243cb132a0STamas Berghammer if (error.Fail()) 9253cb132a0STamas Berghammer return LLDB_INVALID_IMAGE_TOKEN; 9263cb132a0STamas Berghammer 9273cb132a0STamas Berghammer error = result_valobj_sp->GetError(); 9283cb132a0STamas Berghammer if (error.Fail()) 9293cb132a0STamas Berghammer return LLDB_INVALID_IMAGE_TOKEN; 9303cb132a0STamas Berghammer 9313cb132a0STamas Berghammer Scalar scalar; 9323cb132a0STamas Berghammer ValueObjectSP image_ptr_sp = result_valobj_sp->GetChildAtIndex(0, true); 9333cb132a0STamas Berghammer if (!image_ptr_sp || !image_ptr_sp->ResolveValue(scalar)) 9343cb132a0STamas Berghammer { 9353cb132a0STamas Berghammer error.SetErrorStringWithFormat("unable to load '%s'", path); 9363cb132a0STamas Berghammer return LLDB_INVALID_IMAGE_TOKEN; 9373cb132a0STamas Berghammer } 9383cb132a0STamas Berghammer 9393cb132a0STamas Berghammer addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS); 9403cb132a0STamas Berghammer if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS) 9413cb132a0STamas Berghammer return process->AddImageToken(image_ptr); 9423cb132a0STamas Berghammer 9433cb132a0STamas Berghammer if (image_ptr == 0) 9443cb132a0STamas Berghammer { 9453cb132a0STamas Berghammer ValueObjectSP error_str_sp = result_valobj_sp->GetChildAtIndex(1, true); 9463cb132a0STamas Berghammer if (error_str_sp && error_str_sp->IsCStringContainer(true)) 9473cb132a0STamas Berghammer { 9483cb132a0STamas Berghammer DataBufferSP buffer_sp(new DataBufferHeap(10240,0)); 9493cb132a0STamas Berghammer size_t num_chars = error_str_sp->ReadPointedString (buffer_sp, error, 10240).first; 9503cb132a0STamas Berghammer if (error.Success() && num_chars > 0) 9513cb132a0STamas Berghammer error.SetErrorStringWithFormat("dlopen error: %s", buffer_sp->GetBytes()); 9523cb132a0STamas Berghammer else 9533cb132a0STamas Berghammer error.SetErrorStringWithFormat("dlopen failed for unknown reasons."); 9543cb132a0STamas Berghammer return LLDB_INVALID_IMAGE_TOKEN; 9553cb132a0STamas Berghammer } 9563cb132a0STamas Berghammer } 9573cb132a0STamas Berghammer error.SetErrorStringWithFormat("unable to load '%s'", path); 9583cb132a0STamas Berghammer return LLDB_INVALID_IMAGE_TOKEN; 9593cb132a0STamas Berghammer } 9603cb132a0STamas Berghammer 9613cb132a0STamas Berghammer Error 9623cb132a0STamas Berghammer PlatformPOSIX::UnloadImage (lldb_private::Process* process, uint32_t image_token) 9633cb132a0STamas Berghammer { 9643cb132a0STamas Berghammer const addr_t image_addr = process->GetImagePtrFromToken(image_token); 9653cb132a0STamas Berghammer if (image_addr == LLDB_INVALID_ADDRESS) 9663cb132a0STamas Berghammer return Error("Invalid image token"); 9673cb132a0STamas Berghammer 9683cb132a0STamas Berghammer StreamString expr; 9693cb132a0STamas Berghammer expr.Printf("dlclose((void *)0x%" PRIx64 ")", image_addr); 970fcdde63fSTamas Berghammer const char *prefix = GetLibdlFunctionDeclarations(); 9713cb132a0STamas Berghammer lldb::ValueObjectSP result_valobj_sp; 9723cb132a0STamas Berghammer Error error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp); 9733cb132a0STamas Berghammer if (error.Fail()) 9743cb132a0STamas Berghammer return error; 9753cb132a0STamas Berghammer 9763cb132a0STamas Berghammer if (result_valobj_sp->GetError().Fail()) 9773cb132a0STamas Berghammer return result_valobj_sp->GetError(); 9783cb132a0STamas Berghammer 9793cb132a0STamas Berghammer Scalar scalar; 9803cb132a0STamas Berghammer if (result_valobj_sp->ResolveValue(scalar)) 9813cb132a0STamas Berghammer { 9823cb132a0STamas Berghammer if (scalar.UInt(1)) 9833cb132a0STamas Berghammer return Error("expression failed: \"%s\"", expr.GetData()); 9843cb132a0STamas Berghammer process->ResetImageToken(image_token); 9853cb132a0STamas Berghammer } 9863cb132a0STamas Berghammer return Error(); 9873cb132a0STamas Berghammer } 988fcdde63fSTamas Berghammer 989ccd6cffbSTamas Berghammer lldb::ProcessSP 990ccd6cffbSTamas Berghammer PlatformPOSIX::ConnectProcess (const char* connect_url, 991ccd6cffbSTamas Berghammer const char* plugin_name, 992ccd6cffbSTamas Berghammer lldb_private::Debugger &debugger, 993ccd6cffbSTamas Berghammer lldb_private::Target *target, 994ccd6cffbSTamas Berghammer lldb_private::Error &error) 995ccd6cffbSTamas Berghammer { 996ccd6cffbSTamas Berghammer if (m_remote_platform_sp) 997ccd6cffbSTamas Berghammer return m_remote_platform_sp->ConnectProcess(connect_url, 998ccd6cffbSTamas Berghammer plugin_name, 999ccd6cffbSTamas Berghammer debugger, 1000ccd6cffbSTamas Berghammer target, 1001ccd6cffbSTamas Berghammer error); 1002ccd6cffbSTamas Berghammer 1003ccd6cffbSTamas Berghammer return Platform::ConnectProcess(connect_url, plugin_name, debugger, target, error); 1004ccd6cffbSTamas Berghammer } 1005ccd6cffbSTamas Berghammer 1006fcdde63fSTamas Berghammer const char* 1007fcdde63fSTamas Berghammer PlatformPOSIX::GetLibdlFunctionDeclarations() const 1008fcdde63fSTamas Berghammer { 1009fcdde63fSTamas Berghammer return R"( 1010fcdde63fSTamas Berghammer extern "C" void* dlopen(const char*, int); 1011fcdde63fSTamas Berghammer extern "C" void* dlsym(void*, const char*); 1012fcdde63fSTamas Berghammer extern "C" int dlclose(void*); 1013fcdde63fSTamas Berghammer extern "C" char* dlerror(void); 1014fcdde63fSTamas Berghammer )"; 1015fcdde63fSTamas Berghammer } 1016ccd6cffbSTamas Berghammer 1017ccd6cffbSTamas Berghammer size_t 1018ccd6cffbSTamas Berghammer PlatformPOSIX::ConnectToWaitingProcesses(Debugger& debugger, Error& error) 1019ccd6cffbSTamas Berghammer { 1020ccd6cffbSTamas Berghammer if (m_remote_platform_sp) 1021ccd6cffbSTamas Berghammer return m_remote_platform_sp->ConnectToWaitingProcesses(debugger, error); 1022ccd6cffbSTamas Berghammer return Platform::ConnectToWaitingProcesses(debugger, error); 1023ccd6cffbSTamas Berghammer } 1024