Bug Summary

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