1//===-- SymbolFileOnDemand.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/Symbol/SymbolFileOnDemand.h"
10
11#include "lldb/Core/Module.h"
12#include "lldb/Symbol/SymbolFile.h"
13
14#include <memory>
15#include <optional>
16
17using namespace lldb;
18using namespace lldb_private;
19
20char SymbolFileOnDemand::ID;
21
22SymbolFileOnDemand::SymbolFileOnDemand(
23    std::unique_ptr<SymbolFile> &&symbol_file)
24    : m_sym_file_impl(std::move(symbol_file)) {}
25
26SymbolFileOnDemand::~SymbolFileOnDemand() = default;
27
28uint32_t SymbolFileOnDemand::CalculateAbilities() {
29  // Explicitly allow ability checking to pass though.
30  // This should be a cheap operation.
31  return m_sym_file_impl->CalculateAbilities();
32}
33
34std::recursive_mutex &SymbolFileOnDemand::GetModuleMutex() const {
35  return m_sym_file_impl->GetModuleMutex();
36}
37
38void SymbolFileOnDemand::InitializeObject() {
39  if (!m_debug_info_enabled) {
40    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
41             __FUNCTION__);
42    return;
43  }
44  return m_sym_file_impl->InitializeObject();
45}
46
47lldb::LanguageType SymbolFileOnDemand::ParseLanguage(CompileUnit &comp_unit) {
48  if (!m_debug_info_enabled) {
49    Log *log = GetLog();
50    LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
51    if (log) {
52      lldb::LanguageType langType = m_sym_file_impl->ParseLanguage(comp_unit);
53      if (langType != eLanguageTypeUnknown)
54        LLDB_LOG(log, "Language {0} would return if hydrated.", langType);
55    }
56    return eLanguageTypeUnknown;
57  }
58  return m_sym_file_impl->ParseLanguage(comp_unit);
59}
60
61XcodeSDK SymbolFileOnDemand::ParseXcodeSDK(CompileUnit &comp_unit) {
62  if (!m_debug_info_enabled) {
63    Log *log = GetLog();
64    LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
65    XcodeSDK defaultValue{};
66    if (log) {
67      XcodeSDK sdk = m_sym_file_impl->ParseXcodeSDK(comp_unit);
68      if (!(sdk == defaultValue))
69        LLDB_LOG(log, "SDK {0} would return if hydrated.", sdk.GetString());
70    }
71    return defaultValue;
72  }
73  return m_sym_file_impl->ParseXcodeSDK(comp_unit);
74}
75
76size_t SymbolFileOnDemand::ParseFunctions(CompileUnit &comp_unit) {
77  if (!m_debug_info_enabled) {
78    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
79             __FUNCTION__);
80    return 0;
81  }
82  return m_sym_file_impl->ParseFunctions(comp_unit);
83}
84
85bool SymbolFileOnDemand::ParseLineTable(CompileUnit &comp_unit) {
86  if (!m_debug_info_enabled) {
87    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
88             __FUNCTION__);
89    return false;
90  }
91  return m_sym_file_impl->ParseLineTable(comp_unit);
92}
93
94bool SymbolFileOnDemand::ParseDebugMacros(CompileUnit &comp_unit) {
95  if (!m_debug_info_enabled) {
96    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
97             __FUNCTION__);
98    return false;
99  }
100  return m_sym_file_impl->ParseDebugMacros(comp_unit);
101}
102
103bool SymbolFileOnDemand::ForEachExternalModule(
104    CompileUnit &comp_unit,
105    llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files,
106    llvm::function_ref<bool(Module &)> lambda) {
107  if (!m_debug_info_enabled) {
108    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
109             __FUNCTION__);
110    // Return false to not early exit.
111    return false;
112  }
113  return m_sym_file_impl->ForEachExternalModule(comp_unit, visited_symbol_files,
114                                                lambda);
115}
116
117bool SymbolFileOnDemand::ParseSupportFiles(CompileUnit &comp_unit,
118                                           SupportFileList &support_files) {
119  LLDB_LOG(GetLog(),
120           "[{0}] {1} is not skipped: explicitly allowed to support breakpoint",
121           GetSymbolFileName(), __FUNCTION__);
122  // Explicitly allow this API through to support source line breakpoint.
123  return m_sym_file_impl->ParseSupportFiles(comp_unit, support_files);
124}
125
126bool SymbolFileOnDemand::ParseIsOptimized(CompileUnit &comp_unit) {
127  if (!m_debug_info_enabled) {
128    Log *log = GetLog();
129    LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
130    if (log) {
131      bool optimized = m_sym_file_impl->ParseIsOptimized(comp_unit);
132      if (optimized) {
133        LLDB_LOG(log, "Would return optimized if hydrated.");
134      }
135    }
136    return false;
137  }
138  return m_sym_file_impl->ParseIsOptimized(comp_unit);
139}
140
141size_t SymbolFileOnDemand::ParseTypes(CompileUnit &comp_unit) {
142  if (!m_debug_info_enabled) {
143    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
144             __FUNCTION__);
145    return 0;
146  }
147  return m_sym_file_impl->ParseTypes(comp_unit);
148}
149
150bool SymbolFileOnDemand::ParseImportedModules(
151    const lldb_private::SymbolContext &sc,
152    std::vector<SourceModule> &imported_modules) {
153  if (!m_debug_info_enabled) {
154    Log *log = GetLog();
155    LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
156    if (log) {
157      std::vector<SourceModule> tmp_imported_modules;
158      bool succeed =
159          m_sym_file_impl->ParseImportedModules(sc, tmp_imported_modules);
160      if (succeed)
161        LLDB_LOG(log, "{0} imported modules would be parsed if hydrated.",
162                 tmp_imported_modules.size());
163    }
164    return false;
165  }
166  return m_sym_file_impl->ParseImportedModules(sc, imported_modules);
167}
168
169size_t SymbolFileOnDemand::ParseBlocksRecursive(Function &func) {
170  if (!m_debug_info_enabled) {
171    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
172             __FUNCTION__);
173    return 0;
174  }
175  return m_sym_file_impl->ParseBlocksRecursive(func);
176}
177
178size_t SymbolFileOnDemand::ParseVariablesForContext(const SymbolContext &sc) {
179  if (!m_debug_info_enabled) {
180    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
181             __FUNCTION__);
182    return 0;
183  }
184  return m_sym_file_impl->ParseVariablesForContext(sc);
185}
186
187Type *SymbolFileOnDemand::ResolveTypeUID(lldb::user_id_t type_uid) {
188  if (!m_debug_info_enabled) {
189    Log *log = GetLog();
190    LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
191    if (log) {
192      Type *resolved_type = m_sym_file_impl->ResolveTypeUID(type_uid);
193      if (resolved_type)
194        LLDB_LOG(log, "Type would be parsed for {0} if hydrated.", type_uid);
195    }
196    return nullptr;
197  }
198  return m_sym_file_impl->ResolveTypeUID(type_uid);
199}
200
201std::optional<SymbolFile::ArrayInfo>
202SymbolFileOnDemand::GetDynamicArrayInfoForUID(
203    lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
204  if (!m_debug_info_enabled) {
205    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
206             __FUNCTION__);
207    return std::nullopt;
208  }
209  return m_sym_file_impl->GetDynamicArrayInfoForUID(type_uid, exe_ctx);
210}
211
212bool SymbolFileOnDemand::CompleteType(CompilerType &compiler_type) {
213  if (!m_debug_info_enabled) {
214    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
215             __FUNCTION__);
216    return false;
217  }
218  return m_sym_file_impl->CompleteType(compiler_type);
219}
220
221CompilerDecl SymbolFileOnDemand::GetDeclForUID(lldb::user_id_t type_uid) {
222  if (!m_debug_info_enabled) {
223    Log *log = GetLog();
224    LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
225    if (log) {
226      CompilerDecl parsed_decl = m_sym_file_impl->GetDeclForUID(type_uid);
227      if (parsed_decl != CompilerDecl()) {
228        LLDB_LOG(log, "CompilerDecl {0} would be parsed for {1} if hydrated.",
229                 parsed_decl.GetName(), type_uid);
230      }
231    }
232    return CompilerDecl();
233  }
234  return m_sym_file_impl->GetDeclForUID(type_uid);
235}
236
237CompilerDeclContext
238SymbolFileOnDemand::GetDeclContextForUID(lldb::user_id_t type_uid) {
239  if (!m_debug_info_enabled) {
240    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
241             __FUNCTION__);
242    return CompilerDeclContext();
243  }
244  return m_sym_file_impl->GetDeclContextForUID(type_uid);
245}
246
247CompilerDeclContext
248SymbolFileOnDemand::GetDeclContextContainingUID(lldb::user_id_t type_uid) {
249  if (!m_debug_info_enabled) {
250    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
251             __FUNCTION__);
252    return CompilerDeclContext();
253  }
254  return m_sym_file_impl->GetDeclContextContainingUID(type_uid);
255}
256
257void SymbolFileOnDemand::ParseDeclsForContext(CompilerDeclContext decl_ctx) {
258  if (!m_debug_info_enabled) {
259    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
260             __FUNCTION__);
261    return;
262  }
263  return m_sym_file_impl->ParseDeclsForContext(decl_ctx);
264}
265
266uint32_t
267SymbolFileOnDemand::ResolveSymbolContext(const Address &so_addr,
268                                         SymbolContextItem resolve_scope,
269                                         SymbolContext &sc) {
270  if (!m_debug_info_enabled) {
271    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
272             __FUNCTION__);
273    return 0;
274  }
275  return m_sym_file_impl->ResolveSymbolContext(so_addr, resolve_scope, sc);
276}
277
278Status SymbolFileOnDemand::CalculateFrameVariableError(StackFrame &frame) {
279  if (!m_debug_info_enabled) {
280    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
281             __FUNCTION__);
282    return Status();
283  }
284  return m_sym_file_impl->CalculateFrameVariableError(frame);
285}
286
287uint32_t SymbolFileOnDemand::ResolveSymbolContext(
288    const SourceLocationSpec &src_location_spec,
289    SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
290  if (!m_debug_info_enabled) {
291    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
292             __FUNCTION__);
293    return 0;
294  }
295  return m_sym_file_impl->ResolveSymbolContext(src_location_spec, resolve_scope,
296                                               sc_list);
297}
298
299void SymbolFileOnDemand::Dump(lldb_private::Stream &s) {
300  if (!m_debug_info_enabled) {
301    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
302             __FUNCTION__);
303    return;
304  }
305  return m_sym_file_impl->Dump(s);
306}
307
308void SymbolFileOnDemand::DumpClangAST(lldb_private::Stream &s) {
309  if (!m_debug_info_enabled) {
310    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
311             __FUNCTION__);
312    return;
313  }
314  return m_sym_file_impl->DumpClangAST(s);
315}
316
317void SymbolFileOnDemand::FindGlobalVariables(const RegularExpression &regex,
318                                             uint32_t max_matches,
319                                             VariableList &variables) {
320  if (!m_debug_info_enabled) {
321    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
322             __FUNCTION__);
323    return;
324  }
325  return m_sym_file_impl->FindGlobalVariables(regex, max_matches, variables);
326}
327
328void SymbolFileOnDemand::FindGlobalVariables(
329    ConstString name, const CompilerDeclContext &parent_decl_ctx,
330    uint32_t max_matches, VariableList &variables) {
331  if (!m_debug_info_enabled) {
332    Log *log = GetLog();
333    Symtab *symtab = GetSymtab();
334    if (!symtab) {
335      LLDB_LOG(log, "[{0}] {1} is skipped - fail to get symtab",
336               GetSymbolFileName(), __FUNCTION__);
337      return;
338    }
339    Symbol *sym = symtab->FindFirstSymbolWithNameAndType(
340        name, eSymbolTypeData, Symtab::eDebugAny, Symtab::eVisibilityAny);
341    if (!sym) {
342      LLDB_LOG(log, "[{0}] {1} is skipped - fail to find match in symtab",
343               GetSymbolFileName(), __FUNCTION__);
344      return;
345    }
346    LLDB_LOG(log, "[{0}] {1} is NOT skipped - found match in symtab",
347             GetSymbolFileName(), __FUNCTION__);
348
349    // Found match in symbol table hydrate debug info and
350    // allow the FindGlobalVariables to go through.
351    SetLoadDebugInfoEnabled();
352  }
353  return m_sym_file_impl->FindGlobalVariables(name, parent_decl_ctx,
354                                              max_matches, variables);
355}
356
357void SymbolFileOnDemand::FindFunctions(const RegularExpression &regex,
358                                       bool include_inlines,
359                                       SymbolContextList &sc_list) {
360  if (!m_debug_info_enabled) {
361    Log *log = GetLog();
362    Symtab *symtab = GetSymtab();
363    if (!symtab) {
364      LLDB_LOG(log, "[{0}] {1} is skipped - fail to get symtab",
365               GetSymbolFileName(), __FUNCTION__);
366      return;
367    }
368    std::vector<uint32_t> symbol_indexes;
369    symtab->AppendSymbolIndexesMatchingRegExAndType(
370        regex, eSymbolTypeAny, Symtab::eDebugAny, Symtab::eVisibilityAny,
371        symbol_indexes);
372    if (symbol_indexes.empty()) {
373      LLDB_LOG(log, "[{0}] {1} is skipped - fail to find match in symtab",
374               GetSymbolFileName(), __FUNCTION__);
375      return;
376    }
377    LLDB_LOG(log, "[{0}] {1} is NOT skipped - found match in symtab",
378             GetSymbolFileName(), __FUNCTION__);
379
380    // Found match in symbol table hydrate debug info and
381    // allow the FindFucntions to go through.
382    SetLoadDebugInfoEnabled();
383  }
384  return m_sym_file_impl->FindFunctions(regex, include_inlines, sc_list);
385}
386
387void SymbolFileOnDemand::FindFunctions(
388    const Module::LookupInfo &lookup_info,
389    const CompilerDeclContext &parent_decl_ctx, bool include_inlines,
390    SymbolContextList &sc_list) {
391  ConstString name = lookup_info.GetLookupName();
392  FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
393  if (!m_debug_info_enabled) {
394    Log *log = GetLog();
395
396    Symtab *symtab = GetSymtab();
397    if (!symtab) {
398      LLDB_LOG(log, "[{0}] {1}({2}) is skipped  - fail to get symtab",
399               GetSymbolFileName(), __FUNCTION__, name);
400      return;
401    }
402
403    SymbolContextList sc_list_helper;
404    symtab->FindFunctionSymbols(name, name_type_mask, sc_list_helper);
405    if (sc_list_helper.GetSize() == 0) {
406      LLDB_LOG(log, "[{0}] {1}({2}) is skipped - fail to find match in symtab",
407               GetSymbolFileName(), __FUNCTION__, name);
408      return;
409    }
410    LLDB_LOG(log, "[{0}] {1}({2}) is NOT skipped - found match in symtab",
411             GetSymbolFileName(), __FUNCTION__, name);
412
413    // Found match in symbol table hydrate debug info and
414    // allow the FindFucntions to go through.
415    SetLoadDebugInfoEnabled();
416  }
417  return m_sym_file_impl->FindFunctions(lookup_info, parent_decl_ctx,
418                                        include_inlines, sc_list);
419}
420
421void SymbolFileOnDemand::GetMangledNamesForFunction(
422    const std::string &scope_qualified_name,
423    std::vector<ConstString> &mangled_names) {
424  if (!m_debug_info_enabled) {
425    Log *log = GetLog();
426    LLDB_LOG(log, "[{0}] {1}({2}) is skipped", GetSymbolFileName(),
427             __FUNCTION__, scope_qualified_name);
428    return;
429  }
430  return m_sym_file_impl->GetMangledNamesForFunction(scope_qualified_name,
431                                                     mangled_names);
432}
433
434void SymbolFileOnDemand::FindTypes(const TypeQuery &match,
435                                   TypeResults &results) {
436  if (!m_debug_info_enabled) {
437    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
438             __FUNCTION__);
439    return;
440  }
441  return m_sym_file_impl->FindTypes(match, results);
442}
443
444void SymbolFileOnDemand::GetTypes(SymbolContextScope *sc_scope,
445                                  TypeClass type_mask, TypeList &type_list) {
446  if (!m_debug_info_enabled) {
447    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
448             __FUNCTION__);
449    return;
450  }
451  return m_sym_file_impl->GetTypes(sc_scope, type_mask, type_list);
452}
453
454llvm::Expected<lldb::TypeSystemSP>
455SymbolFileOnDemand::GetTypeSystemForLanguage(LanguageType language) {
456  if (!m_debug_info_enabled) {
457    Log *log = GetLog();
458    LLDB_LOG(log, "[{0}] {1} is skipped for language type {2}",
459             GetSymbolFileName(), __FUNCTION__, language);
460    return llvm::make_error<llvm::StringError>(
461        "GetTypeSystemForLanguage is skipped by SymbolFileOnDemand",
462        llvm::inconvertibleErrorCode());
463  }
464  return m_sym_file_impl->GetTypeSystemForLanguage(language);
465}
466
467CompilerDeclContext
468SymbolFileOnDemand::FindNamespace(ConstString name,
469                                  const CompilerDeclContext &parent_decl_ctx,
470                                  bool only_root_namespaces) {
471  if (!m_debug_info_enabled) {
472    LLDB_LOG(GetLog(), "[{0}] {1}({2}) is skipped", GetSymbolFileName(),
473             __FUNCTION__, name);
474    return SymbolFile::FindNamespace(name, parent_decl_ctx,
475                                     only_root_namespaces);
476  }
477  return m_sym_file_impl->FindNamespace(name, parent_decl_ctx,
478                                        only_root_namespaces);
479}
480
481std::vector<std::unique_ptr<lldb_private::CallEdge>>
482SymbolFileOnDemand::ParseCallEdgesInFunction(UserID func_id) {
483  if (!m_debug_info_enabled) {
484    Log *log = GetLog();
485    LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
486    if (log) {
487      std::vector<std::unique_ptr<lldb_private::CallEdge>> call_edges =
488          m_sym_file_impl->ParseCallEdgesInFunction(func_id);
489      if (call_edges.size() > 0) {
490        LLDB_LOG(log, "{0} call edges would be parsed for {1} if hydrated.",
491                 call_edges.size(), func_id.GetID());
492      }
493    }
494    return {};
495  }
496  return m_sym_file_impl->ParseCallEdgesInFunction(func_id);
497}
498
499lldb::UnwindPlanSP
500SymbolFileOnDemand::GetUnwindPlan(const Address &address,
501                                  const RegisterInfoResolver &resolver) {
502  if (!m_debug_info_enabled) {
503    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
504             __FUNCTION__);
505    return nullptr;
506  }
507  return m_sym_file_impl->GetUnwindPlan(address, resolver);
508}
509
510llvm::Expected<lldb::addr_t>
511SymbolFileOnDemand::GetParameterStackSize(Symbol &symbol) {
512  if (!m_debug_info_enabled) {
513    Log *log = GetLog();
514    LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);
515    if (log) {
516      llvm::Expected<lldb::addr_t> stack_size =
517          m_sym_file_impl->GetParameterStackSize(symbol);
518      if (stack_size) {
519        LLDB_LOG(log, "{0} stack size would return for symbol {1} if hydrated.",
520                 *stack_size, symbol.GetName());
521      }
522    }
523    return SymbolFile::GetParameterStackSize(symbol);
524  }
525  return m_sym_file_impl->GetParameterStackSize(symbol);
526}
527
528void SymbolFileOnDemand::PreloadSymbols() {
529  m_preload_symbols = true;
530  if (!m_debug_info_enabled) {
531    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
532             __FUNCTION__);
533    return;
534  }
535  return m_sym_file_impl->PreloadSymbols();
536}
537
538uint64_t SymbolFileOnDemand::GetDebugInfoSize() {
539  // Always return the real debug info size.
540  LLDB_LOG(GetLog(), "[{0}] {1} is not skipped", GetSymbolFileName(),
541           __FUNCTION__);
542  return m_sym_file_impl->GetDebugInfoSize();
543}
544
545StatsDuration::Duration SymbolFileOnDemand::GetDebugInfoParseTime() {
546  // Always return the real parse time.
547  LLDB_LOG(GetLog(), "[{0}] {1} is not skipped", GetSymbolFileName(),
548           __FUNCTION__);
549  return m_sym_file_impl->GetDebugInfoParseTime();
550}
551
552StatsDuration::Duration SymbolFileOnDemand::GetDebugInfoIndexTime() {
553  // Always return the real index time.
554  LLDB_LOG(GetLog(), "[{0}] {1} is not skipped", GetSymbolFileName(),
555           __FUNCTION__);
556  return m_sym_file_impl->GetDebugInfoIndexTime();
557}
558
559void SymbolFileOnDemand::SetLoadDebugInfoEnabled() {
560  if (m_debug_info_enabled)
561    return;
562  LLDB_LOG(GetLog(), "[{0}] Hydrate debug info", GetSymbolFileName());
563  m_debug_info_enabled = true;
564  InitializeObject();
565  if (m_preload_symbols)
566    PreloadSymbols();
567}
568
569uint32_t SymbolFileOnDemand::GetNumCompileUnits() {
570  LLDB_LOG(GetLog(), "[{0}] {1} is not skipped to support breakpoint hydration",
571           GetSymbolFileName(), __FUNCTION__);
572  return m_sym_file_impl->GetNumCompileUnits();
573}
574
575CompUnitSP SymbolFileOnDemand::GetCompileUnitAtIndex(uint32_t idx) {
576  LLDB_LOG(GetLog(), "[{0}] {1} is not skipped to support breakpoint hydration",
577           GetSymbolFileName(), __FUNCTION__);
578  return m_sym_file_impl->GetCompileUnitAtIndex(idx);
579}
580
581uint32_t SymbolFileOnDemand::GetAbilities() {
582  if (!m_debug_info_enabled) {
583    LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
584             __FUNCTION__);
585    return 0;
586  }
587  return m_sym_file_impl->GetAbilities();
588}
589