Coverage Report

Created: 2022-01-18 06:27

/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/Module.h"
12
#include "lldb/Core/ModuleList.h"
13
#include "lldb/Core/ModuleSpec.h"
14
#include "lldb/Core/PluginManager.h"
15
#include "lldb/Core/Section.h"
16
#include "lldb/Symbol/ObjectFile.h"
17
#include "lldb/Target/MemoryRegionInfo.h"
18
#include "lldb/Target/Process.h"
19
#include "lldb/Target/Target.h"
20
#include "lldb/Utility/ConstString.h"
21
#include "lldb/lldb-private-interfaces.h"
22
23
#include "llvm/ADT/StringRef.h"
24
25
#include <memory>
26
27
#include <cassert>
28
29
using namespace lldb;
30
using namespace lldb_private;
31
32
DynamicLoader *DynamicLoader::FindPlugin(Process *process,
33
2.72k
                                         llvm::StringRef plugin_name) {
34
2.72k
  DynamicLoaderCreateInstance create_callback = nullptr;
35
2.72k
  if (!plugin_name.empty()) {
36
59
    create_callback =
37
59
        PluginManager::GetDynamicLoaderCreateCallbackForPluginName(plugin_name);
38
59
    if (create_callback) {
39
59
      std::unique_ptr<DynamicLoader> instance_up(
40
59
          create_callback(process, true));
41
59
      if (instance_up)
42
59
        return instance_up.release();
43
59
    }
44
2.66k
  } else {
45
2.66k
    for (uint32_t idx = 0;
46
8.11k
         (create_callback =
47
8.11k
              PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) !=
48
8.11k
         nullptr;
49
8.11k
         
++idx5.44k
) {
50
8.11k
      std::unique_ptr<DynamicLoader> instance_up(
51
8.11k
          create_callback(process, false));
52
8.11k
      if (instance_up)
53
2.66k
        return instance_up.release();
54
8.11k
    }
55
2.66k
  }
56
0
  return nullptr;
57
2.72k
}
58
59
2.72k
DynamicLoader::DynamicLoader(Process *process) : m_process(process) {}
60
61
// Accessosors to the global setting as to whether to stop at image (shared
62
// library) loading/unloading.
63
64
2.64k
bool DynamicLoader::GetStopWhenImagesChange() const {
65
2.64k
  return m_process->GetStopOnSharedLibraryEvents();
66
2.64k
}
67
68
0
void DynamicLoader::SetStopWhenImagesChange(bool stop) {
69
0
  m_process->SetStopOnSharedLibraryEvents(stop);
70
0
}
71
72
63
ModuleSP DynamicLoader::GetTargetExecutable() {
73
63
  Target &target = m_process->GetTarget();
74
63
  ModuleSP executable = target.GetExecutableModule();
75
76
63
  if (executable) {
77
24
    if (FileSystem::Instance().Exists(executable->GetFileSpec())) {
78
24
      ModuleSpec module_spec(executable->GetFileSpec(),
79
24
                             executable->GetArchitecture());
80
24
      auto module_sp = std::make_shared<Module>(module_spec);
81
82
      // Check if the executable has changed and set it to the target
83
      // executable if they differ.
84
24
      if (module_sp && module_sp->GetUUID().IsValid() &&
85
24
          executable->GetUUID().IsValid()) {
86
24
        if (module_sp->GetUUID() != executable->GetUUID())
87
0
          executable.reset();
88
24
      } else 
if (0
executable->FileHasChanged()0
) {
89
0
        executable.reset();
90
0
      }
91
92
24
      if (!executable) {
93
0
        executable = target.GetOrCreateModule(module_spec, true /* notify */);
94
0
        if (executable.get() != target.GetExecutableModulePointer()) {
95
          // Don't load dependent images since we are in dyld where we will
96
          // know and find out about all images that are loaded
97
0
          target.SetExecutableModule(executable, eLoadDependentsNo);
98
0
        }
99
0
      }
100
24
    }
101
24
  }
102
63
  return executable;
103
63
}
104
105
void DynamicLoader::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr,
106
                                         addr_t base_addr,
107
3
                                         bool base_addr_is_offset) {
108
3
  UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
109
3
}
110
111
void DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module,
112
                                               addr_t base_addr,
113
34
                                               bool base_addr_is_offset) {
114
34
  bool changed;
115
34
  module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset,
116
34
                         changed);
117
34
}
118
119
132k
void DynamicLoader::UnloadSections(const ModuleSP module) {
120
132k
  UnloadSectionsCommon(module);
121
132k
}
122
123
132k
void DynamicLoader::UnloadSectionsCommon(const ModuleSP module) {
124
132k
  Target &target = m_process->GetTarget();
125
132k
  const SectionList *sections = GetSectionListFromModule(module);
126
127
132k
  assert(sections && "SectionList missing from unloaded module.");
128
129
0
  const size_t num_sections = sections->GetSize();
130
539k
  for (size_t i = 0; i < num_sections; 
++i406k
) {
131
406k
    SectionSP section_sp(sections->GetSectionAtIndex(i));
132
406k
    target.SetSectionUnloaded(section_sp);
133
406k
  }
134
132k
}
135
136
const SectionList *
137
132k
DynamicLoader::GetSectionListFromModule(const ModuleSP module) const {
138
132k
  SectionList *sections = nullptr;
139
132k
  if (module) {
140
132k
    ObjectFile *obj_file = module->GetObjectFile();
141
132k
    if (obj_file != nullptr) {
142
132k
      sections = obj_file->GetSectionList();
143
132k
    }
144
132k
  }
145
132k
  return sections;
146
132k
}
147
148
ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
149
                                            addr_t link_map_addr,
150
                                            addr_t base_addr,
151
21
                                            bool base_addr_is_offset) {
152
21
  Target &target = m_process->GetTarget();
153
21
  ModuleList &modules = target.GetImages();
154
21
  ModuleSpec module_spec(file, target.GetArchitecture());
155
21
  ModuleSP module_sp;
156
157
21
  if ((module_sp = modules.FindFirstModule(module_spec))) {
158
3
    UpdateLoadedSections(module_sp, link_map_addr, base_addr,
159
3
                         base_addr_is_offset);
160
3
    return module_sp;
161
3
  }
162
163
18
  if ((module_sp = target.GetOrCreateModule(module_spec, 
164
18
                                            true /* notify */))) {
165
1
    UpdateLoadedSections(module_sp, link_map_addr, base_addr,
166
1
                         base_addr_is_offset);
167
1
    return module_sp;
168
1
  }
169
170
17
  bool check_alternative_file_name = true;
171
17
  if (base_addr_is_offset) {
172
    // Try to fetch the load address of the file from the process as we need
173
    // absolute load address to read the file out of the memory instead of a
174
    // load bias.
175
15
    bool is_loaded = false;
176
15
    lldb::addr_t load_addr;
177
15
    Status error = m_process->GetFileLoadAddress(file, is_loaded, load_addr);
178
15
    if (error.Success() && 
is_loaded0
) {
179
0
      check_alternative_file_name = false;
180
0
      base_addr = load_addr;
181
0
    }
182
15
  }
183
184
  // We failed to find the module based on its name. Lets try to check if we
185
  // can find a different name based on the memory region info.
186
17
  if (check_alternative_file_name) {
187
17
    MemoryRegionInfo memory_info;
188
17
    Status error = m_process->GetMemoryRegionInfo(base_addr, memory_info);
189
17
    if (error.Success() && 
memory_info.GetMapped()15
&&
190
17
        
memory_info.GetRange().GetRangeBase() == base_addr12
&&
191
17
        
!(memory_info.GetName().IsEmpty())12
) {
192
0
      ModuleSpec new_module_spec(FileSpec(memory_info.GetName().GetStringRef()),
193
0
                                 target.GetArchitecture());
194
195
0
      if ((module_sp = modules.FindFirstModule(new_module_spec))) {
196
0
        UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
197
0
        return module_sp;
198
0
      }
199
200
0
      if ((module_sp = target.GetOrCreateModule(new_module_spec, 
201
0
                                                true /* notify */))) {
202
0
        UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
203
0
        return module_sp;
204
0
      }
205
0
    }
206
17
  }
207
208
17
  if ((module_sp = m_process->ReadModuleFromMemory(file, base_addr))) {
209
2
    UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
210
2
    target.GetImages().AppendIfNeeded(module_sp);
211
2
  }
212
213
17
  return module_sp;
214
17
}
215
216
int64_t DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr,
217
0
                                                      int size_in_bytes) {
218
0
  Status error;
219
0
  uint64_t value =
220
0
      m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error);
221
0
  if (error.Fail())
222
0
    return -1;
223
0
  else
224
0
    return (int64_t)value;
225
0
}
226
227
0
addr_t DynamicLoader::ReadPointer(addr_t addr) {
228
0
  Status error;
229
0
  addr_t value = m_process->ReadPointerFromMemory(addr, error);
230
0
  if (error.Fail())
231
0
    return LLDB_INVALID_ADDRESS;
232
0
  else
233
0
    return value;
234
0
}
235
236
void DynamicLoader::LoadOperatingSystemPlugin(bool flush)
237
0
{
238
0
    if (m_process)
239
0
        m_process->LoadOperatingSystemPlugin(flush);
240
0
}
241