SectionLoadList.cpp revision 49480b158ee907f30afea651d2c81a67b5dbc971
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
24using namespace lldb;
25using namespace lldb_private;
26
27
28bool
29SectionLoadList::IsEmpty() const
30{
31    return m_section_load_info.IsEmpty();
32}
33
34void
35SectionLoadList::Clear ()
36{
37    m_section_load_info.Clear();
38}
39
40addr_t
41SectionLoadList::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
50bool
51SectionLoadList::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
76size_t
77SectionLoadList::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
99bool
100SectionLoadList::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
116bool
117SectionLoadList::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