Bug Summary

File:lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
Warning:line 344, column 10
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ScriptedProcess.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -isystem /usr/include/libxml2 -D HAVE_ROUND -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/lldb/source/Plugins/Process/scripted -I /build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/lldb/source/Plugins/Process/scripted -I /build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/lldb/include -I tools/lldb/include -I include -I /build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/llvm/include -I /usr/include/python3.9 -I /build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/clang/include -I tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/lldb/source -I tools/lldb/source -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/= -O3 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-deprecated-register -Wno-vla-extension -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-01-19-134126-35450-1 -x c++ /build/llvm-toolchain-snapshot-14~++20220119111520+da61cb019eb2/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
1//===-- ScriptedProcess.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 "ScriptedProcess.h"
10
11#include "lldb/Core/Debugger.h"
12#include "lldb/Core/Module.h"
13#include "lldb/Core/PluginManager.h"
14
15#include "lldb/Host/OptionParser.h"
16#include "lldb/Host/ThreadLauncher.h"
17#include "lldb/Interpreter/CommandInterpreter.h"
18#include "lldb/Interpreter/OptionArgParser.h"
19#include "lldb/Interpreter/OptionGroupBoolean.h"
20#include "lldb/Interpreter/ScriptInterpreter.h"
21#include "lldb/Target/MemoryRegionInfo.h"
22#include "lldb/Target/RegisterContext.h"
23#include "lldb/Utility/State.h"
24
25#include <mutex>
26
27LLDB_PLUGIN_DEFINE(ScriptedProcess)namespace lldb_private { void lldb_initialize_ScriptedProcess
() { ScriptedProcess::Initialize(); } void lldb_terminate_ScriptedProcess
() { ScriptedProcess::Terminate(); } }
28
29using namespace lldb;
30using namespace lldb_private;
31
32llvm::StringRef ScriptedProcess::GetPluginDescriptionStatic() {
33 return "Scripted Process plug-in.";
34}
35
36static constexpr lldb::ScriptLanguage g_supported_script_languages[] = {
37 ScriptLanguage::eScriptLanguagePython,
38};
39
40bool ScriptedProcess::IsScriptLanguageSupported(lldb::ScriptLanguage language) {
41 llvm::ArrayRef<lldb::ScriptLanguage> supported_languages =
42 llvm::makeArrayRef(g_supported_script_languages);
43
44 return llvm::is_contained(supported_languages, language);
45}
46
47void ScriptedProcess::CheckInterpreterAndScriptObject() const {
48 lldbassert(m_interpreter && "Invalid Script Interpreter.")lldb_private::lldb_assert(static_cast<bool>(m_interpreter
&& "Invalid Script Interpreter."), "m_interpreter && \"Invalid Script Interpreter.\""
, __FUNCTION__, "lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp"
, 48)
;
49 lldbassert(m_script_object_sp && "Invalid Script Object.")lldb_private::lldb_assert(static_cast<bool>(m_script_object_sp
&& "Invalid Script Object."), "m_script_object_sp && \"Invalid Script Object.\""
, __FUNCTION__, "lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp"
, 49)
;
50}
51
52lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp,
53 lldb::ListenerSP listener_sp,
54 const FileSpec *file,
55 bool can_connect) {
56 if (!target_sp ||
57 !IsScriptLanguageSupported(target_sp->GetDebugger().GetScriptLanguage()))
58 return nullptr;
59
60 Status error;
61 ScriptedProcess::ScriptedProcessInfo scripted_process_info(
62 target_sp->GetProcessLaunchInfo());
63
64 auto process_sp = std::make_shared<ScriptedProcess>(
65 target_sp, listener_sp, scripted_process_info, error);
66
67 if (error.Fail() || !process_sp || !process_sp->m_script_object_sp ||
68 !process_sp->m_script_object_sp->IsValid()) {
69 LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS), "%s",do { ::lldb_private::Log *log_private = (GetLogIfAllCategoriesSet
((1u << 1))); if (log_private) log_private->Printf("%s"
, error.AsCString()); } while (0)
70 error.AsCString())do { ::lldb_private::Log *log_private = (GetLogIfAllCategoriesSet
((1u << 1))); if (log_private) log_private->Printf("%s"
, error.AsCString()); } while (0)
;
71 return nullptr;
72 }
73
74 return process_sp;
75}
76
77bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp,
78 bool plugin_specified_by_name) {
79 return true;
80}
81
82ScriptedProcess::ScriptedProcess(
83 lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
84 const ScriptedProcess::ScriptedProcessInfo &scripted_process_info,
85 Status &error)
86 : Process(target_sp, listener_sp),
87 m_scripted_process_info(scripted_process_info) {
88
89 if (!target_sp) {
90 error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
91 __FUNCTION__, "Invalid target");
92 return;
93 }
94
95 m_interpreter = target_sp->GetDebugger().GetScriptInterpreter();
96
97 if (!m_interpreter) {
98 error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
99 __FUNCTION__,
100 "Debugger has no Script Interpreter");
101 return;
102 }
103
104 ExecutionContext exe_ctx(target_sp, /*get_process=*/false);
105
106 StructuredData::GenericSP object_sp = GetInterface().CreatePluginObject(
107 m_scripted_process_info.GetClassName().c_str(), exe_ctx,
108 m_scripted_process_info.GetArgsSP());
109
110 if (!object_sp || !object_sp->IsValid()) {
111 error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
112 __FUNCTION__,
113 "Failed to create valid script object");
114 return;
115 }
116
117 m_script_object_sp = object_sp;
118}
119
120ScriptedProcess::~ScriptedProcess() {
121 Clear();
122 // We need to call finalize on the process before destroying ourselves to
123 // make sure all of the broadcaster cleanup goes as planned. If we destruct
124 // this class, then Process::~Process() might have problems trying to fully
125 // destroy the broadcaster.
126 Finalize();
127}
128
129void ScriptedProcess::Initialize() {
130 static llvm::once_flag g_once_flag;
131
132 llvm::call_once(g_once_flag, []() {
133 PluginManager::RegisterPlugin(GetPluginNameStatic(),
134 GetPluginDescriptionStatic(), CreateInstance);
135 });
136}
137
138void ScriptedProcess::Terminate() {
139 PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance);
140}
141
142Status ScriptedProcess::DoLoadCore() {
143 ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo();
144
145 return DoLaunch(nullptr, launch_info);
146}
147
148Status ScriptedProcess::DoLaunch(Module *exe_module,
149 ProcessLaunchInfo &launch_info) {
150 CheckInterpreterAndScriptObject();
151
152 /* FIXME: This doesn't reflect how lldb actually launches a process.
153 In reality, it attaches to debugserver, then resume the process. */
154 Status error = GetInterface().Launch();
155 SetPrivateState(eStateRunning);
156
157 if (error.Fail())
158 return error;
159
160 // TODO: Fetch next state from stopped event queue then send stop event
161 // const StateType state = SetThreadStopInfo(response);
162 // if (state != eStateInvalid) {
163 // SetPrivateState(state);
164
165 SetPrivateState(eStateStopped);
166
167 UpdateThreadListIfNeeded();
168 GetThreadList();
169
170 return {};
171}
172
173void ScriptedProcess::DidLaunch() {
174 CheckInterpreterAndScriptObject();
175 m_pid = GetInterface().GetProcessID();
176}
177
178Status ScriptedProcess::DoResume() {
179 CheckInterpreterAndScriptObject();
180
181 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1)));
182 // FIXME: Fetch data from thread.
183 const StateType thread_resume_state = eStateRunning;
184 LLDB_LOGF(log, "ScriptedProcess::%s thread_resume_state = %s", __FUNCTION__,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("ScriptedProcess::%s thread_resume_state = %s"
, __FUNCTION__, StateAsCString(thread_resume_state)); } while
(0)
185 StateAsCString(thread_resume_state))do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("ScriptedProcess::%s thread_resume_state = %s"
, __FUNCTION__, StateAsCString(thread_resume_state)); } while
(0)
;
186
187 bool resume = (thread_resume_state == eStateRunning);
188 assert(thread_resume_state == eStateRunning && "invalid thread resume state")(static_cast <bool> (thread_resume_state == eStateRunning
&& "invalid thread resume state") ? void (0) : __assert_fail
("thread_resume_state == eStateRunning && \"invalid thread resume state\""
, "lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp",
188, __extension__ __PRETTY_FUNCTION__))
;
189
190 Status error;
191 if (resume) {
192 LLDB_LOGF(log, "ScriptedProcess::%s sending resume", __FUNCTION__)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("ScriptedProcess::%s sending resume"
, __FUNCTION__); } while (0)
;
193
194 SetPrivateState(eStateRunning);
195 SetPrivateState(eStateStopped);
196 error = GetInterface().Resume();
197 }
198
199 return error;
200}
201
202Status ScriptedProcess::DoStop() {
203 CheckInterpreterAndScriptObject();
204
205 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1)));
206
207 if (GetInterface().ShouldStop()) {
208 SetPrivateState(eStateStopped);
209 LLDB_LOGF(log, "ScriptedProcess::%s Immediate stop", __FUNCTION__)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("ScriptedProcess::%s Immediate stop"
, __FUNCTION__); } while (0)
;
210 return {};
211 }
212
213 LLDB_LOGF(log, "ScriptedProcess::%s Delayed stop", __FUNCTION__)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("ScriptedProcess::%s Delayed stop", __FUNCTION__
); } while (0)
;
214 return GetInterface().Stop();
215}
216
217Status ScriptedProcess::DoDestroy() { return Status(); }
218
219bool ScriptedProcess::IsAlive() {
220 if (m_interpreter && m_script_object_sp)
221 return GetInterface().IsAlive();
222 return false;
223}
224
225size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
226 Status &error) {
227 if (!m_interpreter)
1
Assuming field 'm_interpreter' is null
2
Taking true branch
228 return GetInterface().ErrorWithMessage<size_t>(LLVM_PRETTY_FUNCTION__PRETTY_FUNCTION__,
3
Calling 'ScriptedProcess::GetInterface'
229 "No interpreter.", error);
230
231 lldb::DataExtractorSP data_extractor_sp =
232 GetInterface().ReadMemoryAtAddress(addr, size, error);
233
234 if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail())
235 return 0;
236
237 offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
238 0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder());
239
240 if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET(18446744073709551615UL))
241 return GetInterface().ErrorWithMessage<size_t>(
242 LLVM_PRETTY_FUNCTION__PRETTY_FUNCTION__, "Failed to copy read memory to buffer.", error);
243
244 return size;
245}
246
247ArchSpec ScriptedProcess::GetArchitecture() {
248 return GetTarget().GetArchitecture();
249}
250
251Status ScriptedProcess::GetMemoryRegionInfo(lldb::addr_t load_addr,
252 MemoryRegionInfo &region) {
253 CheckInterpreterAndScriptObject();
254
255 Status error;
256 if (auto region_or_err =
257 GetInterface().GetMemoryRegionContainingAddress(load_addr, error))
258 region = *region_or_err;
259
260 return error;
261}
262
263Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos &region_list) {
264 CheckInterpreterAndScriptObject();
265
266 Status error;
267 lldb::addr_t address = 0;
268
269 while (auto region_or_err =
270 GetInterface().GetMemoryRegionContainingAddress(address, error)) {
271 if (error.Fail())
272 break;
273
274 MemoryRegionInfo &mem_region = *region_or_err;
275 auto range = mem_region.GetRange();
276 address += range.GetRangeBase() + range.GetByteSize();
277 region_list.push_back(mem_region);
278 }
279
280 return error;
281}
282
283void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
284
285bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
286 ThreadList &new_thread_list) {
287 // TODO: Implement
288 // This is supposed to get the current set of threads, if any of them are in
289 // old_thread_list then they get copied to new_thread_list, and then any
290 // actually new threads will get added to new_thread_list.
291
292 CheckInterpreterAndScriptObject();
293 m_thread_plans.ClearThreadCache();
294
295 Status error;
296 ScriptLanguage language = m_interpreter->GetLanguage();
297
298 if (language != eScriptLanguagePython)
299 return GetInterface().ErrorWithMessage<bool>(
300 LLVM_PRETTY_FUNCTION__PRETTY_FUNCTION__,
301 llvm::Twine("ScriptInterpreter language (" +
302 llvm::Twine(m_interpreter->LanguageToString(language)) +
303 llvm::Twine(") not supported."))
304 .str(),
305 error);
306
307 lldb::ThreadSP thread_sp;
308 thread_sp = std::make_shared<ScriptedThread>(*this, error);
309
310 if (!thread_sp || error.Fail())
311 return GetInterface().ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION__PRETTY_FUNCTION__,
312 error.AsCString(), error);
313
314 RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
315 if (!reg_ctx_sp)
316 return GetInterface().ErrorWithMessage<bool>(
317 LLVM_PRETTY_FUNCTION__PRETTY_FUNCTION__, "Invalid Register Context", error);
318
319 new_thread_list.AddThread(thread_sp);
320
321 return new_thread_list.GetSize(false) > 0;
322}
323
324void ScriptedProcess::RefreshStateAfterStop() {
325 // Let all threads recover from stopping and do any clean up based on the
326 // previous thread state (if any).
327 m_thread_list.RefreshStateAfterStop();
328}
329
330bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
331 info.Clear();
332 info.SetProcessID(GetID());
333 info.SetArchitecture(GetArchitecture());
334 lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
335 if (module_sp) {
336 const bool add_exe_file_as_first_arg = false;
337 info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
338 add_exe_file_as_first_arg);
339 }
340 return true;
341}
342
343ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
344 return m_interpreter->GetScriptedProcessInterface();
4
Called C++ object pointer is null
345}