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