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 "PlatformLinux.h" 11 #include "lldb/Host/Config.h" 12 13 // C Includes 14 #include <stdio.h> 15 #ifndef LLDB_DISABLE_POSIX 16 #include <sys/utsname.h> 17 #endif 18 19 // C++ Includes 20 // Other libraries and framework includes 21 // Project includes 22 #include "lldb/Breakpoint/BreakpointLocation.h" 23 #include "lldb/Core/Debugger.h" 24 #include "lldb/Core/Error.h" 25 #include "lldb/Core/Log.h" 26 #include "lldb/Core/Module.h" 27 #include "lldb/Core/ModuleList.h" 28 #include "lldb/Core/ModuleSpec.h" 29 #include "lldb/Core/PluginManager.h" 30 #include "lldb/Core/State.h" 31 #include "lldb/Core/StreamString.h" 32 #include "lldb/Host/FileSpec.h" 33 #include "lldb/Host/HostInfo.h" 34 #include "lldb/Interpreter/OptionValueProperties.h" 35 #include "lldb/Interpreter/Property.h" 36 #include "lldb/Target/Process.h" 37 #include "lldb/Target/Target.h" 38 39 // Define these constants from Linux mman.h for use when targeting 40 // remote linux systems even when host has different values. 41 #define MAP_PRIVATE 2 42 #define MAP_ANON 0x20 43 44 using namespace lldb; 45 using namespace lldb_private; 46 using namespace lldb_private::platform_linux; 47 48 static uint32_t g_initialize_count = 0; 49 50 //------------------------------------------------------------------ 51 /// Code to handle the PlatformLinux settings 52 //------------------------------------------------------------------ 53 54 namespace { 55 class PlatformLinuxProperties : public Properties { 56 public: 57 PlatformLinuxProperties(); 58 59 ~PlatformLinuxProperties() override = default; 60 61 static ConstString &GetSettingName(); 62 63 private: 64 static const PropertyDefinition *GetStaticPropertyDefinitions(); 65 }; 66 67 typedef std::shared_ptr<PlatformLinuxProperties> PlatformLinuxPropertiesSP; 68 69 } // anonymous namespace 70 71 PlatformLinuxProperties::PlatformLinuxProperties() : Properties() { 72 m_collection_sp.reset(new OptionValueProperties(GetSettingName())); 73 m_collection_sp->Initialize(GetStaticPropertyDefinitions()); 74 } 75 76 ConstString &PlatformLinuxProperties::GetSettingName() { 77 static ConstString g_setting_name("linux"); 78 return g_setting_name; 79 } 80 81 const PropertyDefinition * 82 PlatformLinuxProperties::GetStaticPropertyDefinitions() { 83 static PropertyDefinition g_properties[] = { 84 {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}}; 85 86 return g_properties; 87 } 88 89 static const PlatformLinuxPropertiesSP &GetGlobalProperties() { 90 static PlatformLinuxPropertiesSP g_settings_sp; 91 if (!g_settings_sp) 92 g_settings_sp.reset(new PlatformLinuxProperties()); 93 return g_settings_sp; 94 } 95 96 void PlatformLinux::DebuggerInitialize(Debugger &debugger) { 97 if (!PluginManager::GetSettingForPlatformPlugin( 98 debugger, PlatformLinuxProperties::GetSettingName())) { 99 const bool is_global_setting = true; 100 PluginManager::CreateSettingForPlatformPlugin( 101 debugger, GetGlobalProperties()->GetValueProperties(), 102 ConstString("Properties for the PlatformLinux plug-in."), 103 is_global_setting); 104 } 105 } 106 107 //------------------------------------------------------------------ 108 109 PlatformSP PlatformLinux::CreateInstance(bool force, const ArchSpec *arch) { 110 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); 111 if (log) { 112 const char *arch_name; 113 if (arch && arch->GetArchitectureName()) 114 arch_name = arch->GetArchitectureName(); 115 else 116 arch_name = "<null>"; 117 118 const char *triple_cstr = 119 arch ? arch->GetTriple().getTriple().c_str() : "<null>"; 120 121 log->Printf("PlatformLinux::%s(force=%s, arch={%s,%s})", __FUNCTION__, 122 force ? "true" : "false", arch_name, triple_cstr); 123 } 124 125 bool create = force; 126 if (create == false && arch && arch->IsValid()) { 127 const llvm::Triple &triple = arch->GetTriple(); 128 switch (triple.getOS()) { 129 case llvm::Triple::Linux: 130 create = true; 131 break; 132 133 #if defined(__linux__) 134 // Only accept "unknown" for the OS if the host is linux and 135 // it "unknown" wasn't specified (it was just returned because it 136 // was NOT specified) 137 case llvm::Triple::OSType::UnknownOS: 138 create = !arch->TripleOSWasSpecified(); 139 break; 140 #endif 141 default: 142 break; 143 } 144 } 145 146 if (create) { 147 if (log) 148 log->Printf("PlatformLinux::%s() creating remote-linux platform", 149 __FUNCTION__); 150 return PlatformSP(new PlatformLinux(false)); 151 } 152 153 if (log) 154 log->Printf( 155 "PlatformLinux::%s() aborting creation of remote-linux platform", 156 __FUNCTION__); 157 158 return PlatformSP(); 159 } 160 161 ConstString PlatformLinux::GetPluginNameStatic(bool is_host) { 162 if (is_host) { 163 static ConstString g_host_name(Platform::GetHostPlatformName()); 164 return g_host_name; 165 } else { 166 static ConstString g_remote_name("remote-linux"); 167 return g_remote_name; 168 } 169 } 170 171 const char *PlatformLinux::GetPluginDescriptionStatic(bool is_host) { 172 if (is_host) 173 return "Local Linux user platform plug-in."; 174 else 175 return "Remote Linux user platform plug-in."; 176 } 177 178 ConstString PlatformLinux::GetPluginName() { 179 return GetPluginNameStatic(IsHost()); 180 } 181 182 void PlatformLinux::Initialize() { 183 PlatformPOSIX::Initialize(); 184 185 if (g_initialize_count++ == 0) { 186 #if defined(__linux__) && !defined(__ANDROID__) 187 PlatformSP default_platform_sp(new PlatformLinux(true)); 188 default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); 189 Platform::SetHostPlatform(default_platform_sp); 190 #endif 191 PluginManager::RegisterPlugin( 192 PlatformLinux::GetPluginNameStatic(false), 193 PlatformLinux::GetPluginDescriptionStatic(false), 194 PlatformLinux::CreateInstance, PlatformLinux::DebuggerInitialize); 195 } 196 } 197 198 void PlatformLinux::Terminate() { 199 if (g_initialize_count > 0) { 200 if (--g_initialize_count == 0) { 201 PluginManager::UnregisterPlugin(PlatformLinux::CreateInstance); 202 } 203 } 204 205 PlatformPOSIX::Terminate(); 206 } 207 208 Error PlatformLinux::ResolveExecutable( 209 const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp, 210 const FileSpecList *module_search_paths_ptr) { 211 Error error; 212 // Nothing special to do here, just use the actual file and architecture 213 214 char exe_path[PATH_MAX]; 215 ModuleSpec resolved_module_spec(ms); 216 217 if (IsHost()) { 218 // If we have "ls" as the exe_file, resolve the executable location based on 219 // the current path variables 220 if (!resolved_module_spec.GetFileSpec().Exists()) { 221 resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); 222 resolved_module_spec.GetFileSpec().SetFile(exe_path, true); 223 } 224 225 if (!resolved_module_spec.GetFileSpec().Exists()) 226 resolved_module_spec.GetFileSpec().ResolveExecutableLocation(); 227 228 if (resolved_module_spec.GetFileSpec().Exists()) 229 error.Clear(); 230 else { 231 error.SetErrorStringWithFormat( 232 "unable to find executable for '%s'", 233 resolved_module_spec.GetFileSpec().GetPath().c_str()); 234 } 235 } else { 236 if (m_remote_platform_sp) { 237 error = 238 GetCachedExecutable(resolved_module_spec, exe_module_sp, 239 module_search_paths_ptr, *m_remote_platform_sp); 240 } else { 241 // We may connect to a process and use the provided executable (Don't use 242 // local $PATH). 243 244 if (resolved_module_spec.GetFileSpec().Exists()) 245 error.Clear(); 246 else 247 error.SetErrorStringWithFormat("the platform is not currently " 248 "connected, and '%s' doesn't exist in " 249 "the system root.", 250 exe_path); 251 } 252 } 253 254 if (error.Success()) { 255 if (resolved_module_spec.GetArchitecture().IsValid()) { 256 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 257 NULL, NULL, NULL); 258 if (error.Fail()) { 259 // If we failed, it may be because the vendor and os aren't known. If 260 // that is the 261 // case, try setting them to the host architecture and give it another 262 // try. 263 llvm::Triple &module_triple = 264 resolved_module_spec.GetArchitecture().GetTriple(); 265 bool is_vendor_specified = 266 (module_triple.getVendor() != llvm::Triple::UnknownVendor); 267 bool is_os_specified = 268 (module_triple.getOS() != llvm::Triple::UnknownOS); 269 if (!is_vendor_specified || !is_os_specified) { 270 const llvm::Triple &host_triple = 271 HostInfo::GetArchitecture(HostInfo::eArchKindDefault).GetTriple(); 272 273 if (!is_vendor_specified) 274 module_triple.setVendorName(host_triple.getVendorName()); 275 if (!is_os_specified) 276 module_triple.setOSName(host_triple.getOSName()); 277 278 error = ModuleList::GetSharedModule(resolved_module_spec, 279 exe_module_sp, NULL, NULL, NULL); 280 } 281 } 282 283 // TODO find out why exe_module_sp might be NULL 284 if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL) { 285 exe_module_sp.reset(); 286 error.SetErrorStringWithFormat( 287 "'%s' doesn't contain the architecture %s", 288 resolved_module_spec.GetFileSpec().GetPath().c_str(), 289 resolved_module_spec.GetArchitecture().GetArchitectureName()); 290 } 291 } else { 292 // No valid architecture was specified, ask the platform for 293 // the architectures that we should be using (in the correct order) 294 // and see if we can find a match that way 295 StreamString arch_names; 296 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( 297 idx, resolved_module_spec.GetArchitecture()); 298 ++idx) { 299 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 300 NULL, NULL, NULL); 301 // Did we find an executable using one of the 302 if (error.Success()) { 303 if (exe_module_sp && exe_module_sp->GetObjectFile()) 304 break; 305 else 306 error.SetErrorToGenericError(); 307 } 308 309 if (idx > 0) 310 arch_names.PutCString(", "); 311 arch_names.PutCString( 312 resolved_module_spec.GetArchitecture().GetArchitectureName()); 313 } 314 315 if (error.Fail() || !exe_module_sp) { 316 if (resolved_module_spec.GetFileSpec().Readable()) { 317 error.SetErrorStringWithFormat( 318 "'%s' doesn't contain any '%s' platform architectures: %s", 319 resolved_module_spec.GetFileSpec().GetPath().c_str(), 320 GetPluginName().GetCString(), arch_names.GetString().c_str()); 321 } else { 322 error.SetErrorStringWithFormat( 323 "'%s' is not readable", 324 resolved_module_spec.GetFileSpec().GetPath().c_str()); 325 } 326 } 327 } 328 } 329 330 return error; 331 } 332 333 Error PlatformLinux::GetFileWithUUID(const FileSpec &platform_file, 334 const UUID *uuid_ptr, 335 FileSpec &local_file) { 336 if (IsRemote()) { 337 if (m_remote_platform_sp) 338 return m_remote_platform_sp->GetFileWithUUID(platform_file, uuid_ptr, 339 local_file); 340 } 341 342 // Default to the local case 343 local_file = platform_file; 344 return Error(); 345 } 346 347 //------------------------------------------------------------------ 348 /// Default Constructor 349 //------------------------------------------------------------------ 350 PlatformLinux::PlatformLinux(bool is_host) 351 : PlatformPOSIX(is_host) // This is the local host platform 352 {} 353 354 //------------------------------------------------------------------ 355 /// Destructor. 356 /// 357 /// The destructor is virtual since this class is designed to be 358 /// inherited from by the plug-in instance. 359 //------------------------------------------------------------------ 360 PlatformLinux::~PlatformLinux() = default; 361 362 bool PlatformLinux::GetProcessInfo(lldb::pid_t pid, 363 ProcessInstanceInfo &process_info) { 364 bool success = false; 365 if (IsHost()) { 366 success = Platform::GetProcessInfo(pid, process_info); 367 } else { 368 if (m_remote_platform_sp) 369 success = m_remote_platform_sp->GetProcessInfo(pid, process_info); 370 } 371 return success; 372 } 373 374 uint32_t 375 PlatformLinux::FindProcesses(const ProcessInstanceInfoMatch &match_info, 376 ProcessInstanceInfoList &process_infos) { 377 uint32_t match_count = 0; 378 if (IsHost()) { 379 // Let the base class figure out the host details 380 match_count = Platform::FindProcesses(match_info, process_infos); 381 } else { 382 // If we are remote, we can only return results if we are connected 383 if (m_remote_platform_sp) 384 match_count = 385 m_remote_platform_sp->FindProcesses(match_info, process_infos); 386 } 387 return match_count; 388 } 389 390 bool PlatformLinux::GetSupportedArchitectureAtIndex(uint32_t idx, 391 ArchSpec &arch) { 392 if (IsHost()) { 393 ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); 394 if (hostArch.GetTriple().isOSLinux()) { 395 if (idx == 0) { 396 arch = hostArch; 397 return arch.IsValid(); 398 } else if (idx == 1) { 399 // If the default host architecture is 64-bit, look for a 32-bit variant 400 if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) { 401 arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); 402 return arch.IsValid(); 403 } 404 } 405 } 406 } else { 407 if (m_remote_platform_sp) 408 return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch); 409 410 llvm::Triple triple; 411 // Set the OS to linux 412 triple.setOS(llvm::Triple::Linux); 413 // Set the architecture 414 switch (idx) { 415 case 0: 416 triple.setArchName("x86_64"); 417 break; 418 case 1: 419 triple.setArchName("i386"); 420 break; 421 case 2: 422 triple.setArchName("arm"); 423 break; 424 case 3: 425 triple.setArchName("aarch64"); 426 break; 427 case 4: 428 triple.setArchName("mips64"); 429 break; 430 case 5: 431 triple.setArchName("hexagon"); 432 break; 433 case 6: 434 triple.setArchName("mips"); 435 break; 436 case 7: 437 triple.setArchName("mips64el"); 438 break; 439 case 8: 440 triple.setArchName("mipsel"); 441 break; 442 case 9: 443 triple.setArchName("s390x"); 444 break; 445 default: 446 return false; 447 } 448 // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the 449 // vendor by 450 // calling triple.SetVendorName("unknown") so that it is a "unspecified 451 // unknown". 452 // This means when someone calls triple.GetVendorName() it will return an 453 // empty string 454 // which indicates that the vendor can be set when two architectures are 455 // merged 456 457 // Now set the triple into "arch" and return true 458 arch.SetTriple(triple); 459 return true; 460 } 461 return false; 462 } 463 464 void PlatformLinux::GetStatus(Stream &strm) { 465 Platform::GetStatus(strm); 466 467 #ifndef LLDB_DISABLE_POSIX 468 // Display local kernel information only when we are running in host mode. 469 // Otherwise, we would end up printing non-Linux information (when running 470 // on Mac OS for example). 471 if (IsHost()) { 472 struct utsname un; 473 474 if (uname(&un)) 475 return; 476 477 strm.Printf(" Kernel: %s\n", un.sysname); 478 strm.Printf(" Release: %s\n", un.release); 479 strm.Printf(" Version: %s\n", un.version); 480 } 481 #endif 482 } 483 484 int32_t 485 PlatformLinux::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) { 486 int32_t resume_count = 0; 487 488 // Always resume past the initial stop when we use eLaunchFlagDebug 489 if (launch_info.GetFlags().Test(eLaunchFlagDebug)) { 490 // Resume past the stop for the final exec into the true inferior. 491 ++resume_count; 492 } 493 494 // If we're not launching a shell, we're done. 495 const FileSpec &shell = launch_info.GetShell(); 496 if (!shell) 497 return resume_count; 498 499 std::string shell_string = shell.GetPath(); 500 // We're in a shell, so for sure we have to resume past the shell exec. 501 ++resume_count; 502 503 // Figure out what shell we're planning on using. 504 const char *shell_name = strrchr(shell_string.c_str(), '/'); 505 if (shell_name == NULL) 506 shell_name = shell_string.c_str(); 507 else 508 shell_name++; 509 510 if (strcmp(shell_name, "csh") == 0 || strcmp(shell_name, "tcsh") == 0 || 511 strcmp(shell_name, "zsh") == 0 || strcmp(shell_name, "sh") == 0) { 512 // These shells seem to re-exec themselves. Add another resume. 513 ++resume_count; 514 } 515 516 return resume_count; 517 } 518 519 bool PlatformLinux::CanDebugProcess() { 520 if (IsHost()) { 521 return true; 522 } else { 523 // If we're connected, we can debug. 524 return IsConnected(); 525 } 526 } 527 528 // For local debugging, Linux will override the debug logic to use llgs-launch 529 // rather than 530 // lldb-launch, llgs-attach. This differs from current lldb-launch, 531 // debugserver-attach 532 // approach on MacOSX. 533 lldb::ProcessSP 534 PlatformLinux::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, 535 Target *target, // Can be NULL, if NULL create a new 536 // target, else use existing one 537 Error &error) { 538 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); 539 if (log) 540 log->Printf("PlatformLinux::%s entered (target %p)", __FUNCTION__, 541 static_cast<void *>(target)); 542 543 // If we're a remote host, use standard behavior from parent class. 544 if (!IsHost()) 545 return PlatformPOSIX::DebugProcess(launch_info, debugger, target, error); 546 547 // 548 // For local debugging, we'll insist on having ProcessGDBRemote create the 549 // process. 550 // 551 552 ProcessSP process_sp; 553 554 // Make sure we stop at the entry point 555 launch_info.GetFlags().Set(eLaunchFlagDebug); 556 557 // We always launch the process we are going to debug in a separate process 558 // group, since then we can handle ^C interrupts ourselves w/o having to worry 559 // about the target getting them as well. 560 launch_info.SetLaunchInSeparateProcessGroup(true); 561 562 // Ensure we have a target. 563 if (target == nullptr) { 564 if (log) 565 log->Printf("PlatformLinux::%s creating new target", __FUNCTION__); 566 567 TargetSP new_target_sp; 568 error = debugger.GetTargetList().CreateTarget( 569 debugger, nullptr, nullptr, false, nullptr, new_target_sp); 570 if (error.Fail()) { 571 if (log) 572 log->Printf("PlatformLinux::%s failed to create new target: %s", 573 __FUNCTION__, error.AsCString()); 574 return process_sp; 575 } 576 577 target = new_target_sp.get(); 578 if (!target) { 579 error.SetErrorString("CreateTarget() returned nullptr"); 580 if (log) 581 log->Printf("PlatformLinux::%s failed: %s", __FUNCTION__, 582 error.AsCString()); 583 return process_sp; 584 } 585 } else { 586 if (log) 587 log->Printf("PlatformLinux::%s using provided target", __FUNCTION__); 588 } 589 590 // Mark target as currently selected target. 591 debugger.GetTargetList().SetSelectedTarget(target); 592 593 // Now create the gdb-remote process. 594 if (log) 595 log->Printf( 596 "PlatformLinux::%s having target create process with gdb-remote plugin", 597 __FUNCTION__); 598 process_sp = target->CreateProcess( 599 launch_info.GetListenerForProcess(debugger), "gdb-remote", nullptr); 600 601 if (!process_sp) { 602 error.SetErrorString("CreateProcess() failed for gdb-remote process"); 603 if (log) 604 log->Printf("PlatformLinux::%s failed: %s", __FUNCTION__, 605 error.AsCString()); 606 return process_sp; 607 } else { 608 if (log) 609 log->Printf("PlatformLinux::%s successfully created process", 610 __FUNCTION__); 611 } 612 613 // Adjust launch for a hijacker. 614 ListenerSP listener_sp; 615 if (!launch_info.GetHijackListener()) { 616 if (log) 617 log->Printf("PlatformLinux::%s setting up hijacker", __FUNCTION__); 618 619 listener_sp = 620 Listener::MakeListener("lldb.PlatformLinux.DebugProcess.hijack"); 621 launch_info.SetHijackListener(listener_sp); 622 process_sp->HijackProcessEvents(listener_sp); 623 } 624 625 // Log file actions. 626 if (log) { 627 log->Printf( 628 "PlatformLinux::%s launching process with the following file actions:", 629 __FUNCTION__); 630 631 StreamString stream; 632 size_t i = 0; 633 const FileAction *file_action; 634 while ((file_action = launch_info.GetFileActionAtIndex(i++)) != nullptr) { 635 file_action->Dump(stream); 636 log->PutCString(stream.GetString().c_str()); 637 stream.Clear(); 638 } 639 } 640 641 // Do the launch. 642 error = process_sp->Launch(launch_info); 643 if (error.Success()) { 644 // Handle the hijacking of process events. 645 if (listener_sp) { 646 const StateType state = process_sp->WaitForProcessToStop( 647 std::chrono::microseconds(0), NULL, false, listener_sp); 648 649 if (state == eStateStopped) { 650 if (log) 651 log->Printf("PlatformLinux::%s pid %" PRIu64 " state %s\n", 652 __FUNCTION__, process_sp->GetID(), StateAsCString(state)); 653 } else { 654 if (log) 655 log->Printf("PlatformLinux::%s pid %" PRIu64 656 " state is not stopped - %s\n", 657 __FUNCTION__, process_sp->GetID(), StateAsCString(state)); 658 } 659 } 660 661 // Hook up process PTY if we have one (which we should for local debugging 662 // with llgs). 663 int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); 664 if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd) { 665 process_sp->SetSTDIOFileDescriptor(pty_fd); 666 if (log) 667 log->Printf("PlatformLinux::%s pid %" PRIu64 668 " hooked up STDIO pty to process", 669 __FUNCTION__, process_sp->GetID()); 670 } else { 671 if (log) 672 log->Printf("PlatformLinux::%s pid %" PRIu64 673 " not using process STDIO pty", 674 __FUNCTION__, process_sp->GetID()); 675 } 676 } else { 677 if (log) 678 log->Printf("PlatformLinux::%s process launch failed: %s", __FUNCTION__, 679 error.AsCString()); 680 // FIXME figure out appropriate cleanup here. Do we delete the target? Do 681 // we delete the process? Does our caller do that? 682 } 683 684 return process_sp; 685 } 686 687 void PlatformLinux::CalculateTrapHandlerSymbolNames() { 688 m_trap_handlers.push_back(ConstString("_sigtramp")); 689 } 690 691 uint64_t PlatformLinux::ConvertMmapFlagsToPlatform(const ArchSpec &arch, 692 unsigned flags) { 693 uint64_t flags_platform = 0; 694 uint64_t map_anon = MAP_ANON; 695 696 // To get correct flags for MIPS Architecture 697 if (arch.GetTriple().getArch() == llvm::Triple::mips64 || 698 arch.GetTriple().getArch() == llvm::Triple::mips64el || 699 arch.GetTriple().getArch() == llvm::Triple::mips || 700 arch.GetTriple().getArch() == llvm::Triple::mipsel) 701 map_anon = 0x800; 702 703 if (flags & eMmapFlagsPrivate) 704 flags_platform |= MAP_PRIVATE; 705 if (flags & eMmapFlagsAnon) 706 flags_platform |= map_anon; 707 return flags_platform; 708 } 709 710 ConstString PlatformLinux::GetFullNameForDylib(ConstString basename) { 711 if (basename.IsEmpty()) 712 return basename; 713 714 StreamString stream; 715 stream.Printf("lib%s.so", basename.GetCString()); 716 return ConstString(stream.GetData()); 717 } 718