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 | |
23 | using namespace lldb; |
24 | using namespace lldb_private; |
25 | |
26 | class lldb_private::SBLaunchInfoImpl : public ProcessLaunchInfo { |
27 | public: |
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 | |
39 | private: |
40 | Environment::Envp m_envp; |
41 | }; |
42 | |
43 | SBLaunchInfo::SBLaunchInfo(const char **argv) |
44 | : m_opaque_sp(new SBLaunchInfoImpl()) { |
45 | LLDB_INSTRUMENT_VA(this, argv); |
46 | |
47 | m_opaque_sp->GetFlags().Reset(flags: eLaunchFlagDebug | eLaunchFlagDisableASLR); |
48 | if (argv && argv[0]) |
49 | m_opaque_sp->GetArguments().SetArguments(argv); |
50 | } |
51 | |
52 | SBLaunchInfo::SBLaunchInfo(const SBLaunchInfo &rhs) { |
53 | LLDB_INSTRUMENT_VA(this, rhs); |
54 | |
55 | m_opaque_sp = rhs.m_opaque_sp; |
56 | } |
57 | |
58 | SBLaunchInfo &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 | |
65 | SBLaunchInfo::~SBLaunchInfo() = default; |
66 | |
67 | const lldb_private::ProcessLaunchInfo &SBLaunchInfo::ref() const { |
68 | return *m_opaque_sp; |
69 | } |
70 | |
71 | void SBLaunchInfo::set_ref(const ProcessLaunchInfo &info) { |
72 | *m_opaque_sp = info; |
73 | } |
74 | |
75 | lldb::pid_t SBLaunchInfo::GetProcessID() { |
76 | LLDB_INSTRUMENT_VA(this); |
77 | |
78 | return m_opaque_sp->GetProcessID(); |
79 | } |
80 | |
81 | uint32_t SBLaunchInfo::GetUserID() { |
82 | LLDB_INSTRUMENT_VA(this); |
83 | |
84 | return m_opaque_sp->GetUserID(); |
85 | } |
86 | |
87 | uint32_t SBLaunchInfo::GetGroupID() { |
88 | LLDB_INSTRUMENT_VA(this); |
89 | |
90 | return m_opaque_sp->GetGroupID(); |
91 | } |
92 | |
93 | bool SBLaunchInfo::UserIDIsValid() { |
94 | LLDB_INSTRUMENT_VA(this); |
95 | |
96 | return m_opaque_sp->UserIDIsValid(); |
97 | } |
98 | |
99 | bool SBLaunchInfo::GroupIDIsValid() { |
100 | LLDB_INSTRUMENT_VA(this); |
101 | |
102 | return m_opaque_sp->GroupIDIsValid(); |
103 | } |
104 | |
105 | void SBLaunchInfo::SetUserID(uint32_t uid) { |
106 | LLDB_INSTRUMENT_VA(this, uid); |
107 | |
108 | m_opaque_sp->SetUserID(uid); |
109 | } |
110 | |
111 | void SBLaunchInfo::SetGroupID(uint32_t gid) { |
112 | LLDB_INSTRUMENT_VA(this, gid); |
113 | |
114 | m_opaque_sp->SetGroupID(gid); |
115 | } |
116 | |
117 | SBFileSpec SBLaunchInfo::GetExecutableFile() { |
118 | LLDB_INSTRUMENT_VA(this); |
119 | |
120 | return SBFileSpec(m_opaque_sp->GetExecutableFile()); |
121 | } |
122 | |
123 | void 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: exe_file.ref(), add_exe_file_as_first_arg: add_as_first_arg); |
128 | } |
129 | |
130 | SBListener SBLaunchInfo::GetListener() { |
131 | LLDB_INSTRUMENT_VA(this); |
132 | |
133 | return SBListener(m_opaque_sp->GetListener()); |
134 | } |
135 | |
136 | void SBLaunchInfo::SetListener(SBListener &listener) { |
137 | LLDB_INSTRUMENT_VA(this, listener); |
138 | |
139 | m_opaque_sp->SetListener(listener.GetSP()); |
140 | } |
141 | |
142 | uint32_t SBLaunchInfo::GetNumArguments() { |
143 | LLDB_INSTRUMENT_VA(this); |
144 | |
145 | return m_opaque_sp->GetArguments().GetArgumentCount(); |
146 | } |
147 | |
148 | const 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 | |
155 | void 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 | |
169 | uint32_t SBLaunchInfo::GetNumEnvironmentEntries() { |
170 | LLDB_INSTRUMENT_VA(this); |
171 | |
172 | return m_opaque_sp->GetEnvironment().size(); |
173 | } |
174 | |
175 | const 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 | |
183 | void SBLaunchInfo::SetEnvironmentEntries(const char **envp, bool append) { |
184 | LLDB_INSTRUMENT_VA(this, envp, append); |
185 | SetEnvironment(env: SBEnvironment(Environment(envp)), append); |
186 | } |
187 | |
188 | void 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(Key: KV.first(), Val&: KV.second); |
194 | } else |
195 | m_opaque_sp->GetEnvironment() = refEnv; |
196 | m_opaque_sp->RegenerateEnvp(); |
197 | } |
198 | |
199 | SBEnvironment SBLaunchInfo::GetEnvironment() { |
200 | LLDB_INSTRUMENT_VA(this); |
201 | return SBEnvironment(Environment(m_opaque_sp->GetEnvironment())); |
202 | } |
203 | |
204 | void SBLaunchInfo::Clear() { |
205 | LLDB_INSTRUMENT_VA(this); |
206 | |
207 | m_opaque_sp->Clear(); |
208 | } |
209 | |
210 | const char *SBLaunchInfo::GetWorkingDirectory() const { |
211 | LLDB_INSTRUMENT_VA(this); |
212 | |
213 | return m_opaque_sp->GetWorkingDirectory().GetPathAsConstString().AsCString(); |
214 | } |
215 | |
216 | void SBLaunchInfo::SetWorkingDirectory(const char *working_dir) { |
217 | LLDB_INSTRUMENT_VA(this, working_dir); |
218 | |
219 | m_opaque_sp->SetWorkingDirectory(FileSpec(working_dir)); |
220 | } |
221 | |
222 | uint32_t SBLaunchInfo::GetLaunchFlags() { |
223 | LLDB_INSTRUMENT_VA(this); |
224 | |
225 | return m_opaque_sp->GetFlags().Get(); |
226 | } |
227 | |
228 | void SBLaunchInfo::SetLaunchFlags(uint32_t flags) { |
229 | LLDB_INSTRUMENT_VA(this, flags); |
230 | |
231 | m_opaque_sp->GetFlags().Reset(flags); |
232 | } |
233 | |
234 | const char *SBLaunchInfo::GetProcessPluginName() { |
235 | LLDB_INSTRUMENT_VA(this); |
236 | |
237 | return ConstString(m_opaque_sp->GetProcessPluginName()).GetCString(); |
238 | } |
239 | |
240 | void SBLaunchInfo::SetProcessPluginName(const char *plugin_name) { |
241 | LLDB_INSTRUMENT_VA(this, plugin_name); |
242 | |
243 | return m_opaque_sp->SetProcessPluginName(plugin_name); |
244 | } |
245 | |
246 | const 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 | |
255 | void SBLaunchInfo::SetShell(const char *path) { |
256 | LLDB_INSTRUMENT_VA(this, path); |
257 | |
258 | m_opaque_sp->SetShell(FileSpec(path)); |
259 | } |
260 | |
261 | bool SBLaunchInfo::GetShellExpandArguments() { |
262 | LLDB_INSTRUMENT_VA(this); |
263 | |
264 | return m_opaque_sp->GetShellExpandArguments(); |
265 | } |
266 | |
267 | void SBLaunchInfo::SetShellExpandArguments(bool expand) { |
268 | LLDB_INSTRUMENT_VA(this, expand); |
269 | |
270 | m_opaque_sp->SetShellExpandArguments(expand); |
271 | } |
272 | |
273 | uint32_t SBLaunchInfo::GetResumeCount() { |
274 | LLDB_INSTRUMENT_VA(this); |
275 | |
276 | return m_opaque_sp->GetResumeCount(); |
277 | } |
278 | |
279 | void SBLaunchInfo::SetResumeCount(uint32_t c) { |
280 | LLDB_INSTRUMENT_VA(this, c); |
281 | |
282 | m_opaque_sp->SetResumeCount(c); |
283 | } |
284 | |
285 | bool SBLaunchInfo::AddCloseFileAction(int fd) { |
286 | LLDB_INSTRUMENT_VA(this, fd); |
287 | |
288 | return m_opaque_sp->AppendCloseFileAction(fd); |
289 | } |
290 | |
291 | bool 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 | |
297 | bool 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, file_spec: FileSpec(path), read, write); |
302 | } |
303 | |
304 | bool 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 | |
310 | void SBLaunchInfo::SetLaunchEventData(const char *data) { |
311 | LLDB_INSTRUMENT_VA(this, data); |
312 | |
313 | m_opaque_sp->SetLaunchEventData(data); |
314 | } |
315 | |
316 | const char *SBLaunchInfo::GetLaunchEventData() const { |
317 | LLDB_INSTRUMENT_VA(this); |
318 | |
319 | return ConstString(m_opaque_sp->GetLaunchEventData()).GetCString(); |
320 | } |
321 | |
322 | void SBLaunchInfo::SetDetachOnError(bool enable) { |
323 | LLDB_INSTRUMENT_VA(this, enable); |
324 | |
325 | m_opaque_sp->SetDetachOnError(enable); |
326 | } |
327 | |
328 | bool SBLaunchInfo::GetDetachOnError() const { |
329 | LLDB_INSTRUMENT_VA(this); |
330 | |
331 | return m_opaque_sp->GetDetachOnError(); |
332 | } |
333 | |
334 | const 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 | |
348 | void 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>(args&: class_name, args&: dict_sp); |
354 | m_opaque_sp->SetScriptedMetadata(metadata_sp); |
355 | } |
356 | |
357 | lldb::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 | |
372 | void 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>(args&: 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>(args&: class_name, args&: dict_sp); |
390 | m_opaque_sp->SetScriptedMetadata(metadata_sp); |
391 | } |
392 | |
393 | SBListener 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 | |
402 | void 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 | |