Bug Summary

File:src/gnu/usr.bin/clang/liblldbPluginProcess/../../../llvm/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
Warning:line 178, column 27
Potential leak of memory pointed to by 'reg_interface'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ThreadElfCore.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 -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/liblldbPluginProcess/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/../include -I /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/obj -I /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -I /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/../../../llvm/lldb/include -I /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/../../../llvm/lldb/source -I /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/../../../llvm/clang/include -I /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/obj/../include/lldb/Plugins -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/liblldbPluginProcess/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -stack-protector 2 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/liblldbPluginProcess/../../../llvm/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
1//===-- ThreadElfCore.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/Target/RegisterContext.h"
10#include "lldb/Target/StopInfo.h"
11#include "lldb/Target/Target.h"
12#include "lldb/Target/Unwind.h"
13#include "lldb/Utility/DataExtractor.h"
14#include "lldb/Utility/Log.h"
15
16#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
17#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
18#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
19#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
20#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
21#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
22#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
23#include "Plugins/Process/Utility/RegisterContextNetBSD_i386.h"
24#include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
25#include "Plugins/Process/Utility/RegisterContextOpenBSD_i386.h"
26#include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h"
27#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
28#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
29#include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h"
30#include "ProcessElfCore.h"
31#include "RegisterContextPOSIXCore_arm.h"
32#include "RegisterContextPOSIXCore_arm64.h"
33#include "RegisterContextPOSIXCore_mips64.h"
34#include "RegisterContextPOSIXCore_powerpc.h"
35#include "RegisterContextPOSIXCore_ppc64le.h"
36#include "RegisterContextPOSIXCore_s390x.h"
37#include "RegisterContextPOSIXCore_x86_64.h"
38#include "ThreadElfCore.h"
39
40#include <memory>
41
42using namespace lldb;
43using namespace lldb_private;
44
45// Construct a Thread object with given data
46ThreadElfCore::ThreadElfCore(Process &process, const ThreadData &td)
47 : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(),
48 m_signo(td.signo), m_gpregset_data(td.gpregset), m_notes(td.notes) {}
49
50ThreadElfCore::~ThreadElfCore() { DestroyThread(); }
51
52void ThreadElfCore::RefreshStateAfterStop() {
53 GetRegisterContext()->InvalidateIfNeeded(false);
1
Calling 'ThreadElfCore::GetRegisterContext'
54}
55
56RegisterContextSP ThreadElfCore::GetRegisterContext() {
57 if (!m_reg_context_sp) {
2
Taking true branch
58 m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
3
Calling 'ThreadElfCore::CreateRegisterContextForFrame'
59 }
60 return m_reg_context_sp;
61}
62
63RegisterContextSP
64ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
65 RegisterContextSP reg_ctx_sp;
66 uint32_t concrete_frame_idx = 0;
67 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD(1u << 2)));
68
69 if (frame
3.1
'frame' is null
)
4
Taking false branch
70 concrete_frame_idx = frame->GetConcreteFrameIndex();
71
72 if (concrete_frame_idx
4.1
'concrete_frame_idx' is equal to 0
== 0) {
5
Taking true branch
73 if (m_thread_reg_ctx_sp)
6
Taking false branch
74 return m_thread_reg_ctx_sp;
75
76 ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
77 ArchSpec arch = process->GetArchitecture();
78 RegisterInfoInterface *reg_interface = nullptr;
79
80 switch (arch.GetTriple().getOS()) {
7
Control jumps to 'case Linux:' at line 123
81 case llvm::Triple::FreeBSD: {
82 switch (arch.GetMachine()) {
83 case llvm::Triple::aarch64:
84 case llvm::Triple::arm:
85 break;
86 case llvm::Triple::ppc:
87 reg_interface = new RegisterContextFreeBSD_powerpc32(arch);
88 break;
89 case llvm::Triple::ppc64:
90 reg_interface = new RegisterContextFreeBSD_powerpc64(arch);
91 break;
92 case llvm::Triple::mips64:
93 reg_interface = new RegisterContextFreeBSD_mips64(arch);
94 break;
95 case llvm::Triple::x86:
96 reg_interface = new RegisterContextFreeBSD_i386(arch);
97 break;
98 case llvm::Triple::x86_64:
99 reg_interface = new RegisterContextFreeBSD_x86_64(arch);
100 break;
101 default:
102 break;
103 }
104 break;
105 }
106
107 case llvm::Triple::NetBSD: {
108 switch (arch.GetMachine()) {
109 case llvm::Triple::aarch64:
110 break;
111 case llvm::Triple::x86:
112 reg_interface = new RegisterContextNetBSD_i386(arch);
113 break;
114 case llvm::Triple::x86_64:
115 reg_interface = new RegisterContextNetBSD_x86_64(arch);
116 break;
117 default:
118 break;
119 }
120 break;
121 }
122
123 case llvm::Triple::Linux: {
124 switch (arch.GetMachine()) {
8
Control jumps to 'case x86_64:' at line 136
125 case llvm::Triple::aarch64:
126 break;
127 case llvm::Triple::ppc64le:
128 reg_interface = new RegisterInfoPOSIX_ppc64le(arch);
129 break;
130 case llvm::Triple::systemz:
131 reg_interface = new RegisterContextLinux_s390x(arch);
132 break;
133 case llvm::Triple::x86:
134 reg_interface = new RegisterContextLinux_i386(arch);
135 break;
136 case llvm::Triple::x86_64:
137 reg_interface = new RegisterContextLinux_x86_64(arch);
9
Memory is allocated
138 break;
10
Execution continues on line 142
139 default:
140 break;
141 }
142 break;
11
Execution continues on line 165
143 }
144
145 case llvm::Triple::OpenBSD: {
146 switch (arch.GetMachine()) {
147 case llvm::Triple::aarch64:
148 break;
149 case llvm::Triple::x86:
150 reg_interface = new RegisterContextOpenBSD_i386(arch);
151 break;
152 case llvm::Triple::x86_64:
153 reg_interface = new RegisterContextOpenBSD_x86_64(arch);
154 break;
155 default:
156 break;
157 }
158 break;
159 }
160
161 default:
162 break;
163 }
164
165 if (!reg_interface
11.1
'reg_interface' is non-null
&& arch.GetMachine() != llvm::Triple::aarch64 &&
166 arch.GetMachine() != llvm::Triple::arm) {
167 LLDB_LOGF(log, "elf-core::%s:: Architecture(%d) or OS(%d) not supported",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("elf-core::%s:: Architecture(%d) or OS(%d) not supported"
, __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
} while (0)
168 __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("elf-core::%s:: Architecture(%d) or OS(%d) not supported"
, __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
} while (0)
;
169 assert(false && "Architecture or OS not supported")((void)0);
170 }
171
172 switch (arch.GetMachine()) {
12
Control jumps to 'case arm:' at line 177
173 case llvm::Triple::aarch64:
174 m_thread_reg_ctx_sp = RegisterContextCorePOSIX_arm64::Create(
175 *this, arch, m_gpregset_data, m_notes);
176 break;
177 case llvm::Triple::arm:
178 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm>(
13
Potential leak of memory pointed to by 'reg_interface'
179 *this, std::make_unique<RegisterInfoPOSIX_arm>(arch), m_gpregset_data,
180 m_notes);
181 break;
182 case llvm::Triple::mipsel:
183 case llvm::Triple::mips:
184 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(
185 *this, reg_interface, m_gpregset_data, m_notes);
186 break;
187 case llvm::Triple::mips64:
188 case llvm::Triple::mips64el:
189 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(
190 *this, reg_interface, m_gpregset_data, m_notes);
191 break;
192 case llvm::Triple::ppc:
193 case llvm::Triple::ppc64:
194 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_powerpc>(
195 *this, reg_interface, m_gpregset_data, m_notes);
196 break;
197 case llvm::Triple::ppc64le:
198 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_ppc64le>(
199 *this, reg_interface, m_gpregset_data, m_notes);
200 break;
201 case llvm::Triple::systemz:
202 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_s390x>(
203 *this, reg_interface, m_gpregset_data, m_notes);
204 break;
205 case llvm::Triple::x86:
206 case llvm::Triple::x86_64:
207 m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_x86_64>(
208 *this, reg_interface, m_gpregset_data, m_notes);
209 break;
210 default:
211 break;
212 }
213
214 reg_ctx_sp = m_thread_reg_ctx_sp;
215 } else {
216 reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);
217 }
218 return reg_ctx_sp;
219}
220
221bool ThreadElfCore::CalculateStopInfo() {
222 ProcessSP process_sp(GetProcess());
223 if (process_sp) {
224 SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, m_signo));
225 return true;
226 }
227 return false;
228}
229
230// Parse PRSTATUS from NOTE entry
231ELFLinuxPrStatus::ELFLinuxPrStatus() {
232 memset(this, 0, sizeof(ELFLinuxPrStatus));
233}
234
235size_t ELFLinuxPrStatus::GetSize(const lldb_private::ArchSpec &arch) {
236 constexpr size_t mips_linux_pr_status_size_o32 = 96;
237 constexpr size_t mips_linux_pr_status_size_n32 = 72;
238 constexpr size_t num_ptr_size_members = 10;
239 if (arch.IsMIPS()) {
240 std::string abi = arch.GetTargetABI();
241 assert(!abi.empty() && "ABI is not set")((void)0);
242 if (!abi.compare("n64"))
243 return sizeof(ELFLinuxPrStatus);
244 else if (!abi.compare("o32"))
245 return mips_linux_pr_status_size_o32;
246 // N32 ABI
247 return mips_linux_pr_status_size_n32;
248 }
249 switch (arch.GetCore()) {
250 case lldb_private::ArchSpec::eCore_x86_32_i386:
251 case lldb_private::ArchSpec::eCore_x86_32_i486:
252 return 72;
253 default:
254 if (arch.GetAddressByteSize() == 8)
255 return sizeof(ELFLinuxPrStatus);
256 else
257 return sizeof(ELFLinuxPrStatus) - num_ptr_size_members * 4;
258 }
259}
260
261Status ELFLinuxPrStatus::Parse(const DataExtractor &data,
262 const ArchSpec &arch) {
263 Status error;
264 if (GetSize(arch) > data.GetByteSize()) {
265 error.SetErrorStringWithFormat(
266 "NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64"llu",
267 GetSize(arch), data.GetByteSize());
268 return error;
269 }
270
271 // Read field by field to correctly account for endianess of both the core
272 // dump and the platform running lldb.
273 offset_t offset = 0;
274 si_signo = data.GetU32(&offset);
275 si_code = data.GetU32(&offset);
276 si_errno = data.GetU32(&offset);
277
278 pr_cursig = data.GetU16(&offset);
279 offset += 2; // pad
280
281 pr_sigpend = data.GetAddress(&offset);
282 pr_sighold = data.GetAddress(&offset);
283
284 pr_pid = data.GetU32(&offset);
285 pr_ppid = data.GetU32(&offset);
286 pr_pgrp = data.GetU32(&offset);
287 pr_sid = data.GetU32(&offset);
288
289 pr_utime.tv_sec = data.GetAddress(&offset);
290 pr_utime.tv_usec = data.GetAddress(&offset);
291
292 pr_stime.tv_sec = data.GetAddress(&offset);
293 pr_stime.tv_usec = data.GetAddress(&offset);
294
295 pr_cutime.tv_sec = data.GetAddress(&offset);
296 pr_cutime.tv_usec = data.GetAddress(&offset);
297
298 pr_cstime.tv_sec = data.GetAddress(&offset);
299 pr_cstime.tv_usec = data.GetAddress(&offset);
300
301 return error;
302}
303
304// Parse PRPSINFO from NOTE entry
305ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() {
306 memset(this, 0, sizeof(ELFLinuxPrPsInfo));
307}
308
309size_t ELFLinuxPrPsInfo::GetSize(const lldb_private::ArchSpec &arch) {
310 constexpr size_t mips_linux_pr_psinfo_size_o32_n32 = 128;
311 if (arch.IsMIPS()) {
312 uint8_t address_byte_size = arch.GetAddressByteSize();
313 if (address_byte_size == 8)
314 return sizeof(ELFLinuxPrPsInfo);
315 return mips_linux_pr_psinfo_size_o32_n32;
316 }
317
318 switch (arch.GetCore()) {
319 case lldb_private::ArchSpec::eCore_s390x_generic:
320 case lldb_private::ArchSpec::eCore_x86_64_x86_64:
321 return sizeof(ELFLinuxPrPsInfo);
322 case lldb_private::ArchSpec::eCore_x86_32_i386:
323 case lldb_private::ArchSpec::eCore_x86_32_i486:
324 return 124;
325 default:
326 return 0;
327 }
328}
329
330Status ELFLinuxPrPsInfo::Parse(const DataExtractor &data,
331 const ArchSpec &arch) {
332 Status error;
333 ByteOrder byteorder = data.GetByteOrder();
334 if (GetSize(arch) > data.GetByteSize()) {
335 error.SetErrorStringWithFormat(
336 "NT_PRPSINFO size should be %zu, but the remaining bytes are: %" PRIu64"llu",
337 GetSize(arch), data.GetByteSize());
338 return error;
339 }
340 size_t size = 0;
341 offset_t offset = 0;
342
343 pr_state = data.GetU8(&offset);
344 pr_sname = data.GetU8(&offset);
345 pr_zomb = data.GetU8(&offset);
346 pr_nice = data.GetU8(&offset);
347 if (data.GetAddressByteSize() == 8) {
348 // Word align the next field on 64 bit.
349 offset += 4;
350 }
351
352 pr_flag = data.GetAddress(&offset);
353
354 if (arch.IsMIPS()) {
355 // The pr_uid and pr_gid is always 32 bit irrespective of platforms
356 pr_uid = data.GetU32(&offset);
357 pr_gid = data.GetU32(&offset);
358 } else {
359 // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
360 pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
361 pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
362 }
363
364 pr_pid = data.GetU32(&offset);
365 pr_ppid = data.GetU32(&offset);
366 pr_pgrp = data.GetU32(&offset);
367 pr_sid = data.GetU32(&offset);
368
369 size = 16;
370 data.ExtractBytes(offset, size, byteorder, pr_fname);
371 offset += size;
372
373 size = 80;
374 data.ExtractBytes(offset, size, byteorder, pr_psargs);
375 offset += size;
376
377 return error;
378}
379
380// Parse SIGINFO from NOTE entry
381ELFLinuxSigInfo::ELFLinuxSigInfo() { memset(this, 0, sizeof(ELFLinuxSigInfo)); }
382
383size_t ELFLinuxSigInfo::GetSize(const lldb_private::ArchSpec &arch) {
384 if (arch.IsMIPS())
385 return sizeof(ELFLinuxSigInfo);
386 switch (arch.GetCore()) {
387 case lldb_private::ArchSpec::eCore_x86_64_x86_64:
388 return sizeof(ELFLinuxSigInfo);
389 case lldb_private::ArchSpec::eCore_s390x_generic:
390 case lldb_private::ArchSpec::eCore_x86_32_i386:
391 case lldb_private::ArchSpec::eCore_x86_32_i486:
392 return 12;
393 default:
394 return 0;
395 }
396}
397
398Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) {
399 Status error;
400 if (GetSize(arch) > data.GetByteSize()) {
401 error.SetErrorStringWithFormat(
402 "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64"llu",
403 GetSize(arch), data.GetByteSize());
404 return error;
405 }
406
407 // Parsing from a 32 bit ELF core file, and populating/reusing the structure
408 // properly, because the struct is for the 64 bit version
409 offset_t offset = 0;
410 si_signo = data.GetU32(&offset);
411 si_code = data.GetU32(&offset);
412 si_errno = data.GetU32(&offset);
413
414 return error;
415}