1 //===-- SectionLoadHistory.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/SectionLoadHistory.h"
11 #include "lldb/Target/SectionLoadList.h"
12 #include "lldb/Utility/Stream.h"
15 using namespace lldb_private
;
17 bool SectionLoadHistory::IsEmpty() const {
18 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
19 return m_stop_id_to_section_load_list
.empty();
22 void SectionLoadHistory::Clear() {
23 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
24 m_stop_id_to_section_load_list
.clear();
27 uint32_t SectionLoadHistory::GetLastStopID() const {
28 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
29 if (m_stop_id_to_section_load_list
.empty())
32 return m_stop_id_to_section_load_list
.rbegin()->first
;
36 SectionLoadHistory::GetSectionLoadListForStopID(uint32_t stop_id
,
38 if (!m_stop_id_to_section_load_list
.empty()) {
40 // The section load list is for reading data only so we don't need to
41 // create a new SectionLoadList for the current stop ID, just return the
42 // section load list for the stop ID that is equal to or less than the
44 if (stop_id
== eStopIDNow
) {
45 // If we are asking for the latest and greatest value, it is always at
46 // the end of our list because that will be the highest stop ID.
47 StopIDToSectionLoadList::reverse_iterator rpos
=
48 m_stop_id_to_section_load_list
.rbegin();
49 return rpos
->second
.get();
51 StopIDToSectionLoadList::iterator pos
=
52 m_stop_id_to_section_load_list
.lower_bound(stop_id
);
53 if (pos
!= m_stop_id_to_section_load_list
.end() &&
54 pos
->first
== stop_id
)
55 return pos
->second
.get();
56 else if (pos
!= m_stop_id_to_section_load_list
.begin()) {
58 return pos
->second
.get();
62 // You can only use "eStopIDNow" when reading from the section load
64 assert(stop_id
!= eStopIDNow
);
66 // We are updating the section load list (not read only), so if the stop
67 // ID passed in isn't the same as the last stop ID in our collection,
68 // then create a new node using the current stop ID
69 StopIDToSectionLoadList::iterator pos
=
70 m_stop_id_to_section_load_list
.lower_bound(stop_id
);
71 if (pos
!= m_stop_id_to_section_load_list
.end() &&
72 pos
->first
== stop_id
) {
73 // We already have an entry for this value
74 return pos
->second
.get();
77 // We must make a new section load list that is based on the last valid
78 // section load list, so here we copy the last section load list and add
79 // a new node for the current stop ID.
80 StopIDToSectionLoadList::reverse_iterator rpos
=
81 m_stop_id_to_section_load_list
.rbegin();
82 SectionLoadListSP
section_load_list_sp(
83 new SectionLoadList(*rpos
->second
));
84 m_stop_id_to_section_load_list
[stop_id
] = section_load_list_sp
;
85 return section_load_list_sp
.get();
88 SectionLoadListSP
section_load_list_sp(new SectionLoadList());
89 if (stop_id
== eStopIDNow
)
91 m_stop_id_to_section_load_list
[stop_id
] = section_load_list_sp
;
92 return section_load_list_sp
.get();
95 SectionLoadList
&SectionLoadHistory::GetCurrentSectionLoadList() {
96 const bool read_only
= true;
97 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
98 SectionLoadList
*section_load_list
=
99 GetSectionLoadListForStopID(eStopIDNow
, read_only
);
100 assert(section_load_list
!= nullptr);
101 return *section_load_list
;
105 SectionLoadHistory::GetSectionLoadAddress(uint32_t stop_id
,
106 const lldb::SectionSP
§ion_sp
) {
107 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
108 const bool read_only
= true;
109 SectionLoadList
*section_load_list
=
110 GetSectionLoadListForStopID(stop_id
, read_only
);
111 return section_load_list
->GetSectionLoadAddress(section_sp
);
114 bool SectionLoadHistory::ResolveLoadAddress(uint32_t stop_id
, addr_t load_addr
,
116 // First find the top level section that this load address exists in
117 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
118 const bool read_only
= true;
119 SectionLoadList
*section_load_list
=
120 GetSectionLoadListForStopID(stop_id
, read_only
);
121 return section_load_list
->ResolveLoadAddress(load_addr
, so_addr
);
124 bool SectionLoadHistory::SetSectionLoadAddress(
125 uint32_t stop_id
, const lldb::SectionSP
§ion_sp
, addr_t load_addr
,
126 bool warn_multiple
) {
127 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
128 const bool read_only
= false;
129 SectionLoadList
*section_load_list
=
130 GetSectionLoadListForStopID(stop_id
, read_only
);
131 return section_load_list
->SetSectionLoadAddress(section_sp
, load_addr
,
136 SectionLoadHistory::SetSectionUnloaded(uint32_t stop_id
,
137 const lldb::SectionSP
§ion_sp
) {
138 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
139 const bool read_only
= false;
140 SectionLoadList
*section_load_list
=
141 GetSectionLoadListForStopID(stop_id
, read_only
);
142 return section_load_list
->SetSectionUnloaded(section_sp
);
145 bool SectionLoadHistory::SetSectionUnloaded(uint32_t stop_id
,
146 const lldb::SectionSP
§ion_sp
,
148 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
149 const bool read_only
= false;
150 SectionLoadList
*section_load_list
=
151 GetSectionLoadListForStopID(stop_id
, read_only
);
152 return section_load_list
->SetSectionUnloaded(section_sp
, load_addr
);
155 void SectionLoadHistory::Dump(Stream
&s
, Target
*target
) {
156 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
157 StopIDToSectionLoadList::iterator pos
,
158 end
= m_stop_id_to_section_load_list
.end();
159 for (pos
= m_stop_id_to_section_load_list
.begin(); pos
!= end
; ++pos
) {
160 s
.Printf("StopID = %u:\n", pos
->first
);
161 pos
->second
->Dump(s
, target
);