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" 18e0f8f574SDaniel Malea #include "lldb/Core/Log.h" 19e0f8f574SDaniel Malea #include "lldb/Core/StreamString.h" 20e0f8f574SDaniel Malea #include "lldb/Host/File.h" 21*c00cf4a0SZachary Turner #include "lldb/Host/FileCache.h" 22e0f8f574SDaniel Malea #include "lldb/Host/FileSpec.h" 23*c00cf4a0SZachary Turner #include "lldb/Host/FileSystem.h" 24e0f8f574SDaniel Malea #include "lldb/Host/Host.h" 25015d818bSTodd Fiala #include "lldb/Target/ProcessLaunchInfo.h" 26e0f8f574SDaniel Malea 27e0f8f574SDaniel Malea using namespace lldb; 28e0f8f574SDaniel Malea using namespace lldb_private; 29e0f8f574SDaniel Malea 30e0f8f574SDaniel Malea 31e0f8f574SDaniel Malea //------------------------------------------------------------------ 32e0f8f574SDaniel Malea /// Default Constructor 33e0f8f574SDaniel Malea //------------------------------------------------------------------ 34e0f8f574SDaniel Malea PlatformPOSIX::PlatformPOSIX (bool is_host) : 35e0f8f574SDaniel Malea Platform(is_host), // This is the local host platform 36e0f8f574SDaniel Malea m_remote_platform_sp () 37e0f8f574SDaniel Malea { 38e0f8f574SDaniel Malea } 39e0f8f574SDaniel Malea 40e0f8f574SDaniel Malea //------------------------------------------------------------------ 41e0f8f574SDaniel Malea /// Destructor. 42e0f8f574SDaniel Malea /// 43e0f8f574SDaniel Malea /// The destructor is virtual since this class is designed to be 44e0f8f574SDaniel Malea /// inherited from by the plug-in instance. 45e0f8f574SDaniel Malea //------------------------------------------------------------------ 46e0f8f574SDaniel Malea PlatformPOSIX::~PlatformPOSIX() 47e0f8f574SDaniel Malea { 48e0f8f574SDaniel Malea } 49e0f8f574SDaniel Malea 50e0f8f574SDaniel Malea lldb_private::OptionGroupOptions* 51e0f8f574SDaniel Malea PlatformPOSIX::GetConnectionOptions (lldb_private::CommandInterpreter& interpreter) 52e0f8f574SDaniel Malea { 53e0f8f574SDaniel Malea if (m_options.get() == NULL) 54e0f8f574SDaniel Malea { 55e0f8f574SDaniel Malea m_options.reset(new OptionGroupOptions(interpreter)); 56e0f8f574SDaniel Malea m_options->Append(new OptionGroupPlatformRSync()); 57e0f8f574SDaniel Malea m_options->Append(new OptionGroupPlatformSSH()); 58e0f8f574SDaniel Malea m_options->Append(new OptionGroupPlatformCaching()); 59e0f8f574SDaniel Malea } 60e0f8f574SDaniel Malea return m_options.get(); 61e0f8f574SDaniel Malea } 62e0f8f574SDaniel Malea 63015d818bSTodd Fiala bool 64015d818bSTodd Fiala PlatformPOSIX::IsConnected () const 65015d818bSTodd Fiala { 66015d818bSTodd Fiala if (IsHost()) 67015d818bSTodd Fiala return true; 68015d818bSTodd Fiala else if (m_remote_platform_sp) 69015d818bSTodd Fiala return m_remote_platform_sp->IsConnected(); 70015d818bSTodd Fiala return false; 71015d818bSTodd Fiala } 72015d818bSTodd Fiala 73e0f8f574SDaniel Malea lldb_private::Error 74e0f8f574SDaniel Malea PlatformPOSIX::RunShellCommand (const char *command, // Shouldn't be NULL 75e0f8f574SDaniel Malea const char *working_dir, // Pass NULL to use the current working directory 76e0f8f574SDaniel Malea int *status_ptr, // Pass NULL if you don't want the process exit status 77e0f8f574SDaniel Malea int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit 78e0f8f574SDaniel Malea std::string *command_output, // Pass NULL if you don't want the command output 79e0f8f574SDaniel Malea uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish 80e0f8f574SDaniel Malea { 81e0f8f574SDaniel Malea if (IsHost()) 82e0f8f574SDaniel Malea return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 83e0f8f574SDaniel Malea else 84e0f8f574SDaniel Malea { 85e0f8f574SDaniel Malea if (m_remote_platform_sp) 86e0f8f574SDaniel Malea return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 87e0f8f574SDaniel Malea else 88e0f8f574SDaniel Malea return Error("unable to run a remote command without a platform"); 89e0f8f574SDaniel Malea } 90e0f8f574SDaniel Malea } 91e0f8f574SDaniel Malea 92fbb76349SGreg Clayton Error 93fbb76349SGreg Clayton PlatformPOSIX::MakeDirectory (const char *path, uint32_t file_permissions) 94e0f8f574SDaniel Malea { 95fbb76349SGreg Clayton if (m_remote_platform_sp) 96fbb76349SGreg Clayton return m_remote_platform_sp->MakeDirectory(path, file_permissions); 97fbb76349SGreg Clayton else 98fbb76349SGreg Clayton return Platform::MakeDirectory(path ,file_permissions); 99e0f8f574SDaniel Malea } 100fbb76349SGreg Clayton 101fbb76349SGreg Clayton Error 102fbb76349SGreg Clayton PlatformPOSIX::GetFilePermissions (const char *path, uint32_t &file_permissions) 103fbb76349SGreg Clayton { 104fbb76349SGreg Clayton if (m_remote_platform_sp) 105fbb76349SGreg Clayton return m_remote_platform_sp->GetFilePermissions(path, file_permissions); 106fbb76349SGreg Clayton else 107fbb76349SGreg Clayton return Platform::GetFilePermissions(path ,file_permissions); 108fbb76349SGreg Clayton } 109fbb76349SGreg Clayton 110fbb76349SGreg Clayton Error 111fbb76349SGreg Clayton PlatformPOSIX::SetFilePermissions (const char *path, uint32_t file_permissions) 112fbb76349SGreg Clayton { 113fbb76349SGreg Clayton if (m_remote_platform_sp) 1141cfb98abSZachary Turner return m_remote_platform_sp->SetFilePermissions(path, file_permissions); 115fbb76349SGreg Clayton else 116fbb76349SGreg Clayton return Platform::SetFilePermissions(path ,file_permissions); 117e0f8f574SDaniel Malea } 118e0f8f574SDaniel Malea 119e0f8f574SDaniel Malea lldb::user_id_t 120e0f8f574SDaniel Malea PlatformPOSIX::OpenFile (const FileSpec& file_spec, 121e0f8f574SDaniel Malea uint32_t flags, 122fbb76349SGreg Clayton uint32_t mode, 123e0f8f574SDaniel Malea Error &error) 124e0f8f574SDaniel Malea { 125e0f8f574SDaniel Malea if (IsHost()) 126*c00cf4a0SZachary Turner return FileCache::GetInstance().OpenFile(file_spec, flags, mode, error); 127fbb76349SGreg Clayton else if (m_remote_platform_sp) 128e0f8f574SDaniel Malea return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error); 129fbb76349SGreg Clayton else 130e0f8f574SDaniel Malea return Platform::OpenFile(file_spec, flags, mode, error); 131e0f8f574SDaniel Malea } 132e0f8f574SDaniel Malea 133e0f8f574SDaniel Malea bool 134e0f8f574SDaniel Malea PlatformPOSIX::CloseFile (lldb::user_id_t fd, Error &error) 135e0f8f574SDaniel Malea { 136e0f8f574SDaniel Malea if (IsHost()) 137*c00cf4a0SZachary Turner return FileCache::GetInstance().CloseFile(fd, error); 138fbb76349SGreg Clayton else if (m_remote_platform_sp) 139e0f8f574SDaniel Malea return m_remote_platform_sp->CloseFile(fd, error); 140fbb76349SGreg Clayton else 141e0f8f574SDaniel Malea return Platform::CloseFile(fd, error); 142e0f8f574SDaniel Malea } 143e0f8f574SDaniel Malea 144e0f8f574SDaniel Malea uint64_t 145e0f8f574SDaniel Malea PlatformPOSIX::ReadFile (lldb::user_id_t fd, 146e0f8f574SDaniel Malea uint64_t offset, 147e0f8f574SDaniel Malea void *dst, 148e0f8f574SDaniel Malea uint64_t dst_len, 149e0f8f574SDaniel Malea Error &error) 150e0f8f574SDaniel Malea { 151e0f8f574SDaniel Malea if (IsHost()) 152*c00cf4a0SZachary Turner return FileCache::GetInstance().ReadFile(fd, offset, dst, dst_len, error); 153fbb76349SGreg Clayton else if (m_remote_platform_sp) 154e0f8f574SDaniel Malea return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error); 155fbb76349SGreg Clayton else 156e0f8f574SDaniel Malea return Platform::ReadFile(fd, offset, dst, dst_len, error); 157e0f8f574SDaniel Malea } 158e0f8f574SDaniel Malea 159e0f8f574SDaniel Malea uint64_t 160e0f8f574SDaniel Malea PlatformPOSIX::WriteFile (lldb::user_id_t fd, 161e0f8f574SDaniel Malea uint64_t offset, 162e0f8f574SDaniel Malea const void* src, 163e0f8f574SDaniel Malea uint64_t src_len, 164e0f8f574SDaniel Malea Error &error) 165e0f8f574SDaniel Malea { 166e0f8f574SDaniel Malea if (IsHost()) 167*c00cf4a0SZachary Turner return FileCache::GetInstance().WriteFile(fd, offset, src, src_len, error); 168fbb76349SGreg Clayton else if (m_remote_platform_sp) 169e0f8f574SDaniel Malea return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error); 170fbb76349SGreg Clayton else 171e0f8f574SDaniel Malea return Platform::WriteFile(fd, offset, src, src_len, error); 172e0f8f574SDaniel Malea } 173e0f8f574SDaniel Malea 174e0f8f574SDaniel Malea static uint32_t 175e0f8f574SDaniel Malea chown_file(Platform *platform, 176e0f8f574SDaniel Malea const char* path, 177e0f8f574SDaniel Malea uint32_t uid = UINT32_MAX, 178e0f8f574SDaniel Malea uint32_t gid = UINT32_MAX) 179e0f8f574SDaniel Malea { 180e0f8f574SDaniel Malea if (!platform || !path || *path == 0) 181e0f8f574SDaniel Malea return UINT32_MAX; 182e0f8f574SDaniel Malea 183e0f8f574SDaniel Malea if (uid == UINT32_MAX && gid == UINT32_MAX) 184e0f8f574SDaniel Malea return 0; // pretend I did chown correctly - actually I just didn't care 185e0f8f574SDaniel Malea 186e0f8f574SDaniel Malea StreamString command; 187e0f8f574SDaniel Malea command.PutCString("chown "); 188e0f8f574SDaniel Malea if (uid != UINT32_MAX) 189e0f8f574SDaniel Malea command.Printf("%d",uid); 190e0f8f574SDaniel Malea if (gid != UINT32_MAX) 191e0f8f574SDaniel Malea command.Printf(":%d",gid); 192e0f8f574SDaniel Malea command.Printf("%s",path); 193e0f8f574SDaniel Malea int status; 194e0f8f574SDaniel Malea platform->RunShellCommand(command.GetData(), 195e0f8f574SDaniel Malea NULL, 196e0f8f574SDaniel Malea &status, 197e0f8f574SDaniel Malea NULL, 198e0f8f574SDaniel Malea NULL, 199e0f8f574SDaniel Malea 10); 200e0f8f574SDaniel Malea return status; 201e0f8f574SDaniel Malea } 202e0f8f574SDaniel Malea 203e0f8f574SDaniel Malea lldb_private::Error 204e0f8f574SDaniel Malea PlatformPOSIX::PutFile (const lldb_private::FileSpec& source, 205e0f8f574SDaniel Malea const lldb_private::FileSpec& destination, 206e0f8f574SDaniel Malea uint32_t uid, 207e0f8f574SDaniel Malea uint32_t gid) 208e0f8f574SDaniel Malea { 209fbb76349SGreg Clayton Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 210fbb76349SGreg Clayton 211e0f8f574SDaniel Malea if (IsHost()) 212e0f8f574SDaniel Malea { 213e0f8f574SDaniel Malea if (FileSpec::Equal(source, destination, true)) 214e0f8f574SDaniel Malea return Error(); 215e0f8f574SDaniel Malea // cp src dst 216e0f8f574SDaniel Malea // chown uid:gid dst 217e0f8f574SDaniel Malea std::string src_path (source.GetPath()); 218e0f8f574SDaniel Malea if (src_path.empty()) 219e0f8f574SDaniel Malea return Error("unable to get file path for source"); 220e0f8f574SDaniel Malea std::string dst_path (destination.GetPath()); 221e0f8f574SDaniel Malea if (dst_path.empty()) 222e0f8f574SDaniel Malea return Error("unable to get file path for destination"); 223e0f8f574SDaniel Malea StreamString command; 224e0f8f574SDaniel Malea command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); 225e0f8f574SDaniel Malea int status; 226e0f8f574SDaniel Malea RunShellCommand(command.GetData(), 227e0f8f574SDaniel Malea NULL, 228e0f8f574SDaniel Malea &status, 229e0f8f574SDaniel Malea NULL, 230e0f8f574SDaniel Malea NULL, 231e0f8f574SDaniel Malea 10); 232e0f8f574SDaniel Malea if (status != 0) 233e0f8f574SDaniel Malea return Error("unable to perform copy"); 234e0f8f574SDaniel Malea if (uid == UINT32_MAX && gid == UINT32_MAX) 235e0f8f574SDaniel Malea return Error(); 236e0f8f574SDaniel Malea if (chown_file(this,dst_path.c_str(),uid,gid) != 0) 237e0f8f574SDaniel Malea return Error("unable to perform chown"); 238e0f8f574SDaniel Malea return Error(); 239e0f8f574SDaniel Malea } 240fbb76349SGreg Clayton else if (m_remote_platform_sp) 241e0f8f574SDaniel Malea { 242e0f8f574SDaniel Malea if (GetSupportsRSync()) 243e0f8f574SDaniel Malea { 244e0f8f574SDaniel Malea std::string src_path (source.GetPath()); 245e0f8f574SDaniel Malea if (src_path.empty()) 246e0f8f574SDaniel Malea return Error("unable to get file path for source"); 247e0f8f574SDaniel Malea std::string dst_path (destination.GetPath()); 248e0f8f574SDaniel Malea if (dst_path.empty()) 249e0f8f574SDaniel Malea return Error("unable to get file path for destination"); 250e0f8f574SDaniel Malea StreamString command; 251e0f8f574SDaniel Malea if (GetIgnoresRemoteHostname()) 252e0f8f574SDaniel Malea { 253e0f8f574SDaniel Malea if (!GetRSyncPrefix()) 254e0f8f574SDaniel Malea command.Printf("rsync %s %s %s", 255e0f8f574SDaniel Malea GetRSyncOpts(), 256e0f8f574SDaniel Malea src_path.c_str(), 257e0f8f574SDaniel Malea dst_path.c_str()); 258e0f8f574SDaniel Malea else 259e0f8f574SDaniel Malea command.Printf("rsync %s %s %s%s", 260e0f8f574SDaniel Malea GetRSyncOpts(), 261e0f8f574SDaniel Malea src_path.c_str(), 262e0f8f574SDaniel Malea GetRSyncPrefix(), 263e0f8f574SDaniel Malea dst_path.c_str()); 264e0f8f574SDaniel Malea } 265e0f8f574SDaniel Malea else 266e0f8f574SDaniel Malea command.Printf("rsync %s %s %s:%s", 267e0f8f574SDaniel Malea GetRSyncOpts(), 268e0f8f574SDaniel Malea src_path.c_str(), 269e0f8f574SDaniel Malea GetHostname(), 270e0f8f574SDaniel Malea dst_path.c_str()); 271e0f8f574SDaniel Malea if (log) 272e0f8f574SDaniel Malea log->Printf("[PutFile] Running command: %s\n", command.GetData()); 273e0f8f574SDaniel Malea int retcode; 274e0f8f574SDaniel Malea Host::RunShellCommand(command.GetData(), 275e0f8f574SDaniel Malea NULL, 276e0f8f574SDaniel Malea &retcode, 277e0f8f574SDaniel Malea NULL, 278e0f8f574SDaniel Malea NULL, 279e0f8f574SDaniel Malea 60); 280e0f8f574SDaniel Malea if (retcode == 0) 281e0f8f574SDaniel Malea { 282e0f8f574SDaniel Malea // Don't chown a local file for a remote system 283e0f8f574SDaniel Malea // if (chown_file(this,dst_path.c_str(),uid,gid) != 0) 284e0f8f574SDaniel Malea // return Error("unable to perform chown"); 285e0f8f574SDaniel Malea return Error(); 286e0f8f574SDaniel Malea } 287e0f8f574SDaniel Malea // if we are still here rsync has failed - let's try the slow way before giving up 288e0f8f574SDaniel Malea } 289fbb76349SGreg Clayton 290fbb76349SGreg Clayton if (log) 291fbb76349SGreg Clayton log->Printf ("PlatformPOSIX::PutFile(src='%s', dst='%s', uid=%u, gid=%u)", 292fbb76349SGreg Clayton source.GetPath().c_str(), 293fbb76349SGreg Clayton destination.GetPath().c_str(), 294fbb76349SGreg Clayton uid, 295fbb76349SGreg Clayton gid); // REMOVE THIS PRINTF PRIOR TO CHECKIN 296e0f8f574SDaniel Malea // open 297e0f8f574SDaniel Malea // read, write, read, write, ... 298e0f8f574SDaniel Malea // close 299e0f8f574SDaniel Malea // chown uid:gid dst 300e0f8f574SDaniel Malea if (log) 301e0f8f574SDaniel Malea log->Printf("[PutFile] Using block by block transfer....\n"); 302fbb76349SGreg Clayton 303fbb76349SGreg Clayton uint32_t source_open_options = File::eOpenOptionRead; 304fbb76349SGreg Clayton if (source.GetFileType() == FileSpec::eFileTypeSymbolicLink) 305fbb76349SGreg Clayton source_open_options |= File::eOpenoptionDontFollowSymlinks; 306fbb76349SGreg Clayton 307fbb76349SGreg Clayton File source_file(source, source_open_options, lldb::eFilePermissionsUserRW); 308fbb76349SGreg Clayton Error error; 309fbb76349SGreg Clayton uint32_t permissions = source_file.GetPermissions(error); 310fbb76349SGreg Clayton if (permissions == 0) 311fbb76349SGreg Clayton permissions = lldb::eFilePermissionsFileDefault; 312fbb76349SGreg Clayton 313e0f8f574SDaniel Malea if (!source_file.IsValid()) 314e0f8f574SDaniel Malea return Error("unable to open source file"); 315e0f8f574SDaniel Malea lldb::user_id_t dest_file = OpenFile (destination, 316e0f8f574SDaniel Malea File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate, 317fbb76349SGreg Clayton permissions, 318e0f8f574SDaniel Malea error); 319e0f8f574SDaniel Malea if (log) 320e0f8f574SDaniel Malea log->Printf ("dest_file = %" PRIu64 "\n", dest_file); 321e0f8f574SDaniel Malea if (error.Fail()) 322e0f8f574SDaniel Malea return error; 323e0f8f574SDaniel Malea if (dest_file == UINT64_MAX) 324e0f8f574SDaniel Malea return Error("unable to open target file"); 325e0f8f574SDaniel Malea lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); 326e0f8f574SDaniel Malea uint64_t offset = 0; 327e0f8f574SDaniel Malea while (error.Success()) 328e0f8f574SDaniel Malea { 329e0f8f574SDaniel Malea size_t bytes_read = buffer_sp->GetByteSize(); 330e0f8f574SDaniel Malea error = source_file.Read(buffer_sp->GetBytes(), bytes_read); 331e0f8f574SDaniel Malea if (bytes_read) 332e0f8f574SDaniel Malea { 333e0f8f574SDaniel Malea WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error); 334e0f8f574SDaniel Malea offset += bytes_read; 335e0f8f574SDaniel Malea } 336e0f8f574SDaniel Malea else 337e0f8f574SDaniel Malea break; 338e0f8f574SDaniel Malea } 339e0f8f574SDaniel Malea CloseFile(dest_file, error); 340e0f8f574SDaniel Malea if (uid == UINT32_MAX && gid == UINT32_MAX) 341e0f8f574SDaniel Malea return error; 342e0f8f574SDaniel Malea // This is remopve, don't chown a local file... 343e0f8f574SDaniel Malea // std::string dst_path (destination.GetPath()); 344e0f8f574SDaniel Malea // if (chown_file(this,dst_path.c_str(),uid,gid) != 0) 345e0f8f574SDaniel Malea // return Error("unable to perform chown"); 346e0f8f574SDaniel Malea return error; 347e0f8f574SDaniel Malea } 348e0f8f574SDaniel Malea return Platform::PutFile(source,destination,uid,gid); 349e0f8f574SDaniel Malea } 350e0f8f574SDaniel Malea 351e0f8f574SDaniel Malea lldb::user_id_t 352e0f8f574SDaniel Malea PlatformPOSIX::GetFileSize (const FileSpec& file_spec) 353e0f8f574SDaniel Malea { 354e0f8f574SDaniel Malea if (IsHost()) 355*c00cf4a0SZachary Turner return FileSystem::GetFileSize(file_spec); 356fbb76349SGreg Clayton else if (m_remote_platform_sp) 357e0f8f574SDaniel Malea return m_remote_platform_sp->GetFileSize(file_spec); 358fbb76349SGreg Clayton else 359e0f8f574SDaniel Malea return Platform::GetFileSize(file_spec); 360e0f8f574SDaniel Malea } 361e0f8f574SDaniel Malea 362fbb76349SGreg Clayton Error 363fbb76349SGreg Clayton PlatformPOSIX::CreateSymlink(const char *src, const char *dst) 364fbb76349SGreg Clayton { 365fbb76349SGreg Clayton if (IsHost()) 366*c00cf4a0SZachary Turner return FileSystem::Symlink(src, dst); 367fbb76349SGreg Clayton else if (m_remote_platform_sp) 368fbb76349SGreg Clayton return m_remote_platform_sp->CreateSymlink(src, dst); 369fbb76349SGreg Clayton else 370fbb76349SGreg Clayton return Platform::CreateSymlink(src, dst); 371fbb76349SGreg Clayton } 372fbb76349SGreg Clayton 373e0f8f574SDaniel Malea bool 374e0f8f574SDaniel Malea PlatformPOSIX::GetFileExists (const FileSpec& file_spec) 375e0f8f574SDaniel Malea { 376e0f8f574SDaniel Malea if (IsHost()) 377e0f8f574SDaniel Malea return file_spec.Exists(); 378fbb76349SGreg Clayton else if (m_remote_platform_sp) 379e0f8f574SDaniel Malea return m_remote_platform_sp->GetFileExists(file_spec); 380fbb76349SGreg Clayton else 381e0f8f574SDaniel Malea return Platform::GetFileExists(file_spec); 382e0f8f574SDaniel Malea } 383e0f8f574SDaniel Malea 384fbb76349SGreg Clayton Error 385fbb76349SGreg Clayton PlatformPOSIX::Unlink (const char *path) 386e0f8f574SDaniel Malea { 387e0f8f574SDaniel Malea if (IsHost()) 388*c00cf4a0SZachary Turner return FileSystem::Unlink(path); 389fbb76349SGreg Clayton else if (m_remote_platform_sp) 390fbb76349SGreg Clayton return m_remote_platform_sp->Unlink(path); 391fbb76349SGreg Clayton else 392fbb76349SGreg Clayton return Platform::Unlink(path); 393e0f8f574SDaniel Malea } 394e0f8f574SDaniel Malea 395e0f8f574SDaniel Malea lldb_private::Error 396e0f8f574SDaniel Malea PlatformPOSIX::GetFile (const lldb_private::FileSpec& source /* remote file path */, 397e0f8f574SDaniel Malea const lldb_private::FileSpec& destination /* local file path */) 398e0f8f574SDaniel Malea { 399fbb76349SGreg Clayton Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 400fbb76349SGreg Clayton 401e0f8f574SDaniel Malea // Check the args, first. 402e0f8f574SDaniel Malea std::string src_path (source.GetPath()); 403e0f8f574SDaniel Malea if (src_path.empty()) 404e0f8f574SDaniel Malea return Error("unable to get file path for source"); 405e0f8f574SDaniel Malea std::string dst_path (destination.GetPath()); 406e0f8f574SDaniel Malea if (dst_path.empty()) 407e0f8f574SDaniel Malea return Error("unable to get file path for destination"); 408e0f8f574SDaniel Malea if (IsHost()) 409e0f8f574SDaniel Malea { 410e0f8f574SDaniel Malea if (FileSpec::Equal(source, destination, true)) 411e0f8f574SDaniel Malea return Error("local scenario->source and destination are the same file path: no operation performed"); 412e0f8f574SDaniel Malea // cp src dst 413e0f8f574SDaniel Malea StreamString cp_command; 414e0f8f574SDaniel Malea cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); 415e0f8f574SDaniel Malea int status; 416e0f8f574SDaniel Malea RunShellCommand(cp_command.GetData(), 417e0f8f574SDaniel Malea NULL, 418e0f8f574SDaniel Malea &status, 419e0f8f574SDaniel Malea NULL, 420e0f8f574SDaniel Malea NULL, 421e0f8f574SDaniel Malea 10); 422e0f8f574SDaniel Malea if (status != 0) 423e0f8f574SDaniel Malea return Error("unable to perform copy"); 424e0f8f574SDaniel Malea return Error(); 425e0f8f574SDaniel Malea } 426fbb76349SGreg Clayton else if (m_remote_platform_sp) 427e0f8f574SDaniel Malea { 428e0f8f574SDaniel Malea if (GetSupportsRSync()) 429e0f8f574SDaniel Malea { 430e0f8f574SDaniel Malea StreamString command; 431e0f8f574SDaniel Malea if (GetIgnoresRemoteHostname()) 432e0f8f574SDaniel Malea { 433e0f8f574SDaniel Malea if (!GetRSyncPrefix()) 434e0f8f574SDaniel Malea command.Printf("rsync %s %s %s", 435e0f8f574SDaniel Malea GetRSyncOpts(), 436e0f8f574SDaniel Malea src_path.c_str(), 437e0f8f574SDaniel Malea dst_path.c_str()); 438e0f8f574SDaniel Malea else 439e0f8f574SDaniel Malea command.Printf("rsync %s %s%s %s", 440e0f8f574SDaniel Malea GetRSyncOpts(), 441e0f8f574SDaniel Malea GetRSyncPrefix(), 442e0f8f574SDaniel Malea src_path.c_str(), 443e0f8f574SDaniel Malea dst_path.c_str()); 444e0f8f574SDaniel Malea } 445e0f8f574SDaniel Malea else 446e0f8f574SDaniel Malea command.Printf("rsync %s %s:%s %s", 447e0f8f574SDaniel Malea GetRSyncOpts(), 448e0f8f574SDaniel Malea m_remote_platform_sp->GetHostname(), 449e0f8f574SDaniel Malea src_path.c_str(), 450e0f8f574SDaniel Malea dst_path.c_str()); 451e0f8f574SDaniel Malea if (log) 452e0f8f574SDaniel Malea log->Printf("[GetFile] Running command: %s\n", command.GetData()); 453e0f8f574SDaniel Malea int retcode; 454e0f8f574SDaniel Malea Host::RunShellCommand(command.GetData(), 455e0f8f574SDaniel Malea NULL, 456e0f8f574SDaniel Malea &retcode, 457e0f8f574SDaniel Malea NULL, 458e0f8f574SDaniel Malea NULL, 459e0f8f574SDaniel Malea 60); 460e0f8f574SDaniel Malea if (retcode == 0) 461e0f8f574SDaniel Malea return Error(); 462e0f8f574SDaniel Malea // If we are here, rsync has failed - let's try the slow way before giving up 463e0f8f574SDaniel Malea } 464e0f8f574SDaniel Malea // open src and dst 465e0f8f574SDaniel Malea // read/write, read/write, read/write, ... 466e0f8f574SDaniel Malea // close src 467e0f8f574SDaniel Malea // close dst 468e0f8f574SDaniel Malea if (log) 469e0f8f574SDaniel Malea log->Printf("[GetFile] Using block by block transfer....\n"); 470e0f8f574SDaniel Malea Error error; 471e0f8f574SDaniel Malea user_id_t fd_src = OpenFile (source, 472e0f8f574SDaniel Malea File::eOpenOptionRead, 473fbb76349SGreg Clayton lldb::eFilePermissionsFileDefault, 474e0f8f574SDaniel Malea error); 475e0f8f574SDaniel Malea 476e0f8f574SDaniel Malea if (fd_src == UINT64_MAX) 477e0f8f574SDaniel Malea return Error("unable to open source file"); 478e0f8f574SDaniel Malea 479fbb76349SGreg Clayton uint32_t permissions = 0; 480fbb76349SGreg Clayton error = GetFilePermissions(source.GetPath().c_str(), permissions); 481e0f8f574SDaniel Malea 482e0f8f574SDaniel Malea if (permissions == 0) 483fbb76349SGreg Clayton permissions = lldb::eFilePermissionsFileDefault; 484e0f8f574SDaniel Malea 485*c00cf4a0SZachary Turner user_id_t fd_dst = FileCache::GetInstance().OpenFile( 486*c00cf4a0SZachary Turner destination, File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate, permissions, 487e0f8f574SDaniel Malea error); 488e0f8f574SDaniel Malea 489e0f8f574SDaniel Malea if (fd_dst == UINT64_MAX) 490e0f8f574SDaniel Malea { 491e0f8f574SDaniel Malea if (error.Success()) 492e0f8f574SDaniel Malea error.SetErrorString("unable to open destination file"); 493e0f8f574SDaniel Malea } 494e0f8f574SDaniel Malea 495e0f8f574SDaniel Malea if (error.Success()) 496e0f8f574SDaniel Malea { 497e0f8f574SDaniel Malea lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); 498e0f8f574SDaniel Malea uint64_t offset = 0; 499e0f8f574SDaniel Malea error.Clear(); 500e0f8f574SDaniel Malea while (error.Success()) 501e0f8f574SDaniel Malea { 502e0f8f574SDaniel Malea const uint64_t n_read = ReadFile (fd_src, 503e0f8f574SDaniel Malea offset, 504e0f8f574SDaniel Malea buffer_sp->GetBytes(), 505e0f8f574SDaniel Malea buffer_sp->GetByteSize(), 506e0f8f574SDaniel Malea error); 507e0f8f574SDaniel Malea if (error.Fail()) 508e0f8f574SDaniel Malea break; 509e0f8f574SDaniel Malea if (n_read == 0) 510e0f8f574SDaniel Malea break; 511*c00cf4a0SZachary Turner if (FileCache::GetInstance().WriteFile(fd_dst, offset, buffer_sp->GetBytes(), n_read, error) != n_read) 512e0f8f574SDaniel Malea { 513e0f8f574SDaniel Malea if (!error.Fail()) 514e0f8f574SDaniel Malea error.SetErrorString("unable to write to destination file"); 515e0f8f574SDaniel Malea break; 516e0f8f574SDaniel Malea } 517e0f8f574SDaniel Malea offset += n_read; 518e0f8f574SDaniel Malea } 519e0f8f574SDaniel Malea } 520e0f8f574SDaniel Malea // Ignore the close error of src. 521e0f8f574SDaniel Malea if (fd_src != UINT64_MAX) 522e0f8f574SDaniel Malea CloseFile(fd_src, error); 523e0f8f574SDaniel Malea // And close the dst file descriptot. 524*c00cf4a0SZachary Turner if (fd_dst != UINT64_MAX && !FileCache::GetInstance().CloseFile(fd_dst, error)) 525e0f8f574SDaniel Malea { 526e0f8f574SDaniel Malea if (!error.Fail()) 527e0f8f574SDaniel Malea error.SetErrorString("unable to close destination file"); 528e0f8f574SDaniel Malea 529e0f8f574SDaniel Malea } 530e0f8f574SDaniel Malea return error; 531e0f8f574SDaniel Malea } 532e0f8f574SDaniel Malea return Platform::GetFile(source,destination); 533e0f8f574SDaniel Malea } 534e0f8f574SDaniel Malea 535e0f8f574SDaniel Malea std::string 536e0f8f574SDaniel Malea PlatformPOSIX::GetPlatformSpecificConnectionInformation() 537e0f8f574SDaniel Malea { 538e0f8f574SDaniel Malea StreamString stream; 539e0f8f574SDaniel Malea if (GetSupportsRSync()) 540e0f8f574SDaniel Malea { 541e0f8f574SDaniel Malea stream.PutCString("rsync"); 542e0f8f574SDaniel Malea if ( (GetRSyncOpts() && *GetRSyncOpts()) || 543e0f8f574SDaniel Malea (GetRSyncPrefix() && *GetRSyncPrefix()) || 544e0f8f574SDaniel Malea GetIgnoresRemoteHostname()) 545e0f8f574SDaniel Malea { 546e0f8f574SDaniel Malea stream.Printf(", options: "); 547e0f8f574SDaniel Malea if (GetRSyncOpts() && *GetRSyncOpts()) 548e0f8f574SDaniel Malea stream.Printf("'%s' ",GetRSyncOpts()); 549e0f8f574SDaniel Malea stream.Printf(", prefix: "); 550e0f8f574SDaniel Malea if (GetRSyncPrefix() && *GetRSyncPrefix()) 551e0f8f574SDaniel Malea stream.Printf("'%s' ",GetRSyncPrefix()); 552e0f8f574SDaniel Malea if (GetIgnoresRemoteHostname()) 553e0f8f574SDaniel Malea stream.Printf("ignore remote-hostname "); 554e0f8f574SDaniel Malea } 555e0f8f574SDaniel Malea } 556e0f8f574SDaniel Malea if (GetSupportsSSH()) 557e0f8f574SDaniel Malea { 558e0f8f574SDaniel Malea stream.PutCString("ssh"); 559e0f8f574SDaniel Malea if (GetSSHOpts() && *GetSSHOpts()) 560e0f8f574SDaniel Malea stream.Printf(", options: '%s' ",GetSSHOpts()); 561e0f8f574SDaniel Malea } 562e0f8f574SDaniel Malea if (GetLocalCacheDirectory() && *GetLocalCacheDirectory()) 563e0f8f574SDaniel Malea stream.Printf("cache dir: %s",GetLocalCacheDirectory()); 564e0f8f574SDaniel Malea if (stream.GetSize()) 565e0f8f574SDaniel Malea return stream.GetData(); 566e0f8f574SDaniel Malea else 567e0f8f574SDaniel Malea return ""; 568e0f8f574SDaniel Malea } 569e0f8f574SDaniel Malea 570e0f8f574SDaniel Malea bool 571e0f8f574SDaniel Malea PlatformPOSIX::CalculateMD5 (const FileSpec& file_spec, 572e0f8f574SDaniel Malea uint64_t &low, 573e0f8f574SDaniel Malea uint64_t &high) 574e0f8f574SDaniel Malea { 575e0f8f574SDaniel Malea if (IsHost()) 576e0f8f574SDaniel Malea return Platform::CalculateMD5 (file_spec, low, high); 577e0f8f574SDaniel Malea if (m_remote_platform_sp) 578e0f8f574SDaniel Malea return m_remote_platform_sp->CalculateMD5(file_spec, low, high); 579e0f8f574SDaniel Malea return false; 580e0f8f574SDaniel Malea } 581fbb76349SGreg Clayton 582fbb76349SGreg Clayton lldb_private::ConstString 583fbb76349SGreg Clayton PlatformPOSIX::GetRemoteWorkingDirectory() 584fbb76349SGreg Clayton { 585fbb76349SGreg Clayton if (IsRemote() && m_remote_platform_sp) 586fbb76349SGreg Clayton return m_remote_platform_sp->GetRemoteWorkingDirectory(); 587fbb76349SGreg Clayton else 588fbb76349SGreg Clayton return Platform::GetRemoteWorkingDirectory(); 589fbb76349SGreg Clayton } 590fbb76349SGreg Clayton 591fbb76349SGreg Clayton bool 592fbb76349SGreg Clayton PlatformPOSIX::SetRemoteWorkingDirectory(const lldb_private::ConstString &path) 593fbb76349SGreg Clayton { 594fbb76349SGreg Clayton if (IsRemote() && m_remote_platform_sp) 595fbb76349SGreg Clayton return m_remote_platform_sp->SetRemoteWorkingDirectory(path); 596fbb76349SGreg Clayton else 597fbb76349SGreg Clayton return Platform::SetRemoteWorkingDirectory(path); 598fbb76349SGreg Clayton } 599fbb76349SGreg Clayton 600015d818bSTodd Fiala bool 601015d818bSTodd Fiala PlatformPOSIX::GetRemoteOSVersion () 602015d818bSTodd Fiala { 603015d818bSTodd Fiala if (m_remote_platform_sp) 604015d818bSTodd Fiala return m_remote_platform_sp->GetOSVersion (m_major_os_version, 605015d818bSTodd Fiala m_minor_os_version, 606015d818bSTodd Fiala m_update_os_version); 607015d818bSTodd Fiala return false; 608015d818bSTodd Fiala } 609015d818bSTodd Fiala 610015d818bSTodd Fiala bool 611015d818bSTodd Fiala PlatformPOSIX::GetRemoteOSBuildString (std::string &s) 612015d818bSTodd Fiala { 613015d818bSTodd Fiala if (m_remote_platform_sp) 614015d818bSTodd Fiala return m_remote_platform_sp->GetRemoteOSBuildString (s); 615015d818bSTodd Fiala s.clear(); 616015d818bSTodd Fiala return false; 617015d818bSTodd Fiala } 618015d818bSTodd Fiala 619015d818bSTodd Fiala bool 620015d818bSTodd Fiala PlatformPOSIX::GetRemoteOSKernelDescription (std::string &s) 621015d818bSTodd Fiala { 622015d818bSTodd Fiala if (m_remote_platform_sp) 623015d818bSTodd Fiala return m_remote_platform_sp->GetRemoteOSKernelDescription (s); 624015d818bSTodd Fiala s.clear(); 625015d818bSTodd Fiala return false; 626015d818bSTodd Fiala } 627015d818bSTodd Fiala 628015d818bSTodd Fiala // Remote Platform subclasses need to override this function 629015d818bSTodd Fiala ArchSpec 630015d818bSTodd Fiala PlatformPOSIX::GetRemoteSystemArchitecture () 631015d818bSTodd Fiala { 632015d818bSTodd Fiala if (m_remote_platform_sp) 633015d818bSTodd Fiala return m_remote_platform_sp->GetRemoteSystemArchitecture (); 634015d818bSTodd Fiala return ArchSpec(); 635015d818bSTodd Fiala } 636015d818bSTodd Fiala 637015d818bSTodd Fiala const char * 638015d818bSTodd Fiala PlatformPOSIX::GetHostname () 639015d818bSTodd Fiala { 640015d818bSTodd Fiala if (IsHost()) 641015d818bSTodd Fiala return Platform::GetHostname(); 642015d818bSTodd Fiala 643015d818bSTodd Fiala if (m_remote_platform_sp) 644015d818bSTodd Fiala return m_remote_platform_sp->GetHostname (); 645015d818bSTodd Fiala return NULL; 646015d818bSTodd Fiala } 647015d818bSTodd Fiala 648015d818bSTodd Fiala const char * 649015d818bSTodd Fiala PlatformPOSIX::GetUserName (uint32_t uid) 650015d818bSTodd Fiala { 651015d818bSTodd Fiala // Check the cache in Platform in case we have already looked this uid up 652015d818bSTodd Fiala const char *user_name = Platform::GetUserName(uid); 653015d818bSTodd Fiala if (user_name) 654015d818bSTodd Fiala return user_name; 655015d818bSTodd Fiala 656015d818bSTodd Fiala if (IsRemote() && m_remote_platform_sp) 657015d818bSTodd Fiala return m_remote_platform_sp->GetUserName(uid); 658015d818bSTodd Fiala return NULL; 659015d818bSTodd Fiala } 660015d818bSTodd Fiala 661015d818bSTodd Fiala const char * 662015d818bSTodd Fiala PlatformPOSIX::GetGroupName (uint32_t gid) 663015d818bSTodd Fiala { 664015d818bSTodd Fiala const char *group_name = Platform::GetGroupName(gid); 665015d818bSTodd Fiala if (group_name) 666015d818bSTodd Fiala return group_name; 667015d818bSTodd Fiala 668015d818bSTodd Fiala if (IsRemote() && m_remote_platform_sp) 669015d818bSTodd Fiala return m_remote_platform_sp->GetGroupName(gid); 670015d818bSTodd Fiala return NULL; 671015d818bSTodd Fiala } 672015d818bSTodd Fiala 673015d818bSTodd Fiala Error 674015d818bSTodd Fiala PlatformPOSIX::ConnectRemote (Args& args) 675015d818bSTodd Fiala { 676015d818bSTodd Fiala Error error; 677015d818bSTodd Fiala if (IsHost()) 678015d818bSTodd Fiala { 679015d818bSTodd Fiala error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString()); 680015d818bSTodd Fiala } 681015d818bSTodd Fiala else 682015d818bSTodd Fiala { 683015d818bSTodd Fiala if (!m_remote_platform_sp) 684015d818bSTodd Fiala m_remote_platform_sp = Platform::Create ("remote-gdb-server", error); 685015d818bSTodd Fiala 686015d818bSTodd Fiala if (m_remote_platform_sp && error.Success()) 687015d818bSTodd Fiala error = m_remote_platform_sp->ConnectRemote (args); 688015d818bSTodd Fiala else 689015d818bSTodd Fiala error.SetErrorString ("failed to create a 'remote-gdb-server' platform"); 690015d818bSTodd Fiala 691015d818bSTodd Fiala if (error.Fail()) 692015d818bSTodd Fiala m_remote_platform_sp.reset(); 693015d818bSTodd Fiala } 694015d818bSTodd Fiala 695015d818bSTodd Fiala if (error.Success() && m_remote_platform_sp) 696015d818bSTodd Fiala { 697015d818bSTodd Fiala if (m_options.get()) 698015d818bSTodd Fiala { 699015d818bSTodd Fiala OptionGroupOptions* options = m_options.get(); 700015d818bSTodd Fiala OptionGroupPlatformRSync* m_rsync_options = (OptionGroupPlatformRSync*)options->GetGroupWithOption('r'); 701015d818bSTodd Fiala OptionGroupPlatformSSH* m_ssh_options = (OptionGroupPlatformSSH*)options->GetGroupWithOption('s'); 702015d818bSTodd Fiala OptionGroupPlatformCaching* m_cache_options = (OptionGroupPlatformCaching*)options->GetGroupWithOption('c'); 703015d818bSTodd Fiala 704015d818bSTodd Fiala if (m_rsync_options->m_rsync) 705015d818bSTodd Fiala { 706015d818bSTodd Fiala SetSupportsRSync(true); 707015d818bSTodd Fiala SetRSyncOpts(m_rsync_options->m_rsync_opts.c_str()); 708015d818bSTodd Fiala SetRSyncPrefix(m_rsync_options->m_rsync_prefix.c_str()); 709015d818bSTodd Fiala SetIgnoresRemoteHostname(m_rsync_options->m_ignores_remote_hostname); 710015d818bSTodd Fiala } 711015d818bSTodd Fiala if (m_ssh_options->m_ssh) 712015d818bSTodd Fiala { 713015d818bSTodd Fiala SetSupportsSSH(true); 714015d818bSTodd Fiala SetSSHOpts(m_ssh_options->m_ssh_opts.c_str()); 715015d818bSTodd Fiala } 716015d818bSTodd Fiala SetLocalCacheDirectory(m_cache_options->m_cache_dir.c_str()); 717015d818bSTodd Fiala } 718015d818bSTodd Fiala } 719015d818bSTodd Fiala 720015d818bSTodd Fiala return error; 721015d818bSTodd Fiala } 722015d818bSTodd Fiala 723015d818bSTodd Fiala Error 724015d818bSTodd Fiala PlatformPOSIX::DisconnectRemote () 725015d818bSTodd Fiala { 726015d818bSTodd Fiala Error error; 727015d818bSTodd Fiala 728015d818bSTodd Fiala if (IsHost()) 729015d818bSTodd Fiala { 730015d818bSTodd Fiala error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString()); 731015d818bSTodd Fiala } 732015d818bSTodd Fiala else 733015d818bSTodd Fiala { 734015d818bSTodd Fiala if (m_remote_platform_sp) 735015d818bSTodd Fiala error = m_remote_platform_sp->DisconnectRemote (); 736015d818bSTodd Fiala else 737015d818bSTodd Fiala error.SetErrorString ("the platform is not currently connected"); 738015d818bSTodd Fiala } 739015d818bSTodd Fiala return error; 740015d818bSTodd Fiala } 741015d818bSTodd Fiala 742015d818bSTodd Fiala lldb::ProcessSP 743015d818bSTodd Fiala PlatformPOSIX::DebugProcess (ProcessLaunchInfo &launch_info, 744015d818bSTodd Fiala Debugger &debugger, 745015d818bSTodd Fiala Target *target, // Can be NULL, if NULL create a new target, else use existing one 746015d818bSTodd Fiala Listener &listener, 747015d818bSTodd Fiala Error &error) 748015d818bSTodd Fiala { 749015d818bSTodd Fiala ProcessSP process_sp; 750015d818bSTodd Fiala 751015d818bSTodd Fiala if (IsHost()) 752015d818bSTodd Fiala { 753015d818bSTodd Fiala // We are going to hand this process off to debugserver which will be in charge of setting the exit status. 754015d818bSTodd 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 755015d818bSTodd Fiala // race between debugserver & us for who will find out about the debugged process's death. 756015d818bSTodd Fiala launch_info.GetFlags().Set(eLaunchFlagDontSetExitStatus); 757015d818bSTodd Fiala process_sp = Platform::DebugProcess (launch_info, debugger, target, listener, error); 758015d818bSTodd Fiala } 759015d818bSTodd Fiala else 760015d818bSTodd Fiala { 761015d818bSTodd Fiala if (m_remote_platform_sp) 762015d818bSTodd Fiala process_sp = m_remote_platform_sp->DebugProcess (launch_info, debugger, target, listener, error); 763015d818bSTodd Fiala else 764015d818bSTodd Fiala error.SetErrorString ("the platform is not currently connected"); 765015d818bSTodd Fiala } 766015d818bSTodd Fiala return process_sp; 767015d818bSTodd Fiala 768015d818bSTodd Fiala } 769015d818bSTodd Fiala 7702094dbf4SJason Molenda void 7712094dbf4SJason Molenda PlatformPOSIX::CalculateTrapHandlerSymbolNames () 7722094dbf4SJason Molenda { 7732094dbf4SJason Molenda m_trap_handlers.push_back (ConstString ("_sigtramp")); 7742094dbf4SJason Molenda } 775