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" 22e0f8f574SDaniel Malea #include "lldb/Host/File.h" 23c00cf4a0SZachary Turner #include "lldb/Host/FileCache.h" 24e0f8f574SDaniel Malea #include "lldb/Host/FileSpec.h" 25c00cf4a0SZachary Turner #include "lldb/Host/FileSystem.h" 26e0f8f574SDaniel Malea #include "lldb/Host/Host.h" 27015d818bSTodd Fiala #include "lldb/Target/ProcessLaunchInfo.h" 28e0f8f574SDaniel Malea 29e0f8f574SDaniel Malea using namespace lldb; 30e0f8f574SDaniel Malea using namespace lldb_private; 31e0f8f574SDaniel Malea 32e0f8f574SDaniel Malea 33e0f8f574SDaniel Malea //------------------------------------------------------------------ 34e0f8f574SDaniel Malea /// Default Constructor 35e0f8f574SDaniel Malea //------------------------------------------------------------------ 36e0f8f574SDaniel Malea PlatformPOSIX::PlatformPOSIX (bool is_host) : 37e0f8f574SDaniel Malea Platform(is_host), // This is the local host platform 38e0f8f574SDaniel Malea m_remote_platform_sp () 39e0f8f574SDaniel Malea { 40e0f8f574SDaniel Malea } 41e0f8f574SDaniel Malea 42e0f8f574SDaniel Malea //------------------------------------------------------------------ 43e0f8f574SDaniel Malea /// Destructor. 44e0f8f574SDaniel Malea /// 45e0f8f574SDaniel Malea /// The destructor is virtual since this class is designed to be 46e0f8f574SDaniel Malea /// inherited from by the plug-in instance. 47e0f8f574SDaniel Malea //------------------------------------------------------------------ 48e0f8f574SDaniel Malea PlatformPOSIX::~PlatformPOSIX() 49e0f8f574SDaniel Malea { 50e0f8f574SDaniel Malea } 51e0f8f574SDaniel Malea 52e0f8f574SDaniel Malea lldb_private::OptionGroupOptions* 53e0f8f574SDaniel Malea PlatformPOSIX::GetConnectionOptions (lldb_private::CommandInterpreter& interpreter) 54e0f8f574SDaniel Malea { 55e0f8f574SDaniel Malea if (m_options.get() == NULL) 56e0f8f574SDaniel Malea { 57e0f8f574SDaniel Malea m_options.reset(new OptionGroupOptions(interpreter)); 58e0f8f574SDaniel Malea m_options->Append(new OptionGroupPlatformRSync()); 59e0f8f574SDaniel Malea m_options->Append(new OptionGroupPlatformSSH()); 60e0f8f574SDaniel Malea m_options->Append(new OptionGroupPlatformCaching()); 61e0f8f574SDaniel Malea } 62e0f8f574SDaniel Malea return m_options.get(); 63e0f8f574SDaniel Malea } 64e0f8f574SDaniel Malea 65015d818bSTodd Fiala bool 66015d818bSTodd Fiala PlatformPOSIX::IsConnected () const 67015d818bSTodd Fiala { 68015d818bSTodd Fiala if (IsHost()) 69015d818bSTodd Fiala return true; 70015d818bSTodd Fiala else if (m_remote_platform_sp) 71015d818bSTodd Fiala return m_remote_platform_sp->IsConnected(); 72015d818bSTodd Fiala return false; 73015d818bSTodd Fiala } 74015d818bSTodd Fiala 75e0f8f574SDaniel Malea lldb_private::Error 76e0f8f574SDaniel Malea PlatformPOSIX::RunShellCommand (const char *command, // Shouldn't be NULL 77e0f8f574SDaniel Malea const char *working_dir, // Pass NULL to use the current working directory 78e0f8f574SDaniel Malea int *status_ptr, // Pass NULL if you don't want the process exit status 79e0f8f574SDaniel Malea int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit 80e0f8f574SDaniel Malea std::string *command_output, // Pass NULL if you don't want the command output 81e0f8f574SDaniel Malea uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish 82e0f8f574SDaniel Malea { 83e0f8f574SDaniel Malea if (IsHost()) 84e0f8f574SDaniel Malea return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 85e0f8f574SDaniel Malea else 86e0f8f574SDaniel Malea { 87e0f8f574SDaniel Malea if (m_remote_platform_sp) 88e0f8f574SDaniel Malea return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 89e0f8f574SDaniel Malea else 90e0f8f574SDaniel Malea return Error("unable to run a remote command without a platform"); 91e0f8f574SDaniel Malea } 92e0f8f574SDaniel Malea } 93e0f8f574SDaniel Malea 94fbb76349SGreg Clayton Error 95fbb76349SGreg Clayton PlatformPOSIX::MakeDirectory (const char *path, uint32_t file_permissions) 96e0f8f574SDaniel Malea { 97fbb76349SGreg Clayton if (m_remote_platform_sp) 98fbb76349SGreg Clayton return m_remote_platform_sp->MakeDirectory(path, file_permissions); 99fbb76349SGreg Clayton else 100fbb76349SGreg Clayton return Platform::MakeDirectory(path ,file_permissions); 101e0f8f574SDaniel Malea } 102fbb76349SGreg Clayton 103fbb76349SGreg Clayton Error 104fbb76349SGreg Clayton PlatformPOSIX::GetFilePermissions (const char *path, uint32_t &file_permissions) 105fbb76349SGreg Clayton { 106fbb76349SGreg Clayton if (m_remote_platform_sp) 107fbb76349SGreg Clayton return m_remote_platform_sp->GetFilePermissions(path, file_permissions); 108fbb76349SGreg Clayton else 109fbb76349SGreg Clayton return Platform::GetFilePermissions(path ,file_permissions); 110fbb76349SGreg Clayton } 111fbb76349SGreg Clayton 112fbb76349SGreg Clayton Error 113fbb76349SGreg Clayton PlatformPOSIX::SetFilePermissions (const char *path, uint32_t file_permissions) 114fbb76349SGreg Clayton { 115fbb76349SGreg Clayton if (m_remote_platform_sp) 1161cfb98abSZachary Turner return m_remote_platform_sp->SetFilePermissions(path, file_permissions); 117fbb76349SGreg Clayton else 118fbb76349SGreg Clayton return Platform::SetFilePermissions(path ,file_permissions); 119e0f8f574SDaniel Malea } 120e0f8f574SDaniel Malea 121e0f8f574SDaniel Malea lldb::user_id_t 122e0f8f574SDaniel Malea PlatformPOSIX::OpenFile (const FileSpec& file_spec, 123e0f8f574SDaniel Malea uint32_t flags, 124fbb76349SGreg Clayton uint32_t mode, 125e0f8f574SDaniel Malea Error &error) 126e0f8f574SDaniel Malea { 127e0f8f574SDaniel Malea if (IsHost()) 128c00cf4a0SZachary Turner return FileCache::GetInstance().OpenFile(file_spec, flags, mode, error); 129fbb76349SGreg Clayton else if (m_remote_platform_sp) 130e0f8f574SDaniel Malea return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error); 131fbb76349SGreg Clayton else 132e0f8f574SDaniel Malea return Platform::OpenFile(file_spec, flags, mode, error); 133e0f8f574SDaniel Malea } 134e0f8f574SDaniel Malea 135e0f8f574SDaniel Malea bool 136e0f8f574SDaniel Malea PlatformPOSIX::CloseFile (lldb::user_id_t fd, Error &error) 137e0f8f574SDaniel Malea { 138e0f8f574SDaniel Malea if (IsHost()) 139c00cf4a0SZachary Turner return FileCache::GetInstance().CloseFile(fd, error); 140fbb76349SGreg Clayton else if (m_remote_platform_sp) 141e0f8f574SDaniel Malea return m_remote_platform_sp->CloseFile(fd, error); 142fbb76349SGreg Clayton else 143e0f8f574SDaniel Malea return Platform::CloseFile(fd, error); 144e0f8f574SDaniel Malea } 145e0f8f574SDaniel Malea 146e0f8f574SDaniel Malea uint64_t 147e0f8f574SDaniel Malea PlatformPOSIX::ReadFile (lldb::user_id_t fd, 148e0f8f574SDaniel Malea uint64_t offset, 149e0f8f574SDaniel Malea void *dst, 150e0f8f574SDaniel Malea uint64_t dst_len, 151e0f8f574SDaniel Malea Error &error) 152e0f8f574SDaniel Malea { 153e0f8f574SDaniel Malea if (IsHost()) 154c00cf4a0SZachary Turner return FileCache::GetInstance().ReadFile(fd, offset, dst, dst_len, error); 155fbb76349SGreg Clayton else if (m_remote_platform_sp) 156e0f8f574SDaniel Malea return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error); 157fbb76349SGreg Clayton else 158e0f8f574SDaniel Malea return Platform::ReadFile(fd, offset, dst, dst_len, error); 159e0f8f574SDaniel Malea } 160e0f8f574SDaniel Malea 161e0f8f574SDaniel Malea uint64_t 162e0f8f574SDaniel Malea PlatformPOSIX::WriteFile (lldb::user_id_t fd, 163e0f8f574SDaniel Malea uint64_t offset, 164e0f8f574SDaniel Malea const void* src, 165e0f8f574SDaniel Malea uint64_t src_len, 166e0f8f574SDaniel Malea Error &error) 167e0f8f574SDaniel Malea { 168e0f8f574SDaniel Malea if (IsHost()) 169c00cf4a0SZachary Turner return FileCache::GetInstance().WriteFile(fd, offset, src, src_len, error); 170fbb76349SGreg Clayton else if (m_remote_platform_sp) 171e0f8f574SDaniel Malea return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error); 172fbb76349SGreg Clayton else 173e0f8f574SDaniel Malea return Platform::WriteFile(fd, offset, src, src_len, error); 174e0f8f574SDaniel Malea } 175e0f8f574SDaniel Malea 176e0f8f574SDaniel Malea static uint32_t 177e0f8f574SDaniel Malea chown_file(Platform *platform, 178e0f8f574SDaniel Malea const char* path, 179e0f8f574SDaniel Malea uint32_t uid = UINT32_MAX, 180e0f8f574SDaniel Malea uint32_t gid = UINT32_MAX) 181e0f8f574SDaniel Malea { 182e0f8f574SDaniel Malea if (!platform || !path || *path == 0) 183e0f8f574SDaniel Malea return UINT32_MAX; 184e0f8f574SDaniel Malea 185e0f8f574SDaniel Malea if (uid == UINT32_MAX && gid == UINT32_MAX) 186e0f8f574SDaniel Malea return 0; // pretend I did chown correctly - actually I just didn't care 187e0f8f574SDaniel Malea 188e0f8f574SDaniel Malea StreamString command; 189e0f8f574SDaniel Malea command.PutCString("chown "); 190e0f8f574SDaniel Malea if (uid != UINT32_MAX) 191e0f8f574SDaniel Malea command.Printf("%d",uid); 192e0f8f574SDaniel Malea if (gid != UINT32_MAX) 193e0f8f574SDaniel Malea command.Printf(":%d",gid); 194e0f8f574SDaniel Malea command.Printf("%s",path); 195e0f8f574SDaniel Malea int status; 196e0f8f574SDaniel Malea platform->RunShellCommand(command.GetData(), 197e0f8f574SDaniel Malea NULL, 198e0f8f574SDaniel Malea &status, 199e0f8f574SDaniel Malea NULL, 200e0f8f574SDaniel Malea NULL, 201e0f8f574SDaniel Malea 10); 202e0f8f574SDaniel Malea return status; 203e0f8f574SDaniel Malea } 204e0f8f574SDaniel Malea 205e0f8f574SDaniel Malea lldb_private::Error 206e0f8f574SDaniel Malea PlatformPOSIX::PutFile (const lldb_private::FileSpec& source, 207e0f8f574SDaniel Malea const lldb_private::FileSpec& destination, 208e0f8f574SDaniel Malea uint32_t uid, 209e0f8f574SDaniel Malea uint32_t gid) 210e0f8f574SDaniel Malea { 211fbb76349SGreg Clayton Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 212fbb76349SGreg Clayton 213e0f8f574SDaniel Malea if (IsHost()) 214e0f8f574SDaniel Malea { 215e0f8f574SDaniel Malea if (FileSpec::Equal(source, destination, true)) 216e0f8f574SDaniel Malea return Error(); 217e0f8f574SDaniel Malea // cp src dst 218e0f8f574SDaniel Malea // chown uid:gid dst 219e0f8f574SDaniel Malea std::string src_path (source.GetPath()); 220e0f8f574SDaniel Malea if (src_path.empty()) 221e0f8f574SDaniel Malea return Error("unable to get file path for source"); 222e0f8f574SDaniel Malea std::string dst_path (destination.GetPath()); 223e0f8f574SDaniel Malea if (dst_path.empty()) 224e0f8f574SDaniel Malea return Error("unable to get file path for destination"); 225e0f8f574SDaniel Malea StreamString command; 226e0f8f574SDaniel Malea command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); 227e0f8f574SDaniel Malea int status; 228e0f8f574SDaniel Malea RunShellCommand(command.GetData(), 229e0f8f574SDaniel Malea NULL, 230e0f8f574SDaniel Malea &status, 231e0f8f574SDaniel Malea NULL, 232e0f8f574SDaniel Malea NULL, 233e0f8f574SDaniel Malea 10); 234e0f8f574SDaniel Malea if (status != 0) 235e0f8f574SDaniel Malea return Error("unable to perform copy"); 236e0f8f574SDaniel Malea if (uid == UINT32_MAX && gid == UINT32_MAX) 237e0f8f574SDaniel Malea return Error(); 238e0f8f574SDaniel Malea if (chown_file(this,dst_path.c_str(),uid,gid) != 0) 239e0f8f574SDaniel Malea return Error("unable to perform chown"); 240e0f8f574SDaniel Malea return Error(); 241e0f8f574SDaniel Malea } 242fbb76349SGreg Clayton else if (m_remote_platform_sp) 243e0f8f574SDaniel Malea { 244e0f8f574SDaniel Malea if (GetSupportsRSync()) 245e0f8f574SDaniel Malea { 246e0f8f574SDaniel Malea std::string src_path (source.GetPath()); 247e0f8f574SDaniel Malea if (src_path.empty()) 248e0f8f574SDaniel Malea return Error("unable to get file path for source"); 249e0f8f574SDaniel Malea std::string dst_path (destination.GetPath()); 250e0f8f574SDaniel Malea if (dst_path.empty()) 251e0f8f574SDaniel Malea return Error("unable to get file path for destination"); 252e0f8f574SDaniel Malea StreamString command; 253e0f8f574SDaniel Malea if (GetIgnoresRemoteHostname()) 254e0f8f574SDaniel Malea { 255e0f8f574SDaniel Malea if (!GetRSyncPrefix()) 256e0f8f574SDaniel Malea command.Printf("rsync %s %s %s", 257e0f8f574SDaniel Malea GetRSyncOpts(), 258e0f8f574SDaniel Malea src_path.c_str(), 259e0f8f574SDaniel Malea dst_path.c_str()); 260e0f8f574SDaniel Malea else 261e0f8f574SDaniel Malea command.Printf("rsync %s %s %s%s", 262e0f8f574SDaniel Malea GetRSyncOpts(), 263e0f8f574SDaniel Malea src_path.c_str(), 264e0f8f574SDaniel Malea GetRSyncPrefix(), 265e0f8f574SDaniel Malea dst_path.c_str()); 266e0f8f574SDaniel Malea } 267e0f8f574SDaniel Malea else 268e0f8f574SDaniel Malea command.Printf("rsync %s %s %s:%s", 269e0f8f574SDaniel Malea GetRSyncOpts(), 270e0f8f574SDaniel Malea src_path.c_str(), 271e0f8f574SDaniel Malea GetHostname(), 272e0f8f574SDaniel Malea dst_path.c_str()); 273e0f8f574SDaniel Malea if (log) 274e0f8f574SDaniel Malea log->Printf("[PutFile] Running command: %s\n", command.GetData()); 275e0f8f574SDaniel Malea int retcode; 276e0f8f574SDaniel Malea Host::RunShellCommand(command.GetData(), 277e0f8f574SDaniel Malea NULL, 278e0f8f574SDaniel Malea &retcode, 279e0f8f574SDaniel Malea NULL, 280e0f8f574SDaniel Malea NULL, 281e0f8f574SDaniel Malea 60); 282e0f8f574SDaniel Malea if (retcode == 0) 283e0f8f574SDaniel Malea { 284e0f8f574SDaniel Malea // Don't chown a local file for a remote system 285e0f8f574SDaniel Malea // if (chown_file(this,dst_path.c_str(),uid,gid) != 0) 286e0f8f574SDaniel Malea // return Error("unable to perform chown"); 287e0f8f574SDaniel Malea return Error(); 288e0f8f574SDaniel Malea } 289e0f8f574SDaniel Malea // if we are still here rsync has failed - let's try the slow way before giving up 290e0f8f574SDaniel Malea } 291fbb76349SGreg Clayton 292fbb76349SGreg Clayton if (log) 293fbb76349SGreg Clayton log->Printf ("PlatformPOSIX::PutFile(src='%s', dst='%s', uid=%u, gid=%u)", 294fbb76349SGreg Clayton source.GetPath().c_str(), 295fbb76349SGreg Clayton destination.GetPath().c_str(), 296fbb76349SGreg Clayton uid, 297fbb76349SGreg Clayton gid); // REMOVE THIS PRINTF PRIOR TO CHECKIN 298e0f8f574SDaniel Malea // open 299e0f8f574SDaniel Malea // read, write, read, write, ... 300e0f8f574SDaniel Malea // close 301e0f8f574SDaniel Malea // chown uid:gid dst 302e0f8f574SDaniel Malea if (log) 303e0f8f574SDaniel Malea log->Printf("[PutFile] Using block by block transfer....\n"); 304fbb76349SGreg Clayton 305fbb76349SGreg Clayton uint32_t source_open_options = File::eOpenOptionRead; 306fbb76349SGreg Clayton if (source.GetFileType() == FileSpec::eFileTypeSymbolicLink) 307fbb76349SGreg Clayton source_open_options |= File::eOpenoptionDontFollowSymlinks; 308fbb76349SGreg Clayton 309fbb76349SGreg Clayton File source_file(source, source_open_options, lldb::eFilePermissionsUserRW); 310fbb76349SGreg Clayton Error error; 311fbb76349SGreg Clayton uint32_t permissions = source_file.GetPermissions(error); 312fbb76349SGreg Clayton if (permissions == 0) 313fbb76349SGreg Clayton permissions = lldb::eFilePermissionsFileDefault; 314fbb76349SGreg Clayton 315e0f8f574SDaniel Malea if (!source_file.IsValid()) 316e0f8f574SDaniel Malea return Error("unable to open source file"); 317e0f8f574SDaniel Malea lldb::user_id_t dest_file = OpenFile (destination, 318e0f8f574SDaniel Malea File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate, 319fbb76349SGreg Clayton permissions, 320e0f8f574SDaniel Malea error); 321e0f8f574SDaniel Malea if (log) 322e0f8f574SDaniel Malea log->Printf ("dest_file = %" PRIu64 "\n", dest_file); 323e0f8f574SDaniel Malea if (error.Fail()) 324e0f8f574SDaniel Malea return error; 325e0f8f574SDaniel Malea if (dest_file == UINT64_MAX) 326e0f8f574SDaniel Malea return Error("unable to open target file"); 327e0f8f574SDaniel Malea lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); 328e0f8f574SDaniel Malea uint64_t offset = 0; 329e0f8f574SDaniel Malea while (error.Success()) 330e0f8f574SDaniel Malea { 331e0f8f574SDaniel Malea size_t bytes_read = buffer_sp->GetByteSize(); 332e0f8f574SDaniel Malea error = source_file.Read(buffer_sp->GetBytes(), bytes_read); 333e0f8f574SDaniel Malea if (bytes_read) 334e0f8f574SDaniel Malea { 33590d9a35fSGreg Clayton const uint64_t bytes_written = WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error); 33690d9a35fSGreg Clayton offset += bytes_written; 33790d9a35fSGreg Clayton if (bytes_written != bytes_read) 33890d9a35fSGreg Clayton { 33990d9a35fSGreg Clayton // We didn't write the correct numbe of bytes, so adjust 34090d9a35fSGreg Clayton // the file position in the source file we are reading from... 34190d9a35fSGreg Clayton source_file.SeekFromStart(offset); 34290d9a35fSGreg Clayton } 343e0f8f574SDaniel Malea } 344e0f8f574SDaniel Malea else 345e0f8f574SDaniel Malea break; 346e0f8f574SDaniel Malea } 347e0f8f574SDaniel Malea CloseFile(dest_file, error); 348e0f8f574SDaniel Malea if (uid == UINT32_MAX && gid == UINT32_MAX) 349e0f8f574SDaniel Malea return error; 350e0f8f574SDaniel Malea // This is remopve, don't chown a local file... 351e0f8f574SDaniel Malea // std::string dst_path (destination.GetPath()); 352e0f8f574SDaniel Malea // if (chown_file(this,dst_path.c_str(),uid,gid) != 0) 353e0f8f574SDaniel Malea // return Error("unable to perform chown"); 35490d9a35fSGreg Clayton 35590d9a35fSGreg Clayton 35690d9a35fSGreg Clayton uint64_t src_md5[2]; 35790d9a35fSGreg Clayton uint64_t dst_md5[2]; 35890d9a35fSGreg Clayton 35990d9a35fSGreg Clayton if (FileSystem::CalculateMD5 (source, src_md5[0], src_md5[1]) && CalculateMD5 (destination, dst_md5[0], dst_md5[1])) 36090d9a35fSGreg Clayton { 36190d9a35fSGreg Clayton if (src_md5[0] != dst_md5[0] || src_md5[1] != dst_md5[1]) 36290d9a35fSGreg Clayton { 36390d9a35fSGreg Clayton error.SetErrorString("md5 checksum of installed file doesn't match, installation failed"); 36490d9a35fSGreg Clayton } 36590d9a35fSGreg Clayton } 366e0f8f574SDaniel Malea return error; 367e0f8f574SDaniel Malea } 368e0f8f574SDaniel Malea return Platform::PutFile(source,destination,uid,gid); 369e0f8f574SDaniel Malea } 370e0f8f574SDaniel Malea 371e0f8f574SDaniel Malea lldb::user_id_t 372e0f8f574SDaniel Malea PlatformPOSIX::GetFileSize (const FileSpec& file_spec) 373e0f8f574SDaniel Malea { 374e0f8f574SDaniel Malea if (IsHost()) 375c00cf4a0SZachary Turner return FileSystem::GetFileSize(file_spec); 376fbb76349SGreg Clayton else if (m_remote_platform_sp) 377e0f8f574SDaniel Malea return m_remote_platform_sp->GetFileSize(file_spec); 378fbb76349SGreg Clayton else 379e0f8f574SDaniel Malea return Platform::GetFileSize(file_spec); 380e0f8f574SDaniel Malea } 381e0f8f574SDaniel Malea 382fbb76349SGreg Clayton Error 383fbb76349SGreg Clayton PlatformPOSIX::CreateSymlink(const char *src, const char *dst) 384fbb76349SGreg Clayton { 385fbb76349SGreg Clayton if (IsHost()) 386c00cf4a0SZachary Turner return FileSystem::Symlink(src, dst); 387fbb76349SGreg Clayton else if (m_remote_platform_sp) 388fbb76349SGreg Clayton return m_remote_platform_sp->CreateSymlink(src, dst); 389fbb76349SGreg Clayton else 390fbb76349SGreg Clayton return Platform::CreateSymlink(src, dst); 391fbb76349SGreg Clayton } 392fbb76349SGreg Clayton 393e0f8f574SDaniel Malea bool 394e0f8f574SDaniel Malea PlatformPOSIX::GetFileExists (const FileSpec& file_spec) 395e0f8f574SDaniel Malea { 396e0f8f574SDaniel Malea if (IsHost()) 397e0f8f574SDaniel Malea return file_spec.Exists(); 398fbb76349SGreg Clayton else if (m_remote_platform_sp) 399e0f8f574SDaniel Malea return m_remote_platform_sp->GetFileExists(file_spec); 400fbb76349SGreg Clayton else 401e0f8f574SDaniel Malea return Platform::GetFileExists(file_spec); 402e0f8f574SDaniel Malea } 403e0f8f574SDaniel Malea 404fbb76349SGreg Clayton Error 405fbb76349SGreg Clayton PlatformPOSIX::Unlink (const char *path) 406e0f8f574SDaniel Malea { 407e0f8f574SDaniel Malea if (IsHost()) 408c00cf4a0SZachary Turner return FileSystem::Unlink(path); 409fbb76349SGreg Clayton else if (m_remote_platform_sp) 410fbb76349SGreg Clayton return m_remote_platform_sp->Unlink(path); 411fbb76349SGreg Clayton else 412fbb76349SGreg Clayton return Platform::Unlink(path); 413e0f8f574SDaniel Malea } 414e0f8f574SDaniel Malea 415e0f8f574SDaniel Malea lldb_private::Error 416e0f8f574SDaniel Malea PlatformPOSIX::GetFile (const lldb_private::FileSpec& source /* remote file path */, 417e0f8f574SDaniel Malea const lldb_private::FileSpec& destination /* local file path */) 418e0f8f574SDaniel Malea { 419fbb76349SGreg Clayton Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 420fbb76349SGreg Clayton 421e0f8f574SDaniel Malea // Check the args, first. 422e0f8f574SDaniel Malea std::string src_path (source.GetPath()); 423e0f8f574SDaniel Malea if (src_path.empty()) 424e0f8f574SDaniel Malea return Error("unable to get file path for source"); 425e0f8f574SDaniel Malea std::string dst_path (destination.GetPath()); 426e0f8f574SDaniel Malea if (dst_path.empty()) 427e0f8f574SDaniel Malea return Error("unable to get file path for destination"); 428e0f8f574SDaniel Malea if (IsHost()) 429e0f8f574SDaniel Malea { 430e0f8f574SDaniel Malea if (FileSpec::Equal(source, destination, true)) 431e0f8f574SDaniel Malea return Error("local scenario->source and destination are the same file path: no operation performed"); 432e0f8f574SDaniel Malea // cp src dst 433e0f8f574SDaniel Malea StreamString cp_command; 434e0f8f574SDaniel Malea cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); 435e0f8f574SDaniel Malea int status; 436e0f8f574SDaniel Malea RunShellCommand(cp_command.GetData(), 437e0f8f574SDaniel Malea NULL, 438e0f8f574SDaniel Malea &status, 439e0f8f574SDaniel Malea NULL, 440e0f8f574SDaniel Malea NULL, 441e0f8f574SDaniel Malea 10); 442e0f8f574SDaniel Malea if (status != 0) 443e0f8f574SDaniel Malea return Error("unable to perform copy"); 444e0f8f574SDaniel Malea return Error(); 445e0f8f574SDaniel Malea } 446fbb76349SGreg Clayton else if (m_remote_platform_sp) 447e0f8f574SDaniel Malea { 448e0f8f574SDaniel Malea if (GetSupportsRSync()) 449e0f8f574SDaniel Malea { 450e0f8f574SDaniel Malea StreamString command; 451e0f8f574SDaniel Malea if (GetIgnoresRemoteHostname()) 452e0f8f574SDaniel Malea { 453e0f8f574SDaniel Malea if (!GetRSyncPrefix()) 454e0f8f574SDaniel Malea command.Printf("rsync %s %s %s", 455e0f8f574SDaniel Malea GetRSyncOpts(), 456e0f8f574SDaniel Malea src_path.c_str(), 457e0f8f574SDaniel Malea dst_path.c_str()); 458e0f8f574SDaniel Malea else 459e0f8f574SDaniel Malea command.Printf("rsync %s %s%s %s", 460e0f8f574SDaniel Malea GetRSyncOpts(), 461e0f8f574SDaniel Malea GetRSyncPrefix(), 462e0f8f574SDaniel Malea src_path.c_str(), 463e0f8f574SDaniel Malea dst_path.c_str()); 464e0f8f574SDaniel Malea } 465e0f8f574SDaniel Malea else 466e0f8f574SDaniel Malea command.Printf("rsync %s %s:%s %s", 467e0f8f574SDaniel Malea GetRSyncOpts(), 468e0f8f574SDaniel Malea m_remote_platform_sp->GetHostname(), 469e0f8f574SDaniel Malea src_path.c_str(), 470e0f8f574SDaniel Malea dst_path.c_str()); 471e0f8f574SDaniel Malea if (log) 472e0f8f574SDaniel Malea log->Printf("[GetFile] Running command: %s\n", command.GetData()); 473e0f8f574SDaniel Malea int retcode; 474e0f8f574SDaniel Malea Host::RunShellCommand(command.GetData(), 475e0f8f574SDaniel Malea NULL, 476e0f8f574SDaniel Malea &retcode, 477e0f8f574SDaniel Malea NULL, 478e0f8f574SDaniel Malea NULL, 479e0f8f574SDaniel Malea 60); 480e0f8f574SDaniel Malea if (retcode == 0) 481e0f8f574SDaniel Malea return Error(); 482e0f8f574SDaniel Malea // If we are here, rsync has failed - let's try the slow way before giving up 483e0f8f574SDaniel Malea } 484e0f8f574SDaniel Malea // open src and dst 485e0f8f574SDaniel Malea // read/write, read/write, read/write, ... 486e0f8f574SDaniel Malea // close src 487e0f8f574SDaniel Malea // close dst 488e0f8f574SDaniel Malea if (log) 489e0f8f574SDaniel Malea log->Printf("[GetFile] Using block by block transfer....\n"); 490e0f8f574SDaniel Malea Error error; 491e0f8f574SDaniel Malea user_id_t fd_src = OpenFile (source, 492e0f8f574SDaniel Malea File::eOpenOptionRead, 493fbb76349SGreg Clayton lldb::eFilePermissionsFileDefault, 494e0f8f574SDaniel Malea error); 495e0f8f574SDaniel Malea 496e0f8f574SDaniel Malea if (fd_src == UINT64_MAX) 497e0f8f574SDaniel Malea return Error("unable to open source file"); 498e0f8f574SDaniel Malea 499fbb76349SGreg Clayton uint32_t permissions = 0; 500fbb76349SGreg Clayton error = GetFilePermissions(source.GetPath().c_str(), permissions); 501e0f8f574SDaniel Malea 502e0f8f574SDaniel Malea if (permissions == 0) 503fbb76349SGreg Clayton permissions = lldb::eFilePermissionsFileDefault; 504e0f8f574SDaniel Malea 505c00cf4a0SZachary Turner user_id_t fd_dst = FileCache::GetInstance().OpenFile( 506c00cf4a0SZachary Turner destination, File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate, permissions, 507e0f8f574SDaniel Malea error); 508e0f8f574SDaniel Malea 509e0f8f574SDaniel Malea if (fd_dst == UINT64_MAX) 510e0f8f574SDaniel Malea { 511e0f8f574SDaniel Malea if (error.Success()) 512e0f8f574SDaniel Malea error.SetErrorString("unable to open destination file"); 513e0f8f574SDaniel Malea } 514e0f8f574SDaniel Malea 515e0f8f574SDaniel Malea if (error.Success()) 516e0f8f574SDaniel Malea { 517e0f8f574SDaniel Malea lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); 518e0f8f574SDaniel Malea uint64_t offset = 0; 519e0f8f574SDaniel Malea error.Clear(); 520e0f8f574SDaniel Malea while (error.Success()) 521e0f8f574SDaniel Malea { 522e0f8f574SDaniel Malea const uint64_t n_read = ReadFile (fd_src, 523e0f8f574SDaniel Malea offset, 524e0f8f574SDaniel Malea buffer_sp->GetBytes(), 525e0f8f574SDaniel Malea buffer_sp->GetByteSize(), 526e0f8f574SDaniel Malea error); 527e0f8f574SDaniel Malea if (error.Fail()) 528e0f8f574SDaniel Malea break; 529e0f8f574SDaniel Malea if (n_read == 0) 530e0f8f574SDaniel Malea break; 531c00cf4a0SZachary Turner if (FileCache::GetInstance().WriteFile(fd_dst, offset, buffer_sp->GetBytes(), n_read, error) != n_read) 532e0f8f574SDaniel Malea { 533e0f8f574SDaniel Malea if (!error.Fail()) 534e0f8f574SDaniel Malea error.SetErrorString("unable to write to destination file"); 535e0f8f574SDaniel Malea break; 536e0f8f574SDaniel Malea } 537e0f8f574SDaniel Malea offset += n_read; 538e0f8f574SDaniel Malea } 539e0f8f574SDaniel Malea } 540e0f8f574SDaniel Malea // Ignore the close error of src. 541e0f8f574SDaniel Malea if (fd_src != UINT64_MAX) 542e0f8f574SDaniel Malea CloseFile(fd_src, error); 543e0f8f574SDaniel Malea // And close the dst file descriptot. 544c00cf4a0SZachary Turner if (fd_dst != UINT64_MAX && !FileCache::GetInstance().CloseFile(fd_dst, error)) 545e0f8f574SDaniel Malea { 546e0f8f574SDaniel Malea if (!error.Fail()) 547e0f8f574SDaniel Malea error.SetErrorString("unable to close destination file"); 548e0f8f574SDaniel Malea 549e0f8f574SDaniel Malea } 550e0f8f574SDaniel Malea return error; 551e0f8f574SDaniel Malea } 552e0f8f574SDaniel Malea return Platform::GetFile(source,destination); 553e0f8f574SDaniel Malea } 554e0f8f574SDaniel Malea 555e0f8f574SDaniel Malea std::string 556e0f8f574SDaniel Malea PlatformPOSIX::GetPlatformSpecificConnectionInformation() 557e0f8f574SDaniel Malea { 558e0f8f574SDaniel Malea StreamString stream; 559e0f8f574SDaniel Malea if (GetSupportsRSync()) 560e0f8f574SDaniel Malea { 561e0f8f574SDaniel Malea stream.PutCString("rsync"); 562e0f8f574SDaniel Malea if ( (GetRSyncOpts() && *GetRSyncOpts()) || 563e0f8f574SDaniel Malea (GetRSyncPrefix() && *GetRSyncPrefix()) || 564e0f8f574SDaniel Malea GetIgnoresRemoteHostname()) 565e0f8f574SDaniel Malea { 566e0f8f574SDaniel Malea stream.Printf(", options: "); 567e0f8f574SDaniel Malea if (GetRSyncOpts() && *GetRSyncOpts()) 568e0f8f574SDaniel Malea stream.Printf("'%s' ",GetRSyncOpts()); 569e0f8f574SDaniel Malea stream.Printf(", prefix: "); 570e0f8f574SDaniel Malea if (GetRSyncPrefix() && *GetRSyncPrefix()) 571e0f8f574SDaniel Malea stream.Printf("'%s' ",GetRSyncPrefix()); 572e0f8f574SDaniel Malea if (GetIgnoresRemoteHostname()) 573e0f8f574SDaniel Malea stream.Printf("ignore remote-hostname "); 574e0f8f574SDaniel Malea } 575e0f8f574SDaniel Malea } 576e0f8f574SDaniel Malea if (GetSupportsSSH()) 577e0f8f574SDaniel Malea { 578e0f8f574SDaniel Malea stream.PutCString("ssh"); 579e0f8f574SDaniel Malea if (GetSSHOpts() && *GetSSHOpts()) 580e0f8f574SDaniel Malea stream.Printf(", options: '%s' ",GetSSHOpts()); 581e0f8f574SDaniel Malea } 582e0f8f574SDaniel Malea if (GetLocalCacheDirectory() && *GetLocalCacheDirectory()) 583e0f8f574SDaniel Malea stream.Printf("cache dir: %s",GetLocalCacheDirectory()); 584e0f8f574SDaniel Malea if (stream.GetSize()) 585e0f8f574SDaniel Malea return stream.GetData(); 586e0f8f574SDaniel Malea else 587e0f8f574SDaniel Malea return ""; 588e0f8f574SDaniel Malea } 589e0f8f574SDaniel Malea 590e0f8f574SDaniel Malea bool 591e0f8f574SDaniel Malea PlatformPOSIX::CalculateMD5 (const FileSpec& file_spec, 592e0f8f574SDaniel Malea uint64_t &low, 593e0f8f574SDaniel Malea uint64_t &high) 594e0f8f574SDaniel Malea { 595e0f8f574SDaniel Malea if (IsHost()) 596e0f8f574SDaniel Malea return Platform::CalculateMD5 (file_spec, low, high); 597e0f8f574SDaniel Malea if (m_remote_platform_sp) 598e0f8f574SDaniel Malea return m_remote_platform_sp->CalculateMD5(file_spec, low, high); 599e0f8f574SDaniel Malea return false; 600e0f8f574SDaniel Malea } 601fbb76349SGreg Clayton 602fbb76349SGreg Clayton lldb_private::ConstString 603fbb76349SGreg Clayton PlatformPOSIX::GetRemoteWorkingDirectory() 604fbb76349SGreg Clayton { 605fbb76349SGreg Clayton if (IsRemote() && m_remote_platform_sp) 606fbb76349SGreg Clayton return m_remote_platform_sp->GetRemoteWorkingDirectory(); 607fbb76349SGreg Clayton else 608fbb76349SGreg Clayton return Platform::GetRemoteWorkingDirectory(); 609fbb76349SGreg Clayton } 610fbb76349SGreg Clayton 611fbb76349SGreg Clayton bool 612fbb76349SGreg Clayton PlatformPOSIX::SetRemoteWorkingDirectory(const lldb_private::ConstString &path) 613fbb76349SGreg Clayton { 614fbb76349SGreg Clayton if (IsRemote() && m_remote_platform_sp) 615fbb76349SGreg Clayton return m_remote_platform_sp->SetRemoteWorkingDirectory(path); 616fbb76349SGreg Clayton else 617fbb76349SGreg Clayton return Platform::SetRemoteWorkingDirectory(path); 618fbb76349SGreg Clayton } 619fbb76349SGreg Clayton 620015d818bSTodd Fiala bool 621015d818bSTodd Fiala PlatformPOSIX::GetRemoteOSVersion () 622015d818bSTodd Fiala { 623015d818bSTodd Fiala if (m_remote_platform_sp) 624015d818bSTodd Fiala return m_remote_platform_sp->GetOSVersion (m_major_os_version, 625015d818bSTodd Fiala m_minor_os_version, 626015d818bSTodd Fiala m_update_os_version); 627015d818bSTodd Fiala return false; 628015d818bSTodd Fiala } 629015d818bSTodd Fiala 630015d818bSTodd Fiala bool 631015d818bSTodd Fiala PlatformPOSIX::GetRemoteOSBuildString (std::string &s) 632015d818bSTodd Fiala { 633015d818bSTodd Fiala if (m_remote_platform_sp) 634015d818bSTodd Fiala return m_remote_platform_sp->GetRemoteOSBuildString (s); 635015d818bSTodd Fiala s.clear(); 636015d818bSTodd Fiala return false; 637015d818bSTodd Fiala } 638015d818bSTodd Fiala 639e15fcaa2STodd Fiala size_t 640e15fcaa2STodd Fiala PlatformPOSIX::GetEnvironment (StringList &env) 641e15fcaa2STodd Fiala { 642e15fcaa2STodd Fiala if (IsRemote()) 643e15fcaa2STodd Fiala { 644e15fcaa2STodd Fiala if (m_remote_platform_sp) 645e15fcaa2STodd Fiala return m_remote_platform_sp->GetEnvironment(env); 646e15fcaa2STodd Fiala return 0; 647e15fcaa2STodd Fiala } 648e15fcaa2STodd Fiala return Host::GetEnvironment(env); 649e15fcaa2STodd Fiala } 650e15fcaa2STodd Fiala 651015d818bSTodd Fiala bool 652015d818bSTodd Fiala PlatformPOSIX::GetRemoteOSKernelDescription (std::string &s) 653015d818bSTodd Fiala { 654015d818bSTodd Fiala if (m_remote_platform_sp) 655015d818bSTodd Fiala return m_remote_platform_sp->GetRemoteOSKernelDescription (s); 656015d818bSTodd Fiala s.clear(); 657015d818bSTodd Fiala return false; 658015d818bSTodd Fiala } 659015d818bSTodd Fiala 660015d818bSTodd Fiala // Remote Platform subclasses need to override this function 661015d818bSTodd Fiala ArchSpec 662015d818bSTodd Fiala PlatformPOSIX::GetRemoteSystemArchitecture () 663015d818bSTodd Fiala { 664015d818bSTodd Fiala if (m_remote_platform_sp) 665015d818bSTodd Fiala return m_remote_platform_sp->GetRemoteSystemArchitecture (); 666015d818bSTodd Fiala return ArchSpec(); 667015d818bSTodd Fiala } 668015d818bSTodd Fiala 669015d818bSTodd Fiala const char * 670015d818bSTodd Fiala PlatformPOSIX::GetHostname () 671015d818bSTodd Fiala { 672015d818bSTodd Fiala if (IsHost()) 673015d818bSTodd Fiala return Platform::GetHostname(); 674015d818bSTodd Fiala 675015d818bSTodd Fiala if (m_remote_platform_sp) 676015d818bSTodd Fiala return m_remote_platform_sp->GetHostname (); 677015d818bSTodd Fiala return NULL; 678015d818bSTodd Fiala } 679015d818bSTodd Fiala 680015d818bSTodd Fiala const char * 681015d818bSTodd Fiala PlatformPOSIX::GetUserName (uint32_t uid) 682015d818bSTodd Fiala { 683015d818bSTodd Fiala // Check the cache in Platform in case we have already looked this uid up 684015d818bSTodd Fiala const char *user_name = Platform::GetUserName(uid); 685015d818bSTodd Fiala if (user_name) 686015d818bSTodd Fiala return user_name; 687015d818bSTodd Fiala 688015d818bSTodd Fiala if (IsRemote() && m_remote_platform_sp) 689015d818bSTodd Fiala return m_remote_platform_sp->GetUserName(uid); 690015d818bSTodd Fiala return NULL; 691015d818bSTodd Fiala } 692015d818bSTodd Fiala 693015d818bSTodd Fiala const char * 694015d818bSTodd Fiala PlatformPOSIX::GetGroupName (uint32_t gid) 695015d818bSTodd Fiala { 696015d818bSTodd Fiala const char *group_name = Platform::GetGroupName(gid); 697015d818bSTodd Fiala if (group_name) 698015d818bSTodd Fiala return group_name; 699015d818bSTodd Fiala 700015d818bSTodd Fiala if (IsRemote() && m_remote_platform_sp) 701015d818bSTodd Fiala return m_remote_platform_sp->GetGroupName(gid); 702015d818bSTodd Fiala return NULL; 703015d818bSTodd Fiala } 704015d818bSTodd Fiala 705015d818bSTodd Fiala Error 706015d818bSTodd Fiala PlatformPOSIX::ConnectRemote (Args& args) 707015d818bSTodd Fiala { 708015d818bSTodd Fiala Error error; 709015d818bSTodd Fiala if (IsHost()) 710015d818bSTodd Fiala { 711015d818bSTodd Fiala error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString()); 712015d818bSTodd Fiala } 713015d818bSTodd Fiala else 714015d818bSTodd Fiala { 715015d818bSTodd Fiala if (!m_remote_platform_sp) 716615eb7e6SGreg Clayton m_remote_platform_sp = Platform::Create (ConstString("remote-gdb-server"), error); 717015d818bSTodd Fiala 718015d818bSTodd Fiala if (m_remote_platform_sp && error.Success()) 719015d818bSTodd Fiala error = m_remote_platform_sp->ConnectRemote (args); 720015d818bSTodd Fiala else 721015d818bSTodd Fiala error.SetErrorString ("failed to create a 'remote-gdb-server' platform"); 722015d818bSTodd Fiala 723015d818bSTodd Fiala if (error.Fail()) 724015d818bSTodd Fiala m_remote_platform_sp.reset(); 725015d818bSTodd Fiala } 726015d818bSTodd Fiala 727015d818bSTodd Fiala if (error.Success() && m_remote_platform_sp) 728015d818bSTodd Fiala { 729015d818bSTodd Fiala if (m_options.get()) 730015d818bSTodd Fiala { 731015d818bSTodd Fiala OptionGroupOptions* options = m_options.get(); 732015d818bSTodd Fiala OptionGroupPlatformRSync* m_rsync_options = (OptionGroupPlatformRSync*)options->GetGroupWithOption('r'); 733015d818bSTodd Fiala OptionGroupPlatformSSH* m_ssh_options = (OptionGroupPlatformSSH*)options->GetGroupWithOption('s'); 734015d818bSTodd Fiala OptionGroupPlatformCaching* m_cache_options = (OptionGroupPlatformCaching*)options->GetGroupWithOption('c'); 735015d818bSTodd Fiala 736015d818bSTodd Fiala if (m_rsync_options->m_rsync) 737015d818bSTodd Fiala { 738015d818bSTodd Fiala SetSupportsRSync(true); 739015d818bSTodd Fiala SetRSyncOpts(m_rsync_options->m_rsync_opts.c_str()); 740015d818bSTodd Fiala SetRSyncPrefix(m_rsync_options->m_rsync_prefix.c_str()); 741015d818bSTodd Fiala SetIgnoresRemoteHostname(m_rsync_options->m_ignores_remote_hostname); 742015d818bSTodd Fiala } 743015d818bSTodd Fiala if (m_ssh_options->m_ssh) 744015d818bSTodd Fiala { 745015d818bSTodd Fiala SetSupportsSSH(true); 746015d818bSTodd Fiala SetSSHOpts(m_ssh_options->m_ssh_opts.c_str()); 747015d818bSTodd Fiala } 748015d818bSTodd Fiala SetLocalCacheDirectory(m_cache_options->m_cache_dir.c_str()); 749015d818bSTodd Fiala } 750015d818bSTodd Fiala } 751015d818bSTodd Fiala 752015d818bSTodd Fiala return error; 753015d818bSTodd Fiala } 754015d818bSTodd Fiala 755015d818bSTodd Fiala Error 756015d818bSTodd Fiala PlatformPOSIX::DisconnectRemote () 757015d818bSTodd Fiala { 758015d818bSTodd Fiala Error error; 759015d818bSTodd Fiala 760015d818bSTodd Fiala if (IsHost()) 761015d818bSTodd Fiala { 762015d818bSTodd Fiala error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString()); 763015d818bSTodd Fiala } 764015d818bSTodd Fiala else 765015d818bSTodd Fiala { 766015d818bSTodd Fiala if (m_remote_platform_sp) 767015d818bSTodd Fiala error = m_remote_platform_sp->DisconnectRemote (); 768015d818bSTodd Fiala else 769015d818bSTodd Fiala error.SetErrorString ("the platform is not currently connected"); 770015d818bSTodd Fiala } 771015d818bSTodd Fiala return error; 772015d818bSTodd Fiala } 773015d818bSTodd Fiala 774348fb385STodd Fiala Error 775348fb385STodd Fiala PlatformPOSIX::LaunchProcess (ProcessLaunchInfo &launch_info) 776348fb385STodd Fiala { 777348fb385STodd Fiala Error error; 778348fb385STodd Fiala 779348fb385STodd Fiala if (IsHost()) 780348fb385STodd Fiala { 781348fb385STodd Fiala error = Platform::LaunchProcess (launch_info); 782348fb385STodd Fiala } 783348fb385STodd Fiala else 784348fb385STodd Fiala { 785348fb385STodd Fiala if (m_remote_platform_sp) 786348fb385STodd Fiala error = m_remote_platform_sp->LaunchProcess (launch_info); 787348fb385STodd Fiala else 788348fb385STodd Fiala error.SetErrorString ("the platform is not currently connected"); 789348fb385STodd Fiala } 790348fb385STodd Fiala return error; 791348fb385STodd Fiala } 792348fb385STodd Fiala 793348fb385STodd Fiala lldb::ProcessSP 794348fb385STodd Fiala PlatformPOSIX::Attach (ProcessAttachInfo &attach_info, 795348fb385STodd Fiala Debugger &debugger, 796348fb385STodd Fiala Target *target, 797348fb385STodd Fiala Error &error) 798348fb385STodd Fiala { 799348fb385STodd Fiala lldb::ProcessSP process_sp; 800348fb385STodd Fiala Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 801348fb385STodd Fiala 802348fb385STodd Fiala if (IsHost()) 803348fb385STodd Fiala { 804348fb385STodd Fiala if (target == NULL) 805348fb385STodd Fiala { 806348fb385STodd Fiala TargetSP new_target_sp; 807348fb385STodd Fiala 808348fb385STodd Fiala error = debugger.GetTargetList().CreateTarget (debugger, 809348fb385STodd Fiala NULL, 810348fb385STodd Fiala NULL, 811348fb385STodd Fiala false, 812348fb385STodd Fiala NULL, 813348fb385STodd Fiala new_target_sp); 814348fb385STodd Fiala target = new_target_sp.get(); 815348fb385STodd Fiala if (log) 816348fb385STodd Fiala log->Printf ("PlatformPOSIX::%s created new target", __FUNCTION__); 817348fb385STodd Fiala } 818348fb385STodd Fiala else 819348fb385STodd Fiala { 820348fb385STodd Fiala error.Clear(); 821348fb385STodd Fiala if (log) 822348fb385STodd Fiala log->Printf ("PlatformPOSIX::%s target already existed, setting target", __FUNCTION__); 823348fb385STodd Fiala } 824348fb385STodd Fiala 825348fb385STodd Fiala if (target && error.Success()) 826348fb385STodd Fiala { 827348fb385STodd Fiala debugger.GetTargetList().SetSelectedTarget(target); 828348fb385STodd Fiala if (log) 829348fb385STodd Fiala { 830348fb385STodd Fiala ModuleSP exe_module_sp = target->GetExecutableModule (); 831348fb385STodd Fiala log->Printf ("PlatformPOSIX::%s set selected target to %p %s", __FUNCTION__, 832348fb385STodd Fiala target, 833348fb385STodd Fiala exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str () : "<null>" ); 834348fb385STodd Fiala } 835348fb385STodd Fiala 836348fb385STodd Fiala 837*8012cadbSGreg Clayton process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), attach_info.GetProcessPluginName(), NULL); 838348fb385STodd Fiala 839348fb385STodd Fiala if (process_sp) 840348fb385STodd Fiala { 841348fb385STodd Fiala // Set UnixSignals appropriately. 842348fb385STodd Fiala process_sp->SetUnixSignals (Host::GetUnixSignals ()); 843348fb385STodd Fiala 844348fb385STodd Fiala ListenerSP listener_sp (new Listener("lldb.PlatformPOSIX.attach.hijack")); 845348fb385STodd Fiala attach_info.SetHijackListener(listener_sp); 846348fb385STodd Fiala process_sp->HijackProcessEvents(listener_sp.get()); 847348fb385STodd Fiala error = process_sp->Attach (attach_info); 848348fb385STodd Fiala } 849348fb385STodd Fiala } 850348fb385STodd Fiala } 851348fb385STodd Fiala else 852348fb385STodd Fiala { 853348fb385STodd Fiala if (m_remote_platform_sp) 854*8012cadbSGreg Clayton process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error); 855348fb385STodd Fiala else 856348fb385STodd Fiala error.SetErrorString ("the platform is not currently connected"); 857348fb385STodd Fiala } 858348fb385STodd Fiala return process_sp; 859348fb385STodd Fiala } 860348fb385STodd Fiala 861015d818bSTodd Fiala lldb::ProcessSP 862015d818bSTodd Fiala PlatformPOSIX::DebugProcess (ProcessLaunchInfo &launch_info, 863015d818bSTodd Fiala Debugger &debugger, 864015d818bSTodd Fiala Target *target, // Can be NULL, if NULL create a new target, else use existing one 865015d818bSTodd Fiala Error &error) 866015d818bSTodd Fiala { 867015d818bSTodd Fiala ProcessSP process_sp; 868015d818bSTodd Fiala 869015d818bSTodd Fiala if (IsHost()) 870015d818bSTodd Fiala { 871015d818bSTodd Fiala // We are going to hand this process off to debugserver which will be in charge of setting the exit status. 872015d818bSTodd 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 873015d818bSTodd Fiala // race between debugserver & us for who will find out about the debugged process's death. 874015d818bSTodd Fiala launch_info.GetFlags().Set(eLaunchFlagDontSetExitStatus); 875*8012cadbSGreg Clayton process_sp = Platform::DebugProcess (launch_info, debugger, target, error); 876015d818bSTodd Fiala } 877015d818bSTodd Fiala else 878015d818bSTodd Fiala { 879015d818bSTodd Fiala if (m_remote_platform_sp) 880*8012cadbSGreg Clayton process_sp = m_remote_platform_sp->DebugProcess (launch_info, debugger, target, error); 881015d818bSTodd Fiala else 882015d818bSTodd Fiala error.SetErrorString ("the platform is not currently connected"); 883015d818bSTodd Fiala } 884015d818bSTodd Fiala return process_sp; 885015d818bSTodd Fiala 886015d818bSTodd Fiala } 887015d818bSTodd Fiala 8882094dbf4SJason Molenda void 8892094dbf4SJason Molenda PlatformPOSIX::CalculateTrapHandlerSymbolNames () 8902094dbf4SJason Molenda { 8912094dbf4SJason Molenda m_trap_handlers.push_back (ConstString ("_sigtramp")); 8922094dbf4SJason Molenda } 893