Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Core/DynamicLoader.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- DynamicLoader.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/Target/DynamicLoader.h"
10
11
#include "lldb/Core/Debugger.h"
12
#include "lldb/Core/Module.h"
13
#include "lldb/Core/ModuleList.h"
14
#include "lldb/Core/ModuleSpec.h"
15
#include "lldb/Core/PluginManager.h"
16
#include "lldb/Core/Section.h"
17
#include "lldb/Symbol/LocateSymbolFile.h"
18
#include "lldb/Symbol/ObjectFile.h"
19
#include "lldb/Target/MemoryRegionInfo.h"
20
#include "lldb/Target/Platform.h"
21
#include "lldb/Target/Process.h"
22
#include "lldb/Target/Target.h"
23
#include "lldb/Utility/ConstString.h"
24
#include "lldb/Utility/LLDBLog.h"
25
#include "lldb/Utility/Log.h"
26
#include "lldb/lldb-private-interfaces.h"
27
28
#include "llvm/ADT/StringRef.h"
29
30
#include <memory>
31
32
#include <cassert>
33
34
using namespace lldb;
35
using namespace lldb_private;
36
37
DynamicLoader *DynamicLoader::FindPlugin(Process *process,
38
2.31k
                                         llvm::StringRef plugin_name) {
39
2.31k
  DynamicLoaderCreateInstance create_callback = nullptr;
40
2.31k
  if (!plugin_name.empty()) {
41
73
    create_callback =
42
73
        PluginManager::GetDynamicLoaderCreateCallbackForPluginName(plugin_name);
43
73
    if (create_callback) {
44
73
      std::unique_ptr<DynamicLoader> instance_up(
45
73
          create_callback(process, true));
46
73
      if (instance_up)
47
73
        return instance_up.release();
48
73
    }
49
2.24k
  } else {
50
2.24k
    for (uint32_t idx = 0;
51
6.93k
         (create_callback =
52
6.93k
              PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) !=
53
6.93k
         nullptr;
54
6.93k
         
++idx4.69k
) {
55
6.93k
      std::unique_ptr<DynamicLoader> instance_up(
56
6.93k
          create_callback(process, false));
57
6.93k
      if (instance_up)
58
2.24k
        return instance_up.release();
59
6.93k
    }
60
2.24k
  }
61
0
  return nullptr;
62
2.31k
}
63
64
2.31k
DynamicLoader::DynamicLoader(Process *process) : m_process(process) {}
65
66
// Accessors to the global setting as to whether to stop at image (shared
67
// library) loading/unloading.
68
69
2.17k
bool DynamicLoader::GetStopWhenImagesChange() const {
70
2.17k
  return m_process->GetStopOnSharedLibraryEvents();
71
2.17k
}
72
73
0
void DynamicLoader::SetStopWhenImagesChange(bool stop) {
74
0
  m_process->SetStopOnSharedLibraryEvents(stop);
75
0
}
76
77
80
ModuleSP DynamicLoader::GetTargetExecutable() {
78
80
  Target &target = m_process->GetTarget();
79
80
  ModuleSP executable = target.GetExecutableModule();
80
81
80
  if (executable) {
82
29
    if (FileSystem::Instance().Exists(executable->GetFileSpec())) {
83
29
      ModuleSpec module_spec(executable->GetFileSpec(),
84
29
                             executable->GetArchitecture());
85
29
      auto module_sp = std::make_shared<Module>(module_spec);
86
87
      // Check if the executable has changed and set it to the target
88
      // executable if they differ.
89
29
      if (module_sp && module_sp->GetUUID().IsValid() &&
90
29
          executable->GetUUID().IsValid()) {
91
29
        if (module_sp->GetUUID() != executable->GetUUID())
92
0
          executable.reset();
93
29
      } else 
if (0
executable->FileHasChanged()0
) {
94
0
        executable.reset();
95
0
      }
96
97
29
      if (!executable) {
98
0
        executable = target.GetOrCreateModule(module_spec, true /* notify */);
99
0
        if (executable.get() != target.GetExecutableModulePointer()) {
100
          // Don't load dependent images since we are in dyld where we will
101
          // know and find out about all images that are loaded
102
0
          target.SetExecutableModule(executable, eLoadDependentsNo);
103
0
        }
104
0
      }
105
29
    }
106
29
  }
107
80
  return executable;
108
80
}
109
110
void DynamicLoader::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr,
111
                                         addr_t base_addr,
112
3
                                         bool base_addr_is_offset) {
113
3
  UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
114
3
}
115
116
void DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module,
117
                                               addr_t base_addr,
118
40
                                               bool base_addr_is_offset) {
119
40
  bool changed;
120
40
  module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset,
121
40
                         changed);
122
40
}
123
124
109k
void DynamicLoader::UnloadSections(const ModuleSP module) {
125
109k
  UnloadSectionsCommon(module);
126
109k
}
127
128
109k
void DynamicLoader::UnloadSectionsCommon(const ModuleSP module) {
129
109k
  Target &target = m_process->GetTarget();
130
109k
  const SectionList *sections = GetSectionListFromModule(module);
131
132
109k
  assert(sections && "SectionList missing from unloaded module.");
133
134
109k
  const size_t num_sections = sections->GetSize();
135
450k
  for (size_t i = 0; i < num_sections; 
++i341k
) {
136
341k
    SectionSP section_sp(sections->GetSectionAtIndex(i));
137
341k
    target.SetSectionUnloaded(section_sp);
138
341k
  }
139
109k
}
140
141
const SectionList *
142
109k
DynamicLoader::GetSectionListFromModule(const ModuleSP module) const {
143
109k
  SectionList *sections = nullptr;
144
109k
  if (module) {
145
109k
    ObjectFile *obj_file = module->GetObjectFile();
146
109k
    if (obj_file != nullptr) {
147
109k
      sections = obj_file->GetSectionList();
148
109k
    }
149
109k
  }
150
109k
  return sections;
151
109k
}
152
153
24
ModuleSP DynamicLoader::FindModuleViaTarget(const FileSpec &file) {
154
24
  Target &target = m_process->GetTarget();
155
24
  ModuleSpec module_spec(file, target.GetArchitecture());
156
157
24
  if (ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec))
158
3
    return module_sp;
159
160
21
  if (ModuleSP module_sp = target.GetOrCreateModule(module_spec, false))
161
2
    return module_sp;
162
163
19
  return nullptr;
164
21
}
165
166
ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
167
                                            addr_t link_map_addr,
168
                                            addr_t base_addr,
169
24
                                            bool base_addr_is_offset) {
170
24
  if (ModuleSP module_sp = FindModuleViaTarget(file)) {
171
5
    UpdateLoadedSections(module_sp, link_map_addr, base_addr,
172
5
                         base_addr_is_offset);
173
5
    return module_sp;
174
5
  }
175
176
19
  return nullptr;
177
24
}
178
179
static ModuleSP ReadUnnamedMemoryModule(Process *process, addr_t addr,
180
6
                                        llvm::StringRef name) {
181
6
  char namebuf[80];
182
6
  if (name.empty()) {
183
6
    snprintf(namebuf, sizeof(namebuf), "memory-image-0x%" PRIx64, addr);
184
6
    name = namebuf;
185
6
  }
186
6
  return process->ReadModuleFromMemory(FileSpec(name), addr);
187
6
}
188
189
ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
190
    Process *process, llvm::StringRef name, UUID uuid, addr_t value,
191
    bool value_is_offset, bool force_symbol_search, bool notify,
192
13
    bool set_address_in_target, bool allow_memory_image_last_resort) {
193
13
  ModuleSP memory_module_sp;
194
13
  ModuleSP module_sp;
195
13
  PlatformSP platform_sp = process->GetTarget().GetPlatform();
196
13
  Target &target = process->GetTarget();
197
13
  Status error;
198
199
13
  if (!uuid.IsValid() && 
!value_is_offset6
) {
200
6
    memory_module_sp = ReadUnnamedMemoryModule(process, value, name);
201
202
6
    if (memory_module_sp)
203
6
      uuid = memory_module_sp->GetUUID();
204
6
  }
205
13
  ModuleSpec module_spec;
206
13
  module_spec.GetUUID() = uuid;
207
13
  FileSpec name_filespec(name);
208
13
  if (FileSystem::Instance().Exists(name_filespec))
209
0
    module_spec.GetFileSpec() = name_filespec;
210
211
13
  if (uuid.IsValid()) {
212
    // Has lldb already seen a module with this UUID?
213
13
    if (!module_sp)
214
13
      error = ModuleList::GetSharedModule(module_spec, module_sp, nullptr,
215
13
                                          nullptr, nullptr);
216
217
    // Can lldb's symbol/executable location schemes
218
    // find an executable and symbol file.
219
13
    if (!module_sp) {
220
5
      FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
221
5
      module_spec.GetSymbolFileSpec() =
222
5
          Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
223
5
      ModuleSpec objfile_module_spec =
224
5
          Symbols::LocateExecutableObjectFile(module_spec);
225
5
      module_spec.GetFileSpec() = objfile_module_spec.GetFileSpec();
226
5
      if (FileSystem::Instance().Exists(module_spec.GetFileSpec()) &&
227
5
          
FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec())0
) {
228
0
        module_sp = std::make_shared<Module>(module_spec);
229
0
      }
230
5
    }
231
232
    // If we haven't found a binary, or we don't have a SymbolFile, see
233
    // if there is an external search tool that can find it.
234
13
    if (!module_sp || 
!module_sp->GetSymbolFileFileSpec()8
) {
235
7
      Symbols::DownloadObjectAndSymbolFile(module_spec, error,
236
7
                                           force_symbol_search);
237
7
      if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
238
4
        module_sp = std::make_shared<Module>(module_spec);
239
4
      } else 
if (3
force_symbol_search3
&&
error.AsCString("")3
&&
240
3
                 
error.AsCString("")[0] != '\0'1
) {
241
1
        target.GetDebugger().GetErrorStream() << error.AsCString();
242
1
      }
243
7
    }
244
245
    // If we only found the executable, create a Module based on that.
246
13
    if (!module_sp && 
FileSystem::Instance().Exists(module_spec.GetFileSpec())2
)
247
0
      module_sp = std::make_shared<Module>(module_spec);
248
13
  }
249
250
  // If we couldn't find the binary anywhere else, as a last resort,
251
  // read it out of memory.
252
13
  if (allow_memory_image_last_resort && 
!module_sp.get()0
&&
253
13
      
value != 0
LLDB_INVALID_ADDRESS0
&&
!value_is_offset0
) {
254
0
    if (!memory_module_sp)
255
0
      memory_module_sp = ReadUnnamedMemoryModule(process, value, name);
256
0
    if (memory_module_sp)
257
0
      module_sp = memory_module_sp;
258
0
  }
259
260
13
  Log *log = GetLog(LLDBLog::DynamicLoader);
261
13
  if (module_sp.get()) {
262
    // Ensure the Target has an architecture set in case
263
    // we need it while processing this binary/eh_frame/debug info.
264
11
    if (!target.GetArchitecture().IsValid())
265
0
      target.SetArchitecture(module_sp->GetArchitecture());
266
11
    target.GetImages().AppendIfNeeded(module_sp, false);
267
268
11
    bool changed = false;
269
11
    if (set_address_in_target) {
270
11
      if (module_sp->GetObjectFile()) {
271
11
        if (value != LLDB_INVALID_ADDRESS) {
272
8
          LLDB_LOGF(log,
273
8
                    "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading "
274
8
                    "binary %s UUID %s at %s 0x%" PRIx64,
275
8
                    name.str().c_str(), uuid.GetAsString().c_str(),
276
8
                    value_is_offset ? "offset" : "address", value);
277
8
          module_sp->SetLoadAddress(target, value, value_is_offset, changed);
278
8
        } else {
279
          // No address/offset/slide, load the binary at file address,
280
          // offset 0.
281
3
          LLDB_LOGF(log,
282
3
                    "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading "
283
3
                    "binary %s UUID %s at file address",
284
3
                    name.str().c_str(), uuid.GetAsString().c_str());
285
3
          module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
286
3
                                    changed);
287
3
        }
288
11
      } else {
289
        // In-memory image, load at its true address, offset 0.
290
0
        LLDB_LOGF(log,
291
0
                  "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading binary "
292
0
                  "%s UUID %s from memory at address 0x%" PRIx64,
293
0
                  name.str().c_str(), uuid.GetAsString().c_str(), value);
294
0
        module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
295
0
                                  changed);
296
0
      }
297
11
    }
298
299
11
    if (notify) {
300
9
      ModuleList added_module;
301
9
      added_module.Append(module_sp, false);
302
9
      target.ModulesDidLoad(added_module);
303
9
    }
304
11
  } else {
305
2
    if (force_symbol_search) {
306
2
      Stream &s = target.GetDebugger().GetErrorStream();
307
2
      s.Printf("Unable to find file");
308
2
      if (!name.empty())
309
0
        s.Printf(" %s", name.str().c_str());
310
2
      if (uuid.IsValid())
311
2
        s.Printf(" with UUID %s", uuid.GetAsString().c_str());
312
2
      if (value != LLDB_INVALID_ADDRESS) {
313
2
        if (value_is_offset)
314
0
          s.Printf(" with slide 0x%" PRIx64, value);
315
2
        else
316
2
          s.Printf(" at address 0x%" PRIx64, value);
317
2
      }
318
2
      s.Printf("\n");
319
2
    }
320
2
    LLDB_LOGF(log,
321
2
              "Unable to find binary %s with UUID %s and load it at "
322
2
              "%s 0x%" PRIx64,
323
2
              name.str().c_str(), uuid.GetAsString().c_str(),
324
2
              value_is_offset ? "offset" : "address", value);
325
2
  }
326
327
13
  return module_sp;
328
13
}
329
330
int64_t DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr,
331
0
                                                      int size_in_bytes) {
332
0
  Status error;
333
0
  uint64_t value =
334
0
      m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error);
335
0
  if (error.Fail())
336
0
    return -1;
337
0
  else
338
0
    return (int64_t)value;
339
0
}
340
341
0
addr_t DynamicLoader::ReadPointer(addr_t addr) {
342
0
  Status error;
343
0
  addr_t value = m_process->ReadPointerFromMemory(addr, error);
344
0
  if (error.Fail())
345
0
    return LLDB_INVALID_ADDRESS;
346
0
  else
347
0
    return value;
348
0
}
349
350
void DynamicLoader::LoadOperatingSystemPlugin(bool flush)
351
0
{
352
0
    if (m_process)
353
0
        m_process->LoadOperatingSystemPlugin(flush);
354
0
}
355