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     return m_section_load_info.IsEmpty();
32 }
33 
34 void
35 SectionLoadList::Clear ()
36 {
37     m_section_load_info.Clear();
38 }
39 
40 addr_t
41 SectionLoadList::GetSectionLoadAddress (const Section *section) const
42 {
43     // TODO: add support for the same section having multiple load addresses
44     addr_t section_load_addr = LLDB_INVALID_ADDRESS;
45     if (m_section_load_info.GetFirstKeyForValue (section, section_load_addr))
46         return section_load_addr;
47     return LLDB_INVALID_ADDRESS;
48 }
49 
50 bool
51 SectionLoadList::SetSectionLoadAddress (const Section *section, addr_t load_addr)
52 {
53     Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_SHLIB | LIBLLDB_LOG_VERBOSE);
54 
55     if (log)
56         log->Printf ("SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16llx)",
57                      __FUNCTION__,
58                      section,
59                      section->GetModule()->GetFileSpec().GetFilename().AsCString(),
60                      section->GetName().AsCString(),
61                      load_addr);
62 
63 
64     const Section *existing_section = NULL;
65     Mutex::Locker locker(m_section_load_info.GetMutex());
66 
67     if (m_section_load_info.GetValueForKeyNoLock (load_addr, existing_section))
68     {
69         if (existing_section == section)
70             return false;   // No change
71     }
72     m_section_load_info.SetValueForKeyNoLock (load_addr, section);
73     return true;    // Changed
74 }
75 
76 size_t
77 SectionLoadList::SetSectionUnloaded (const Section *section)
78 {
79     Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_SHLIB | LIBLLDB_LOG_VERBOSE);
80 
81     if (log)
82         log->Printf ("SectionLoadList::%s (section = %p (%s.%s))",
83                      __FUNCTION__,
84                      section,
85                      section->GetModule()->GetFileSpec().GetFilename().AsCString(),
86                      section->GetName().AsCString());
87 
88     Mutex::Locker locker(m_section_load_info.GetMutex());
89 
90     size_t unload_count = 0;
91     addr_t section_load_addr;
92     while (m_section_load_info.GetFirstKeyForValueNoLock (section, section_load_addr))
93     {
94         unload_count += m_section_load_info.EraseNoLock (section_load_addr);
95     }
96     return unload_count;
97 }
98 
99 bool
100 SectionLoadList::SetSectionUnloaded (const Section *section, addr_t load_addr)
101 {
102     Log *log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_SHLIB | LIBLLDB_LOG_VERBOSE);
103 
104     if (log)
105         log->Printf ("SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16llx)",
106                      __FUNCTION__,
107                      section,
108                      section->GetModule()->GetFileSpec().GetFilename().AsCString(),
109                      section->GetName().AsCString(),
110                      load_addr);
111 
112     return m_section_load_info.Erase (load_addr) == 1;
113 }
114 
115 
116 bool
117 SectionLoadList::ResolveLoadAddress (addr_t load_addr, Address &so_addr) const
118 {
119     addr_t section_load_addr = LLDB_INVALID_ADDRESS;
120     const Section *section = NULL;
121 
122     // First find the top level section that this load address exists in
123     if (m_section_load_info.LowerBound (load_addr, section_load_addr, section, true))
124     {
125         addr_t offset = load_addr - section_load_addr;
126         if (offset < section->GetByteSize())
127         {
128             // We have found the top level section, now we need to find the
129             // deepest child section.
130             return section->ResolveContainedAddress (offset, so_addr);
131         }
132     }
133     so_addr.Clear();
134     return false;
135 }
136