1 //===-- SectionLoadList.cpp -------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Target/SectionLoadList.h"
14 // Other libraries and framework includes
16 #include "lldb/Core/Log.h"
17 #include "lldb/Core/Module.h"
18 #include "lldb/Core/Section.h"
19 #include "lldb/Core/Stream.h"
20 #include "lldb/Symbol/Block.h"
21 #include "lldb/Symbol/Symbol.h"
22 #include "lldb/Symbol/SymbolContext.h"
25 using namespace lldb_private;
27 SectionLoadList::SectionLoadList(const SectionLoadList &rhs) : m_addr_to_sect(), m_sect_to_addr(), m_mutex()
29 std::lock_guard<std::recursive_mutex> guard(rhs.m_mutex);
30 m_addr_to_sect = rhs.m_addr_to_sect;
31 m_sect_to_addr = rhs.m_sect_to_addr;
35 SectionLoadList::operator=(const SectionLoadList &rhs)
37 std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex);
38 std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex);
39 m_addr_to_sect = rhs.m_addr_to_sect;
40 m_sect_to_addr = rhs.m_sect_to_addr;
44 SectionLoadList::IsEmpty() const
46 std::lock_guard<std::recursive_mutex> guard(m_mutex);
47 return m_addr_to_sect.empty();
51 SectionLoadList::Clear ()
53 std::lock_guard<std::recursive_mutex> guard(m_mutex);
54 m_addr_to_sect.clear();
55 m_sect_to_addr.clear();
59 SectionLoadList::GetSectionLoadAddress (const lldb::SectionSP §ion) const
61 // TODO: add support for the same section having multiple load addresses
62 addr_t section_load_addr = LLDB_INVALID_ADDRESS;
65 std::lock_guard<std::recursive_mutex> guard(m_mutex);
66 sect_to_addr_collection::const_iterator pos = m_sect_to_addr.find (section.get());
68 if (pos != m_sect_to_addr.end())
69 section_load_addr = pos->second;
71 return section_load_addr;
75 SectionLoadList::SetSectionLoadAddress (const lldb::SectionSP §ion, addr_t load_addr, bool warn_multiple)
77 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));
79 ModuleSP module_sp (section->GetModule());
85 const FileSpec &module_file_spec (module_sp->GetFileSpec());
86 log->Printf ("SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64 ") module = %p",
87 __FUNCTION__, static_cast<void*>(section.get()),
88 module_file_spec.GetPath().c_str(),
89 section->GetName().AsCString(), load_addr,
90 static_cast<void*>(module_sp.get()));
93 if (section->GetByteSize() == 0)
94 return false; // No change
96 // Fill in the section -> load_addr map
97 std::lock_guard<std::recursive_mutex> guard(m_mutex);
98 sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section.get());
99 if (sta_pos != m_sect_to_addr.end())
101 if (load_addr == sta_pos->second)
102 return false; // No change...
104 sta_pos->second = load_addr;
107 m_sect_to_addr[section.get()] = load_addr;
109 // Fill in the load_addr -> section map
110 addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
111 if (ats_pos != m_addr_to_sect.end())
113 // Some sections are ok to overlap, and for others we should warn. When
114 // we have multiple load addresses that correspond to a section, we will
115 // always attribute the section to the be last section that claims it
116 // exists at that address. Sometimes it is ok for more that one section
117 // to be loaded at a specific load address, and other times it isn't.
118 // The "warn_multiple" parameter tells us if we should warn in this case
119 // or not. The DynamicLoader plug-in subclasses should know which
120 // sections should warn and which shouldn't (darwin shared cache modules
121 // all shared the same "__LINKEDIT" sections, so the dynamic loader can
122 // pass false for "warn_multiple").
123 if (warn_multiple && section != ats_pos->second)
125 ModuleSP module_sp (section->GetModule());
128 ModuleSP curr_module_sp (ats_pos->second->GetModule());
131 module_sp->ReportWarning ("address 0x%16.16" PRIx64 " maps to more than one section: %s.%s and %s.%s",
133 module_sp->GetFileSpec().GetFilename().GetCString(),
134 section->GetName().GetCString(),
135 curr_module_sp->GetFileSpec().GetFilename().GetCString(),
136 ats_pos->second->GetName().GetCString());
140 ats_pos->second = section;
143 m_addr_to_sect[load_addr] = section;
144 return true; // Changed
151 log->Printf ("SectionLoadList::%s (section = %p (%s), load_addr = 0x%16.16" PRIx64 ") error: module has been deleted",
152 __FUNCTION__, static_cast<void*>(section.get()),
153 section->GetName().AsCString(),
161 SectionLoadList::SetSectionUnloaded (const lldb::SectionSP §ion_sp)
163 size_t unload_count = 0;
167 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));
171 ModuleSP module_sp = section_sp->GetModule();
172 std::string module_name("<Unknown>");
175 const FileSpec &module_file_spec (section_sp->GetModule()->GetFileSpec());
176 module_name = module_file_spec.GetPath();
178 log->Printf ("SectionLoadList::%s (section = %p (%s.%s))",
179 __FUNCTION__, static_cast<void*>(section_sp.get()),
181 section_sp->GetName().AsCString());
184 std::lock_guard<std::recursive_mutex> guard(m_mutex);
186 sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section_sp.get());
187 if (sta_pos != m_sect_to_addr.end())
190 addr_t load_addr = sta_pos->second;
191 m_sect_to_addr.erase (sta_pos);
193 addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
194 if (ats_pos != m_addr_to_sect.end())
195 m_addr_to_sect.erase (ats_pos);
202 SectionLoadList::SetSectionUnloaded (const lldb::SectionSP §ion_sp, addr_t load_addr)
204 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));
208 ModuleSP module_sp = section_sp->GetModule();
209 std::string module_name("<Unknown>");
212 const FileSpec &module_file_spec (section_sp->GetModule()->GetFileSpec());
213 module_name = module_file_spec.GetPath();
215 log->Printf ("SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64 ")",
216 __FUNCTION__, static_cast<void*>(section_sp.get()),
218 section_sp->GetName().AsCString(), load_addr);
221 std::lock_guard<std::recursive_mutex> guard(m_mutex);
222 sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section_sp.get());
223 if (sta_pos != m_sect_to_addr.end())
226 m_sect_to_addr.erase (sta_pos);
229 addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
230 if (ats_pos != m_addr_to_sect.end())
233 m_addr_to_sect.erase (ats_pos);
241 SectionLoadList::ResolveLoadAddress (addr_t load_addr, Address &so_addr) const
243 // First find the top level section that this load address exists in
244 std::lock_guard<std::recursive_mutex> guard(m_mutex);
245 if (!m_addr_to_sect.empty())
247 addr_to_sect_collection::const_iterator pos = m_addr_to_sect.lower_bound (load_addr);
248 if (pos != m_addr_to_sect.end())
250 if (load_addr != pos->first && pos != m_addr_to_sect.begin())
252 const addr_t pos_load_addr = pos->first;
253 if (load_addr >= pos_load_addr)
255 addr_t offset = load_addr - pos_load_addr;
256 if (offset < pos->second->GetByteSize())
258 // We have found the top level section, now we need to find the
259 // deepest child section.
260 return pos->second->ResolveContainedAddress (offset, so_addr);
266 // There are no entries that have an address that is >= load_addr,
267 // so we need to check the last entry on our collection.
268 addr_to_sect_collection::const_reverse_iterator rpos = m_addr_to_sect.rbegin();
269 if (load_addr >= rpos->first)
271 addr_t offset = load_addr - rpos->first;
272 if (offset < rpos->second->GetByteSize())
274 // We have found the top level section, now we need to find the
275 // deepest child section.
276 return rpos->second->ResolveContainedAddress (offset, so_addr);
286 SectionLoadList::Dump (Stream &s, Target *target)
288 std::lock_guard<std::recursive_mutex> guard(m_mutex);
289 addr_to_sect_collection::const_iterator pos, end;
290 for (pos = m_addr_to_sect.begin(), end = m_addr_to_sect.end(); pos != end; ++pos)
292 s.Printf("addr = 0x%16.16" PRIx64 ", section = %p: ",
293 pos->first, static_cast<void*>(pos->second.get()));
294 pos->second->Dump (&s, target, 0);