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  // Remove the old address->section entry, if
121  // there is one.
122  for (const auto &entry : m_addr_to_sect) {
123  if (entry.second == section) {
124  const auto &it_pos = m_addr_to_sect.find(entry.first);
125  m_addr_to_sect.erase(it_pos);
126  break;
127  }
128  }
129  m_addr_to_sect[load_addr] = section;
130  }
131  return true; // Changed
132 
133  } else {
134  if (log) {
135  LLDB_LOGF(
136  log,
137  "SectionLoadList::%s (section = %p (%s), load_addr = 0x%16.16" PRIx64
138  ") error: module has been deleted",
139  __FUNCTION__, static_cast<void *>(section.get()),
140  section->GetName().AsCString(), load_addr);
141  }
142  }
143  return false;
144 }
145 
146 size_t SectionLoadList::SetSectionUnloaded(const lldb::SectionSP &section_sp) {
147  size_t unload_count = 0;
148 
149  if (section_sp) {
151 
152  if (log && log->GetVerbose()) {
153  ModuleSP module_sp = section_sp->GetModule();
154  std::string module_name("<Unknown>");
155  if (module_sp) {
156  const FileSpec &module_file_spec(
157  section_sp->GetModule()->GetFileSpec());
158  module_name = module_file_spec.GetPath();
159  }
160  LLDB_LOGF(log, "SectionLoadList::%s (section = %p (%s.%s))", __FUNCTION__,
161  static_cast<void *>(section_sp.get()), module_name.c_str(),
162  section_sp->GetName().AsCString());
163  }
164 
165  std::lock_guard<std::recursive_mutex> guard(m_mutex);
166 
167  sect_to_addr_collection::iterator sta_pos =
168  m_sect_to_addr.find(section_sp.get());
169  if (sta_pos != m_sect_to_addr.end()) {
170  ++unload_count;
171  addr_t load_addr = sta_pos->second;
172  m_sect_to_addr.erase(sta_pos);
173 
174  addr_to_sect_collection::iterator ats_pos =
175  m_addr_to_sect.find(load_addr);
176  if (ats_pos != m_addr_to_sect.end())
177  m_addr_to_sect.erase(ats_pos);
178  }
179  }
180  return unload_count;
181 }
182 
183 bool SectionLoadList::SetSectionUnloaded(const lldb::SectionSP &section_sp,
184  addr_t load_addr) {
186 
187  if (log && log->GetVerbose()) {
188  ModuleSP module_sp = section_sp->GetModule();
189  std::string module_name("<Unknown>");
190  if (module_sp) {
191  const FileSpec &module_file_spec(section_sp->GetModule()->GetFileSpec());
192  module_name = module_file_spec.GetPath();
193  }
194  LLDB_LOGF(
195  log,
196  "SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64
197  ")",
198  __FUNCTION__, static_cast<void *>(section_sp.get()),
199  module_name.c_str(), section_sp->GetName().AsCString(), load_addr);
200  }
201  bool erased = false;
202  std::lock_guard<std::recursive_mutex> guard(m_mutex);
203  sect_to_addr_collection::iterator sta_pos =
204  m_sect_to_addr.find(section_sp.get());
205  if (sta_pos != m_sect_to_addr.end()) {
206  erased = true;
207  m_sect_to_addr.erase(sta_pos);
208  }
209 
210  addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
211  if (ats_pos != m_addr_to_sect.end()) {
212  erased = true;
213  m_addr_to_sect.erase(ats_pos);
214  }
215 
216  return erased;
217 }
218 
220  bool allow_section_end) const {
221  // First find the top level section that this load address exists in
222  std::lock_guard<std::recursive_mutex> guard(m_mutex);
223  if (!m_addr_to_sect.empty()) {
224  addr_to_sect_collection::const_iterator pos =
225  m_addr_to_sect.lower_bound(load_addr);
226  if (pos != m_addr_to_sect.end()) {
227  if (load_addr != pos->first && pos != m_addr_to_sect.begin())
228  --pos;
229  const addr_t pos_load_addr = pos->first;
230  if (load_addr >= pos_load_addr) {
231  addr_t offset = load_addr - pos_load_addr;
232  if (offset < pos->second->GetByteSize() + (allow_section_end ? 1 : 0)) {
233  // We have found the top level section, now we need to find the
234  // deepest child section.
235  return pos->second->ResolveContainedAddress(offset, so_addr,
236  allow_section_end);
237  }
238  }
239  } else {
240  // There are no entries that have an address that is >= load_addr, so we
241  // need to check the last entry on our collection.
242  addr_to_sect_collection::const_reverse_iterator rpos =
243  m_addr_to_sect.rbegin();
244  if (load_addr >= rpos->first) {
245  addr_t offset = load_addr - rpos->first;
246  if (offset <
247  rpos->second->GetByteSize() + (allow_section_end ? 1 : 0)) {
248  // We have found the top level section, now we need to find the
249  // deepest child section.
250  return rpos->second->ResolveContainedAddress(offset, so_addr,
251  allow_section_end);
252  }
253  }
254  }
255  }
256  so_addr.Clear();
257  return false;
258 }
259 
261  std::lock_guard<std::recursive_mutex> guard(m_mutex);
262  addr_to_sect_collection::const_iterator pos, end;
263  for (pos = m_addr_to_sect.begin(), end = m_addr_to_sect.end(); pos != end;
264  ++pos) {
265  s.Printf("addr = 0x%16.16" PRIx64 ", section = %p: ", pos->first,
266  static_cast<void *>(pos->second.get()));
267  pos->second->Dump(s.AsRawOstream(), s.GetIndentLevel(), target, 0);
268  }
269 }
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:301
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:344
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:469
Section.h
LLDB_LOGV
#define LLDB_LOGV(log,...)
Definition: Log.h:351
lldb_private::SectionLoadList::m_mutex
std::recursive_mutex m_mutex
Definition: SectionLoadList.h:68
lldb_private::FileSpec
Definition: FileSpec.h:55
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:260
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:219
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:183
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:115
lldb_private::GetLog
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:309
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:364
lldb
Definition: SBAddress.h:15
LLDBLog.h