Bug Summary

File:build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
Warning:line 576, column 9
Although the value stored to 'addr' is used in the enclosing expression, the value is never actually read from 'addr'

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-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-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-16/lib/clang/16.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-16~++20220904122748+c444af1c20b3/lldb/source/Plugins/DynamicLoader/POSIX-DYLD -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lldb/include -I tools/lldb/include -I include -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/llvm/include -I /usr/include/python3.9 -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/clang/include -I tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/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-16/lib/clang/16.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-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -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/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -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-09-04-125545-48738-1 -x c++ /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/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.GetPath().c_str()); } while (
0)
122 __FUNCTION__, m_exe_file_spec.GetPath().c_str())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.GetPath().c_str()); } 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)))
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 return eNoAction;
214 }
215
216 return eNoAction;
217}
218
219bool DYLDRendezvous::UpdateSOEntriesFromRemote() {
220 auto action = GetAction();
221
222 if (action == eNoAction)
223 return false;
224
225 m_added_soentries.clear();
226 m_removed_soentries.clear();
227 if (action == eTakeSnapshot) {
228 // We already have the loaded list from the previous update so no need to
229 // find all the modules again.
230 if (!m_loaded_modules.m_list.empty())
231 return true;
232 }
233
234 llvm::Expected<LoadedModuleInfoList> module_list =
235 m_process->GetLoadedModuleList();
236 if (!module_list) {
237 llvm::consumeError(module_list.takeError());
238 return false;
239 }
240
241 switch (action) {
242 case eTakeSnapshot:
243 m_soentries.clear();
244 return SaveSOEntriesFromRemote(*module_list);
245 case eAddModules:
246 return AddSOEntriesFromRemote(*module_list);
247 case eRemoveModules:
248 return RemoveSOEntriesFromRemote(*module_list);
249 case eNoAction:
250 return false;
251 }
252 llvm_unreachable("Fully covered switch above!")::llvm::llvm_unreachable_internal("Fully covered switch above!"
, "lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp"
, 252)
;
253}
254
255bool DYLDRendezvous::UpdateSOEntries() {
256 m_added_soentries.clear();
257 m_removed_soentries.clear();
258 switch (GetAction()) {
259 case eTakeSnapshot:
260 m_soentries.clear();
261 return TakeSnapshot(m_soentries);
262 case eAddModules:
263 return AddSOEntries();
264 case eRemoveModules:
265 return RemoveSOEntries();
266 case eNoAction:
267 return false;
268 }
269 llvm_unreachable("Fully covered switch above!")::llvm::llvm_unreachable_internal("Fully covered switch above!"
, "lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp"
, 269)
;
270}
271
272bool DYLDRendezvous::FillSOEntryFromModuleInfo(
273 LoadedModuleInfoList::LoadedModuleInfo const &modInfo, SOEntry &entry) {
274 addr_t link_map_addr;
275 addr_t base_addr;
276 addr_t dyn_addr;
277 std::string name;
278
279 if (!modInfo.get_link_map(link_map_addr) || !modInfo.get_base(base_addr) ||
280 !modInfo.get_dynamic(dyn_addr) || !modInfo.get_name(name))
281 return false;
282
283 entry.link_addr = link_map_addr;
284 entry.base_addr = base_addr;
285 entry.dyn_addr = dyn_addr;
286
287 entry.file_spec.SetFile(name, FileSpec::Style::native);
288
289 UpdateBaseAddrIfNecessary(entry, name);
290
291 // not needed if we're using ModuleInfos
292 entry.next = 0;
293 entry.prev = 0;
294 entry.path_addr = 0;
295
296 return true;
297}
298
299bool DYLDRendezvous::SaveSOEntriesFromRemote(
300 const LoadedModuleInfoList &module_list) {
301 for (auto const &modInfo : module_list.m_list) {
302 SOEntry entry;
303 if (!FillSOEntryFromModuleInfo(modInfo, entry))
304 return false;
305
306 // Only add shared libraries and not the executable.
307 if (!SOEntryIsMainExecutable(entry)) {
308 UpdateFileSpecIfNecessary(entry);
309 m_soentries.push_back(entry);
310 }
311 }
312
313 m_loaded_modules = module_list;
314 return true;
315}
316
317bool DYLDRendezvous::AddSOEntriesFromRemote(
318 const LoadedModuleInfoList &module_list) {
319 for (auto const &modInfo : module_list.m_list) {
320 bool found = false;
321 for (auto const &existing : m_loaded_modules.m_list) {
322 if (modInfo == existing) {
323 found = true;
324 break;
325 }
326 }
327
328 if (found)
329 continue;
330
331 SOEntry entry;
332 if (!FillSOEntryFromModuleInfo(modInfo, entry))
333 return false;
334
335 // Only add shared libraries and not the executable.
336 if (!SOEntryIsMainExecutable(entry)) {
337 UpdateFileSpecIfNecessary(entry);
338 m_soentries.push_back(entry);
339 m_added_soentries.push_back(entry);
340 }
341 }
342
343 m_loaded_modules = module_list;
344 return true;
345}
346
347bool DYLDRendezvous::RemoveSOEntriesFromRemote(
348 const LoadedModuleInfoList &module_list) {
349 for (auto const &existing : m_loaded_modules.m_list) {
350 bool found = false;
351 for (auto const &modInfo : module_list.m_list) {
352 if (modInfo == existing) {
353 found = true;
354 break;
355 }
356 }
357
358 if (found)
359 continue;
360
361 SOEntry entry;
362 if (!FillSOEntryFromModuleInfo(existing, entry))
363 return false;
364
365 // Only add shared libraries and not the executable.
366 if (!SOEntryIsMainExecutable(entry)) {
367 auto pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
368 if (pos == m_soentries.end())
369 return false;
370
371 m_soentries.erase(pos);
372 m_removed_soentries.push_back(entry);
373 }
374 }
375
376 m_loaded_modules = module_list;
377 return true;
378}
379
380bool DYLDRendezvous::AddSOEntries() {
381 SOEntry entry;
382 iterator pos;
383
384 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"
, 384, __extension__ __PRETTY_FUNCTION__))
;
385
386 if (m_current.map_addr == 0)
387 return false;
388
389 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) {
390 if (!ReadSOEntryFromMemory(cursor, entry))
391 return false;
392
393 // Only add shared libraries and not the executable.
394 if (SOEntryIsMainExecutable(entry))
395 continue;
396
397 UpdateFileSpecIfNecessary(entry);
398
399 if (!llvm::is_contained(m_soentries, entry)) {
400 m_soentries.push_back(entry);
401 m_added_soentries.push_back(entry);
402 }
403 }
404
405 return true;
406}
407
408bool DYLDRendezvous::RemoveSOEntries() {
409 SOEntryList entry_list;
410 iterator pos;
411
412 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"
, 412, __extension__ __PRETTY_FUNCTION__))
;
413
414 if (!TakeSnapshot(entry_list))
415 return false;
416
417 for (iterator I = begin(); I != end(); ++I) {
418 if (!llvm::is_contained(entry_list, *I))
419 m_removed_soentries.push_back(*I);
420 }
421
422 m_soentries = entry_list;
423 return true;
424}
425
426bool DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) {
427 // On some systes the executable is indicated by an empty path in the entry.
428 // On others it is the full path to the executable.
429
430 auto triple = m_process->GetTarget().GetArchitecture().GetTriple();
431 switch (triple.getOS()) {
432 case llvm::Triple::FreeBSD:
433 case llvm::Triple::NetBSD:
434 return entry.file_spec == m_exe_file_spec;
435 case llvm::Triple::Linux:
436 if (triple.isAndroid())
437 return entry.file_spec == m_exe_file_spec;
438 // If we are debugging ld.so, then all SOEntries should be treated as
439 // libraries, including the "main" one (denoted by an empty string).
440 if (!entry.file_spec && m_executable_interpreter)
441 return false;
442 return !entry.file_spec;
443 default:
444 return false;
445 }
446}
447
448bool DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) {
449 SOEntry entry;
450
451 if (m_current.map_addr == 0)
452 return false;
453
454 // Clear previous entries since we are about to obtain an up to date list.
455 entry_list.clear();
456
457 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) {
458 if (!ReadSOEntryFromMemory(cursor, entry))
459 return false;
460
461 // Only add shared libraries and not the executable.
462 if (SOEntryIsMainExecutable(entry))
463 continue;
464
465 UpdateFileSpecIfNecessary(entry);
466
467 entry_list.push_back(entry);
468 }
469
470 return true;
471}
472
473addr_t DYLDRendezvous::ReadWord(addr_t addr, uint64_t *dst, size_t size) {
474 Status error;
475
476 *dst = m_process->ReadUnsignedIntegerFromMemory(addr, size, 0, error);
477 if (error.Fail())
478 return 0;
479
480 return addr + size;
481}
482
483addr_t DYLDRendezvous::ReadPointer(addr_t addr, addr_t *dst) {
484 Status error;
485
486 *dst = m_process->ReadPointerFromMemory(addr, error);
487 if (error.Fail())
488 return 0;
489
490 return addr + m_process->GetAddressByteSize();
491}
492
493std::string DYLDRendezvous::ReadStringFromMemory(addr_t addr) {
494 std::string str;
495 Status error;
496
497 if (addr == LLDB_INVALID_ADDRESS(18446744073709551615UL))
498 return std::string();
499
500 m_process->ReadCStringFromMemory(addr, str, error);
501
502 return str;
503}
504
505// Returns true if the load bias reported by the linker is incorrect for the
506// given entry. This function is used to handle cases where we want to work
507// around a bug in the system linker.
508static bool isLoadBiasIncorrect(Target &target, const std::string &file_path) {
509 // On Android L (API 21, 22) the load address of the "/system/bin/linker"
510 // isn't filled in correctly.
511 unsigned os_major = target.GetPlatform()->GetOSVersion().getMajor();
512 return target.GetArchitecture().GetTriple().isAndroid() &&
513 (os_major == 21 || os_major == 22) &&
514 (file_path == "/system/bin/linker" ||
515 file_path == "/system/bin/linker64");
516}
517
518void DYLDRendezvous::UpdateBaseAddrIfNecessary(SOEntry &entry,
519 std::string const &file_path) {
520 // If the load bias reported by the linker is incorrect then fetch the load
521 // address of the file from the proc file system.
522 if (isLoadBiasIncorrect(m_process->GetTarget(), file_path)) {
523 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS(18446744073709551615UL);
524 bool is_loaded = false;
525 Status error =
526 m_process->GetFileLoadAddress(entry.file_spec, is_loaded, load_addr);
527 if (error.Success() && is_loaded)
528 entry.base_addr = load_addr;
529 }
530}
531
532void DYLDRendezvous::UpdateFileSpecIfNecessary(SOEntry &entry) {
533 // Updates filename if empty. It is useful while debugging ld.so,
534 // when the link map returns empty string for the main executable.
535 if (!entry.file_spec) {
536 MemoryRegionInfo region;
537 Status region_status =
538 m_process->GetMemoryRegionInfo(entry.dyn_addr, region);
539 if (!region.GetName().IsEmpty())
540 entry.file_spec.SetFile(region.GetName().AsCString(),
541 FileSpec::Style::native);
542 }
543}
544
545bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) {
546 entry.clear();
547
548 entry.link_addr = addr;
549
550 if (!(addr = ReadPointer(addr, &entry.base_addr)))
551 return false;
552
553 // mips adds an extra load offset field to the link map struct on FreeBSD and
554 // NetBSD (need to validate other OSes).
555 // http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57
556 const ArchSpec &arch = m_process->GetTarget().GetArchitecture();
557 if ((arch.GetTriple().getOS() == llvm::Triple::FreeBSD ||
558 arch.GetTriple().getOS() == llvm::Triple::NetBSD) &&
559 arch.IsMIPS()) {
560 addr_t mips_l_offs;
561 if (!(addr = ReadPointer(addr, &mips_l_offs)))
562 return false;
563 if (mips_l_offs != 0 && mips_l_offs != entry.base_addr)
564 return false;
565 }
566
567 if (!(addr = ReadPointer(addr, &entry.path_addr)))
568 return false;
569
570 if (!(addr = ReadPointer(addr, &entry.dyn_addr)))
571 return false;
572
573 if (!(addr = ReadPointer(addr, &entry.next)))
574 return false;
575
576 if (!(addr = ReadPointer(addr, &entry.prev)))
Although the value stored to 'addr' is used in the enclosing expression, the value is never actually read from 'addr'
577 return false;
578
579 std::string file_path = ReadStringFromMemory(entry.path_addr);
580 entry.file_spec.SetFile(file_path, FileSpec::Style::native);
581
582 UpdateBaseAddrIfNecessary(entry, file_path);
583
584 return true;
585}
586
587bool DYLDRendezvous::FindMetadata(const char *name, PThreadField field,
588 uint32_t &value) {
589 Target &target = m_process->GetTarget();
590
591 SymbolContextList list;
592 target.GetImages().FindSymbolsWithNameAndType(ConstString(name),
593 eSymbolTypeAny, list);
594 if (list.IsEmpty())
595 return false;
596
597 Address address = list[0].symbol->GetAddress();
598 addr_t addr = address.GetLoadAddress(&target);
599 if (addr == LLDB_INVALID_ADDRESS(18446744073709551615UL))
600 return false;
601
602 Status error;
603 value = (uint32_t)m_process->ReadUnsignedIntegerFromMemory(
604 addr + field * sizeof(uint32_t), sizeof(uint32_t), 0, error);
605 if (error.Fail())
606 return false;
607
608 if (field == eSize)
609 value /= 8; // convert bits to bytes
610
611 return true;
612}
613
614const DYLDRendezvous::ThreadInfo &DYLDRendezvous::GetThreadInfo() {
615 if (!m_thread_info.valid) {
616 bool ok = true;
617
618 ok &= FindMetadata("_thread_db_pthread_dtvp", eOffset,
619 m_thread_info.dtv_offset);
620 ok &=
621 FindMetadata("_thread_db_dtv_dtv", eSize, m_thread_info.dtv_slot_size);
622 ok &= FindMetadata("_thread_db_link_map_l_tls_modid", eOffset,
623 m_thread_info.modid_offset);
624 ok &= FindMetadata("_thread_db_dtv_t_pointer_val", eOffset,
625 m_thread_info.tls_offset);
626
627 if (ok)
628 m_thread_info.valid = true;
629 }
630
631 return m_thread_info;
632}
633
634void DYLDRendezvous::DumpToLog(Log *log) const {
635 int state = GetState();
636
637 if (!log)
638 return;
639
640 log->PutCString("DYLDRendezvous:");
641 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)
;
642 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)
;
643 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)
;
644 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)
;
645 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)
;
646 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)
647 (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)
648 ? "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)
649 : (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)
650 : (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)
;
651
652 iterator I = begin();
653 iterator E = end();
654
655 if (I != E)
656 log->PutCString("DYLDRendezvous SOEntries:");
657
658 for (int i = 1; I != E; ++I, ++i) {
659 LLDB_LOGF(log, "\n SOEntry [%d] %s", i, I->file_spec.GetPath().c_str())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("\n SOEntry [%d] %s", i, I->file_spec
.GetPath().c_str()); } while (0)
;
660 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)
;
661 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)
;
662 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)
;
663 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)
;
664 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)
;
665 }
666}