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/Log.h"
17 #include "lldb/Utility/Stream.h"
20 using namespace lldb_private
;
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
);
25 m_addr_to_sect
= rhs
.m_addr_to_sect
;
26 m_sect_to_addr
= rhs
.m_sect_to_addr
;
29 void SectionLoadList::operator=(const SectionLoadList
&rhs
) {
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
);
33 m_addr_to_sect
= rhs
.m_addr_to_sect
;
34 m_sect_to_addr
= rhs
.m_sect_to_addr
;
37 bool SectionLoadList::IsEmpty() const {
38 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
39 return m_addr_to_sect
.empty();
42 void SectionLoadList::Clear() {
43 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
44 m_addr_to_sect
.clear();
45 m_sect_to_addr
.clear();
49 SectionLoadList::GetSectionLoadAddress(const lldb::SectionSP
§ion
) const {
50 // TODO: add support for the same section having multiple load addresses
51 addr_t section_load_addr
= LLDB_INVALID_ADDRESS
;
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());
57 if (pos
!= m_sect_to_addr
.end())
58 section_load_addr
= pos
->second
;
60 return section_load_addr
;
63 bool SectionLoadList::SetSectionLoadAddress(const lldb::SectionSP
§ion
,
66 Log
*log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER
));
67 ModuleSP
module_sp(section
->GetModule());
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());
74 if (section
->GetByteSize() == 0)
75 return false; // No change
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...
85 sta_pos
->second
= load_addr
;
87 m_sect_to_addr
[section
.get()] = load_addr
;
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());
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());
117 ats_pos
->second
= section
;
119 m_addr_to_sect
[load_addr
] = section
;
120 return true; // Changed
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
);
135 size_t SectionLoadList::SetSectionUnloaded(const lldb::SectionSP
§ion_sp
) {
136 size_t unload_count
= 0;
139 Log
*log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER
));
141 if (log
&& log
->GetVerbose()) {
142 ModuleSP module_sp
= section_sp
->GetModule();
143 std::string
module_name("<Unknown>");
145 const FileSpec
&module_file_spec(
146 section_sp
->GetModule()->GetFileSpec());
147 module_name
= module_file_spec
.GetPath();
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());
154 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
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()) {
160 addr_t load_addr
= sta_pos
->second
;
161 m_sect_to_addr
.erase(sta_pos
);
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
);
172 bool SectionLoadList::SetSectionUnloaded(const lldb::SectionSP
§ion_sp
,
174 Log
*log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER
));
176 if (log
&& log
->GetVerbose()) {
177 ModuleSP module_sp
= section_sp
->GetModule();
178 std::string
module_name("<Unknown>");
180 const FileSpec
&module_file_spec(section_sp
->GetModule()->GetFileSpec());
181 module_name
= module_file_spec
.GetPath();
185 "SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64
187 __FUNCTION__
, static_cast<void *>(section_sp
.get()),
188 module_name
.c_str(), section_sp
->GetName().AsCString(), load_addr
);
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()) {
196 m_sect_to_addr
.erase(sta_pos
);
199 addr_to_sect_collection::iterator ats_pos
= m_addr_to_sect
.find(load_addr
);
200 if (ats_pos
!= m_addr_to_sect
.end()) {
202 m_addr_to_sect
.erase(ats_pos
);
208 bool SectionLoadList::ResolveLoadAddress(addr_t load_addr
, Address
&so_addr
,
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())
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
,
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
;
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
,
249 void SectionLoadList::Dump(Stream
&s
, Target
*target
) {
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
;
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);