1//===-- SBLaunchInfo.cpp --------------------------------------------------===//
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 "lldb/API/SBLaunchInfo.h"
10#include "lldb/Utility/Instrumentation.h"
11
12#include "lldb/API/SBEnvironment.h"
13#include "lldb/API/SBError.h"
14#include "lldb/API/SBFileSpec.h"
15#include "lldb/API/SBListener.h"
16#include "lldb/API/SBStream.h"
17#include "lldb/API/SBStructuredData.h"
18#include "lldb/Core/StructuredDataImpl.h"
19#include "lldb/Host/ProcessLaunchInfo.h"
20#include "lldb/Utility/Listener.h"
21#include "lldb/Utility/ScriptedMetadata.h"
22
23using namespace lldb;
24using namespace lldb_private;
25
26class lldb_private::SBLaunchInfoImpl : public ProcessLaunchInfo {
27public:
28  SBLaunchInfoImpl() : m_envp(GetEnvironment().getEnvp()) {}
29
30  const char *const *GetEnvp() const { return m_envp; }
31  void RegenerateEnvp() { m_envp = GetEnvironment().getEnvp(); }
32
33  SBLaunchInfoImpl &operator=(const ProcessLaunchInfo &rhs) {
34    ProcessLaunchInfo::operator=(rhs);
35    RegenerateEnvp();
36    return *this;
37  }
38
39private:
40  Environment::Envp m_envp;
41};
42
43SBLaunchInfo::SBLaunchInfo(const char **argv)
44    : m_opaque_sp(new SBLaunchInfoImpl()) {
45  LLDB_INSTRUMENT_VA(this, argv);
46
47  m_opaque_sp->GetFlags().Reset(eLaunchFlagDebug | eLaunchFlagDisableASLR);
48  if (argv && argv[0])
49    m_opaque_sp->GetArguments().SetArguments(argv);
50}
51
52SBLaunchInfo::SBLaunchInfo(const SBLaunchInfo &rhs) {
53  LLDB_INSTRUMENT_VA(this, rhs);
54
55  m_opaque_sp = rhs.m_opaque_sp;
56}
57
58SBLaunchInfo &SBLaunchInfo::operator=(const SBLaunchInfo &rhs) {
59  LLDB_INSTRUMENT_VA(this, rhs);
60
61  m_opaque_sp = rhs.m_opaque_sp;
62  return *this;
63}
64
65SBLaunchInfo::~SBLaunchInfo() = default;
66
67const lldb_private::ProcessLaunchInfo &SBLaunchInfo::ref() const {
68  return *m_opaque_sp;
69}
70
71void SBLaunchInfo::set_ref(const ProcessLaunchInfo &info) {
72  *m_opaque_sp = info;
73}
74
75lldb::pid_t SBLaunchInfo::GetProcessID() {
76  LLDB_INSTRUMENT_VA(this);
77
78  return m_opaque_sp->GetProcessID();
79}
80
81uint32_t SBLaunchInfo::GetUserID() {
82  LLDB_INSTRUMENT_VA(this);
83
84  return m_opaque_sp->GetUserID();
85}
86
87uint32_t SBLaunchInfo::GetGroupID() {
88  LLDB_INSTRUMENT_VA(this);
89
90  return m_opaque_sp->GetGroupID();
91}
92
93bool SBLaunchInfo::UserIDIsValid() {
94  LLDB_INSTRUMENT_VA(this);
95
96  return m_opaque_sp->UserIDIsValid();
97}
98
99bool SBLaunchInfo::GroupIDIsValid() {
100  LLDB_INSTRUMENT_VA(this);
101
102  return m_opaque_sp->GroupIDIsValid();
103}
104
105void SBLaunchInfo::SetUserID(uint32_t uid) {
106  LLDB_INSTRUMENT_VA(this, uid);
107
108  m_opaque_sp->SetUserID(uid);
109}
110
111void SBLaunchInfo::SetGroupID(uint32_t gid) {
112  LLDB_INSTRUMENT_VA(this, gid);
113
114  m_opaque_sp->SetGroupID(gid);
115}
116
117SBFileSpec SBLaunchInfo::GetExecutableFile() {
118  LLDB_INSTRUMENT_VA(this);
119
120  return SBFileSpec(m_opaque_sp->GetExecutableFile());
121}
122
123void SBLaunchInfo::SetExecutableFile(SBFileSpec exe_file,
124                                     bool add_as_first_arg) {
125  LLDB_INSTRUMENT_VA(this, exe_file, add_as_first_arg);
126
127  m_opaque_sp->SetExecutableFile(exe_file.ref(), add_as_first_arg);
128}
129
130SBListener SBLaunchInfo::GetListener() {
131  LLDB_INSTRUMENT_VA(this);
132
133  return SBListener(m_opaque_sp->GetListener());
134}
135
136void SBLaunchInfo::SetListener(SBListener &listener) {
137  LLDB_INSTRUMENT_VA(this, listener);
138
139  m_opaque_sp->SetListener(listener.GetSP());
140}
141
142uint32_t SBLaunchInfo::GetNumArguments() {
143  LLDB_INSTRUMENT_VA(this);
144
145  return m_opaque_sp->GetArguments().GetArgumentCount();
146}
147
148const char *SBLaunchInfo::GetArgumentAtIndex(uint32_t idx) {
149  LLDB_INSTRUMENT_VA(this, idx);
150
151  return ConstString(m_opaque_sp->GetArguments().GetArgumentAtIndex(idx))
152      .GetCString();
153}
154
155void SBLaunchInfo::SetArguments(const char **argv, bool append) {
156  LLDB_INSTRUMENT_VA(this, argv, append);
157
158  if (append) {
159    if (argv)
160      m_opaque_sp->GetArguments().AppendArguments(argv);
161  } else {
162    if (argv)
163      m_opaque_sp->GetArguments().SetArguments(argv);
164    else
165      m_opaque_sp->GetArguments().Clear();
166  }
167}
168
169uint32_t SBLaunchInfo::GetNumEnvironmentEntries() {
170  LLDB_INSTRUMENT_VA(this);
171
172  return m_opaque_sp->GetEnvironment().size();
173}
174
175const char *SBLaunchInfo::GetEnvironmentEntryAtIndex(uint32_t idx) {
176  LLDB_INSTRUMENT_VA(this, idx);
177
178  if (idx > GetNumEnvironmentEntries())
179    return nullptr;
180  return ConstString(m_opaque_sp->GetEnvp()[idx]).GetCString();
181}
182
183void SBLaunchInfo::SetEnvironmentEntries(const char **envp, bool append) {
184  LLDB_INSTRUMENT_VA(this, envp, append);
185  SetEnvironment(SBEnvironment(Environment(envp)), append);
186}
187
188void SBLaunchInfo::SetEnvironment(const SBEnvironment &env, bool append) {
189  LLDB_INSTRUMENT_VA(this, env, append);
190  Environment &refEnv = env.ref();
191  if (append) {
192    for (auto &KV : refEnv)
193      m_opaque_sp->GetEnvironment().insert_or_assign(KV.first(), KV.second);
194  } else
195    m_opaque_sp->GetEnvironment() = refEnv;
196  m_opaque_sp->RegenerateEnvp();
197}
198
199SBEnvironment SBLaunchInfo::GetEnvironment() {
200  LLDB_INSTRUMENT_VA(this);
201  return SBEnvironment(Environment(m_opaque_sp->GetEnvironment()));
202}
203
204void SBLaunchInfo::Clear() {
205  LLDB_INSTRUMENT_VA(this);
206
207  m_opaque_sp->Clear();
208}
209
210const char *SBLaunchInfo::GetWorkingDirectory() const {
211  LLDB_INSTRUMENT_VA(this);
212
213  return m_opaque_sp->GetWorkingDirectory().GetPathAsConstString().AsCString();
214}
215
216void SBLaunchInfo::SetWorkingDirectory(const char *working_dir) {
217  LLDB_INSTRUMENT_VA(this, working_dir);
218
219  m_opaque_sp->SetWorkingDirectory(FileSpec(working_dir));
220}
221
222uint32_t SBLaunchInfo::GetLaunchFlags() {
223  LLDB_INSTRUMENT_VA(this);
224
225  return m_opaque_sp->GetFlags().Get();
226}
227
228void SBLaunchInfo::SetLaunchFlags(uint32_t flags) {
229  LLDB_INSTRUMENT_VA(this, flags);
230
231  m_opaque_sp->GetFlags().Reset(flags);
232}
233
234const char *SBLaunchInfo::GetProcessPluginName() {
235  LLDB_INSTRUMENT_VA(this);
236
237  return ConstString(m_opaque_sp->GetProcessPluginName()).GetCString();
238}
239
240void SBLaunchInfo::SetProcessPluginName(const char *plugin_name) {
241  LLDB_INSTRUMENT_VA(this, plugin_name);
242
243  return m_opaque_sp->SetProcessPluginName(plugin_name);
244}
245
246const char *SBLaunchInfo::GetShell() {
247  LLDB_INSTRUMENT_VA(this);
248
249  // Constify this string so that it is saved in the string pool.  Otherwise it
250  // would be freed when this function goes out of scope.
251  ConstString shell(m_opaque_sp->GetShell().GetPath().c_str());
252  return shell.AsCString();
253}
254
255void SBLaunchInfo::SetShell(const char *path) {
256  LLDB_INSTRUMENT_VA(this, path);
257
258  m_opaque_sp->SetShell(FileSpec(path));
259}
260
261bool SBLaunchInfo::GetShellExpandArguments() {
262  LLDB_INSTRUMENT_VA(this);
263
264  return m_opaque_sp->GetShellExpandArguments();
265}
266
267void SBLaunchInfo::SetShellExpandArguments(bool expand) {
268  LLDB_INSTRUMENT_VA(this, expand);
269
270  m_opaque_sp->SetShellExpandArguments(expand);
271}
272
273uint32_t SBLaunchInfo::GetResumeCount() {
274  LLDB_INSTRUMENT_VA(this);
275
276  return m_opaque_sp->GetResumeCount();
277}
278
279void SBLaunchInfo::SetResumeCount(uint32_t c) {
280  LLDB_INSTRUMENT_VA(this, c);
281
282  m_opaque_sp->SetResumeCount(c);
283}
284
285bool SBLaunchInfo::AddCloseFileAction(int fd) {
286  LLDB_INSTRUMENT_VA(this, fd);
287
288  return m_opaque_sp->AppendCloseFileAction(fd);
289}
290
291bool SBLaunchInfo::AddDuplicateFileAction(int fd, int dup_fd) {
292  LLDB_INSTRUMENT_VA(this, fd, dup_fd);
293
294  return m_opaque_sp->AppendDuplicateFileAction(fd, dup_fd);
295}
296
297bool SBLaunchInfo::AddOpenFileAction(int fd, const char *path, bool read,
298                                     bool write) {
299  LLDB_INSTRUMENT_VA(this, fd, path, read, write);
300
301  return m_opaque_sp->AppendOpenFileAction(fd, FileSpec(path), read, write);
302}
303
304bool SBLaunchInfo::AddSuppressFileAction(int fd, bool read, bool write) {
305  LLDB_INSTRUMENT_VA(this, fd, read, write);
306
307  return m_opaque_sp->AppendSuppressFileAction(fd, read, write);
308}
309
310void SBLaunchInfo::SetLaunchEventData(const char *data) {
311  LLDB_INSTRUMENT_VA(this, data);
312
313  m_opaque_sp->SetLaunchEventData(data);
314}
315
316const char *SBLaunchInfo::GetLaunchEventData() const {
317  LLDB_INSTRUMENT_VA(this);
318
319  return ConstString(m_opaque_sp->GetLaunchEventData()).GetCString();
320}
321
322void SBLaunchInfo::SetDetachOnError(bool enable) {
323  LLDB_INSTRUMENT_VA(this, enable);
324
325  m_opaque_sp->SetDetachOnError(enable);
326}
327
328bool SBLaunchInfo::GetDetachOnError() const {
329  LLDB_INSTRUMENT_VA(this);
330
331  return m_opaque_sp->GetDetachOnError();
332}
333
334const char *SBLaunchInfo::GetScriptedProcessClassName() const {
335  LLDB_INSTRUMENT_VA(this);
336
337  ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata();
338
339  if (!metadata_sp || !*metadata_sp)
340    return nullptr;
341
342  // Constify this string so that it is saved in the string pool.  Otherwise it
343  // would be freed when this function goes out of scope.
344  ConstString class_name(metadata_sp->GetClassName().data());
345  return class_name.AsCString();
346}
347
348void SBLaunchInfo::SetScriptedProcessClassName(const char *class_name) {
349  LLDB_INSTRUMENT_VA(this, class_name);
350  ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata();
351  StructuredData::DictionarySP dict_sp =
352      metadata_sp ? metadata_sp->GetArgsSP() : nullptr;
353  metadata_sp = std::make_shared<ScriptedMetadata>(class_name, dict_sp);
354  m_opaque_sp->SetScriptedMetadata(metadata_sp);
355}
356
357lldb::SBStructuredData SBLaunchInfo::GetScriptedProcessDictionary() const {
358  LLDB_INSTRUMENT_VA(this);
359
360  ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata();
361
362  SBStructuredData data;
363  if (!metadata_sp)
364    return data;
365
366  lldb_private::StructuredData::DictionarySP dict_sp = metadata_sp->GetArgsSP();
367  data.m_impl_up->SetObjectSP(dict_sp);
368
369  return data;
370}
371
372void SBLaunchInfo::SetScriptedProcessDictionary(lldb::SBStructuredData dict) {
373  LLDB_INSTRUMENT_VA(this, dict);
374  if (!dict.IsValid() || !dict.m_impl_up)
375    return;
376
377  StructuredData::ObjectSP obj_sp = dict.m_impl_up->GetObjectSP();
378
379  if (!obj_sp)
380    return;
381
382  StructuredData::DictionarySP dict_sp =
383      std::make_shared<StructuredData::Dictionary>(obj_sp);
384  if (!dict_sp || dict_sp->GetType() == lldb::eStructuredDataTypeInvalid)
385    return;
386
387  ScriptedMetadataSP metadata_sp = m_opaque_sp->GetScriptedMetadata();
388  llvm::StringRef class_name = metadata_sp ? metadata_sp->GetClassName() : "";
389  metadata_sp = std::make_shared<ScriptedMetadata>(class_name, dict_sp);
390  m_opaque_sp->SetScriptedMetadata(metadata_sp);
391}
392
393SBListener SBLaunchInfo::GetShadowListener() {
394  LLDB_INSTRUMENT_VA(this);
395
396  lldb::ListenerSP shadow_sp = m_opaque_sp->GetShadowListener();
397  if (!shadow_sp)
398    return SBListener();
399  return SBListener(shadow_sp);
400}
401
402void SBLaunchInfo::SetShadowListener(SBListener &listener) {
403  LLDB_INSTRUMENT_VA(this, listener);
404
405  ListenerSP listener_sp = listener.GetSP();
406  if (listener_sp && listener.IsValid())
407    listener_sp->SetShadow(true);
408  else
409    listener_sp = nullptr;
410
411  m_opaque_sp->SetShadowListener(listener_sp);
412}
413