MemoryArea.cpp revision 6f75755c9204b1d8817ae5a65a2f7e5af0ec3f70
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 15using 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. 23MemoryArea::MemoryArea(Space& pUniverse) 24 : m_pFileHandle(NULL) { 25 m_SpaceMap.insert(std::make_pair(Key(pUniverse.start(), pUniverse.size()), 26 &pUniverse)); 27} 28 29MemoryArea::MemoryArea(FileHandle& pFileHandle) 30 : m_pFileHandle(&pFileHandle) { 31} 32 33MemoryArea::~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// 54MemoryRegion* 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 78void 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 114void 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//===--------------------------------------------------------------------===// 142Space* 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 151const 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