Bug Summary

File:build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
Warning:line 171, column 9
Although the value stored to 'cursor' is used in the enclosing expression, the value is never actually read from 'cursor'

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 DYLDRendezvous.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-15~++20220420111733+e13d2efed663/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-15/lib/clang/15.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/DynamicLoader/POSIX-DYLD -I /build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/lldb/source/Plugins/DynamicLoader/POSIX-DYLD -I /build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/lldb/include -I tools/lldb/include -I include -I /build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/llvm/include -I /usr/include/python3.9 -I /build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/clang/include -I tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/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-15/lib/clang/15.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-15~++20220420111733+e13d2efed663/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/= -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-stringop-truncation -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/= -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-04-20-140412-16051-1 -x c++ /build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
1//===-- DYLDRendezvous.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/Core/Module.h"
10#include "lldb/Symbol/ObjectFile.h"
11#include "lldb/Symbol/Symbol.h"
12#include "lldb/Symbol/SymbolContext.h"
13#include "lldb/Target/Platform.h"
14#include "lldb/Target/Process.h"
15#include "lldb/Target/Target.h"
16#include "lldb/Utility/ArchSpec.h"
17#include "lldb/Utility/LLDBLog.h"
18#include "lldb/Utility/Log.h"
19#include "lldb/Utility/Status.h"
20
21#include "llvm/Support/Path.h"
22
23#include "DYLDRendezvous.h"
24
25using namespace lldb;
26using namespace lldb_private;
27
28DYLDRendezvous::DYLDRendezvous(Process *process)
29 : m_process(process), m_rendezvous_addr(LLDB_INVALID_ADDRESS(18446744073709551615UL)),
30 m_executable_interpreter(false), m_current(), m_previous(),
31 m_loaded_modules(), m_soentries(), m_added_soentries(),
32 m_removed_soentries() {
33 m_thread_info.valid = false;
34 UpdateExecutablePath();
35}
36
37addr_t DYLDRendezvous::ResolveRendezvousAddress() {
38 Log *log = GetLog(LLDBLog::DynamicLoader);
39 addr_t info_location;
40 addr_t info_addr;
41 Status error;
42
43 if (!m_process) {
44 LLDB_LOGF(log, "%s null process provided", __FUNCTION__)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s null process provided", __FUNCTION__
); } while (0)
;
45 return LLDB_INVALID_ADDRESS(18446744073709551615UL);
46 }
47
48 // Try to get it from our process. This might be a remote process and might
49 // grab it via some remote-specific mechanism.
50 info_location = m_process->GetImageInfoAddress();
51 LLDB_LOGF(log, "%s info_location = 0x%" PRIx64, __FUNCTION__, info_location)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s info_location = 0x%" "l" "x", __FUNCTION__
, info_location); } while (0)
;
52
53 // If the process fails to return an address, fall back to seeing if the
54 // local object file can help us find it.
55 if (info_location == LLDB_INVALID_ADDRESS(18446744073709551615UL)) {
56 Target *target = &m_process->GetTarget();
57 if (target) {
58 ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
59 Address addr = obj_file->GetImageInfoAddress(target);
60
61 if (addr.IsValid()) {
62 info_location = addr.GetLoadAddress(target);
63 LLDB_LOGF(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s resolved via direct object file approach to 0x%"
"l" "x", __FUNCTION__, info_location); } while (0)
64 "%s resolved via direct object file approach to 0x%" PRIx64,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s resolved via direct object file approach to 0x%"
"l" "x", __FUNCTION__, info_location); } while (0)
65 __FUNCTION__, info_location)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s resolved via direct object file approach to 0x%"
"l" "x", __FUNCTION__, info_location); } while (0)
;
66 } else {
67 const Symbol *_r_debug =
68 target->GetExecutableModule()->FindFirstSymbolWithNameAndType(
69 ConstString("_r_debug"));
70 if (_r_debug) {
71 info_addr = _r_debug->GetAddress().GetLoadAddress(target);
72 if (info_addr != LLDB_INVALID_ADDRESS(18446744073709551615UL)) {
73 LLDB_LOGF(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s resolved by finding symbol '_r_debug' whose value is "
"0x%" "l" "x", __FUNCTION__, info_addr); } while (0)
74 "%s resolved by finding symbol '_r_debug' whose value is "do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s resolved by finding symbol '_r_debug' whose value is "
"0x%" "l" "x", __FUNCTION__, info_addr); } while (0)
75 "0x%" PRIx64,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s resolved by finding symbol '_r_debug' whose value is "
"0x%" "l" "x", __FUNCTION__, info_addr); } while (0)
76 __FUNCTION__, info_addr)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s resolved by finding symbol '_r_debug' whose value is "
"0x%" "l" "x", __FUNCTION__, info_addr); } while (0)
;
77 m_executable_interpreter = true;
78 return info_addr;
79 }
80 }
81 LLDB_LOGF(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s FAILED - direct object file approach did not yield a "
"valid address", __FUNCTION__); } while (0)
82 "%s FAILED - direct object file approach did not yield a "do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s FAILED - direct object file approach did not yield a "
"valid address", __FUNCTION__); } while (0)
83 "valid address",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s FAILED - direct object file approach did not yield a "
"valid address", __FUNCTION__); } while (0)
84 __FUNCTION__)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s FAILED - direct object file approach did not yield a "
"valid address", __FUNCTION__); } while (0)
;
85 }
86 }
87 }
88
89 if (info_location == LLDB_INVALID_ADDRESS(18446744073709551615UL)) {
90 LLDB_LOGF(log, "%s FAILED - invalid info address", __FUNCTION__)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s FAILED - invalid info address", __FUNCTION__
); } while (0)
;
91 return LLDB_INVALID_ADDRESS(18446744073709551615UL);
92 }
93
94 LLDB_LOGF(log, "%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s reading pointer (%" "u" " bytes) from 0x%"
"l" "x", __FUNCTION__, m_process->GetAddressByteSize(), info_location
); } while (0)
95 __FUNCTION__, m_process->GetAddressByteSize(), info_location)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s reading pointer (%" "u" " bytes) from 0x%"
"l" "x", __FUNCTION__, m_process->GetAddressByteSize(), info_location
); } while (0)
;
96
97 info_addr = m_process->ReadPointerFromMemory(info_location, error);
98 if (error.Fail()) {
99 LLDB_LOGF(log, "%s FAILED - could not read from the info location: %s",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s FAILED - could not read from the info location: %s"
, __FUNCTION__, error.AsCString()); } while (0)
100 __FUNCTION__, error.AsCString())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s FAILED - could not read from the info location: %s"
, __FUNCTION__, error.AsCString()); } while (0)
;
101 return LLDB_INVALID_ADDRESS(18446744073709551615UL);
102 }
103
104 if (info_addr == 0) {
105 LLDB_LOGF(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s FAILED - the rendezvous address contained at 0x%"
"l" "x" " returned a null value", __FUNCTION__, info_location
); } while (0)
106 "%s FAILED - the rendezvous address contained at 0x%" PRIx64do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s FAILED - the rendezvous address contained at 0x%"
"l" "x" " returned a null value", __FUNCTION__, info_location
); } while (0)
107 " returned a null value",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s FAILED - the rendezvous address contained at 0x%"
"l" "x" " returned a null value", __FUNCTION__, info_location
); } while (0)
108 __FUNCTION__, info_location)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("%s FAILED - the rendezvous address contained at 0x%"
"l" "x" " returned a null value", __FUNCTION__, info_location
); } while (0)
;
109 return LLDB_INVALID_ADDRESS(18446744073709551615UL);
110 }
111
112 return info_addr;
113}
114
115void DYLDRendezvous::UpdateExecutablePath() {
116 if (m_process) {
117 Log *log = GetLog(LLDBLog::DynamicLoader);
118 Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
119 if (exe_mod) {
120 m_exe_file_spec = exe_mod->GetPlatformFileSpec();
121 LLDB_LOGF(log, "DYLDRendezvous::%s exe module executable path set: '%s'",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("DYLDRendezvous::%s exe module executable path set: '%s'"
, __FUNCTION__, m_exe_file_spec.GetCString()); } while (0)
122 __FUNCTION__, m_exe_file_spec.GetCString())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("DYLDRendezvous::%s exe module executable path set: '%s'"
, __FUNCTION__, m_exe_file_spec.GetCString()); } while (0)
;
123 } else {
124 LLDB_LOGF(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("DYLDRendezvous::%s cannot cache exe module path: null "
"executable module pointer", __FUNCTION__); } while (0)
125 "DYLDRendezvous::%s cannot cache exe module path: null "do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("DYLDRendezvous::%s cannot cache exe module path: null "
"executable module pointer", __FUNCTION__); } while (0)
126 "executable module pointer",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("DYLDRendezvous::%s cannot cache exe module path: null "
"executable module pointer", __FUNCTION__); } while (0)
127 __FUNCTION__)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("DYLDRendezvous::%s cannot cache exe module path: null "
"executable module pointer", __FUNCTION__); } while (0)
;
128 }
129 }
130}
131
132bool DYLDRendezvous::Resolve() {
133 Log *log = GetLog(LLDBLog::DynamicLoader);
134
135 const size_t word_size = 4;
136 Rendezvous info;
137 size_t address_size;
138 size_t padding;
139 addr_t info_addr;
140 addr_t cursor;
141
142 address_size = m_process->GetAddressByteSize();
143 padding = address_size - word_size;
144 LLDB_LOGF(log,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("DYLDRendezvous::%s address size: %"
"l" "u" ", padding %" "l" "u", __FUNCTION__, uint64_t(address_size
), uint64_t(padding)); } while (0)
145 "DYLDRendezvous::%s address size: %" PRIu64 ", padding %" PRIu64,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("DYLDRendezvous::%s address size: %"
"l" "u" ", padding %" "l" "u", __FUNCTION__, uint64_t(address_size
), uint64_t(padding)); } while (0)
146 __FUNCTION__, uint64_t(address_size), uint64_t(padding))do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("DYLDRendezvous::%s address size: %"
"l" "u" ", padding %" "l" "u", __FUNCTION__, uint64_t(address_size
), uint64_t(padding)); } while (0)
;
147
148 if (m_rendezvous_addr == LLDB_INVALID_ADDRESS(18446744073709551615UL))
149 cursor = info_addr =
150 ResolveRendezvousAddress();
151 else
152 cursor = info_addr = m_rendezvous_addr;
153 LLDB_LOGF(log, "DYLDRendezvous::%s cursor = 0x%" PRIx64, __FUNCTION__,do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("DYLDRendezvous::%s cursor = 0x%" "l"
"x", __FUNCTION__, cursor); } while (0)
154 cursor)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("DYLDRendezvous::%s cursor = 0x%" "l"
"x", __FUNCTION__, cursor); } while (0)
;
155
156 if (cursor == LLDB_INVALID_ADDRESS(18446744073709551615UL))
157 return false;
158
159 if (!(cursor = ReadWord(cursor, &info.version, word_size)))
160 return false;
161
162 if (!(cursor = ReadPointer(cursor + padding, &info.map_addr)))
163 return false;
164
165 if (!(cursor = ReadPointer(cursor, &info.brk)))
166 return false;
167
168 if (!(cursor = ReadWord(cursor, &info.state, word_size)))
169 return false;
170
171 if (!(cursor = ReadPointer(cursor + padding, &info.ldbase)))
Although the value stored to 'cursor' is used in the enclosing expression, the value is never actually read from 'cursor'
172 return false;
173
174 // The rendezvous was successfully read. Update our internal state.
175 m_rendezvous_addr = info_addr;
176 m_previous = m_current;
177 m_current = info;
178
179 if (m_current.map_addr == 0)
180 return false;
181
182 if (UpdateSOEntriesFromRemote())
183 return true;
184
185 return UpdateSOEntries();
186}
187
188bool DYLDRendezvous::IsValid() {
189 return m_rendezvous_addr != LLDB_INVALID_ADDRESS(18446744073709551615UL);
190}
191
192DYLDRendezvous::RendezvousAction DYLDRendezvous::GetAction() const {
193 switch (m_current.state) {
194
195 case eConsistent:
196 switch (m_previous.state) {
197 // When the previous and current states are consistent this is the first
198 // time we have been asked to update. Just take a snapshot of the
199 // currently loaded modules.
200 case eConsistent:
201 return eTakeSnapshot;
202 // If we are about to add or remove a shared object clear out the current
203 // state and take a snapshot of the currently loaded images.
204 case eAdd:
205 return eAddModules;
206 case eDelete:
207 return eRemoveModules;
208 }
209 break;
210
211 case eAdd:
212 case eDelete:
213 // Some versions of the android dynamic linker might send two
214 // notifications with state == eAdd back to back. Ignore them until we
215 // get an eConsistent notification.
216 if (!(m_previous.state == eConsistent ||
217 (m_previous.state == eAdd && m_current.state == eDelete)))
218 return eNoAction;
219
220 return eTakeSnapshot;
221 }
222
223 return eNoAction;
224}
225
226bool DYLDRendezvous::UpdateSOEntriesFromRemote() {
227 auto action = GetAction();
228
229 if (action == eNoAction)
230 return false;
231
232 if (action == eTakeSnapshot) {
233 m_added_soentries.clear();
234 m_removed_soentries.clear();
235 // We already have the loaded list from the previous update so no need to
236 // find all the modules again.
237 if (!m_loaded_modules.m_list.empty())
238 return true;
239 }
240
241 llvm::Expected<LoadedModuleInfoList> module_list =
242 m_process->GetLoadedModuleList();
243 if (!module_list) {
244 llvm::consumeError(module_list.takeError());
245 return false;
246 }
247
248 switch (action) {
249 case eTakeSnapshot:
250 m_soentries.clear();
251 return SaveSOEntriesFromRemote(*module_list);
252 case eAddModules:
253 return AddSOEntriesFromRemote(*module_list);
254 case eRemoveModules:
255 return RemoveSOEntriesFromRemote(*module_list);
256 case eNoAction:
257 return false;
258 }
259 llvm_unreachable("Fully covered switch above!")::llvm::llvm_unreachable_internal("Fully covered switch above!"
, "lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp"
, 259)
;
260}
261
262bool DYLDRendezvous::UpdateSOEntries() {
263 switch (GetAction()) {
264 case eTakeSnapshot:
265 m_soentries.clear();
266 m_added_soentries.clear();
267 m_removed_soentries.clear();
268 return TakeSnapshot(m_soentries);
269 case eAddModules:
270 return AddSOEntries();
271 case eRemoveModules:
272 return RemoveSOEntries();
273 case eNoAction:
274 return false;
275 }
276 llvm_unreachable("Fully covered switch above!")::llvm::llvm_unreachable_internal("Fully covered switch above!"
, "lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp"
, 276)
;
277}
278
279bool DYLDRendezvous::FillSOEntryFromModuleInfo(
280 LoadedModuleInfoList::LoadedModuleInfo const &modInfo, SOEntry &entry) {
281 addr_t link_map_addr;
282 addr_t base_addr;
283 addr_t dyn_addr;
284 std::string name;
285
286 if (!modInfo.get_link_map(link_map_addr) || !modInfo.get_base(base_addr) ||
287 !modInfo.get_dynamic(dyn_addr) || !modInfo.get_name(name))
288 return false;
289
290 entry.link_addr = link_map_addr;
291 entry.base_addr = base_addr;
292 entry.dyn_addr = dyn_addr;
293
294 entry.file_spec.SetFile(name, FileSpec::Style::native);
295
296 UpdateBaseAddrIfNecessary(entry, name);
297
298 // not needed if we're using ModuleInfos
299 entry.next = 0;
300 entry.prev = 0;
301 entry.path_addr = 0;
302
303 return true;
304}
305
306bool DYLDRendezvous::SaveSOEntriesFromRemote(
307 const LoadedModuleInfoList &module_list) {
308 for (auto const &modInfo : module_list.m_list) {
309 SOEntry entry;
310 if (!FillSOEntryFromModuleInfo(modInfo, entry))
311 return false;
312
313 // Only add shared libraries and not the executable.
314 if (!SOEntryIsMainExecutable(entry)) {
315 UpdateFileSpecIfNecessary(entry);
316 m_soentries.push_back(entry);
317 }
318 }
319
320 m_loaded_modules = module_list;
321 return true;
322}
323
324bool DYLDRendezvous::AddSOEntriesFromRemote(
325 const LoadedModuleInfoList &module_list) {
326 for (auto const &modInfo : module_list.m_list) {
327 bool found = false;
328 for (auto const &existing : m_loaded_modules.m_list) {
329 if (modInfo == existing) {
330 found = true;
331 break;
332 }
333 }
334
335 if (found)
336 continue;
337
338 SOEntry entry;
339 if (!FillSOEntryFromModuleInfo(modInfo, entry))
340 return false;
341
342 // Only add shared libraries and not the executable.
343 if (!SOEntryIsMainExecutable(entry)) {
344 UpdateFileSpecIfNecessary(entry);
345 m_soentries.push_back(entry);
346 m_added_soentries.push_back(entry);
347 }
348 }
349
350 m_loaded_modules = module_list;
351 return true;
352}
353
354bool DYLDRendezvous::RemoveSOEntriesFromRemote(
355 const LoadedModuleInfoList &module_list) {
356 for (auto const &existing : m_loaded_modules.m_list) {
357 bool found = false;
358 for (auto const &modInfo : module_list.m_list) {
359 if (modInfo == existing) {
360 found = true;
361 break;
362 }
363 }
364
365 if (found)
366 continue;
367
368 SOEntry entry;
369 if (!FillSOEntryFromModuleInfo(existing, entry))
370 return false;
371
372 // Only add shared libraries and not the executable.
373 if (!SOEntryIsMainExecutable(entry)) {
374 auto pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
375 if (pos == m_soentries.end())
376 return false;
377
378 m_soentries.erase(pos);
379 m_removed_soentries.push_back(entry);
380 }
381 }
382
383 m_loaded_modules = module_list;
384 return true;
385}
386
387bool DYLDRendezvous::AddSOEntries() {
388 SOEntry entry;
389 iterator pos;
390
391 assert(m_previous.state == eAdd)(static_cast <bool> (m_previous.state == eAdd) ? void (
0) : __assert_fail ("m_previous.state == eAdd", "lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp"
, 391, __extension__ __PRETTY_FUNCTION__))
;
392
393 if (m_current.map_addr == 0)
394 return false;
395
396 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) {
397 if (!ReadSOEntryFromMemory(cursor, entry))
398 return false;
399
400 // Only add shared libraries and not the executable.
401 if (SOEntryIsMainExecutable(entry))
402 continue;
403
404 UpdateFileSpecIfNecessary(entry);
405
406 pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
407 if (pos == m_soentries.end()) {
408 m_soentries.push_back(entry);
409 m_added_soentries.push_back(entry);
410 }
411 }
412
413 return true;
414}
415
416bool DYLDRendezvous::RemoveSOEntries() {
417 SOEntryList entry_list;
418 iterator pos;
419
420 assert(m_previous.state == eDelete)(static_cast <bool> (m_previous.state == eDelete) ? void
(0) : __assert_fail ("m_previous.state == eDelete", "lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp"
, 420, __extension__ __PRETTY_FUNCTION__))
;
421
422 if (!TakeSnapshot(entry_list))
423 return false;
424
425 for (iterator I = begin(); I != end(); ++I) {
426 pos = std::find(entry_list.begin(), entry_list.end(), *I);
427 if (pos == entry_list.end())
428 m_removed_soentries.push_back(*I);
429 }
430
431 m_soentries = entry_list;
432 return true;
433}
434
435bool DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) {
436 // On some systes the executable is indicated by an empty path in the entry.
437 // On others it is the full path to the executable.
438
439 auto triple = m_process->GetTarget().GetArchitecture().GetTriple();
440 switch (triple.getOS()) {
441 case llvm::Triple::FreeBSD:
442 case llvm::Triple::NetBSD:
443 return entry.file_spec == m_exe_file_spec;
444 case llvm::Triple::Linux:
445 if (triple.isAndroid())
446 return entry.file_spec == m_exe_file_spec;
447 // If we are debugging ld.so, then all SOEntries should be treated as
448 // libraries, including the "main" one (denoted by an empty string).
449 if (!entry.file_spec && m_executable_interpreter)
450 return false;
451 return !entry.file_spec;
452 default:
453 return false;
454 }
455}
456
457bool DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) {
458 SOEntry entry;
459
460 if (m_current.map_addr == 0)
461 return false;
462
463 // Clear previous entries since we are about to obtain an up to date list.
464 entry_list.clear();
465
466 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) {
467 if (!ReadSOEntryFromMemory(cursor, entry))
468 return false;
469
470 // Only add shared libraries and not the executable.
471 if (SOEntryIsMainExecutable(entry))
472 continue;
473
474 UpdateFileSpecIfNecessary(entry);
475
476 entry_list.push_back(entry);
477 }
478
479 return true;
480}
481
482addr_t DYLDRendezvous::ReadWord(addr_t addr, uint64_t *dst, size_t size) {
483 Status error;
484
485 *dst = m_process->ReadUnsignedIntegerFromMemory(addr, size, 0, error);
486 if (error.Fail())
487 return 0;
488
489 return addr + size;
490}
491
492addr_t DYLDRendezvous::ReadPointer(addr_t addr, addr_t *dst) {
493 Status error;
494
495 *dst = m_process->ReadPointerFromMemory(addr, error);
496 if (error.Fail())
497 return 0;
498
499 return addr + m_process->GetAddressByteSize();
500}
501
502std::string DYLDRendezvous::ReadStringFromMemory(addr_t addr) {
503 std::string str;
504 Status error;
505
506 if (addr == LLDB_INVALID_ADDRESS(18446744073709551615UL))
507 return std::string();
508
509 m_process->ReadCStringFromMemory(addr, str, error);
510
511 return str;
512}
513
514// Returns true if the load bias reported by the linker is incorrect for the
515// given entry. This function is used to handle cases where we want to work
516// around a bug in the system linker.
517static bool isLoadBiasIncorrect(Target &target, const std::string &file_path) {
518 // On Android L (API 21, 22) the load address of the "/system/bin/linker"
519 // isn't filled in correctly.
520 unsigned os_major = target.GetPlatform()->GetOSVersion().getMajor();
521 return target.GetArchitecture().GetTriple().isAndroid() &&
522 (os_major == 21 || os_major == 22) &&
523 (file_path == "/system/bin/linker" ||
524 file_path == "/system/bin/linker64");
525}
526
527void DYLDRendezvous::UpdateBaseAddrIfNecessary(SOEntry &entry,
528 std::string const &file_path) {
529 // If the load bias reported by the linker is incorrect then fetch the load
530 // address of the file from the proc file system.
531 if (isLoadBiasIncorrect(m_process->GetTarget(), file_path)) {
532 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS(18446744073709551615UL);
533 bool is_loaded = false;
534 Status error =
535 m_process->GetFileLoadAddress(entry.file_spec, is_loaded, load_addr);
536 if (error.Success() && is_loaded)
537 entry.base_addr = load_addr;
538 }
539}
540
541void DYLDRendezvous::UpdateFileSpecIfNecessary(SOEntry &entry) {
542 // Updates filename if empty. It is useful while debugging ld.so,
543 // when the link map returns empty string for the main executable.
544 if (!entry.file_spec) {
545 MemoryRegionInfo region;
546 Status region_status =
547 m_process->GetMemoryRegionInfo(entry.dyn_addr, region);
548 if (!region.GetName().IsEmpty())
549 entry.file_spec.SetFile(region.GetName().AsCString(),
550 FileSpec::Style::native);
551 }
552}
553
554bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) {
555 entry.clear();
556
557 entry.link_addr = addr;
558
559 if (!(addr = ReadPointer(addr, &entry.base_addr)))
560 return false;
561
562 // mips adds an extra load offset field to the link map struct on FreeBSD and
563 // NetBSD (need to validate other OSes).
564 // http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57
565 const ArchSpec &arch = m_process->GetTarget().GetArchitecture();
566 if ((arch.GetTriple().getOS() == llvm::Triple::FreeBSD ||
567 arch.GetTriple().getOS() == llvm::Triple::NetBSD) &&
568 arch.IsMIPS()) {
569 addr_t mips_l_offs;
570 if (!(addr = ReadPointer(addr, &mips_l_offs)))
571 return false;
572 if (mips_l_offs != 0 && mips_l_offs != entry.base_addr)
573 return false;
574 }
575
576 if (!(addr = ReadPointer(addr, &entry.path_addr)))
577 return false;
578
579 if (!(addr = ReadPointer(addr, &entry.dyn_addr)))
580 return false;
581
582 if (!(addr = ReadPointer(addr, &entry.next)))
583 return false;
584
585 if (!(addr = ReadPointer(addr, &entry.prev)))
586 return false;
587
588 std::string file_path = ReadStringFromMemory(entry.path_addr);
589 entry.file_spec.SetFile(file_path, FileSpec::Style::native);
590
591 UpdateBaseAddrIfNecessary(entry, file_path);
592
593 return true;
594}
595
596bool DYLDRendezvous::FindMetadata(const char *name, PThreadField field,
597 uint32_t &value) {
598 Target &target = m_process->GetTarget();
599
600 SymbolContextList list;
601 target.GetImages().FindSymbolsWithNameAndType(ConstString(name),
602 eSymbolTypeAny, list);
603 if (list.IsEmpty())
604 return false;
605
606 Address address = list[0].symbol->GetAddress();
607 addr_t addr = address.GetLoadAddress(&target);
608 if (addr == LLDB_INVALID_ADDRESS(18446744073709551615UL))
609 return false;
610
611 Status error;
612 value = (uint32_t)m_process->ReadUnsignedIntegerFromMemory(
613 addr + field * sizeof(uint32_t), sizeof(uint32_t), 0, error);
614 if (error.Fail())
615 return false;
616
617 if (field == eSize)
618 value /= 8; // convert bits to bytes
619
620 return true;
621}
622
623const DYLDRendezvous::ThreadInfo &DYLDRendezvous::GetThreadInfo() {
624 if (!m_thread_info.valid) {
625 bool ok = true;
626
627 ok &= FindMetadata("_thread_db_pthread_dtvp", eOffset,
628 m_thread_info.dtv_offset);
629 ok &=
630 FindMetadata("_thread_db_dtv_dtv", eSize, m_thread_info.dtv_slot_size);
631 ok &= FindMetadata("_thread_db_link_map_l_tls_modid", eOffset,
632 m_thread_info.modid_offset);
633 ok &= FindMetadata("_thread_db_dtv_t_pointer_val", eOffset,
634 m_thread_info.tls_offset);
635
636 if (ok)
637 m_thread_info.valid = true;
638 }
639
640 return m_thread_info;
641}
642
643void DYLDRendezvous::DumpToLog(Log *log) const {
644 int state = GetState();
645
646 if (!log)
647 return;
648
649 log->PutCString("DYLDRendezvous:");
650 LLDB_LOGF(log, " Address: %" PRIx64, GetRendezvousAddress())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf(" Address: %" "l" "x", GetRendezvousAddress
()); } while (0)
;
651 LLDB_LOGF(log, " Version: %" PRIu64, GetVersion())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf(" Version: %" "l" "u", GetVersion(
)); } while (0)
;
652 LLDB_LOGF(log, " Link : %" PRIx64, GetLinkMapAddress())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf(" Link : %" "l" "x", GetLinkMapAddress
()); } while (0)
;
653 LLDB_LOGF(log, " Break : %" PRIx64, GetBreakAddress())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf(" Break : %" "l" "x", GetBreakAddress
()); } while (0)
;
654 LLDB_LOGF(log, " LDBase : %" PRIx64, GetLDBase())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf(" LDBase : %" "l" "x", GetLDBase()
); } while (0)
;
655 LLDB_LOGF(log, " State : %s",do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf(" State : %s", (state == eConsistent
) ? "consistent" : (state == eAdd) ? "add" : (state == eDelete
) ? "delete" : "unknown"); } while (0)
656 (state == eConsistent)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf(" State : %s", (state == eConsistent
) ? "consistent" : (state == eAdd) ? "add" : (state == eDelete
) ? "delete" : "unknown"); } while (0)
657 ? "consistent"do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf(" State : %s", (state == eConsistent
) ? "consistent" : (state == eAdd) ? "add" : (state == eDelete
) ? "delete" : "unknown"); } while (0)
658 : (state == eAdd) ? "add"do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf(" State : %s", (state == eConsistent
) ? "consistent" : (state == eAdd) ? "add" : (state == eDelete
) ? "delete" : "unknown"); } while (0)
659 : (state == eDelete) ? "delete" : "unknown")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf(" State : %s", (state == eConsistent
) ? "consistent" : (state == eAdd) ? "add" : (state == eDelete
) ? "delete" : "unknown"); } while (0)
;
660
661 iterator I = begin();
662 iterator E = end();
663
664 if (I != E)
665 log->PutCString("DYLDRendezvous SOEntries:");
666
667 for (int i = 1; I != E; ++I, ++i) {
668 LLDB_LOGF(log, "\n SOEntry [%d] %s", i, I->file_spec.GetCString())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("\n SOEntry [%d] %s", i, I->file_spec
.GetCString()); } while (0)
;
669 LLDB_LOGF(log, " Base : %" PRIx64, I->base_addr)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf(" Base : %" "l" "x", I->base_addr
); } while (0)
;
670 LLDB_LOGF(log, " Path : %" PRIx64, I->path_addr)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf(" Path : %" "l" "x", I->path_addr
); } while (0)
;
671 LLDB_LOGF(log, " Dyn : %" PRIx64, I->dyn_addr)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf(" Dyn : %" "l" "x", I->dyn_addr
); } while (0)
;
672 LLDB_LOGF(log, " Next : %" PRIx64, I->next)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf(" Next : %" "l" "x", I->next
); } while (0)
;
673 LLDB_LOGF(log, " Prev : %" PRIx64, I->prev)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf(" Prev : %" "l" "x", I->prev
); } while (0)
;
674 }
675}