1//===-- PlatformLinux.cpp ---------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "lldb/lldb-python.h" 11 12#include "PlatformLinux.h" 13 14// C Includes 15#include <stdio.h> 16#include <sys/utsname.h> 17 18// C++ Includes 19// Other libraries and framework includes 20// Project includes 21#include "lldb/Core/Error.h" 22#include "lldb/Core/Debugger.h" 23#include "lldb/Core/Module.h" 24#include "lldb/Core/ModuleList.h" 25#include "lldb/Core/ModuleSpec.h" 26#include "lldb/Core/PluginManager.h" 27#include "lldb/Core/StreamString.h" 28#include "lldb/Host/FileSpec.h" 29#include "lldb/Host/Host.h" 30#include "lldb/Target/Target.h" 31#include "lldb/Target/Process.h" 32 33using namespace lldb; 34using namespace lldb_private; 35 36static uint32_t g_initialize_count = 0; 37 38Platform * 39PlatformLinux::CreateInstance (bool force, const ArchSpec *arch) 40{ 41 bool create = force; 42 if (create == false && arch && arch->IsValid()) 43 { 44 const llvm::Triple &triple = arch->GetTriple(); 45 switch (triple.getVendor()) 46 { 47 case llvm::Triple::PC: 48 create = true; 49 break; 50 51#if defined(__linux__) 52 // Only accept "unknown" for the vendor if the host is linux and 53 // it "unknown" wasn't specified (it was just returned becasue it 54 // was NOT specified_ 55 case llvm::Triple::UnknownArch: 56 create = !arch->TripleVendorWasSpecified(); 57 break; 58#endif 59 default: 60 break; 61 } 62 63 if (create) 64 { 65 switch (triple.getOS()) 66 { 67 case llvm::Triple::Linux: 68 break; 69 70#if defined(__linux__) 71 // Only accept "unknown" for the OS if the host is linux and 72 // it "unknown" wasn't specified (it was just returned becasue it 73 // was NOT specified) 74 case llvm::Triple::UnknownOS: 75 create = !arch->TripleOSWasSpecified(); 76 break; 77#endif 78 default: 79 create = false; 80 break; 81 } 82 } 83 } 84 if (create) 85 return new PlatformLinux(true); 86 return NULL; 87} 88 89 90lldb_private::ConstString 91PlatformLinux::GetPluginNameStatic (bool is_host) 92{ 93 if (is_host) 94 { 95 static ConstString g_host_name(Platform::GetHostPlatformName ()); 96 return g_host_name; 97 } 98 else 99 { 100 static ConstString g_remote_name("remote-linux"); 101 return g_remote_name; 102 } 103} 104 105const char * 106PlatformLinux::GetPluginDescriptionStatic (bool is_host) 107{ 108 if (is_host) 109 return "Local Linux user platform plug-in."; 110 else 111 return "Remote Linux user platform plug-in."; 112} 113 114lldb_private::ConstString 115PlatformLinux::GetPluginName() 116{ 117 return GetPluginNameStatic(IsHost()); 118} 119 120void 121PlatformLinux::Initialize () 122{ 123 if (g_initialize_count++ == 0) 124 { 125#if defined(__linux__) 126 PlatformSP default_platform_sp (new PlatformLinux(true)); 127 default_platform_sp->SetSystemArchitecture (Host::GetArchitecture()); 128 Platform::SetDefaultPlatform (default_platform_sp); 129#endif 130 PluginManager::RegisterPlugin(PlatformLinux::GetPluginNameStatic(false), 131 PlatformLinux::GetPluginDescriptionStatic(false), 132 PlatformLinux::CreateInstance); 133 } 134} 135 136void 137PlatformLinux::Terminate () 138{ 139 if (g_initialize_count > 0) 140 { 141 if (--g_initialize_count == 0) 142 { 143 PluginManager::UnregisterPlugin (PlatformLinux::CreateInstance); 144 } 145 } 146} 147 148Error 149PlatformLinux::ResolveExecutable (const FileSpec &exe_file, 150 const ArchSpec &exe_arch, 151 lldb::ModuleSP &exe_module_sp, 152 const FileSpecList *module_search_paths_ptr) 153{ 154 Error error; 155 // Nothing special to do here, just use the actual file and architecture 156 157 char exe_path[PATH_MAX]; 158 FileSpec resolved_exe_file (exe_file); 159 160 if (IsHost()) 161 { 162 // If we have "ls" as the exe_file, resolve the executable location based on 163 // the current path variables 164 if (!resolved_exe_file.Exists()) 165 { 166 exe_file.GetPath(exe_path, sizeof(exe_path)); 167 resolved_exe_file.SetFile(exe_path, true); 168 } 169 170 if (!resolved_exe_file.Exists()) 171 resolved_exe_file.ResolveExecutableLocation (); 172 173 if (resolved_exe_file.Exists()) 174 error.Clear(); 175 else 176 { 177 exe_file.GetPath(exe_path, sizeof(exe_path)); 178 error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path); 179 } 180 } 181 else 182 { 183 if (m_remote_platform_sp) 184 { 185 error = m_remote_platform_sp->ResolveExecutable (exe_file, 186 exe_arch, 187 exe_module_sp, 188 NULL); 189 } 190 else 191 { 192 // We may connect to a process and use the provided executable (Don't use local $PATH). 193 194 if (resolved_exe_file.Exists()) 195 error.Clear(); 196 else 197 error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path); 198 } 199 } 200 201 if (error.Success()) 202 { 203 ModuleSpec module_spec (resolved_exe_file, exe_arch); 204 if (exe_arch.IsValid()) 205 { 206 error = ModuleList::GetSharedModule (module_spec, 207 exe_module_sp, 208 NULL, 209 NULL, 210 NULL); 211 if (error.Fail()) 212 { 213 // If we failed, it may be because the vendor and os aren't known. If that is the 214 // case, try setting them to the host architecture and give it another try. 215 llvm::Triple &module_triple = module_spec.GetArchitecture().GetTriple(); 216 bool is_vendor_specified = (module_triple.getVendor() != llvm::Triple::UnknownVendor); 217 bool is_os_specified = (module_triple.getOS() != llvm::Triple::UnknownOS); 218 if (!is_vendor_specified || !is_os_specified) 219 { 220 const llvm::Triple &host_triple = Host::GetArchitecture (Host::eSystemDefaultArchitecture).GetTriple(); 221 222 if (!is_vendor_specified) 223 module_triple.setVendorName (host_triple.getVendorName()); 224 if (!is_os_specified) 225 module_triple.setOSName (host_triple.getOSName()); 226 227 error = ModuleList::GetSharedModule (module_spec, 228 exe_module_sp, 229 NULL, 230 NULL, 231 NULL); 232 } 233 } 234 235 // TODO find out why exe_module_sp might be NULL 236 if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL) 237 { 238 exe_module_sp.reset(); 239 error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s", 240 exe_file.GetPath().c_str(), 241 exe_arch.GetArchitectureName()); 242 } 243 } 244 else 245 { 246 // No valid architecture was specified, ask the platform for 247 // the architectures that we should be using (in the correct order) 248 // and see if we can find a match that way 249 StreamString arch_names; 250 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx) 251 { 252 error = ModuleList::GetSharedModule (module_spec, 253 exe_module_sp, 254 NULL, 255 NULL, 256 NULL); 257 // Did we find an executable using one of the 258 if (error.Success()) 259 { 260 if (exe_module_sp && exe_module_sp->GetObjectFile()) 261 break; 262 else 263 error.SetErrorToGenericError(); 264 } 265 266 if (idx > 0) 267 arch_names.PutCString (", "); 268 arch_names.PutCString (module_spec.GetArchitecture().GetArchitectureName()); 269 } 270 271 if (error.Fail() || !exe_module_sp) 272 { 273 error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s", 274 exe_file.GetPath().c_str(), 275 GetPluginName().GetCString(), 276 arch_names.GetString().c_str()); 277 } 278 } 279 } 280 281 return error; 282} 283 284Error 285PlatformLinux::GetFile (const FileSpec &platform_file, 286 const UUID *uuid_ptr, FileSpec &local_file) 287{ 288 if (IsRemote()) 289 { 290 if (m_remote_platform_sp) 291 return m_remote_platform_sp->GetFile (platform_file, uuid_ptr, local_file); 292 } 293 294 // Default to the local case 295 local_file = platform_file; 296 return Error(); 297} 298 299 300//------------------------------------------------------------------ 301/// Default Constructor 302//------------------------------------------------------------------ 303PlatformLinux::PlatformLinux (bool is_host) : 304 Platform(is_host), // This is the local host platform 305 m_remote_platform_sp () 306{ 307} 308 309//------------------------------------------------------------------ 310/// Destructor. 311/// 312/// The destructor is virtual since this class is designed to be 313/// inherited from by the plug-in instance. 314//------------------------------------------------------------------ 315PlatformLinux::~PlatformLinux() 316{ 317} 318 319bool 320PlatformLinux::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 321{ 322 bool success = false; 323 if (IsHost()) 324 { 325 success = Platform::GetProcessInfo (pid, process_info); 326 } 327 else 328 { 329 if (m_remote_platform_sp) 330 success = m_remote_platform_sp->GetProcessInfo (pid, process_info); 331 } 332 return success; 333} 334 335bool 336PlatformLinux::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) 337{ 338 if (idx == 0) 339 { 340 arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture); 341 return arch.IsValid(); 342 } 343 else if (idx == 1) 344 { 345 // If the default host architecture is 64-bit, look for a 32-bit variant 346 ArchSpec hostArch 347 = Host::GetArchitecture(Host::eSystemDefaultArchitecture); 348 if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) 349 { 350 arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32); 351 return arch.IsValid(); 352 } 353 } 354 return false; 355} 356 357void 358PlatformLinux::GetStatus (Stream &strm) 359{ 360 struct utsname un; 361 362 Platform::GetStatus(strm); 363 364 if (uname(&un)) 365 return; 366 367 strm.Printf (" Kernel: %s\n", un.sysname); 368 strm.Printf (" Release: %s\n", un.release); 369 strm.Printf (" Version: %s\n", un.version); 370} 371 372size_t 373PlatformLinux::GetSoftwareBreakpointTrapOpcode (Target &target, 374 BreakpointSite *bp_site) 375{ 376 ArchSpec arch = target.GetArchitecture(); 377 const uint8_t *trap_opcode = NULL; 378 size_t trap_opcode_size = 0; 379 380 switch (arch.GetCore()) 381 { 382 default: 383 assert(false && "CPU type not supported!"); 384 break; 385 386 case ArchSpec::eCore_x86_32_i386: 387 case ArchSpec::eCore_x86_64_x86_64: 388 { 389 static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC }; 390 trap_opcode = g_i386_breakpoint_opcode; 391 trap_opcode_size = sizeof(g_i386_breakpoint_opcode); 392 } 393 break; 394 } 395 396 if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) 397 return trap_opcode_size; 398 return 0; 399} 400 401Error 402PlatformLinux::LaunchProcess (ProcessLaunchInfo &launch_info) 403{ 404 Error error; 405 406 if (IsHost()) 407 { 408 if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell)) 409 { 410 const bool is_localhost = true; 411 const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug); 412 const bool first_arg_is_full_shell_command = false; 413 if (!launch_info.ConvertArgumentsForLaunchingInShell (error, 414 is_localhost, 415 will_debug, 416 first_arg_is_full_shell_command)) 417 return error; 418 } 419 error = Platform::LaunchProcess (launch_info); 420 } 421 else 422 { 423 error.SetErrorString ("the platform is not currently connected"); 424 } 425 return error; 426} 427 428lldb::ProcessSP 429PlatformLinux::Attach(ProcessAttachInfo &attach_info, 430 Debugger &debugger, 431 Target *target, 432 Listener &listener, 433 Error &error) 434{ 435 lldb::ProcessSP process_sp; 436 if (IsHost()) 437 { 438 if (target == NULL) 439 { 440 TargetSP new_target_sp; 441 ArchSpec emptyArchSpec; 442 443 error = debugger.GetTargetList().CreateTarget (debugger, 444 NULL, 445 emptyArchSpec, 446 false, 447 m_remote_platform_sp, 448 new_target_sp); 449 target = new_target_sp.get(); 450 } 451 else 452 error.Clear(); 453 454 if (target && error.Success()) 455 { 456 debugger.GetTargetList().SetSelectedTarget(target); 457 458 process_sp = target->CreateProcess (listener, 459 attach_info.GetProcessPluginName(), 460 NULL); 461 462 if (process_sp) 463 error = process_sp->Attach (attach_info); 464 } 465 } 466 else 467 { 468 if (m_remote_platform_sp) 469 process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error); 470 else 471 error.SetErrorString ("the platform is not currently connected"); 472 } 473 return process_sp; 474} 475