Bug Summary

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