1 | //===-- Module.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 | |
11 | #include "lldb/Core/AddressRange.h" |
12 | #include "lldb/Core/AddressResolverFileLine.h" |
13 | #include "lldb/Core/Debugger.h" |
14 | #include "lldb/Core/FileSpecList.h" |
15 | #include "lldb/Core/Mangled.h" |
16 | #include "lldb/Core/ModuleSpec.h" |
17 | #include "lldb/Core/SearchFilter.h" |
18 | #include "lldb/Core/Section.h" |
19 | #include "lldb/Host/FileSystem.h" |
20 | #include "lldb/Host/Host.h" |
21 | #include "lldb/Host/HostInfo.h" |
22 | #include "lldb/Interpreter/CommandInterpreter.h" |
23 | #include "lldb/Interpreter/ScriptInterpreter.h" |
24 | #include "lldb/Symbol/CompileUnit.h" |
25 | #include "lldb/Symbol/Function.h" |
26 | #include "lldb/Symbol/ObjectFile.h" |
27 | #include "lldb/Symbol/Symbol.h" |
28 | #include "lldb/Symbol/SymbolContext.h" |
29 | #include "lldb/Symbol/SymbolFile.h" |
30 | #include "lldb/Symbol/SymbolVendor.h" |
31 | #include "lldb/Symbol/Symtab.h" |
32 | #include "lldb/Symbol/Type.h" |
33 | #include "lldb/Symbol/TypeList.h" |
34 | #include "lldb/Symbol/TypeMap.h" |
35 | #include "lldb/Symbol/TypeSystem.h" |
36 | #include "lldb/Target/Language.h" |
37 | #include "lldb/Target/Process.h" |
38 | #include "lldb/Target/Target.h" |
39 | #include "lldb/Utility/DataBufferHeap.h" |
40 | #include "lldb/Utility/LLDBAssert.h" |
41 | #include "lldb/Utility/Log.h" |
42 | #include "lldb/Utility/Logging.h" |
43 | #include "lldb/Utility/RegularExpression.h" |
44 | #include "lldb/Utility/Status.h" |
45 | #include "lldb/Utility/Stream.h" |
46 | #include "lldb/Utility/StreamString.h" |
47 | #include "lldb/Utility/Timer.h" |
48 | |
49 | #if defined(_WIN32) |
50 | #include "lldb/Host/windows/PosixApi.h" |
51 | #endif |
52 | |
53 | #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" |
54 | #include "Plugins/Language/ObjC/ObjCLanguage.h" |
55 | |
56 | #include "llvm/ADT/STLExtras.h" |
57 | #include "llvm/Support/Compiler.h" |
58 | #include "llvm/Support/FileSystem.h" |
59 | #include "llvm/Support/Signals.h" |
60 | #include "llvm/Support/raw_ostream.h" |
61 | |
62 | #include <assert.h> |
63 | #include <cstdint> |
64 | #include <inttypes.h> |
65 | #include <map> |
66 | #include <stdarg.h> |
67 | #include <string.h> |
68 | #include <type_traits> |
69 | #include <utility> |
70 | |
71 | namespace lldb_private { |
72 | class CompilerDeclContext; |
73 | } |
74 | namespace lldb_private { |
75 | class VariableList; |
76 | } |
77 | |
78 | using namespace lldb; |
79 | using namespace lldb_private; |
80 | |
81 | // Shared pointers to modules track module lifetimes in targets and in the |
82 | // global module, but this collection will track all module objects that are |
83 | // still alive |
84 | typedef std::vector<Module *> ModuleCollection; |
85 | |
86 | static ModuleCollection &GetModuleCollection() { |
87 | // This module collection needs to live past any module, so we could either |
88 | // make it a shared pointer in each module or just leak is. Since it is only |
89 | // an empty vector by the time all the modules have gone away, we just leak |
90 | // it for now. If we decide this is a big problem we can introduce a |
91 | // Finalize method that will tear everything down in a predictable order. |
92 | |
93 | static ModuleCollection *g_module_collection = nullptr; |
94 | if (g_module_collection == nullptr) |
95 | g_module_collection = new ModuleCollection(); |
96 | |
97 | return *g_module_collection; |
98 | } |
99 | |
100 | std::recursive_mutex &Module::GetAllocationModuleCollectionMutex() { |
101 | // NOTE: The mutex below must be leaked since the global module list in |
102 | // the ModuleList class will get torn at some point, and we can't know if it |
103 | // will tear itself down before the "g_module_collection_mutex" below will. |
104 | // So we leak a Mutex object below to safeguard against that |
105 | |
106 | static std::recursive_mutex *g_module_collection_mutex = nullptr; |
107 | if (g_module_collection_mutex == nullptr) |
108 | g_module_collection_mutex = new std::recursive_mutex; // NOTE: known leak |
109 | return *g_module_collection_mutex; |
110 | } |
111 | |
112 | size_t Module::GetNumberAllocatedModules() { |
113 | std::lock_guard<std::recursive_mutex> guard( |
114 | GetAllocationModuleCollectionMutex()); |
115 | return GetModuleCollection().size(); |
116 | } |
117 | |
118 | Module *Module::GetAllocatedModuleAtIndex(size_t idx) { |
119 | std::lock_guard<std::recursive_mutex> guard( |
120 | GetAllocationModuleCollectionMutex()); |
121 | ModuleCollection &modules = GetModuleCollection(); |
122 | if (idx < modules.size()) |
123 | return modules[idx]; |
124 | return nullptr; |
125 | } |
126 | |
127 | Module::Module(const ModuleSpec &module_spec) |
128 | : m_object_offset(0), m_file_has_changed(false), |
129 | m_first_file_changed_log(false) { |
130 | // Scope for locker below... |
131 | { |
132 | std::lock_guard<std::recursive_mutex> guard( |
133 | GetAllocationModuleCollectionMutex()); |
134 | GetModuleCollection().push_back(this); |
135 | } |
136 | |
137 | Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT | |
138 | LIBLLDB_LOG_MODULES)); |
139 | if (log != nullptr) |
140 | LLDB_LOGF(log, "%p Module::Module((%s) '%s%s%s%s')" , |
141 | static_cast<void *>(this), |
142 | module_spec.GetArchitecture().GetArchitectureName(), |
143 | module_spec.GetFileSpec().GetPath().c_str(), |
144 | module_spec.GetObjectName().IsEmpty() ? "" : "(" , |
145 | module_spec.GetObjectName().IsEmpty() |
146 | ? "" |
147 | : module_spec.GetObjectName().AsCString("" ), |
148 | module_spec.GetObjectName().IsEmpty() ? "" : ")" ); |
149 | |
150 | auto data_sp = module_spec.GetData(); |
151 | lldb::offset_t file_size = 0; |
152 | if (data_sp) |
153 | file_size = data_sp->GetByteSize(); |
154 | |
155 | // First extract all module specifications from the file using the local file |
156 | // path. If there are no specifications, then don't fill anything in |
157 | ModuleSpecList modules_specs; |
158 | if (ObjectFile::GetModuleSpecifications( |
159 | module_spec.GetFileSpec(), 0, file_size, modules_specs, data_sp) == 0) |
160 | return; |
161 | |
162 | // Now make sure that one of the module specifications matches what we just |
163 | // extract. We might have a module specification that specifies a file |
164 | // "/usr/lib/dyld" with UUID XXX, but we might have a local version of |
165 | // "/usr/lib/dyld" that has |
166 | // UUID YYY and we don't want those to match. If they don't match, just don't |
167 | // fill any ivars in so we don't accidentally grab the wrong file later since |
168 | // they don't match... |
169 | ModuleSpec matching_module_spec; |
170 | if (!modules_specs.FindMatchingModuleSpec(module_spec, |
171 | matching_module_spec)) { |
172 | if (log) { |
173 | LLDB_LOGF(log, "Found local object file but the specs didn't match" ); |
174 | } |
175 | return; |
176 | } |
177 | |
178 | // Set m_data_sp if it was initially provided in the ModuleSpec. Note that |
179 | // we cannot use the data_sp variable here, because it will have been |
180 | // modified by GetModuleSpecifications(). |
181 | if (auto module_spec_data_sp = module_spec.GetData()) { |
182 | m_data_sp = module_spec_data_sp; |
183 | m_mod_time = {}; |
184 | } else { |
185 | if (module_spec.GetFileSpec()) |
186 | m_mod_time = |
187 | FileSystem::Instance().GetModificationTime(module_spec.GetFileSpec()); |
188 | else if (matching_module_spec.GetFileSpec()) |
189 | m_mod_time = FileSystem::Instance().GetModificationTime( |
190 | matching_module_spec.GetFileSpec()); |
191 | } |
192 | |
193 | // Copy the architecture from the actual spec if we got one back, else use |
194 | // the one that was specified |
195 | if (matching_module_spec.GetArchitecture().IsValid()) |
196 | m_arch = matching_module_spec.GetArchitecture(); |
197 | else if (module_spec.GetArchitecture().IsValid()) |
198 | m_arch = module_spec.GetArchitecture(); |
199 | |
200 | // Copy the file spec over and use the specified one (if there was one) so we |
201 | // don't use a path that might have gotten resolved a path in |
202 | // 'matching_module_spec' |
203 | if (module_spec.GetFileSpec()) |
204 | m_file = module_spec.GetFileSpec(); |
205 | else if (matching_module_spec.GetFileSpec()) |
206 | m_file = matching_module_spec.GetFileSpec(); |
207 | |
208 | // Copy the platform file spec over |
209 | if (module_spec.GetPlatformFileSpec()) |
210 | m_platform_file = module_spec.GetPlatformFileSpec(); |
211 | else if (matching_module_spec.GetPlatformFileSpec()) |
212 | m_platform_file = matching_module_spec.GetPlatformFileSpec(); |
213 | |
214 | // Copy the symbol file spec over |
215 | if (module_spec.GetSymbolFileSpec()) |
216 | m_symfile_spec = module_spec.GetSymbolFileSpec(); |
217 | else if (matching_module_spec.GetSymbolFileSpec()) |
218 | m_symfile_spec = matching_module_spec.GetSymbolFileSpec(); |
219 | |
220 | // Copy the object name over |
221 | if (matching_module_spec.GetObjectName()) |
222 | m_object_name = matching_module_spec.GetObjectName(); |
223 | else |
224 | m_object_name = module_spec.GetObjectName(); |
225 | |
226 | // Always trust the object offset (file offset) and object modification time |
227 | // (for mod time in a BSD static archive) of from the matching module |
228 | // specification |
229 | m_object_offset = matching_module_spec.GetObjectOffset(); |
230 | m_object_mod_time = matching_module_spec.GetObjectModificationTime(); |
231 | } |
232 | |
233 | Module::Module(const FileSpec &file_spec, const ArchSpec &arch, |
234 | const ConstString *object_name, lldb::offset_t object_offset, |
235 | const llvm::sys::TimePoint<> &object_mod_time) |
236 | : m_mod_time(FileSystem::Instance().GetModificationTime(file_spec)), m_arch(arch), |
237 | m_file(file_spec), m_object_offset(object_offset), |
238 | m_object_mod_time(object_mod_time), m_file_has_changed(false), |
239 | m_first_file_changed_log(false) { |
240 | // Scope for locker below... |
241 | { |
242 | std::lock_guard<std::recursive_mutex> guard( |
243 | GetAllocationModuleCollectionMutex()); |
244 | GetModuleCollection().push_back(this); |
245 | } |
246 | |
247 | if (object_name) |
248 | m_object_name = *object_name; |
249 | |
250 | Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT | |
251 | LIBLLDB_LOG_MODULES)); |
252 | if (log != nullptr) |
253 | LLDB_LOGF(log, "%p Module::Module((%s) '%s%s%s%s')" , |
254 | static_cast<void *>(this), m_arch.GetArchitectureName(), |
255 | m_file.GetPath().c_str(), m_object_name.IsEmpty() ? "" : "(" , |
256 | m_object_name.IsEmpty() ? "" : m_object_name.AsCString("" ), |
257 | m_object_name.IsEmpty() ? "" : ")" ); |
258 | } |
259 | |
260 | Module::Module() |
261 | : m_object_offset(0), m_file_has_changed(false), |
262 | m_first_file_changed_log(false) { |
263 | std::lock_guard<std::recursive_mutex> guard( |
264 | GetAllocationModuleCollectionMutex()); |
265 | GetModuleCollection().push_back(this); |
266 | } |
267 | |
268 | Module::~Module() { |
269 | // Lock our module down while we tear everything down to make sure we don't |
270 | // get any access to the module while it is being destroyed |
271 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
272 | // Scope for locker below... |
273 | { |
274 | std::lock_guard<std::recursive_mutex> guard( |
275 | GetAllocationModuleCollectionMutex()); |
276 | ModuleCollection &modules = GetModuleCollection(); |
277 | ModuleCollection::iterator end = modules.end(); |
278 | ModuleCollection::iterator pos = std::find(modules.begin(), end, this); |
279 | assert(pos != end); |
280 | modules.erase(pos); |
281 | } |
282 | Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT | |
283 | LIBLLDB_LOG_MODULES)); |
284 | if (log != nullptr) |
285 | LLDB_LOGF(log, "%p Module::~Module((%s) '%s%s%s%s')" , |
286 | static_cast<void *>(this), m_arch.GetArchitectureName(), |
287 | m_file.GetPath().c_str(), m_object_name.IsEmpty() ? "" : "(" , |
288 | m_object_name.IsEmpty() ? "" : m_object_name.AsCString("" ), |
289 | m_object_name.IsEmpty() ? "" : ")" ); |
290 | // Release any auto pointers before we start tearing down our member |
291 | // variables since the object file and symbol files might need to make |
292 | // function calls back into this module object. The ordering is important |
293 | // here because symbol files can require the module object file. So we tear |
294 | // down the symbol file first, then the object file. |
295 | m_sections_up.reset(); |
296 | m_symfile_up.reset(); |
297 | m_objfile_sp.reset(); |
298 | } |
299 | |
300 | ObjectFile *Module::GetMemoryObjectFile(const lldb::ProcessSP &process_sp, |
301 | lldb::addr_t , Status &error, |
302 | size_t size_to_read) { |
303 | if (m_objfile_sp) { |
304 | error.SetErrorString("object file already exists" ); |
305 | } else { |
306 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
307 | if (process_sp) { |
308 | m_did_load_objfile = true; |
309 | auto data_up = std::make_unique<DataBufferHeap>(size_to_read, 0); |
310 | Status readmem_error; |
311 | const size_t bytes_read = |
312 | process_sp->ReadMemory(header_addr, data_up->GetBytes(), |
313 | data_up->GetByteSize(), readmem_error); |
314 | if (bytes_read < size_to_read) |
315 | data_up->SetByteSize(bytes_read); |
316 | if (data_up->GetByteSize() > 0) { |
317 | DataBufferSP data_sp(data_up.release()); |
318 | m_objfile_sp = ObjectFile::FindPlugin(shared_from_this(), process_sp, |
319 | header_addr, data_sp); |
320 | if (m_objfile_sp) { |
321 | StreamString s; |
322 | s.Printf("0x%16.16" PRIx64, header_addr); |
323 | m_object_name.SetString(s.GetString()); |
324 | |
325 | // Once we get the object file, update our module with the object |
326 | // file's architecture since it might differ in vendor/os if some |
327 | // parts were unknown. |
328 | m_arch = m_objfile_sp->GetArchitecture(); |
329 | |
330 | // Augment the arch with the target's information in case |
331 | // we are unable to extract the os/environment from memory. |
332 | m_arch.MergeFrom(process_sp->GetTarget().GetArchitecture()); |
333 | } else { |
334 | error.SetErrorString("unable to find suitable object file plug-in" ); |
335 | } |
336 | } else { |
337 | error.SetErrorStringWithFormat("unable to read header from memory: %s" , |
338 | readmem_error.AsCString()); |
339 | } |
340 | } else { |
341 | error.SetErrorString("invalid process" ); |
342 | } |
343 | } |
344 | return m_objfile_sp.get(); |
345 | } |
346 | |
347 | const lldb_private::UUID &Module::GetUUID() { |
348 | if (!m_did_set_uuid.load()) { |
349 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
350 | if (!m_did_set_uuid.load()) { |
351 | ObjectFile *obj_file = GetObjectFile(); |
352 | |
353 | if (obj_file != nullptr) { |
354 | m_uuid = obj_file->GetUUID(); |
355 | m_did_set_uuid = true; |
356 | } |
357 | } |
358 | } |
359 | return m_uuid; |
360 | } |
361 | |
362 | void Module::SetUUID(const lldb_private::UUID &uuid) { |
363 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
364 | if (!m_did_set_uuid) { |
365 | m_uuid = uuid; |
366 | m_did_set_uuid = true; |
367 | } else { |
368 | lldbassert(0 && "Attempting to overwrite the existing module UUID" ); |
369 | } |
370 | } |
371 | |
372 | llvm::Expected<TypeSystem &> |
373 | Module::GetTypeSystemForLanguage(LanguageType language) { |
374 | return m_type_system_map.GetTypeSystemForLanguage(language, this, true); |
375 | } |
376 | |
377 | void Module::ParseAllDebugSymbols() { |
378 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
379 | size_t num_comp_units = GetNumCompileUnits(); |
380 | if (num_comp_units == 0) |
381 | return; |
382 | |
383 | SymbolFile *symbols = GetSymbolFile(); |
384 | |
385 | for (size_t cu_idx = 0; cu_idx < num_comp_units; cu_idx++) { |
386 | SymbolContext sc; |
387 | sc.module_sp = shared_from_this(); |
388 | sc.comp_unit = symbols->GetCompileUnitAtIndex(cu_idx).get(); |
389 | if (!sc.comp_unit) |
390 | continue; |
391 | |
392 | symbols->ParseVariablesForContext(sc); |
393 | |
394 | symbols->ParseFunctions(*sc.comp_unit); |
395 | |
396 | sc.comp_unit->ForeachFunction([&sc, &symbols](const FunctionSP &f) { |
397 | symbols->ParseBlocksRecursive(*f); |
398 | |
399 | // Parse the variables for this function and all its blocks |
400 | sc.function = f.get(); |
401 | symbols->ParseVariablesForContext(sc); |
402 | return false; |
403 | }); |
404 | |
405 | // Parse all types for this compile unit |
406 | symbols->ParseTypes(*sc.comp_unit); |
407 | } |
408 | } |
409 | |
410 | void Module::CalculateSymbolContext(SymbolContext *sc) { |
411 | sc->module_sp = shared_from_this(); |
412 | } |
413 | |
414 | ModuleSP Module::CalculateSymbolContextModule() { return shared_from_this(); } |
415 | |
416 | void Module::DumpSymbolContext(Stream *s) { |
417 | s->Printf(", Module{%p}" , static_cast<void *>(this)); |
418 | } |
419 | |
420 | size_t Module::GetNumCompileUnits() { |
421 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
422 | LLDB_SCOPED_TIMERF("Module::GetNumCompileUnits (module = %p)" , |
423 | static_cast<void *>(this)); |
424 | if (SymbolFile *symbols = GetSymbolFile()) |
425 | return symbols->GetNumCompileUnits(); |
426 | return 0; |
427 | } |
428 | |
429 | CompUnitSP Module::GetCompileUnitAtIndex(size_t index) { |
430 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
431 | size_t num_comp_units = GetNumCompileUnits(); |
432 | CompUnitSP cu_sp; |
433 | |
434 | if (index < num_comp_units) { |
435 | if (SymbolFile *symbols = GetSymbolFile()) |
436 | cu_sp = symbols->GetCompileUnitAtIndex(index); |
437 | } |
438 | return cu_sp; |
439 | } |
440 | |
441 | bool Module::ResolveFileAddress(lldb::addr_t vm_addr, Address &so_addr) { |
442 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
443 | LLDB_SCOPED_TIMERF("Module::ResolveFileAddress (vm_addr = 0x%" PRIx64 ")" , |
444 | vm_addr); |
445 | SectionList *section_list = GetSectionList(); |
446 | if (section_list) |
447 | return so_addr.ResolveAddressUsingFileSections(vm_addr, section_list); |
448 | return false; |
449 | } |
450 | |
451 | uint32_t Module::ResolveSymbolContextForAddress( |
452 | const Address &so_addr, lldb::SymbolContextItem resolve_scope, |
453 | SymbolContext &sc, bool resolve_tail_call_address) { |
454 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
455 | uint32_t resolved_flags = 0; |
456 | |
457 | // Clear the result symbol context in case we don't find anything, but don't |
458 | // clear the target |
459 | sc.Clear(false); |
460 | |
461 | // Get the section from the section/offset address. |
462 | SectionSP section_sp(so_addr.GetSection()); |
463 | |
464 | // Make sure the section matches this module before we try and match anything |
465 | if (section_sp && section_sp->GetModule().get() == this) { |
466 | // If the section offset based address resolved itself, then this is the |
467 | // right module. |
468 | sc.module_sp = shared_from_this(); |
469 | resolved_flags |= eSymbolContextModule; |
470 | |
471 | SymbolFile *symfile = GetSymbolFile(); |
472 | if (!symfile) |
473 | return resolved_flags; |
474 | |
475 | // Resolve the compile unit, function, block, line table or line entry if |
476 | // requested. |
477 | if (resolve_scope & eSymbolContextCompUnit || |
478 | resolve_scope & eSymbolContextFunction || |
479 | resolve_scope & eSymbolContextBlock || |
480 | resolve_scope & eSymbolContextLineEntry || |
481 | resolve_scope & eSymbolContextVariable) { |
482 | resolved_flags |= |
483 | symfile->ResolveSymbolContext(so_addr, resolve_scope, sc); |
484 | } |
485 | |
486 | // Resolve the symbol if requested, but don't re-look it up if we've |
487 | // already found it. |
488 | if (resolve_scope & eSymbolContextSymbol && |
489 | !(resolved_flags & eSymbolContextSymbol)) { |
490 | Symtab *symtab = symfile->GetSymtab(); |
491 | if (symtab && so_addr.IsSectionOffset()) { |
492 | Symbol *matching_symbol = nullptr; |
493 | |
494 | symtab->ForEachSymbolContainingFileAddress( |
495 | so_addr.GetFileAddress(), |
496 | [&matching_symbol](Symbol *symbol) -> bool { |
497 | if (symbol->GetType() != eSymbolTypeInvalid) { |
498 | matching_symbol = symbol; |
499 | return false; // Stop iterating |
500 | } |
501 | return true; // Keep iterating |
502 | }); |
503 | sc.symbol = matching_symbol; |
504 | if (!sc.symbol && resolve_scope & eSymbolContextFunction && |
505 | !(resolved_flags & eSymbolContextFunction)) { |
506 | bool verify_unique = false; // No need to check again since |
507 | // ResolveSymbolContext failed to find a |
508 | // symbol at this address. |
509 | if (ObjectFile *obj_file = sc.module_sp->GetObjectFile()) |
510 | sc.symbol = |
511 | obj_file->ResolveSymbolForAddress(so_addr, verify_unique); |
512 | } |
513 | |
514 | if (sc.symbol) { |
515 | if (sc.symbol->IsSynthetic()) { |
516 | // We have a synthetic symbol so lets check if the object file from |
517 | // the symbol file in the symbol vendor is different than the |
518 | // object file for the module, and if so search its symbol table to |
519 | // see if we can come up with a better symbol. For example dSYM |
520 | // files on MacOSX have an unstripped symbol table inside of them. |
521 | ObjectFile *symtab_objfile = symtab->GetObjectFile(); |
522 | if (symtab_objfile && symtab_objfile->IsStripped()) { |
523 | ObjectFile *symfile_objfile = symfile->GetObjectFile(); |
524 | if (symfile_objfile != symtab_objfile) { |
525 | Symtab *symfile_symtab = symfile_objfile->GetSymtab(); |
526 | if (symfile_symtab) { |
527 | Symbol *symbol = |
528 | symfile_symtab->FindSymbolContainingFileAddress( |
529 | so_addr.GetFileAddress()); |
530 | if (symbol && !symbol->IsSynthetic()) { |
531 | sc.symbol = symbol; |
532 | } |
533 | } |
534 | } |
535 | } |
536 | } |
537 | resolved_flags |= eSymbolContextSymbol; |
538 | } |
539 | } |
540 | } |
541 | |
542 | // For function symbols, so_addr may be off by one. This is a convention |
543 | // consistent with FDE row indices in eh_frame sections, but requires extra |
544 | // logic here to permit symbol lookup for disassembly and unwind. |
545 | if (resolve_scope & eSymbolContextSymbol && |
546 | !(resolved_flags & eSymbolContextSymbol) && resolve_tail_call_address && |
547 | so_addr.IsSectionOffset()) { |
548 | Address previous_addr = so_addr; |
549 | previous_addr.Slide(-1); |
550 | |
551 | bool do_resolve_tail_call_address = false; // prevent recursion |
552 | const uint32_t flags = ResolveSymbolContextForAddress( |
553 | previous_addr, resolve_scope, sc, do_resolve_tail_call_address); |
554 | if (flags & eSymbolContextSymbol) { |
555 | AddressRange addr_range; |
556 | if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, |
557 | false, addr_range)) { |
558 | if (addr_range.GetBaseAddress().GetSection() == |
559 | so_addr.GetSection()) { |
560 | // If the requested address is one past the address range of a |
561 | // function (i.e. a tail call), or the decremented address is the |
562 | // start of a function (i.e. some forms of trampoline), indicate |
563 | // that the symbol has been resolved. |
564 | if (so_addr.GetOffset() == |
565 | addr_range.GetBaseAddress().GetOffset() || |
566 | so_addr.GetOffset() == |
567 | addr_range.GetBaseAddress().GetOffset() + |
568 | addr_range.GetByteSize()) { |
569 | resolved_flags |= flags; |
570 | } |
571 | } else { |
572 | sc.symbol = |
573 | nullptr; // Don't trust the symbol if the sections didn't match. |
574 | } |
575 | } |
576 | } |
577 | } |
578 | } |
579 | return resolved_flags; |
580 | } |
581 | |
582 | uint32_t Module::ResolveSymbolContextForFilePath( |
583 | const char *file_path, uint32_t line, bool check_inlines, |
584 | lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) { |
585 | FileSpec file_spec(file_path); |
586 | return ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines, |
587 | resolve_scope, sc_list); |
588 | } |
589 | |
590 | uint32_t Module::ResolveSymbolContextsForFileSpec( |
591 | const FileSpec &file_spec, uint32_t line, bool check_inlines, |
592 | lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) { |
593 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
594 | LLDB_SCOPED_TIMERF("Module::ResolveSymbolContextForFilePath (%s:%u, " |
595 | "check_inlines = %s, resolve_scope = 0x%8.8x)" , |
596 | file_spec.GetPath().c_str(), line, |
597 | check_inlines ? "yes" : "no" , resolve_scope); |
598 | |
599 | const uint32_t initial_count = sc_list.GetSize(); |
600 | |
601 | if (SymbolFile *symbols = GetSymbolFile()) { |
602 | // TODO: Handle SourceLocationSpec column information |
603 | SourceLocationSpec location_spec(file_spec, line, /*column=*/llvm::None, |
604 | check_inlines, /*exact_match=*/false); |
605 | |
606 | symbols->ResolveSymbolContext(location_spec, resolve_scope, sc_list); |
607 | } |
608 | |
609 | return sc_list.GetSize() - initial_count; |
610 | } |
611 | |
612 | void Module::FindGlobalVariables(ConstString name, |
613 | const CompilerDeclContext &parent_decl_ctx, |
614 | size_t max_matches, VariableList &variables) { |
615 | if (SymbolFile *symbols = GetSymbolFile()) |
616 | symbols->FindGlobalVariables(name, parent_decl_ctx, max_matches, variables); |
617 | } |
618 | |
619 | void Module::FindGlobalVariables(const RegularExpression ®ex, |
620 | size_t max_matches, VariableList &variables) { |
621 | SymbolFile *symbols = GetSymbolFile(); |
622 | if (symbols) |
623 | symbols->FindGlobalVariables(regex, max_matches, variables); |
624 | } |
625 | |
626 | void Module::FindCompileUnits(const FileSpec &path, |
627 | SymbolContextList &sc_list) { |
628 | const size_t num_compile_units = GetNumCompileUnits(); |
629 | SymbolContext sc; |
630 | sc.module_sp = shared_from_this(); |
631 | for (size_t i = 0; i < num_compile_units; ++i) { |
632 | sc.comp_unit = GetCompileUnitAtIndex(i).get(); |
633 | if (sc.comp_unit) { |
634 | if (FileSpec::Match(path, sc.comp_unit->GetPrimaryFile())) |
635 | sc_list.Append(sc); |
636 | } |
637 | } |
638 | } |
639 | |
640 | Module::LookupInfo::LookupInfo(ConstString name, |
641 | FunctionNameType name_type_mask, |
642 | LanguageType language) |
643 | : m_name(name), m_lookup_name(), m_language(language), |
644 | m_name_type_mask(eFunctionNameTypeNone), |
645 | m_match_name_after_lookup(false) { |
646 | const char *name_cstr = name.GetCString(); |
647 | llvm::StringRef basename; |
648 | llvm::StringRef context; |
649 | |
650 | if (name_type_mask & eFunctionNameTypeAuto) { |
651 | if (CPlusPlusLanguage::IsCPPMangledName(name_cstr)) |
652 | m_name_type_mask = eFunctionNameTypeFull; |
653 | else if ((language == eLanguageTypeUnknown || |
654 | Language::LanguageIsObjC(language)) && |
655 | ObjCLanguage::IsPossibleObjCMethodName(name_cstr)) |
656 | m_name_type_mask = eFunctionNameTypeFull; |
657 | else if (Language::LanguageIsC(language)) { |
658 | m_name_type_mask = eFunctionNameTypeFull; |
659 | } else { |
660 | if ((language == eLanguageTypeUnknown || |
661 | Language::LanguageIsObjC(language)) && |
662 | ObjCLanguage::IsPossibleObjCSelector(name_cstr)) |
663 | m_name_type_mask |= eFunctionNameTypeSelector; |
664 | |
665 | CPlusPlusLanguage::MethodName cpp_method(name); |
666 | basename = cpp_method.GetBasename(); |
667 | if (basename.empty()) { |
668 | if (CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, |
669 | basename)) |
670 | m_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); |
671 | else |
672 | m_name_type_mask |= eFunctionNameTypeFull; |
673 | } else { |
674 | m_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); |
675 | } |
676 | } |
677 | } else { |
678 | m_name_type_mask = name_type_mask; |
679 | if (name_type_mask & eFunctionNameTypeMethod || |
680 | name_type_mask & eFunctionNameTypeBase) { |
681 | // If they've asked for a CPP method or function name and it can't be |
682 | // that, we don't even need to search for CPP methods or names. |
683 | CPlusPlusLanguage::MethodName cpp_method(name); |
684 | if (cpp_method.IsValid()) { |
685 | basename = cpp_method.GetBasename(); |
686 | |
687 | if (!cpp_method.GetQualifiers().empty()) { |
688 | // There is a "const" or other qualifier following the end of the |
689 | // function parens, this can't be a eFunctionNameTypeBase |
690 | m_name_type_mask &= ~(eFunctionNameTypeBase); |
691 | if (m_name_type_mask == eFunctionNameTypeNone) |
692 | return; |
693 | } |
694 | } else { |
695 | // If the CPP method parser didn't manage to chop this up, try to fill |
696 | // in the base name if we can. If a::b::c is passed in, we need to just |
697 | // look up "c", and then we'll filter the result later. |
698 | CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, |
699 | basename); |
700 | } |
701 | } |
702 | |
703 | if (name_type_mask & eFunctionNameTypeSelector) { |
704 | if (!ObjCLanguage::IsPossibleObjCSelector(name_cstr)) { |
705 | m_name_type_mask &= ~(eFunctionNameTypeSelector); |
706 | if (m_name_type_mask == eFunctionNameTypeNone) |
707 | return; |
708 | } |
709 | } |
710 | |
711 | // Still try and get a basename in case someone specifies a name type mask |
712 | // of eFunctionNameTypeFull and a name like "A::func" |
713 | if (basename.empty()) { |
714 | if (name_type_mask & eFunctionNameTypeFull && |
715 | !CPlusPlusLanguage::IsCPPMangledName(name_cstr)) { |
716 | CPlusPlusLanguage::MethodName cpp_method(name); |
717 | basename = cpp_method.GetBasename(); |
718 | if (basename.empty()) |
719 | CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, |
720 | basename); |
721 | } |
722 | } |
723 | } |
724 | |
725 | if (!basename.empty()) { |
726 | // The name supplied was a partial C++ path like "a::count". In this case |
727 | // we want to do a lookup on the basename "count" and then make sure any |
728 | // matching results contain "a::count" so that it would match "b::a::count" |
729 | // and "a::count". This is why we set "match_name_after_lookup" to true |
730 | m_lookup_name.SetString(basename); |
731 | m_match_name_after_lookup = true; |
732 | } else { |
733 | // The name is already correct, just use the exact name as supplied, and we |
734 | // won't need to check if any matches contain "name" |
735 | m_lookup_name = name; |
736 | m_match_name_after_lookup = false; |
737 | } |
738 | } |
739 | |
740 | void Module::LookupInfo::Prune(SymbolContextList &sc_list, |
741 | size_t start_idx) const { |
742 | if (m_match_name_after_lookup && m_name) { |
743 | SymbolContext sc; |
744 | size_t i = start_idx; |
745 | while (i < sc_list.GetSize()) { |
746 | if (!sc_list.GetContextAtIndex(i, sc)) |
747 | break; |
748 | ConstString full_name(sc.GetFunctionName()); |
749 | if (full_name && |
750 | ::strstr(full_name.GetCString(), m_name.GetCString()) == nullptr) { |
751 | sc_list.RemoveContextAtIndex(i); |
752 | } else { |
753 | ++i; |
754 | } |
755 | } |
756 | } |
757 | |
758 | // If we have only full name matches we might have tried to set breakpoint on |
759 | // "func" and specified eFunctionNameTypeFull, but we might have found |
760 | // "a::func()", "a::b::func()", "c::func()", "func()" and "func". Only |
761 | // "func()" and "func" should end up matching. |
762 | if (m_name_type_mask == eFunctionNameTypeFull) { |
763 | SymbolContext sc; |
764 | size_t i = start_idx; |
765 | while (i < sc_list.GetSize()) { |
766 | if (!sc_list.GetContextAtIndex(i, sc)) |
767 | break; |
768 | // Make sure the mangled and demangled names don't match before we try to |
769 | // pull anything out |
770 | ConstString mangled_name(sc.GetFunctionName(Mangled::ePreferMangled)); |
771 | ConstString full_name(sc.GetFunctionName()); |
772 | if (mangled_name != m_name && full_name != m_name) |
773 | { |
774 | CPlusPlusLanguage::MethodName cpp_method(full_name); |
775 | if (cpp_method.IsValid()) { |
776 | if (cpp_method.GetContext().empty()) { |
777 | if (cpp_method.GetBasename().compare(m_name.GetStringRef()) != 0) { |
778 | sc_list.RemoveContextAtIndex(i); |
779 | continue; |
780 | } |
781 | } else { |
782 | std::string qualified_name; |
783 | llvm::StringRef anon_prefix("(anonymous namespace)" ); |
784 | if (cpp_method.GetContext() == anon_prefix) |
785 | qualified_name = cpp_method.GetBasename().str(); |
786 | else |
787 | qualified_name = cpp_method.GetScopeQualifiedName(); |
788 | if (qualified_name != m_name.GetCString()) { |
789 | sc_list.RemoveContextAtIndex(i); |
790 | continue; |
791 | } |
792 | } |
793 | } |
794 | } |
795 | ++i; |
796 | } |
797 | } |
798 | } |
799 | |
800 | void Module::FindFunctions(ConstString name, |
801 | const CompilerDeclContext &parent_decl_ctx, |
802 | FunctionNameType name_type_mask, |
803 | bool include_symbols, bool include_inlines, |
804 | SymbolContextList &sc_list) { |
805 | const size_t old_size = sc_list.GetSize(); |
806 | |
807 | // Find all the functions (not symbols, but debug information functions... |
808 | SymbolFile *symbols = GetSymbolFile(); |
809 | |
810 | if (name_type_mask & eFunctionNameTypeAuto) { |
811 | LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown); |
812 | |
813 | if (symbols) { |
814 | symbols->FindFunctions(lookup_info.GetLookupName(), parent_decl_ctx, |
815 | lookup_info.GetNameTypeMask(), include_inlines, |
816 | sc_list); |
817 | |
818 | // Now check our symbol table for symbols that are code symbols if |
819 | // requested |
820 | if (include_symbols) { |
821 | Symtab *symtab = symbols->GetSymtab(); |
822 | if (symtab) |
823 | symtab->FindFunctionSymbols(lookup_info.GetLookupName(), |
824 | lookup_info.GetNameTypeMask(), sc_list); |
825 | } |
826 | } |
827 | |
828 | const size_t new_size = sc_list.GetSize(); |
829 | |
830 | if (old_size < new_size) |
831 | lookup_info.Prune(sc_list, old_size); |
832 | } else { |
833 | if (symbols) { |
834 | symbols->FindFunctions(name, parent_decl_ctx, name_type_mask, |
835 | include_inlines, sc_list); |
836 | |
837 | // Now check our symbol table for symbols that are code symbols if |
838 | // requested |
839 | if (include_symbols) { |
840 | Symtab *symtab = symbols->GetSymtab(); |
841 | if (symtab) |
842 | symtab->FindFunctionSymbols(name, name_type_mask, sc_list); |
843 | } |
844 | } |
845 | } |
846 | } |
847 | |
848 | void Module::FindFunctions(const RegularExpression ®ex, bool include_symbols, |
849 | bool include_inlines, |
850 | SymbolContextList &sc_list) { |
851 | const size_t start_size = sc_list.GetSize(); |
852 | |
853 | if (SymbolFile *symbols = GetSymbolFile()) { |
854 | symbols->FindFunctions(regex, include_inlines, sc_list); |
855 | |
856 | // Now check our symbol table for symbols that are code symbols if |
857 | // requested |
858 | if (include_symbols) { |
859 | Symtab *symtab = symbols->GetSymtab(); |
860 | if (symtab) { |
861 | std::vector<uint32_t> symbol_indexes; |
862 | symtab->AppendSymbolIndexesMatchingRegExAndType( |
863 | regex, eSymbolTypeAny, Symtab::eDebugAny, Symtab::eVisibilityAny, |
864 | symbol_indexes); |
865 | const size_t num_matches = symbol_indexes.size(); |
866 | if (num_matches) { |
867 | SymbolContext sc(this); |
868 | const size_t end_functions_added_index = sc_list.GetSize(); |
869 | size_t num_functions_added_to_sc_list = |
870 | end_functions_added_index - start_size; |
871 | if (num_functions_added_to_sc_list == 0) { |
872 | // No functions were added, just symbols, so we can just append |
873 | // them |
874 | for (size_t i = 0; i < num_matches; ++i) { |
875 | sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); |
876 | SymbolType sym_type = sc.symbol->GetType(); |
877 | if (sc.symbol && (sym_type == eSymbolTypeCode || |
878 | sym_type == eSymbolTypeResolver)) |
879 | sc_list.Append(sc); |
880 | } |
881 | } else { |
882 | typedef std::map<lldb::addr_t, uint32_t> FileAddrToIndexMap; |
883 | FileAddrToIndexMap file_addr_to_index; |
884 | for (size_t i = start_size; i < end_functions_added_index; ++i) { |
885 | const SymbolContext &sc = sc_list[i]; |
886 | if (sc.block) |
887 | continue; |
888 | file_addr_to_index[sc.function->GetAddressRange() |
889 | .GetBaseAddress() |
890 | .GetFileAddress()] = i; |
891 | } |
892 | |
893 | FileAddrToIndexMap::const_iterator end = file_addr_to_index.end(); |
894 | // Functions were added so we need to merge symbols into any |
895 | // existing function symbol contexts |
896 | for (size_t i = start_size; i < num_matches; ++i) { |
897 | sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); |
898 | SymbolType sym_type = sc.symbol->GetType(); |
899 | if (sc.symbol && sc.symbol->ValueIsAddress() && |
900 | (sym_type == eSymbolTypeCode || |
901 | sym_type == eSymbolTypeResolver)) { |
902 | FileAddrToIndexMap::const_iterator pos = |
903 | file_addr_to_index.find( |
904 | sc.symbol->GetAddressRef().GetFileAddress()); |
905 | if (pos == end) |
906 | sc_list.Append(sc); |
907 | else |
908 | sc_list[pos->second].symbol = sc.symbol; |
909 | } |
910 | } |
911 | } |
912 | } |
913 | } |
914 | } |
915 | } |
916 | } |
917 | |
918 | void Module::FindAddressesForLine(const lldb::TargetSP target_sp, |
919 | const FileSpec &file, uint32_t line, |
920 | Function *function, |
921 | std::vector<Address> &output_local, |
922 | std::vector<Address> &output_extern) { |
923 | SearchFilterByModule filter(target_sp, m_file); |
924 | |
925 | // TODO: Handle SourceLocationSpec column information |
926 | SourceLocationSpec location_spec(file, line, /*column=*/llvm::None, |
927 | /*check_inlines=*/true, |
928 | /*exact_match=*/false); |
929 | AddressResolverFileLine resolver(location_spec); |
930 | resolver.ResolveAddress(filter); |
931 | |
932 | for (size_t n = 0; n < resolver.GetNumberOfAddresses(); n++) { |
933 | Address addr = resolver.GetAddressRangeAtIndex(n).GetBaseAddress(); |
934 | Function *f = addr.CalculateSymbolContextFunction(); |
935 | if (f && f == function) |
936 | output_local.push_back(addr); |
937 | else |
938 | output_extern.push_back(addr); |
939 | } |
940 | } |
941 | |
942 | void Module::FindTypes_Impl( |
943 | ConstString name, const CompilerDeclContext &parent_decl_ctx, |
944 | size_t max_matches, |
945 | llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, |
946 | TypeMap &types) { |
947 | LLDB_SCOPED_TIMER(); |
948 | if (SymbolFile *symbols = GetSymbolFile()) |
949 | symbols->FindTypes(name, parent_decl_ctx, max_matches, |
950 | searched_symbol_files, types); |
951 | } |
952 | |
953 | void Module::FindTypesInNamespace(ConstString type_name, |
954 | const CompilerDeclContext &parent_decl_ctx, |
955 | size_t max_matches, TypeList &type_list) { |
956 | TypeMap types_map; |
957 | llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; |
958 | FindTypes_Impl(type_name, parent_decl_ctx, max_matches, searched_symbol_files, |
959 | types_map); |
960 | if (types_map.GetSize()) { |
961 | SymbolContext sc; |
962 | sc.module_sp = shared_from_this(); |
963 | sc.SortTypeList(types_map, type_list); |
964 | } |
965 | } |
966 | |
967 | lldb::TypeSP Module::FindFirstType(const SymbolContext &sc, |
968 | ConstString name, bool exact_match) { |
969 | TypeList type_list; |
970 | llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; |
971 | FindTypes(name, exact_match, 1, searched_symbol_files, type_list); |
972 | if (type_list.GetSize()) |
973 | return type_list.GetTypeAtIndex(0); |
974 | return TypeSP(); |
975 | } |
976 | |
977 | void Module::FindTypes( |
978 | ConstString name, bool exact_match, size_t max_matches, |
979 | llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, |
980 | TypeList &types) { |
981 | const char *type_name_cstr = name.GetCString(); |
982 | llvm::StringRef type_scope; |
983 | llvm::StringRef type_basename; |
984 | TypeClass type_class = eTypeClassAny; |
985 | TypeMap typesmap; |
986 | |
987 | if (Type::GetTypeScopeAndBasename(type_name_cstr, type_scope, type_basename, |
988 | type_class)) { |
989 | // Check if "name" starts with "::" which means the qualified type starts |
990 | // from the root namespace and implies and exact match. The typenames we |
991 | // get back from clang do not start with "::" so we need to strip this off |
992 | // in order to get the qualified names to match |
993 | exact_match = type_scope.consume_front("::" ); |
994 | |
995 | ConstString type_basename_const_str(type_basename); |
996 | FindTypes_Impl(type_basename_const_str, CompilerDeclContext(), max_matches, |
997 | searched_symbol_files, typesmap); |
998 | if (typesmap.GetSize()) |
999 | typesmap.RemoveMismatchedTypes(std::string(type_scope), |
1000 | std::string(type_basename), type_class, |
1001 | exact_match); |
1002 | } else { |
1003 | // The type is not in a namespace/class scope, just search for it by |
1004 | // basename |
1005 | if (type_class != eTypeClassAny && !type_basename.empty()) { |
1006 | // The "type_name_cstr" will have been modified if we have a valid type |
1007 | // class prefix (like "struct", "class", "union", "typedef" etc). |
1008 | FindTypes_Impl(ConstString(type_basename), CompilerDeclContext(), |
1009 | UINT_MAX, searched_symbol_files, typesmap); |
1010 | typesmap.RemoveMismatchedTypes(std::string(type_scope), |
1011 | std::string(type_basename), type_class, |
1012 | exact_match); |
1013 | } else { |
1014 | FindTypes_Impl(name, CompilerDeclContext(), UINT_MAX, |
1015 | searched_symbol_files, typesmap); |
1016 | if (exact_match) { |
1017 | std::string name_str(name.AsCString("" )); |
1018 | typesmap.RemoveMismatchedTypes(std::string(type_scope), name_str, |
1019 | type_class, exact_match); |
1020 | } |
1021 | } |
1022 | } |
1023 | if (typesmap.GetSize()) { |
1024 | SymbolContext sc; |
1025 | sc.module_sp = shared_from_this(); |
1026 | sc.SortTypeList(typesmap, types); |
1027 | } |
1028 | } |
1029 | |
1030 | void Module::FindTypes( |
1031 | llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, |
1032 | llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, |
1033 | TypeMap &types) { |
1034 | LLDB_SCOPED_TIMER(); |
1035 | if (SymbolFile *symbols = GetSymbolFile()) |
1036 | symbols->FindTypes(pattern, languages, searched_symbol_files, types); |
1037 | } |
1038 | |
1039 | SymbolFile *Module::GetSymbolFile(bool can_create, Stream *feedback_strm) { |
1040 | if (!m_did_load_symfile.load()) { |
1041 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
1042 | if (!m_did_load_symfile.load() && can_create) { |
1043 | ObjectFile *obj_file = GetObjectFile(); |
1044 | if (obj_file != nullptr) { |
1045 | LLDB_SCOPED_TIMER(); |
1046 | m_symfile_up.reset( |
1047 | SymbolVendor::FindPlugin(shared_from_this(), feedback_strm)); |
1048 | m_did_load_symfile = true; |
1049 | } |
1050 | } |
1051 | } |
1052 | return m_symfile_up ? m_symfile_up->GetSymbolFile() : nullptr; |
1053 | } |
1054 | |
1055 | Symtab *Module::GetSymtab() { |
1056 | if (SymbolFile *symbols = GetSymbolFile()) |
1057 | return symbols->GetSymtab(); |
1058 | return nullptr; |
1059 | } |
1060 | |
1061 | void Module::SetFileSpecAndObjectName(const FileSpec &file, |
1062 | ConstString object_name) { |
1063 | // Container objects whose paths do not specify a file directly can call this |
1064 | // function to correct the file and object names. |
1065 | m_file = file; |
1066 | m_mod_time = FileSystem::Instance().GetModificationTime(file); |
1067 | m_object_name = object_name; |
1068 | } |
1069 | |
1070 | const ArchSpec &Module::GetArchitecture() const { return m_arch; } |
1071 | |
1072 | std::string Module::GetSpecificationDescription() const { |
1073 | std::string spec(GetFileSpec().GetPath()); |
1074 | if (m_object_name) { |
1075 | spec += '('; |
1076 | spec += m_object_name.GetCString(); |
1077 | spec += ')'; |
1078 | } |
1079 | return spec; |
1080 | } |
1081 | |
1082 | void Module::GetDescription(llvm::raw_ostream &s, |
1083 | lldb::DescriptionLevel level) { |
1084 | if (level >= eDescriptionLevelFull) { |
1085 | if (m_arch.IsValid()) |
1086 | s << llvm::formatv("({0}) " , m_arch.GetArchitectureName()); |
1087 | } |
1088 | |
1089 | if (level == eDescriptionLevelBrief) { |
1090 | const char *filename = m_file.GetFilename().GetCString(); |
1091 | if (filename) |
1092 | s << filename; |
1093 | } else { |
1094 | char path[PATH_MAX]; |
1095 | if (m_file.GetPath(path, sizeof(path))) |
1096 | s << path; |
1097 | } |
1098 | |
1099 | const char *object_name = m_object_name.GetCString(); |
1100 | if (object_name) |
1101 | s << llvm::formatv("({0})" , object_name); |
1102 | } |
1103 | |
1104 | void Module::ReportError(const char *format, ...) { |
1105 | if (format && format[0]) { |
1106 | StreamString strm; |
1107 | strm.PutCString("error: " ); |
1108 | GetDescription(strm.AsRawOstream(), lldb::eDescriptionLevelBrief); |
1109 | strm.PutChar(' '); |
1110 | va_list args; |
1111 | va_start(args, format); |
1112 | strm.PrintfVarArg(format, args); |
1113 | va_end(args); |
1114 | |
1115 | const int format_len = strlen(format); |
1116 | if (format_len > 0) { |
1117 | const char last_char = format[format_len - 1]; |
1118 | if (last_char != '\n' && last_char != '\r') |
1119 | strm.EOL(); |
1120 | } |
1121 | Host::SystemLog(Host::eSystemLogError, "%s" , strm.GetData()); |
1122 | } |
1123 | } |
1124 | |
1125 | bool Module::FileHasChanged() const { |
1126 | // We have provided the DataBuffer for this module to avoid accessing the |
1127 | // filesystem. We never want to reload those files. |
1128 | if (m_data_sp) |
1129 | return false; |
1130 | if (!m_file_has_changed) |
1131 | m_file_has_changed = |
1132 | (FileSystem::Instance().GetModificationTime(m_file) != m_mod_time); |
1133 | return m_file_has_changed; |
1134 | } |
1135 | |
1136 | void Module::ReportErrorIfModifyDetected(const char *format, ...) { |
1137 | if (!m_first_file_changed_log) { |
1138 | if (FileHasChanged()) { |
1139 | m_first_file_changed_log = true; |
1140 | if (format) { |
1141 | StreamString strm; |
1142 | strm.PutCString("error: the object file " ); |
1143 | GetDescription(strm.AsRawOstream(), lldb::eDescriptionLevelFull); |
1144 | strm.PutCString(" has been modified\n" ); |
1145 | |
1146 | va_list args; |
1147 | va_start(args, format); |
1148 | strm.PrintfVarArg(format, args); |
1149 | va_end(args); |
1150 | |
1151 | const int format_len = strlen(format); |
1152 | if (format_len > 0) { |
1153 | const char last_char = format[format_len - 1]; |
1154 | if (last_char != '\n' && last_char != '\r') |
1155 | strm.EOL(); |
1156 | } |
1157 | strm.PutCString("The debug session should be aborted as the original " |
1158 | "debug information has been overwritten.\n" ); |
1159 | Host::SystemLog(Host::eSystemLogError, "%s" , strm.GetData()); |
1160 | } |
1161 | } |
1162 | } |
1163 | } |
1164 | |
1165 | void Module::ReportWarning(const char *format, ...) { |
1166 | if (format && format[0]) { |
1167 | StreamString strm; |
1168 | strm.PutCString("warning: " ); |
1169 | GetDescription(strm.AsRawOstream(), lldb::eDescriptionLevelFull); |
1170 | strm.PutChar(' '); |
1171 | |
1172 | va_list args; |
1173 | va_start(args, format); |
1174 | strm.PrintfVarArg(format, args); |
1175 | va_end(args); |
1176 | |
1177 | const int format_len = strlen(format); |
1178 | if (format_len > 0) { |
1179 | const char last_char = format[format_len - 1]; |
1180 | if (last_char != '\n' && last_char != '\r') |
1181 | strm.EOL(); |
1182 | } |
1183 | Host::SystemLog(Host::eSystemLogWarning, "%s" , strm.GetData()); |
1184 | } |
1185 | } |
1186 | |
1187 | void Module::LogMessage(Log *log, const char *format, ...) { |
1188 | if (log != nullptr) { |
1189 | StreamString log_message; |
1190 | GetDescription(log_message.AsRawOstream(), lldb::eDescriptionLevelFull); |
1191 | log_message.PutCString(": " ); |
1192 | va_list args; |
1193 | va_start(args, format); |
1194 | log_message.PrintfVarArg(format, args); |
1195 | va_end(args); |
1196 | log->PutCString(log_message.GetData()); |
1197 | } |
1198 | } |
1199 | |
1200 | void Module::LogMessageVerboseBacktrace(Log *log, const char *format, ...) { |
1201 | if (log != nullptr) { |
1202 | StreamString log_message; |
1203 | GetDescription(log_message.AsRawOstream(), lldb::eDescriptionLevelFull); |
1204 | log_message.PutCString(": " ); |
1205 | va_list args; |
1206 | va_start(args, format); |
1207 | log_message.PrintfVarArg(format, args); |
1208 | va_end(args); |
1209 | if (log->GetVerbose()) { |
1210 | std::string back_trace; |
1211 | llvm::raw_string_ostream stream(back_trace); |
1212 | llvm::sys::PrintStackTrace(stream); |
1213 | log_message.PutCString(back_trace); |
1214 | } |
1215 | log->PutCString(log_message.GetData()); |
1216 | } |
1217 | } |
1218 | |
1219 | void Module::Dump(Stream *s) { |
1220 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
1221 | // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); |
1222 | s->Indent(); |
1223 | s->Printf("Module %s%s%s%s\n" , m_file.GetPath().c_str(), |
1224 | m_object_name ? "(" : "" , |
1225 | m_object_name ? m_object_name.GetCString() : "" , |
1226 | m_object_name ? ")" : "" ); |
1227 | |
1228 | s->IndentMore(); |
1229 | |
1230 | ObjectFile *objfile = GetObjectFile(); |
1231 | if (objfile) |
1232 | objfile->Dump(s); |
1233 | |
1234 | if (SymbolFile *symbols = GetSymbolFile()) |
1235 | symbols->Dump(*s); |
1236 | |
1237 | s->IndentLess(); |
1238 | } |
1239 | |
1240 | ConstString Module::GetObjectName() const { return m_object_name; } |
1241 | |
1242 | ObjectFile *Module::GetObjectFile() { |
1243 | if (!m_did_load_objfile.load()) { |
1244 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
1245 | if (!m_did_load_objfile.load()) { |
1246 | LLDB_SCOPED_TIMERF("Module::GetObjectFile () module = %s" , |
1247 | GetFileSpec().GetFilename().AsCString("" )); |
1248 | lldb::offset_t data_offset = 0; |
1249 | lldb::offset_t file_size = 0; |
1250 | |
1251 | if (m_data_sp) |
1252 | file_size = m_data_sp->GetByteSize(); |
1253 | else if (m_file) |
1254 | file_size = FileSystem::Instance().GetByteSize(m_file); |
1255 | |
1256 | if (file_size > m_object_offset) { |
1257 | m_did_load_objfile = true; |
1258 | // FindPlugin will modify its data_sp argument. Do not let it |
1259 | // modify our m_data_sp member. |
1260 | auto data_sp = m_data_sp; |
1261 | m_objfile_sp = ObjectFile::FindPlugin( |
1262 | shared_from_this(), &m_file, m_object_offset, |
1263 | file_size - m_object_offset, data_sp, data_offset); |
1264 | if (m_objfile_sp) { |
1265 | // Once we get the object file, update our module with the object |
1266 | // file's architecture since it might differ in vendor/os if some |
1267 | // parts were unknown. But since the matching arch might already be |
1268 | // more specific than the generic COFF architecture, only merge in |
1269 | // those values that overwrite unspecified unknown values. |
1270 | m_arch.MergeFrom(m_objfile_sp->GetArchitecture()); |
1271 | } else { |
1272 | ReportError("failed to load objfile for %s" , |
1273 | GetFileSpec().GetPath().c_str()); |
1274 | } |
1275 | } |
1276 | } |
1277 | } |
1278 | return m_objfile_sp.get(); |
1279 | } |
1280 | |
1281 | SectionList *Module::GetSectionList() { |
1282 | // Populate m_sections_up with sections from objfile. |
1283 | if (!m_sections_up) { |
1284 | ObjectFile *obj_file = GetObjectFile(); |
1285 | if (obj_file != nullptr) |
1286 | obj_file->CreateSections(*GetUnifiedSectionList()); |
1287 | } |
1288 | return m_sections_up.get(); |
1289 | } |
1290 | |
1291 | void Module::SectionFileAddressesChanged() { |
1292 | ObjectFile *obj_file = GetObjectFile(); |
1293 | if (obj_file) |
1294 | obj_file->SectionFileAddressesChanged(); |
1295 | if (SymbolFile *symbols = GetSymbolFile()) |
1296 | symbols->SectionFileAddressesChanged(); |
1297 | } |
1298 | |
1299 | UnwindTable &Module::GetUnwindTable() { |
1300 | if (!m_unwind_table) |
1301 | m_unwind_table.emplace(*this); |
1302 | return *m_unwind_table; |
1303 | } |
1304 | |
1305 | SectionList *Module::GetUnifiedSectionList() { |
1306 | if (!m_sections_up) |
1307 | m_sections_up = std::make_unique<SectionList>(); |
1308 | return m_sections_up.get(); |
1309 | } |
1310 | |
1311 | const Symbol *Module::FindFirstSymbolWithNameAndType(ConstString name, |
1312 | SymbolType symbol_type) { |
1313 | LLDB_SCOPED_TIMERF( |
1314 | "Module::FindFirstSymbolWithNameAndType (name = %s, type = %i)" , |
1315 | name.AsCString(), symbol_type); |
1316 | if (Symtab *symtab = GetSymtab()) |
1317 | return symtab->FindFirstSymbolWithNameAndType( |
1318 | name, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny); |
1319 | return nullptr; |
1320 | } |
1321 | void Module::SymbolIndicesToSymbolContextList( |
1322 | Symtab *symtab, std::vector<uint32_t> &symbol_indexes, |
1323 | SymbolContextList &sc_list) { |
1324 | // No need to protect this call using m_mutex all other method calls are |
1325 | // already thread safe. |
1326 | |
1327 | size_t num_indices = symbol_indexes.size(); |
1328 | if (num_indices > 0) { |
1329 | SymbolContext sc; |
1330 | CalculateSymbolContext(&sc); |
1331 | for (size_t i = 0; i < num_indices; i++) { |
1332 | sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); |
1333 | if (sc.symbol) |
1334 | sc_list.Append(sc); |
1335 | } |
1336 | } |
1337 | } |
1338 | |
1339 | void Module::FindFunctionSymbols(ConstString name, |
1340 | uint32_t name_type_mask, |
1341 | SymbolContextList &sc_list) { |
1342 | LLDB_SCOPED_TIMERF("Module::FindSymbolsFunctions (name = %s, mask = 0x%8.8x)" , |
1343 | name.AsCString(), name_type_mask); |
1344 | if (Symtab *symtab = GetSymtab()) |
1345 | symtab->FindFunctionSymbols(name, name_type_mask, sc_list); |
1346 | } |
1347 | |
1348 | void Module::FindSymbolsWithNameAndType(ConstString name, |
1349 | SymbolType symbol_type, |
1350 | SymbolContextList &sc_list) { |
1351 | // No need to protect this call using m_mutex all other method calls are |
1352 | // already thread safe. |
1353 | LLDB_SCOPED_TIMERF( |
1354 | "Module::FindSymbolsWithNameAndType (name = %s, type = %i)" , |
1355 | name.AsCString(), symbol_type); |
1356 | if (Symtab *symtab = GetSymtab()) { |
1357 | std::vector<uint32_t> symbol_indexes; |
1358 | symtab->FindAllSymbolsWithNameAndType(name, symbol_type, symbol_indexes); |
1359 | SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list); |
1360 | } |
1361 | } |
1362 | |
1363 | void Module::FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, |
1364 | SymbolType symbol_type, |
1365 | SymbolContextList &sc_list) { |
1366 | // No need to protect this call using m_mutex all other method calls are |
1367 | // already thread safe. |
1368 | LLDB_SCOPED_TIMERF( |
1369 | "Module::FindSymbolsMatchingRegExAndType (regex = %s, type = %i)" , |
1370 | regex.GetText().str().c_str(), symbol_type); |
1371 | if (Symtab *symtab = GetSymtab()) { |
1372 | std::vector<uint32_t> symbol_indexes; |
1373 | symtab->FindAllSymbolsMatchingRexExAndType( |
1374 | regex, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny, |
1375 | symbol_indexes); |
1376 | SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list); |
1377 | } |
1378 | } |
1379 | |
1380 | void Module::PreloadSymbols() { |
1381 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
1382 | SymbolFile *sym_file = GetSymbolFile(); |
1383 | if (!sym_file) |
1384 | return; |
1385 | |
1386 | // Prime the symbol file first, since it adds symbols to the symbol table. |
1387 | sym_file->PreloadSymbols(); |
1388 | |
1389 | // Now we can prime the symbol table. |
1390 | if (Symtab *symtab = sym_file->GetSymtab()) |
1391 | symtab->PreloadSymbols(); |
1392 | } |
1393 | |
1394 | void Module::SetSymbolFileFileSpec(const FileSpec &file) { |
1395 | if (!FileSystem::Instance().Exists(file)) |
1396 | return; |
1397 | if (m_symfile_up) { |
1398 | // Remove any sections in the unified section list that come from the |
1399 | // current symbol vendor. |
1400 | SectionList *section_list = GetSectionList(); |
1401 | SymbolFile *symbol_file = GetSymbolFile(); |
1402 | if (section_list && symbol_file) { |
1403 | ObjectFile *obj_file = symbol_file->GetObjectFile(); |
1404 | // Make sure we have an object file and that the symbol vendor's objfile |
1405 | // isn't the same as the module's objfile before we remove any sections |
1406 | // for it... |
1407 | if (obj_file) { |
1408 | // Check to make sure we aren't trying to specify the file we already |
1409 | // have |
1410 | if (obj_file->GetFileSpec() == file) { |
1411 | // We are being told to add the exact same file that we already have |
1412 | // we don't have to do anything. |
1413 | return; |
1414 | } |
1415 | |
1416 | // Cleare the current symtab as we are going to replace it with a new |
1417 | // one |
1418 | obj_file->ClearSymtab(); |
1419 | |
1420 | // Clear the unwind table too, as that may also be affected by the |
1421 | // symbol file information. |
1422 | m_unwind_table.reset(); |
1423 | |
1424 | // The symbol file might be a directory bundle ("/tmp/a.out.dSYM") |
1425 | // instead of a full path to the symbol file within the bundle |
1426 | // ("/tmp/a.out.dSYM/Contents/Resources/DWARF/a.out"). So we need to |
1427 | // check this |
1428 | |
1429 | if (FileSystem::Instance().IsDirectory(file)) { |
1430 | std::string new_path(file.GetPath()); |
1431 | std::string old_path(obj_file->GetFileSpec().GetPath()); |
1432 | if (llvm::StringRef(old_path).startswith(new_path)) { |
1433 | // We specified the same bundle as the symbol file that we already |
1434 | // have |
1435 | return; |
1436 | } |
1437 | } |
1438 | |
1439 | if (obj_file != m_objfile_sp.get()) { |
1440 | size_t num_sections = section_list->GetNumSections(0); |
1441 | for (size_t idx = num_sections; idx > 0; --idx) { |
1442 | lldb::SectionSP section_sp( |
1443 | section_list->GetSectionAtIndex(idx - 1)); |
1444 | if (section_sp->GetObjectFile() == obj_file) { |
1445 | section_list->DeleteSection(idx - 1); |
1446 | } |
1447 | } |
1448 | } |
1449 | } |
1450 | } |
1451 | // Keep all old symbol files around in case there are any lingering type |
1452 | // references in any SBValue objects that might have been handed out. |
1453 | m_old_symfiles.push_back(std::move(m_symfile_up)); |
1454 | } |
1455 | m_symfile_spec = file; |
1456 | m_symfile_up.reset(); |
1457 | m_did_load_symfile = false; |
1458 | } |
1459 | |
1460 | bool Module::IsExecutable() { |
1461 | if (GetObjectFile() == nullptr) |
1462 | return false; |
1463 | else |
1464 | return GetObjectFile()->IsExecutable(); |
1465 | } |
1466 | |
1467 | bool Module::IsLoadedInTarget(Target *target) { |
1468 | ObjectFile *obj_file = GetObjectFile(); |
1469 | if (obj_file) { |
1470 | SectionList *sections = GetSectionList(); |
1471 | if (sections != nullptr) { |
1472 | size_t num_sections = sections->GetSize(); |
1473 | for (size_t sect_idx = 0; sect_idx < num_sections; sect_idx++) { |
1474 | SectionSP section_sp = sections->GetSectionAtIndex(sect_idx); |
1475 | if (section_sp->GetLoadBaseAddress(target) != LLDB_INVALID_ADDRESS) { |
1476 | return true; |
1477 | } |
1478 | } |
1479 | } |
1480 | } |
1481 | return false; |
1482 | } |
1483 | |
1484 | bool Module::LoadScriptingResourceInTarget(Target *target, Status &error, |
1485 | Stream *feedback_stream) { |
1486 | if (!target) { |
1487 | error.SetErrorString("invalid destination Target" ); |
1488 | return false; |
1489 | } |
1490 | |
1491 | LoadScriptFromSymFile should_load = |
1492 | target->TargetProperties::GetLoadScriptFromSymbolFile(); |
1493 | |
1494 | if (should_load == eLoadScriptFromSymFileFalse) |
1495 | return false; |
1496 | |
1497 | Debugger &debugger = target->GetDebugger(); |
1498 | const ScriptLanguage script_language = debugger.GetScriptLanguage(); |
1499 | if (script_language != eScriptLanguageNone) { |
1500 | |
1501 | PlatformSP platform_sp(target->GetPlatform()); |
1502 | |
1503 | if (!platform_sp) { |
1504 | error.SetErrorString("invalid Platform" ); |
1505 | return false; |
1506 | } |
1507 | |
1508 | FileSpecList file_specs = platform_sp->LocateExecutableScriptingResources( |
1509 | target, *this, feedback_stream); |
1510 | |
1511 | const uint32_t num_specs = file_specs.GetSize(); |
1512 | if (num_specs) { |
1513 | ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter(); |
1514 | if (script_interpreter) { |
1515 | for (uint32_t i = 0; i < num_specs; ++i) { |
1516 | FileSpec scripting_fspec(file_specs.GetFileSpecAtIndex(i)); |
1517 | if (scripting_fspec && |
1518 | FileSystem::Instance().Exists(scripting_fspec)) { |
1519 | if (should_load == eLoadScriptFromSymFileWarn) { |
1520 | if (feedback_stream) |
1521 | feedback_stream->Printf( |
1522 | "warning: '%s' contains a debug script. To run this script " |
1523 | "in " |
1524 | "this debug session:\n\n command script import " |
1525 | "\"%s\"\n\n" |
1526 | "To run all discovered debug scripts in this session:\n\n" |
1527 | " settings set target.load-script-from-symbol-file " |
1528 | "true\n" , |
1529 | GetFileSpec().GetFileNameStrippingExtension().GetCString(), |
1530 | scripting_fspec.GetPath().c_str()); |
1531 | return false; |
1532 | } |
1533 | StreamString scripting_stream; |
1534 | scripting_fspec.Dump(scripting_stream.AsRawOstream()); |
1535 | const bool init_lldb_globals = false; |
1536 | bool did_load = script_interpreter->LoadScriptingModule( |
1537 | scripting_stream.GetData(), init_lldb_globals, error); |
1538 | if (!did_load) |
1539 | return false; |
1540 | } |
1541 | } |
1542 | } else { |
1543 | error.SetErrorString("invalid ScriptInterpreter" ); |
1544 | return false; |
1545 | } |
1546 | } |
1547 | } |
1548 | return true; |
1549 | } |
1550 | |
1551 | bool Module::SetArchitecture(const ArchSpec &new_arch) { |
1552 | if (!m_arch.IsValid()) { |
1553 | m_arch = new_arch; |
1554 | return true; |
1555 | } |
1556 | return m_arch.IsCompatibleMatch(new_arch); |
1557 | } |
1558 | |
1559 | bool Module::SetLoadAddress(Target &target, lldb::addr_t value, |
1560 | bool value_is_offset, bool &changed) { |
1561 | ObjectFile *object_file = GetObjectFile(); |
1562 | if (object_file != nullptr) { |
1563 | changed = object_file->SetLoadAddress(target, value, value_is_offset); |
1564 | return true; |
1565 | } else { |
1566 | changed = false; |
1567 | } |
1568 | return false; |
1569 | } |
1570 | |
1571 | bool Module::MatchesModuleSpec(const ModuleSpec &module_ref) { |
1572 | const UUID &uuid = module_ref.GetUUID(); |
1573 | |
1574 | if (uuid.IsValid()) { |
1575 | // If the UUID matches, then nothing more needs to match... |
1576 | return (uuid == GetUUID()); |
1577 | } |
1578 | |
1579 | const FileSpec &file_spec = module_ref.GetFileSpec(); |
1580 | if (!FileSpec::Match(file_spec, m_file) && |
1581 | !FileSpec::Match(file_spec, m_platform_file)) |
1582 | return false; |
1583 | |
1584 | const FileSpec &platform_file_spec = module_ref.GetPlatformFileSpec(); |
1585 | if (!FileSpec::Match(platform_file_spec, GetPlatformFileSpec())) |
1586 | return false; |
1587 | |
1588 | const ArchSpec &arch = module_ref.GetArchitecture(); |
1589 | if (arch.IsValid()) { |
1590 | if (!m_arch.IsCompatibleMatch(arch)) |
1591 | return false; |
1592 | } |
1593 | |
1594 | ConstString object_name = module_ref.GetObjectName(); |
1595 | if (object_name) { |
1596 | if (object_name != GetObjectName()) |
1597 | return false; |
1598 | } |
1599 | return true; |
1600 | } |
1601 | |
1602 | bool Module::FindSourceFile(const FileSpec &orig_spec, |
1603 | FileSpec &new_spec) const { |
1604 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
1605 | return m_source_mappings.FindFile(orig_spec, new_spec); |
1606 | } |
1607 | |
1608 | bool Module::RemapSourceFile(llvm::StringRef path, |
1609 | std::string &new_path) const { |
1610 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
1611 | return m_source_mappings.RemapPath(path, new_path); |
1612 | } |
1613 | |
1614 | void Module::RegisterXcodeSDK(llvm::StringRef sdk_name, llvm::StringRef sysroot) { |
1615 | XcodeSDK sdk(sdk_name.str()); |
1616 | ConstString sdk_path(HostInfo::GetXcodeSDKPath(sdk)); |
1617 | if (!sdk_path) |
1618 | return; |
1619 | // If the SDK changed for a previously registered source path, update it. |
1620 | // This could happend with -fdebug-prefix-map, otherwise it's unlikely. |
1621 | ConstString sysroot_cs(sysroot); |
1622 | if (!m_source_mappings.Replace(sysroot_cs, sdk_path, true)) |
1623 | // In the general case, however, append it to the list. |
1624 | m_source_mappings.Append(sysroot_cs, sdk_path, false); |
1625 | } |
1626 | |
1627 | bool Module::MergeArchitecture(const ArchSpec &arch_spec) { |
1628 | if (!arch_spec.IsValid()) |
1629 | return false; |
1630 | LLDB_LOG(GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_MODULES), |
1631 | "module has arch %s, merging/replacing with arch %s" , |
1632 | m_arch.GetTriple().getTriple().c_str(), |
1633 | arch_spec.GetTriple().getTriple().c_str()); |
1634 | if (!m_arch.IsCompatibleMatch(arch_spec)) { |
1635 | // The new architecture is different, we just need to replace it. |
1636 | return SetArchitecture(arch_spec); |
1637 | } |
1638 | |
1639 | // Merge bits from arch_spec into "merged_arch" and set our architecture. |
1640 | ArchSpec merged_arch(m_arch); |
1641 | merged_arch.MergeFrom(arch_spec); |
1642 | // SetArchitecture() is a no-op if m_arch is already valid. |
1643 | m_arch = ArchSpec(); |
1644 | return SetArchitecture(merged_arch); |
1645 | } |
1646 | |
1647 | llvm::VersionTuple Module::GetVersion() { |
1648 | if (ObjectFile *obj_file = GetObjectFile()) |
1649 | return obj_file->GetVersion(); |
1650 | return llvm::VersionTuple(); |
1651 | } |
1652 | |
1653 | bool Module::GetIsDynamicLinkEditor() { |
1654 | ObjectFile *obj_file = GetObjectFile(); |
1655 | |
1656 | if (obj_file) |
1657 | return obj_file->GetIsDynamicLinkEditor(); |
1658 | |
1659 | return false; |
1660 | } |
1661 | |