1262182Semaste//===-- SectionLoadHistory.cpp ----------------------------------*- C++ -*-===//
2262182Semaste//
3262182Semaste//                     The LLVM Compiler Infrastructure
4262182Semaste//
5262182Semaste// This file is distributed under the University of Illinois Open Source
6262182Semaste// License. See LICENSE.TXT for details.
7262182Semaste//
8262182Semaste//===----------------------------------------------------------------------===//
9262182Semaste
10262182Semaste#include "lldb/Target/SectionLoadHistory.h"
11262182Semaste
12262182Semaste// C Includes
13262182Semaste// C++ Includes
14262182Semaste// Other libraries and framework includes
15262182Semaste// Project includes
16262182Semaste#include "lldb/Core/Stream.h"
17262182Semaste#include "lldb/Target/SectionLoadList.h"
18262182Semaste
19262182Semasteusing namespace lldb;
20262182Semasteusing namespace lldb_private;
21262182Semaste
22262182Semaste
23262182Semastebool
24262182SemasteSectionLoadHistory::IsEmpty() const
25262182Semaste{
26262182Semaste    Mutex::Locker locker(m_mutex);
27262182Semaste    return m_stop_id_to_section_load_list.empty();
28262182Semaste}
29262182Semaste
30262182Semastevoid
31262182SemasteSectionLoadHistory::Clear ()
32262182Semaste{
33262182Semaste    Mutex::Locker locker(m_mutex);
34262182Semaste    m_stop_id_to_section_load_list.clear();
35262182Semaste}
36262182Semaste
37262182Semasteuint32_t
38262182SemasteSectionLoadHistory::GetLastStopID() const
39262182Semaste{
40262182Semaste    Mutex::Locker locker(m_mutex);
41262182Semaste    if (m_stop_id_to_section_load_list.empty())
42262182Semaste        return 0;
43262182Semaste    else
44262182Semaste        return m_stop_id_to_section_load_list.rbegin()->first;
45262182Semaste}
46262182Semaste
47262182SemasteSectionLoadList *
48262182SemasteSectionLoadHistory::GetSectionLoadListForStopID (uint32_t stop_id, bool read_only)
49262182Semaste{
50262182Semaste    if (m_stop_id_to_section_load_list.empty())
51262182Semaste    {
52262182Semaste        SectionLoadListSP section_load_list_sp(new SectionLoadList());
53262182Semaste        if (stop_id == eStopIDNow)
54262182Semaste            stop_id = 0;
55262182Semaste        m_stop_id_to_section_load_list[stop_id] = section_load_list_sp;
56262182Semaste        return section_load_list_sp.get();
57262182Semaste    }
58262182Semaste    else
59262182Semaste    {
60262182Semaste        if (read_only)
61262182Semaste        {
62262182Semaste            // The section load list is for reading data only so we don't need to create
63262182Semaste            // a new SectionLoadList for the current stop ID, just return the section
64262182Semaste            // load list for the stop ID that is equal to or less than the current stop ID
65262182Semaste            if (stop_id == eStopIDNow)
66262182Semaste            {
67262182Semaste                // If we are asking for the latest and greatest value, it is always
68262182Semaste                // at the end of our list becuase that will be the highest stop ID.
69262182Semaste                StopIDToSectionLoadList::reverse_iterator rpos = m_stop_id_to_section_load_list.rbegin();
70262182Semaste                return rpos->second.get();
71262182Semaste            }
72262182Semaste            else
73262182Semaste            {
74262182Semaste                StopIDToSectionLoadList::iterator pos = m_stop_id_to_section_load_list.lower_bound(stop_id);
75262182Semaste                if (pos != m_stop_id_to_section_load_list.end() && pos->first == stop_id)
76262182Semaste                    return pos->second.get();
77262182Semaste                else if (pos != m_stop_id_to_section_load_list.begin())
78262182Semaste                {
79262182Semaste                    --pos;
80262182Semaste                    return pos->second.get();
81262182Semaste                }
82262182Semaste            }
83262182Semaste        }
84262182Semaste        else
85262182Semaste        {
86262182Semaste            // You can only use "eStopIDNow" when reading from the section load history
87262182Semaste            assert(stop_id != eStopIDNow);
88262182Semaste
89262182Semaste            // We are updating the section load list (not read only), so if the stop ID
90262182Semaste            // passed in isn't the same as the last stop ID in our collection, then create
91262182Semaste            // a new node using the current stop ID
92262182Semaste            StopIDToSectionLoadList::iterator pos = m_stop_id_to_section_load_list.lower_bound(stop_id);
93262182Semaste            if (pos != m_stop_id_to_section_load_list.end() && pos->first == stop_id)
94262182Semaste            {
95262182Semaste                // We already have an entry for this value
96262182Semaste                return pos->second.get();
97262182Semaste            }
98262182Semaste
99262182Semaste            // We must make a new section load list that is based on the last valid
100262182Semaste            // section load list, so here we copy the last section load list and add
101262182Semaste            // a new node for the current stop ID.
102262182Semaste            StopIDToSectionLoadList::reverse_iterator rpos = m_stop_id_to_section_load_list.rbegin();
103262182Semaste            SectionLoadListSP section_load_list_sp(new SectionLoadList(*rpos->second.get()));
104262182Semaste            m_stop_id_to_section_load_list[stop_id] = section_load_list_sp;
105262182Semaste            return section_load_list_sp.get();
106262182Semaste        }
107262182Semaste    }
108262182Semaste    return NULL;
109262182Semaste}
110262182Semaste
111262182SemasteSectionLoadList &
112262182SemasteSectionLoadHistory::GetCurrentSectionLoadList ()
113262182Semaste{
114262182Semaste    const bool read_only = true;
115262182Semaste    SectionLoadList *section_load_list = GetSectionLoadListForStopID (eStopIDNow, read_only);
116262182Semaste    assert(section_load_list != NULL);
117262182Semaste    return *section_load_list;
118262182Semaste}
119262182Semaste
120262182Semasteaddr_t
121262182SemasteSectionLoadHistory::GetSectionLoadAddress (uint32_t stop_id, const lldb::SectionSP &section_sp)
122262182Semaste{
123262182Semaste    Mutex::Locker locker(m_mutex);
124262182Semaste    const bool read_only = true;
125262182Semaste    SectionLoadList *section_load_list = GetSectionLoadListForStopID (stop_id, read_only);
126262182Semaste    return section_load_list->GetSectionLoadAddress(section_sp);
127262182Semaste}
128262182Semaste
129262182Semastebool
130262182SemasteSectionLoadHistory::ResolveLoadAddress (uint32_t stop_id, addr_t load_addr, Address &so_addr)
131262182Semaste{
132262182Semaste    // First find the top level section that this load address exists in
133262182Semaste    Mutex::Locker locker(m_mutex);
134262182Semaste    const bool read_only = true;
135262182Semaste    SectionLoadList *section_load_list = GetSectionLoadListForStopID (stop_id, read_only);
136262182Semaste    return section_load_list->ResolveLoadAddress (load_addr, so_addr);
137262182Semaste}
138262182Semaste
139262182Semastebool
140262182SemasteSectionLoadHistory::SetSectionLoadAddress (uint32_t stop_id,
141262182Semaste                                           const lldb::SectionSP &section_sp,
142262182Semaste                                           addr_t load_addr,
143262182Semaste                                           bool warn_multiple)
144262182Semaste{
145262182Semaste    Mutex::Locker locker(m_mutex);
146262182Semaste    const bool read_only = false;
147262182Semaste    SectionLoadList *section_load_list = GetSectionLoadListForStopID (stop_id, read_only);
148262182Semaste    return section_load_list->SetSectionLoadAddress(section_sp, load_addr, warn_multiple);
149262182Semaste}
150262182Semaste
151262182Semastesize_t
152262182SemasteSectionLoadHistory::SetSectionUnloaded (uint32_t stop_id, const lldb::SectionSP &section_sp)
153262182Semaste{
154262182Semaste    Mutex::Locker locker(m_mutex);
155262182Semaste    const bool read_only = false;
156262182Semaste    SectionLoadList *section_load_list = GetSectionLoadListForStopID (stop_id, read_only);
157262182Semaste    return section_load_list->SetSectionUnloaded (section_sp);
158262182Semaste}
159262182Semaste
160262182Semastebool
161262182SemasteSectionLoadHistory::SetSectionUnloaded (uint32_t stop_id, const lldb::SectionSP &section_sp, addr_t load_addr)
162262182Semaste{
163262182Semaste    Mutex::Locker locker(m_mutex);
164262182Semaste    const bool read_only = false;
165262182Semaste    SectionLoadList *section_load_list = GetSectionLoadListForStopID (stop_id, read_only);
166262182Semaste    return section_load_list->SetSectionUnloaded (section_sp, load_addr);
167262182Semaste}
168262182Semaste
169262182Semastevoid
170262182SemasteSectionLoadHistory::Dump (Stream &s, Target *target)
171262182Semaste{
172262182Semaste    Mutex::Locker locker(m_mutex);
173262182Semaste    StopIDToSectionLoadList::iterator pos, end = m_stop_id_to_section_load_list.end();
174262182Semaste    for (pos = m_stop_id_to_section_load_list.begin(); pos != end; ++pos)
175262182Semaste    {
176262182Semaste        s.Printf("StopID = %u:\n", pos->first);
177262182Semaste        pos->second->Dump(s, target);
178262182Semaste        s.EOL();
179262182Semaste    }
180262182Semaste}
181262182Semaste
182262182Semaste
183