• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- MemoryArea.cpp -----------------------------------------------------===//
2 //
3 //                     The MCLinker Project
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include <mcld/Support/MemoryArea.h>
10 #include <mcld/Support/Space.h>
11 #include <mcld/Support/MemoryRegion.h>
12 #include <mcld/Support/FileHandle.h>
13 #include <mcld/Support/MsgHandling.h>
14 
15 using namespace mcld;
16 
17 //===--------------------------------------------------------------------===//
18 // MemoryArea
19 //===--------------------------------------------------------------------===//
20 // MemoryArea - special constructor
21 // This constructor is used for *SPECIAL* situation. I'm sorry I can not
22 // reveal what is the special situation.
MemoryArea(Space & pUniverse)23 MemoryArea::MemoryArea(Space& pUniverse)
24   : m_pFileHandle(NULL) {
25   m_SpaceMap.insert(std::make_pair(Key(pUniverse.start(), pUniverse.size()),
26                                    &pUniverse));
27 }
28 
MemoryArea(FileHandle & pFileHandle)29 MemoryArea::MemoryArea(FileHandle& pFileHandle)
30   : m_pFileHandle(&pFileHandle) {
31 }
32 
~MemoryArea()33 MemoryArea::~MemoryArea()
34 {
35 }
36 
37 // The layout of MemorySpace in the virtual memory space
38 //
39 // |  : page boundary
40 // [,]: MemoryRegion
41 // -  : fillment
42 // =  : data
43 //
44 // |---[=|====|====|==]--|
45 // ^   ^              ^  ^
46 // |   |              |  |
47 // | r_start      +r_len |
48 // space.data      +space.size
49 //
50 // space.file_offset is the offset of the mapped file segment from the start of
51 // the file. if the MemorySpace's type is ALLOCATED_ARRAY, the distances of
52 // (space.data, r_start) and (r_len, space.size) are zero.
53 //
request(size_t pOffset,size_t pLength)54 MemoryRegion* MemoryArea::request(size_t pOffset, size_t pLength)
55 {
56   Space* space = find(pOffset, pLength);
57   if (NULL == space) {
58     // not found
59     if (NULL == m_pFileHandle) {
60       // if m_pFileHandle is NULL, clients delegate us an universal Space and
61       // we never remove it. In that way, space can not be NULL.
62       unreachable(diag::err_out_of_range_region) << pOffset << pLength;
63     }
64 
65     space = Space::Create(*m_pFileHandle, pOffset, pLength);
66     m_SpaceMap.insert(std::make_pair(Key(space->start(), space->size()), space));
67   }
68 
69   // adjust r_start
70   off_t distance = pOffset - space->start();
71   void* r_start = space->memory() + distance;
72 
73   // now, we have a legal space to hold the new MemoryRegion
74   return MemoryRegion::Create(r_start, pLength, *space);
75 }
76 
77 // release - release a MemoryRegion
release(MemoryRegion * pRegion)78 void MemoryArea::release(MemoryRegion* pRegion)
79 {
80   if (NULL == pRegion)
81     return;
82 
83   Space *space = pRegion->parent();
84   MemoryRegion::Destroy(pRegion);
85 
86   if (0 == space->numOfRegions()) {
87 
88     if (NULL != m_pFileHandle) {
89       // if m_pFileHandle is NULL, clients delegate us an universal Space and
90       // we never remove it. Otherwise, we have to synchronize and release
91       // Space.
92       if (m_pFileHandle->isWritable()) {
93         // synchronize writable space before we release it.
94         Space::Sync(space, *m_pFileHandle);
95       }
96 
97       std::pair<SpaceMapType::iterator, SpaceMapType::iterator> range =
98         m_SpaceMap.equal_range(Key(space->start(), space->size()));
99       SpaceMapType::iterator it;
100       for (it = range.first; it != range.second; ++it) {
101         if (space == it->second)
102           break;
103       }
104       m_SpaceMap.erase(it);
105 
106       Space::Release(space, *m_pFileHandle);
107       assert(NULL != space);
108       Space::Destroy(space);
109     }
110   }
111 }
112 
113 // clear - release all MemoryRegions
clear()114 void MemoryArea::clear()
115 {
116   if (NULL == m_pFileHandle)
117     return;
118 
119   SpaceMapType::iterator space, sEnd = m_SpaceMap.end();
120   if (m_pFileHandle->isWritable()) {
121     for (space = m_SpaceMap.begin(); space != sEnd; ++space) {
122       Space::Sync(space->second, *m_pFileHandle);
123       Space::Release(space->second, *m_pFileHandle);
124       assert(NULL != space->second);
125       Space::Destroy(space->second);
126     }
127   }
128   else {
129     for (space = m_SpaceMap.begin(); space != sEnd; ++space) {
130       Space::Release(space->second, *m_pFileHandle);
131       assert(NULL != space->second);
132       Space::Destroy(space->second);
133     }
134   }
135 
136   m_SpaceMap.clear();
137 }
138 
139 //===--------------------------------------------------------------------===//
140 // SpaceList methods
141 //===--------------------------------------------------------------------===//
find(size_t pOffset,size_t pLength)142 Space* MemoryArea::find(size_t pOffset, size_t pLength)
143 {
144   SpaceMapType::iterator it = m_SpaceMap.find(Key(pOffset, pLength));
145   if (it != m_SpaceMap.end())
146     return it->second;
147 
148   return NULL;
149 }
150 
find(size_t pOffset,size_t pLength) const151 const Space* MemoryArea::find(size_t pOffset, size_t pLength) const
152 {
153   SpaceMapType::const_iterator it = m_SpaceMap.find(Key(pOffset, pLength));
154   if (it != m_SpaceMap.end())
155     return it->second;
156 
157   return NULL;
158 }
159 
160