1 //===-- SectionLoadList.cpp -------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Target/SectionLoadList.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project 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"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 
27 
28 bool
29 SectionLoadList::IsEmpty() const
30 {
31     Mutex::Locker locker(m_mutex);
32     return m_collection.empty();
33 }
34 
35 void
36 SectionLoadList::Clear ()
37 {
38     Mutex::Locker locker(m_mutex);
39     return m_collection.clear();
40 }
41 
42 addr_t
43 SectionLoadList::GetSectionLoadAddress (const Section *section) const
44 {
45     // TODO: add support for the same section having multiple load addresses
46     addr_t section_load_addr = LLDB_INVALID_ADDRESS;
47     if (section)
48     {
49         Mutex::Locker locker(m_mutex);
50         collection::const_iterator pos, end = m_collection.end();
51         for (pos = m_collection.begin(); pos != end; ++pos)
52         {
53             const addr_t pos_load_addr = pos->first;
54             const Section *pos_section = pos->second;
55             if (pos_section == section)
56             {
57                 section_load_addr = pos_load_addr;
58                 break;
59             }
60         }
61     }
62     return section_load_addr;
63 }
64 
65 bool
66 SectionLoadList::SetSectionLoadAddress (const Section *section, addr_t load_addr)
67 {
68     LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));
69 
70     if (log)
71     {
72         const FileSpec &module_file_spec (section->GetModule()->GetFileSpec());
73         log->Printf ("SectionLoadList::%s (section = %p (%s%s%s.%s), load_addr = 0x%16.16llx)",
74                      __FUNCTION__,
75                      section,
76                      module_file_spec.GetDirectory().AsCString(),
77                      module_file_spec.GetDirectory() ? "/" : "",
78                      module_file_spec.GetFilename().AsCString(),
79                      section->GetName().AsCString(),
80                      load_addr);
81     }
82 
83     Mutex::Locker locker(m_mutex);
84     collection::iterator pos = m_collection.find(load_addr);
85     if (pos != m_collection.end())
86     {
87         if (section == pos->second)
88             return false; // No change...
89         else
90             pos->second = section;
91     }
92     else
93     {
94         m_collection[load_addr] = section;
95     }
96     return true;    // Changed
97 }
98 
99 size_t
100 SectionLoadList::SetSectionUnloaded (const Section *section)
101 {
102     LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));
103 
104     if (log)
105     {
106         const FileSpec &module_file_spec (section->GetModule()->GetFileSpec());
107         log->Printf ("SectionLoadList::%s (section = %p (%s%s%s.%s))",
108                      __FUNCTION__,
109                      section,
110                      module_file_spec.GetDirectory().AsCString(),
111                      module_file_spec.GetDirectory() ? "/" : "",
112                      module_file_spec.GetFilename().AsCString(),
113                      section->GetName().AsCString());
114     }
115 
116     size_t unload_count = 0;
117     Mutex::Locker locker(m_mutex);
118     bool erased = false;
119     do
120     {
121         erased = false;
122         for (collection::iterator pos = m_collection.begin(); pos != m_collection.end(); ++pos)
123         {
124             if (pos->second == section)
125             {
126                 m_collection.erase(pos);
127                 erased = true;
128             }
129         }
130     } while (erased);
131 
132     return unload_count;
133 }
134 
135 bool
136 SectionLoadList::SetSectionUnloaded (const Section *section, addr_t load_addr)
137 {
138     LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));
139 
140     if (log)
141     {
142         const FileSpec &module_file_spec (section->GetModule()->GetFileSpec());
143         log->Printf ("SectionLoadList::%s (section = %p (%s%s%s.%s), load_addr = 0x%16.16llx)",
144                      __FUNCTION__,
145                      section,
146                      module_file_spec.GetDirectory().AsCString(),
147                      module_file_spec.GetDirectory() ? "/" : "",
148                      module_file_spec.GetFilename().AsCString(),
149                      section->GetName().AsCString(),
150                      load_addr);
151     }
152     Mutex::Locker locker(m_mutex);
153     return m_collection.erase (load_addr) != 0;
154 }
155 
156 
157 bool
158 SectionLoadList::ResolveLoadAddress (addr_t load_addr, Address &so_addr) const
159 {
160     // First find the top level section that this load address exists in
161     Mutex::Locker locker(m_mutex);
162     collection::const_iterator pos = m_collection.lower_bound (load_addr);
163     if (pos != m_collection.end())
164     {
165         if (load_addr != pos->first && pos != m_collection.begin())
166             --pos;
167         if (load_addr >= pos->first)
168         {
169             addr_t offset = load_addr - pos->first;
170             if (offset < pos->second->GetByteSize())
171             {
172                 // We have found the top level section, now we need to find the
173                 // deepest child section.
174                 return pos->second->ResolveContainedAddress (offset, so_addr);
175             }
176         }
177     }
178     so_addr.Clear();
179     return false;
180 }
181 
182 void
183 SectionLoadList::Dump (Stream &s, Target *target)
184 {
185     Mutex::Locker locker(m_mutex);
186     collection::const_iterator pos, end;
187     for (pos = m_collection.begin(), end = m_collection.end(); pos != end; ++pos)
188     {
189         s.Printf("addr = 0x%16.16llx, section = %p: ", pos->first, pos->second);
190         pos->second->Dump (&s, target, 0);
191     }
192 }
193 
194 
195