Bug Summary

File:build/source/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
Warning:line 180, column 27
Potential leak of memory pointed to by 'reg_interface'

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