LLDB  mainline
SectionLoadList.cpp
Go to the documentation of this file.
1 //===-- SectionLoadList.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 
10 
11 #include "lldb/Core/Module.h"
12 #include "lldb/Core/Section.h"
13 #include "lldb/Symbol/Block.h"
14 #include "lldb/Symbol/Symbol.h"
16 #include "lldb/Utility/Log.h"
17 #include "lldb/Utility/Stream.h"
18 
19 using namespace lldb;
20 using namespace lldb_private;
21 
22 SectionLoadList::SectionLoadList(const SectionLoadList &rhs)
23  : m_addr_to_sect(), m_sect_to_addr(), m_mutex() {
24  std::lock_guard<std::recursive_mutex> guard(rhs.m_mutex);
27 }
28 
30  std::lock(m_mutex, rhs.m_mutex);
31  std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex, std::adopt_lock);
32  std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex, std::adopt_lock);
35 }
36 
38  std::lock_guard<std::recursive_mutex> guard(m_mutex);
39  return m_addr_to_sect.empty();
40 }
41 
43  std::lock_guard<std::recursive_mutex> guard(m_mutex);
44  m_addr_to_sect.clear();
45  m_sect_to_addr.clear();
46 }
47 
48 addr_t
49 SectionLoadList::GetSectionLoadAddress(const lldb::SectionSP &section) const {
50  // TODO: add support for the same section having multiple load addresses
51  addr_t section_load_addr = LLDB_INVALID_ADDRESS;
52  if (section) {
53  std::lock_guard<std::recursive_mutex> guard(m_mutex);
54  sect_to_addr_collection::const_iterator pos =
55  m_sect_to_addr.find(section.get());
56 
57  if (pos != m_sect_to_addr.end())
58  section_load_addr = pos->second;
59  }
60  return section_load_addr;
61 }
62 
63 bool SectionLoadList::SetSectionLoadAddress(const lldb::SectionSP &section,
64  addr_t load_addr,
65  bool warn_multiple) {
67  ModuleSP module_sp(section->GetModule());
68 
69  if (module_sp) {
70  LLDB_LOGV(log, "(section = {0} ({1}.{2}), load_addr = {3:x}) module = {4}",
71  section.get(), module_sp->GetFileSpec(), section->GetName(),
72  load_addr, module_sp.get());
73 
74  if (section->GetByteSize() == 0)
75  return false; // No change
76 
77  // Fill in the section -> load_addr map
78  std::lock_guard<std::recursive_mutex> guard(m_mutex);
79  sect_to_addr_collection::iterator sta_pos =
80  m_sect_to_addr.find(section.get());
81  if (sta_pos != m_sect_to_addr.end()) {
82  if (load_addr == sta_pos->second)
83  return false; // No change...
84  else
85  sta_pos->second = load_addr;
86  } else
87  m_sect_to_addr[section.get()] = load_addr;
88 
89  // Fill in the load_addr -> section map
90  addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
91  if (ats_pos != m_addr_to_sect.end()) {
92  // Some sections are ok to overlap, and for others we should warn. When
93  // we have multiple load addresses that correspond to a section, we will
94  // always attribute the section to the be last section that claims it
95  // exists at that address. Sometimes it is ok for more that one section
96  // to be loaded at a specific load address, and other times it isn't. The
97  // "warn_multiple" parameter tells us if we should warn in this case or
98  // not. The DynamicLoader plug-in subclasses should know which sections
99  // should warn and which shouldn't (darwin shared cache modules all
100  // shared the same "__LINKEDIT" sections, so the dynamic loader can pass
101  // false for "warn_multiple").
102  if (warn_multiple && section != ats_pos->second) {
103  ModuleSP module_sp(section->GetModule());
104  if (module_sp) {
105  ModuleSP curr_module_sp(ats_pos->second->GetModule());
106  if (curr_module_sp) {
107  module_sp->ReportWarning(
108  "address 0x%16.16" PRIx64
109  " maps to more than one section: %s.%s and %s.%s",
110  load_addr, module_sp->GetFileSpec().GetFilename().GetCString(),
111  section->GetName().GetCString(),
112  curr_module_sp->GetFileSpec().GetFilename().GetCString(),
113  ats_pos->second->GetName().GetCString());
114  }
115  }
116  }
117  ats_pos->second = section;
118  } else
119  m_addr_to_sect[load_addr] = section;
120  return true; // Changed
121 
122  } else {
123  if (log) {
124  LLDB_LOGF(
125  log,
126  "SectionLoadList::%s (section = %p (%s), load_addr = 0x%16.16" PRIx64
127  ") error: module has been deleted",
128  __FUNCTION__, static_cast<void *>(section.get()),
129  section->GetName().AsCString(), load_addr);
130  }
131  }
132  return false;
133 }
134 
135 size_t SectionLoadList::SetSectionUnloaded(const lldb::SectionSP &section_sp) {
136  size_t unload_count = 0;
137 
138  if (section_sp) {
140 
141  if (log && log->GetVerbose()) {
142  ModuleSP module_sp = section_sp->GetModule();
143  std::string module_name("<Unknown>");
144  if (module_sp) {
145  const FileSpec &module_file_spec(
146  section_sp->GetModule()->GetFileSpec());
147  module_name = module_file_spec.GetPath();
148  }
149  LLDB_LOGF(log, "SectionLoadList::%s (section = %p (%s.%s))", __FUNCTION__,
150  static_cast<void *>(section_sp.get()), module_name.c_str(),
151  section_sp->GetName().AsCString());
152  }
153 
154  std::lock_guard<std::recursive_mutex> guard(m_mutex);
155 
156  sect_to_addr_collection::iterator sta_pos =
157  m_sect_to_addr.find(section_sp.get());
158  if (sta_pos != m_sect_to_addr.end()) {
159  ++unload_count;
160  addr_t load_addr = sta_pos->second;
161  m_sect_to_addr.erase(sta_pos);
162 
163  addr_to_sect_collection::iterator ats_pos =
164  m_addr_to_sect.find(load_addr);
165  if (ats_pos != m_addr_to_sect.end())
166  m_addr_to_sect.erase(ats_pos);
167  }
168  }
169  return unload_count;
170 }
171 
172 bool SectionLoadList::SetSectionUnloaded(const lldb::SectionSP &section_sp,
173  addr_t load_addr) {
175 
176  if (log && log->GetVerbose()) {
177  ModuleSP module_sp = section_sp->GetModule();
178  std::string module_name("<Unknown>");
179  if (module_sp) {
180  const FileSpec &module_file_spec(section_sp->GetModule()->GetFileSpec());
181  module_name = module_file_spec.GetPath();
182  }
183  LLDB_LOGF(
184  log,
185  "SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64
186  ")",
187  __FUNCTION__, static_cast<void *>(section_sp.get()),
188  module_name.c_str(), section_sp->GetName().AsCString(), load_addr);
189  }
190  bool erased = false;
191  std::lock_guard<std::recursive_mutex> guard(m_mutex);
192  sect_to_addr_collection::iterator sta_pos =
193  m_sect_to_addr.find(section_sp.get());
194  if (sta_pos != m_sect_to_addr.end()) {
195  erased = true;
196  m_sect_to_addr.erase(sta_pos);
197  }
198 
199  addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
200  if (ats_pos != m_addr_to_sect.end()) {
201  erased = true;
202  m_addr_to_sect.erase(ats_pos);
203  }
204 
205  return erased;
206 }
207 
209  bool allow_section_end) const {
210  // First find the top level section that this load address exists in
211  std::lock_guard<std::recursive_mutex> guard(m_mutex);
212  if (!m_addr_to_sect.empty()) {
213  addr_to_sect_collection::const_iterator pos =
214  m_addr_to_sect.lower_bound(load_addr);
215  if (pos != m_addr_to_sect.end()) {
216  if (load_addr != pos->first && pos != m_addr_to_sect.begin())
217  --pos;
218  const addr_t pos_load_addr = pos->first;
219  if (load_addr >= pos_load_addr) {
220  addr_t offset = load_addr - pos_load_addr;
221  if (offset < pos->second->GetByteSize() + (allow_section_end ? 1 : 0)) {
222  // We have found the top level section, now we need to find the
223  // deepest child section.
224  return pos->second->ResolveContainedAddress(offset, so_addr,
225  allow_section_end);
226  }
227  }
228  } else {
229  // There are no entries that have an address that is >= load_addr, so we
230  // need to check the last entry on our collection.
231  addr_to_sect_collection::const_reverse_iterator rpos =
232  m_addr_to_sect.rbegin();
233  if (load_addr >= rpos->first) {
234  addr_t offset = load_addr - rpos->first;
235  if (offset <
236  rpos->second->GetByteSize() + (allow_section_end ? 1 : 0)) {
237  // We have found the top level section, now we need to find the
238  // deepest child section.
239  return rpos->second->ResolveContainedAddress(offset, so_addr,
240  allow_section_end);
241  }
242  }
243  }
244  }
245  so_addr.Clear();
246  return false;
247 }
248 
250  std::lock_guard<std::recursive_mutex> guard(m_mutex);
251  addr_to_sect_collection::const_iterator pos, end;
252  for (pos = m_addr_to_sect.begin(), end = m_addr_to_sect.end(); pos != end;
253  ++pos) {
254  s.Printf("addr = 0x%16.16" PRIx64 ", section = %p: ", pos->first,
255  static_cast<void *>(pos->second.get()));
256  pos->second->Dump(s.AsRawOstream(), s.GetIndentLevel(), target, 0);
257  }
258 }
lldb_private::SectionLoadList::SetSectionLoadAddress
bool SetSectionLoadAddress(const lldb::SectionSP &section_sp, lldb::addr_t load_addr, bool warn_multiple=false)
Definition: SectionLoadList.cpp:63
Block.h
LIBLLDB_LOG_DYNAMIC_LOADER
#define LIBLLDB_LOG_DYNAMIC_LOADER
Definition: Logging.h:17
lldb_private::Log::GetVerbose
bool GetVerbose() const
Definition: Log.cpp:276
lldb_private::Address::Clear
void Clear()
Clear the object's state.
Definition: Address.h:178
lldb_private::SectionLoadList::Clear
void Clear()
Definition: SectionLoadList.cpp:42
LLDB_LOGF
#define LLDB_LOGF(log,...)
Definition: Log.h:249
Module.h
SectionLoadList.h
lldb_private::Stream
Definition: Stream.h:28
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
lldb_private::Target
Definition: Target.h:451
Section.h
LLDB_LOGV
#define LLDB_LOGV(log,...)
Definition: Log.h:256
lldb_private::SectionLoadList::m_mutex
std::recursive_mutex m_mutex
Definition: SectionLoadList.h:68
lldb_private::FileSpec
Definition: FileSpec.h:56
lldb_private::SectionLoadList::GetSectionLoadAddress
lldb::addr_t GetSectionLoadAddress(const lldb::SectionSP &section_sp) const
Definition: SectionLoadList.cpp:49
Log.h
lldb_private::SectionLoadList::m_addr_to_sect
addr_to_sect_collection m_addr_to_sect
Definition: SectionLoadList.h:66
lldb_private::Stream::GetIndentLevel
unsigned GetIndentLevel() const
Get the current indentation level.
Definition: Stream.cpp:160
lldb_private::SectionLoadList::Dump
void Dump(Stream &s, Target *target)
Definition: SectionLoadList.cpp:249
lldb_private::SectionLoadList
Definition: SectionLoadList.h:22
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
lldb_private::SectionLoadList::operator=
void operator=(const SectionLoadList &rhs)
Definition: SectionLoadList.cpp:29
lldb_private::SectionLoadList::ResolveLoadAddress
bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, bool allow_section_end=false) const
Definition: SectionLoadList.cpp:208
Symbol.h
lldb_private::SectionLoadList::IsEmpty
bool IsEmpty() const
Definition: SectionLoadList.cpp:37
lldb_private::Address
Definition: Address.h:59
lldb_private::Stream::AsRawOstream
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
Definition: Stream.h:357
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:86
lldb_private::Stream::Printf
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
lldb_private::SectionLoadList::SetSectionUnloaded
bool SetSectionUnloaded(const lldb::SectionSP &section_sp, lldb::addr_t load_addr)
Definition: SectionLoadList.cpp:172
SymbolContext.h
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::SectionLoadList::m_sect_to_addr
sect_to_addr_collection m_sect_to_addr
Definition: SectionLoadList.h:67
Stream.h
lldb_private::Log
Definition: Log.h:49
lldb_private::GetLogIfAnyCategoriesSet
Log * GetLogIfAnyCategoriesSet(uint32_t mask)
Definition: Logging.cpp:62
lldb_private::FileSpec::GetPath
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:346
lldb
Definition: SBAddress.h:15