1 //===-- SectionLoadList.cpp -----------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Target/SectionLoadList.h"
11 #include "lldb/Core/Module.h"
12 #include "lldb/Core/Section.h"
13 #include "lldb/Symbol/Block.h"
14 #include "lldb/Symbol/Symbol.h"
15 #include "lldb/Symbol/SymbolContext.h"
16 #include "lldb/Utility/LLDBLog.h"
17 #include "lldb/Utility/Log.h"
18 #include "lldb/Utility/Stream.h"
21 using namespace lldb_private
;
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
);
26 m_addr_to_sect
= rhs
.m_addr_to_sect
;
27 m_sect_to_addr
= rhs
.m_sect_to_addr
;
30 void SectionLoadList::operator=(const SectionLoadList
&rhs
) {
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
);
34 m_addr_to_sect
= rhs
.m_addr_to_sect
;
35 m_sect_to_addr
= rhs
.m_sect_to_addr
;
38 bool SectionLoadList::IsEmpty() const {
39 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
40 return m_addr_to_sect
.empty();
43 void SectionLoadList::Clear() {
44 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
45 m_addr_to_sect
.clear();
46 m_sect_to_addr
.clear();
50 SectionLoadList::GetSectionLoadAddress(const lldb::SectionSP
§ion
) const {
51 // TODO: add support for the same section having multiple load addresses
52 addr_t section_load_addr
= LLDB_INVALID_ADDRESS
;
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());
58 if (pos
!= m_sect_to_addr
.end())
59 section_load_addr
= pos
->second
;
61 return section_load_addr
;
64 bool SectionLoadList::SetSectionLoadAddress(const lldb::SectionSP
§ion
,
67 Log
*log
= GetLog(LLDBLog::DynamicLoader
);
68 ModuleSP
module_sp(section
->GetModule());
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());
75 if (section
->GetByteSize() == 0)
76 return false; // No change
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...
86 sta_pos
->second
= load_addr
;
88 m_sect_to_addr
[section
.get()] = load_addr
;
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());
106 ModuleSP
curr_module_sp(ats_pos
->second
->GetModule());
107 if (curr_module_sp
) {
108 module_sp
->ReportWarning(
109 "address {0:x16} maps to more than one section: {1}.{2} and "
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());
118 ats_pos
->second
= section
;
120 // Remove the old address->section entry, if
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
);
129 m_addr_to_sect
[load_addr
] = section
;
131 return true; // Changed
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
);
146 size_t SectionLoadList::SetSectionUnloaded(const lldb::SectionSP
§ion_sp
) {
147 size_t unload_count
= 0;
150 Log
*log
= GetLog(LLDBLog::DynamicLoader
);
152 if (log
&& log
->GetVerbose()) {
153 ModuleSP module_sp
= section_sp
->GetModule();
154 std::string
module_name("<Unknown>");
156 const FileSpec
&module_file_spec(
157 section_sp
->GetModule()->GetFileSpec());
158 module_name
= module_file_spec
.GetPath();
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());
165 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
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()) {
171 addr_t load_addr
= sta_pos
->second
;
172 m_sect_to_addr
.erase(sta_pos
);
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
);
183 bool SectionLoadList::SetSectionUnloaded(const lldb::SectionSP
§ion_sp
,
185 Log
*log
= GetLog(LLDBLog::DynamicLoader
);
187 if (log
&& log
->GetVerbose()) {
188 ModuleSP module_sp
= section_sp
->GetModule();
189 std::string
module_name("<Unknown>");
191 const FileSpec
&module_file_spec(section_sp
->GetModule()->GetFileSpec());
192 module_name
= module_file_spec
.GetPath();
196 "SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64
198 __FUNCTION__
, static_cast<void *>(section_sp
.get()),
199 module_name
.c_str(), section_sp
->GetName().AsCString(), load_addr
);
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()) {
207 m_sect_to_addr
.erase(sta_pos
);
210 addr_to_sect_collection::iterator ats_pos
= m_addr_to_sect
.find(load_addr
);
211 if (ats_pos
!= m_addr_to_sect
.end()) {
213 m_addr_to_sect
.erase(ats_pos
);
219 bool SectionLoadList::ResolveLoadAddress(addr_t load_addr
, Address
&so_addr
,
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())
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
,
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
;
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
,
260 void SectionLoadList::Dump(Stream
&s
, Target
*target
) {
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
;
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);