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