LLDB  mainline
PlatformLinux.cpp
Go to the documentation of this file.
1 //===-- PlatformLinux.cpp ---------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "PlatformLinux.h"
10 #include "lldb/Host/Config.h"
11 
12 #include <stdio.h>
13 #ifndef LLDB_DISABLE_POSIX
14 #include <sys/utsname.h>
15 #endif
16 
17 #include "lldb/Core/Debugger.h"
19 #include "lldb/Host/HostInfo.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Utility/FileSpec.h"
23 #include "lldb/Utility/Log.h"
24 #include "lldb/Utility/State.h"
25 #include "lldb/Utility/Status.h"
27 
28 // Define these constants from Linux mman.h for use when targeting remote linux
29 // systems even when host has different values.
30 #define MAP_PRIVATE 2
31 #define MAP_ANON 0x20
32 
33 using namespace lldb;
34 using namespace lldb_private;
35 using namespace lldb_private::platform_linux;
36 
38 
39 
40 PlatformSP PlatformLinux::CreateInstance(bool force, const ArchSpec *arch) {
42  LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force,
43  arch ? arch->GetArchitectureName() : "<null>",
44  arch ? arch->GetTriple().getTriple() : "<null>");
45 
46  bool create = force;
47  if (!create && arch && arch->IsValid()) {
48  const llvm::Triple &triple = arch->GetTriple();
49  switch (triple.getOS()) {
50  case llvm::Triple::Linux:
51  create = true;
52  break;
53 
54 #if defined(__linux__)
55  // Only accept "unknown" for the OS if the host is linux and it "unknown"
56  // wasn't specified (it was just returned because it was NOT specified)
57  case llvm::Triple::OSType::UnknownOS:
58  create = !arch->TripleOSWasSpecified();
59  break;
60 #endif
61  default:
62  break;
63  }
64  }
65 
66  LLDB_LOG(log, "create = {0}", create);
67  if (create) {
68  return PlatformSP(new PlatformLinux(false));
69  }
70  return PlatformSP();
71 }
72 
73 ConstString PlatformLinux::GetPluginNameStatic(bool is_host) {
74  if (is_host) {
75  static ConstString g_host_name(Platform::GetHostPlatformName());
76  return g_host_name;
77  } else {
78  static ConstString g_remote_name("remote-linux");
79  return g_remote_name;
80  }
81 }
82 
83 const char *PlatformLinux::GetPluginDescriptionStatic(bool is_host) {
84  if (is_host)
85  return "Local Linux user platform plug-in.";
86  else
87  return "Remote Linux user platform plug-in.";
88 }
89 
90 ConstString PlatformLinux::GetPluginName() {
91  return GetPluginNameStatic(IsHost());
92 }
93 
94 void PlatformLinux::Initialize() {
96 
97  if (g_initialize_count++ == 0) {
98 #if defined(__linux__) && !defined(__ANDROID__)
99  PlatformSP default_platform_sp(new PlatformLinux(true));
100  default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
101  Platform::SetHostPlatform(default_platform_sp);
102 #endif
103  PluginManager::RegisterPlugin(
104  PlatformLinux::GetPluginNameStatic(false),
105  PlatformLinux::GetPluginDescriptionStatic(false),
106  PlatformLinux::CreateInstance, nullptr);
107  }
108 }
109 
110 void PlatformLinux::Terminate() {
111  if (g_initialize_count > 0) {
112  if (--g_initialize_count == 0) {
113  PluginManager::UnregisterPlugin(PlatformLinux::CreateInstance);
114  }
115  }
116 
118 }
119 
120 /// Default Constructor
121 PlatformLinux::PlatformLinux(bool is_host)
122  : PlatformPOSIX(is_host) // This is the local host platform
123 {}
124 
126 
128  ArchSpec &arch) {
129  if (IsHost()) {
130  ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
131  if (hostArch.GetTriple().isOSLinux()) {
132  if (idx == 0) {
133  arch = hostArch;
134  return arch.IsValid();
135  } else if (idx == 1) {
136  // If the default host architecture is 64-bit, look for a 32-bit
137  // variant
138  if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) {
139  arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
140  return arch.IsValid();
141  }
142  }
143  }
144  } else {
146  return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch);
147 
148  llvm::Triple triple;
149  // Set the OS to linux
150  triple.setOS(llvm::Triple::Linux);
151  // Set the architecture
152  switch (idx) {
153  case 0:
154  triple.setArchName("x86_64");
155  break;
156  case 1:
157  triple.setArchName("i386");
158  break;
159  case 2:
160  triple.setArchName("arm");
161  break;
162  case 3:
163  triple.setArchName("aarch64");
164  break;
165  case 4:
166  triple.setArchName("mips64");
167  break;
168  case 5:
169  triple.setArchName("hexagon");
170  break;
171  case 6:
172  triple.setArchName("mips");
173  break;
174  case 7:
175  triple.setArchName("mips64el");
176  break;
177  case 8:
178  triple.setArchName("mipsel");
179  break;
180  case 9:
181  triple.setArchName("s390x");
182  break;
183  default:
184  return false;
185  }
186  // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the
187  // vendor by calling triple.SetVendorName("unknown") so that it is a
188  // "unspecified unknown". This means when someone calls
189  // triple.GetVendorName() it will return an empty string which indicates
190  // that the vendor can be set when two architectures are merged
191 
192  // Now set the triple into "arch" and return true
193  arch.SetTriple(triple);
194  return true;
195  }
196  return false;
197 }
198 
200  Platform::GetStatus(strm);
201 
202 #ifndef LLDB_DISABLE_POSIX
203  // Display local kernel information only when we are running in host mode.
204  // Otherwise, we would end up printing non-Linux information (when running on
205  // Mac OS for example).
206  if (IsHost()) {
207  struct utsname un;
208 
209  if (uname(&un))
210  return;
211 
212  strm.Printf(" Kernel: %s\n", un.sysname);
213  strm.Printf(" Release: %s\n", un.release);
214  strm.Printf(" Version: %s\n", un.version);
215  }
216 #endif
217 }
218 
219 int32_t
221  int32_t resume_count = 0;
222 
223  // Always resume past the initial stop when we use eLaunchFlagDebug
224  if (launch_info.GetFlags().Test(eLaunchFlagDebug)) {
225  // Resume past the stop for the final exec into the true inferior.
226  ++resume_count;
227  }
228 
229  // If we're not launching a shell, we're done.
230  const FileSpec &shell = launch_info.GetShell();
231  if (!shell)
232  return resume_count;
233 
234  std::string shell_string = shell.GetPath();
235  // We're in a shell, so for sure we have to resume past the shell exec.
236  ++resume_count;
237 
238  // Figure out what shell we're planning on using.
239  const char *shell_name = strrchr(shell_string.c_str(), '/');
240  if (shell_name == NULL)
241  shell_name = shell_string.c_str();
242  else
243  shell_name++;
244 
245  if (strcmp(shell_name, "csh") == 0 || strcmp(shell_name, "tcsh") == 0 ||
246  strcmp(shell_name, "zsh") == 0 || strcmp(shell_name, "sh") == 0) {
247  // These shells seem to re-exec themselves. Add another resume.
248  ++resume_count;
249  }
250 
251  return resume_count;
252 }
253 
255  if (IsHost()) {
256  return true;
257  } else {
258  // If we're connected, we can debug.
259  return IsConnected();
260  }
261 }
262 
263 std::vector<std::string>
265  std::string sys_root = GetSDKRootDirectory().AsCString("");
266  switch (lang) {
276  return {sys_root + "/usr/include/"};
277  default:
278  return {};
279  }
280 }
281 
282 // For local debugging, Linux will override the debug logic to use llgs-launch
283 // rather than lldb-launch, llgs-attach. This differs from current lldb-
284 // launch, debugserver-attach approach on MacOSX.
285 lldb::ProcessSP
287  Target *target, // Can be NULL, if NULL create a new
288  // target, else use existing one
289  Status &error) {
291  LLDB_LOG(log, "target {0}", target);
292 
293  // If we're a remote host, use standard behavior from parent class.
294  if (!IsHost())
295  return PlatformPOSIX::DebugProcess(launch_info, debugger, target, error);
296 
297  //
298  // For local debugging, we'll insist on having ProcessGDBRemote create the
299  // process.
300  //
301 
302  ProcessSP process_sp;
303 
304  // Make sure we stop at the entry point
305  launch_info.GetFlags().Set(eLaunchFlagDebug);
306 
307  // We always launch the process we are going to debug in a separate process
308  // group, since then we can handle ^C interrupts ourselves w/o having to
309  // worry about the target getting them as well.
310  launch_info.SetLaunchInSeparateProcessGroup(true);
311 
312  // Ensure we have a target.
313  if (target == nullptr) {
314  LLDB_LOG(log, "creating new target");
315  TargetSP new_target_sp;
316  error = debugger.GetTargetList().CreateTarget(
317  debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp);
318  if (error.Fail()) {
319  LLDB_LOG(log, "failed to create new target: {0}", error);
320  return process_sp;
321  }
322 
323  target = new_target_sp.get();
324  if (!target) {
325  error.SetErrorString("CreateTarget() returned nullptr");
326  LLDB_LOG(log, "error: {0}", error);
327  return process_sp;
328  }
329  }
330 
331  // Mark target as currently selected target.
332  debugger.GetTargetList().SetSelectedTarget(target);
333 
334  // Now create the gdb-remote process.
335  LLDB_LOG(log, "having target create process with gdb-remote plugin");
336  process_sp =
337  target->CreateProcess(launch_info.GetListener(), "gdb-remote", nullptr);
338 
339  if (!process_sp) {
340  error.SetErrorString("CreateProcess() failed for gdb-remote process");
341  LLDB_LOG(log, "error: {0}", error);
342  return process_sp;
343  }
344 
345  LLDB_LOG(log, "successfully created process");
346  // Adjust launch for a hijacker.
347  ListenerSP listener_sp;
348  if (!launch_info.GetHijackListener()) {
349  LLDB_LOG(log, "setting up hijacker");
350  listener_sp =
351  Listener::MakeListener("lldb.PlatformLinux.DebugProcess.hijack");
352  launch_info.SetHijackListener(listener_sp);
353  process_sp->HijackProcessEvents(listener_sp);
354  }
355 
356  // Log file actions.
357  if (log) {
358  LLDB_LOG(log, "launching process with the following file actions:");
359  StreamString stream;
360  size_t i = 0;
361  const FileAction *file_action;
362  while ((file_action = launch_info.GetFileActionAtIndex(i++)) != nullptr) {
363  file_action->Dump(stream);
364  LLDB_LOG(log, "{0}", stream.GetData());
365  stream.Clear();
366  }
367  }
368 
369  // Do the launch.
370  error = process_sp->Launch(launch_info);
371  if (error.Success()) {
372  // Handle the hijacking of process events.
373  if (listener_sp) {
374  const StateType state = process_sp->WaitForProcessToStop(
375  llvm::None, NULL, false, listener_sp);
376 
377  LLDB_LOG(log, "pid {0} state {0}", process_sp->GetID(), state);
378  }
379 
380  // Hook up process PTY if we have one (which we should for local debugging
381  // with llgs).
382  int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
383  if (pty_fd != PseudoTerminal::invalid_fd) {
384  process_sp->SetSTDIOFileDescriptor(pty_fd);
385  LLDB_LOG(log, "hooked up STDIO pty to process");
386  } else
387  LLDB_LOG(log, "not using process STDIO pty");
388  } else {
389  LLDB_LOG(log, "process launch failed: {0}", error);
390  // FIXME figure out appropriate cleanup here. Do we delete the target? Do
391  // we delete the process? Does our caller do that?
392  }
393 
394  return process_sp;
395 }
396 
398  m_trap_handlers.push_back(ConstString("_sigtramp"));
399 }
400 
402  addr_t addr, addr_t length,
403  unsigned prot, unsigned flags,
404  addr_t fd, addr_t offset) {
405  uint64_t flags_platform = 0;
406  uint64_t map_anon = MAP_ANON;
407 
408  // To get correct flags for MIPS Architecture
409  if (arch.GetTriple().getArch() == llvm::Triple::mips64 ||
410  arch.GetTriple().getArch() == llvm::Triple::mips64el ||
411  arch.GetTriple().getArch() == llvm::Triple::mips ||
412  arch.GetTriple().getArch() == llvm::Triple::mipsel)
413  map_anon = 0x800;
414 
415  if (flags & eMmapFlagsPrivate)
416  flags_platform |= MAP_PRIVATE;
417  if (flags & eMmapFlagsAnon)
418  flags_platform |= map_anon;
419 
420  MmapArgList args({addr, length, prot, flags_platform, fd, offset});
421  return args;
422 }
423 
A class to manage flag bits.
Definition: Debugger.h:82
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:224
bool SetTriple(const llvm::Triple &triple)
Architecture triple setter.
Definition: ArchSpec.cpp:797
lldb::ProcessSP DebugProcess(lldb_private::ProcessLaunchInfo &launch_info, lldb_private::Debugger &debugger, lldb_private::Target *target, lldb_private::Status &error) override
Subclasses do not need to implement this function as it uses the Platform::LaunchProcess() followed b...
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
int32_t GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) override
void Dump(Stream &stream) const
Definition: FileAction.cpp:71
void CalculateTrapHandlerSymbolNames() override
Ask the Platform subclass to fill in the list of trap handler names.
static uint32_t g_initialize_count
std::vector< std::string > GetSystemIncludeDirectories(lldb::LanguageType lang) override
Retrieve the system include directories on this platform for the given language.
const lldb::ProcessSP & CreateProcess(lldb::ListenerSP listener_sp, llvm::StringRef plugin_name, const FileSpec *crash_file)
Definition: Target.cpp:195
bool IsHost() const
Definition: Platform.h:450
A file utility class.
Definition: FileSpec.h:55
An architecture specification class.
Definition: ArchSpec.h:32
#define MAP_PRIVATE
llvm::SmallVector< lldb::addr_t, 6 > MmapArgList
Definition: Platform.h:54
#define LIBLLDB_LOG_PLATFORM
Definition: Logging.h:39
lldb::ListenerSP GetListener() const
static void Terminate()
Definition: Platform.cpp:142
const char * GetData() const
Definition: StreamString.h:43
bool IsValid() const
Tests if this ArchSpec is valid.
Definition: ArchSpec.h:329
Status CreateTarget(Debugger &debugger, llvm::StringRef user_exe_path, llvm::StringRef triple_str, LoadDependentFiles get_dependent_modules, const OptionGroupPlatform *platform_options, lldb::TargetSP &target_sp)
Create a new Target.
#define LLDB_LOG(log,...)
Definition: Log.h:209
int ReleaseMasterFileDescriptor()
Release the master file descriptor.
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:431
void GetStatus(Stream &strm) override
Report the current status for this platform.
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition: ArchSpec.cpp:591
static lldb::ListenerSP MakeListener(const char *name)
Definition: Listener.cpp:465
LanguageType
Programming language type.
bool Test(ValueType bit) const
Test a single flag bit.
Definition: Flags.h:107
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:57
static void Initialize()
Definition: Platform.cpp:140
void SetHijackListener(const lldb::ListenerSP &listener_sp)
void SetLaunchInSeparateProcessGroup(bool separate)
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:241
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
bool Success() const
Test for success condition.
Definition: Status.cpp:287
TargetList & GetTargetList()
Get accessor for the target list.
Definition: Debugger.h:180
ValueType Set(ValueType mask)
Set one or more flags by logical OR&#39;ing mask with the current flags.
Definition: Flags.h:84
bool GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) override
Get the platform&#39;s supported architectures in the order in which they should be searched.
uint64_t addr_t
Definition: lldb-types.h:83
bool CanDebugProcess() override
Not all platforms will support debugging a process by spawning somehow halted for a debugger (specifi...
A uniqued constant string class.
Definition: ConstString.h:38
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
Invalid file descriptor value.
Non-standardized C, such as K&R.
MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr, lldb::addr_t length, unsigned prot, unsigned flags, lldb::addr_t fd, lldb::addr_t offset) override
Definition: SBAddress.h:15
uint32_t SetSelectedTarget(Target *target)
Definition: TargetList.cpp:601
bool TripleOSWasSpecified() const
Definition: ArchSpec.h:338
lldb::ListenerSP GetHijackListener() const
const FileSpec & GetShell() const
lldb::ProcessSP DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, Target *target, Status &error) override
Subclasses do not need to implement this function as it uses the Platform::LaunchProcess() followed b...
const FileAction * GetFileActionAtIndex(size_t idx) const
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:376
ConstString GetSDKRootDirectory() const
Definition: Platform.h:480
std::vector< ConstString > m_trap_handlers
Definition: Platform.h:872
#define MAP_ANON
An error handling class.
Definition: Status.h:44
virtual void GetStatus(Stream &strm)
Report the current status for this platform.
Definition: Platform.cpp:403