MemoryArea.cpp revision 22add6ff3426df1a85089fe6a6e1597ee3b6f300
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 SpaceMapType::iterator space, sEnd = m_SpaceMap.end(); 36 for (space = m_SpaceMap.begin(); space != sEnd; ++space) { 37 if (space->second != NULL) 38 Space::Destroy(space->second); 39 } 40} 41 42// The layout of MemorySpace in the virtual memory space 43// 44// | : page boundary 45// [,]: MemoryRegion 46// - : fillment 47// = : data 48// 49// |---[=|====|====|==]--| 50// ^ ^ ^ ^ 51// | | | | 52// | r_start +r_len | 53// space.data +space.size 54// 55// space.file_offset is the offset of the mapped file segment from the start of 56// the file. if the MemorySpace's type is ALLOCATED_ARRAY, the distances of 57// (space.data, r_start) and (r_len, space.size) are zero. 58// 59MemoryRegion* MemoryArea::request(size_t pOffset, size_t pLength) 60{ 61 Space* space = find(pOffset, pLength); 62 if (NULL == space) { 63 // not found 64 if (NULL == m_pFileHandle) { 65 // if m_pFileHandle is NULL, clients delegate us an universal Space and 66 // we never remove it. In that way, space can not be NULL. 67 unreachable(diag::err_out_of_range_region) << pOffset << pLength; 68 } 69 70 space = Space::Create(*m_pFileHandle, pOffset, pLength); 71 m_SpaceMap.insert(std::make_pair(Key(pOffset, pLength), space)); 72 } 73 74 // adjust r_start 75 off_t distance = pOffset - space->start(); 76 void* r_start = space->memory() + distance; 77 78 // now, we have a legal space to hold the new MemoryRegion 79 return MemoryRegion::Create(r_start, pLength, *space); 80} 81 82// release - release a MemoryRegion 83void MemoryArea::release(MemoryRegion* pRegion) 84{ 85 if (NULL == pRegion) 86 return; 87 88 Space *space = pRegion->parent(); 89 MemoryRegion::Destroy(pRegion); 90 91 if (0 == space->numOfRegions()) { 92 93 if (NULL != m_pFileHandle) { 94 // if m_pFileHandle is NULL, clients delegate us an universal Space and 95 // we never remove it. Otherwise, we have to synchronize and release 96 // Space. 97 if (m_pFileHandle->isWritable()) { 98 // synchronize writable space before we release it. 99 Space::Sync(space, *m_pFileHandle); 100 } 101 m_SpaceMap.erase(Key(space->start(), space->size())); 102 Space::Release(space, *m_pFileHandle); 103 } 104 } 105} 106 107// clear - release all MemoryRegions 108void MemoryArea::clear() 109{ 110 if (NULL == m_pFileHandle) 111 return; 112 113 if (m_pFileHandle->isWritable()) { 114 SpaceMapType::iterator space, sEnd = m_SpaceMap.end(); 115 for (space = m_SpaceMap.begin(); space != sEnd; ++space) { 116 Space::Sync(space->second, *m_pFileHandle); 117 Space::Release(space->second, *m_pFileHandle); 118 } 119 } 120 else { 121 SpaceMapType::iterator space, sEnd = m_SpaceMap.end(); 122 for (space = m_SpaceMap.begin(); space != sEnd; ++space) 123 Space::Release(space->second, *m_pFileHandle); 124 } 125 126 for (SpaceMapType::iterator space = m_SpaceMap.begin(), 127 sEnd = m_SpaceMap.end(); space != sEnd; ++space) { 128 if (space->second != NULL) 129 Space::Destroy(space->second); 130 } 131 m_SpaceMap.clear(); 132} 133 134//===--------------------------------------------------------------------===// 135// SpaceList methods 136//===--------------------------------------------------------------------===// 137Space* MemoryArea::find(size_t pOffset, size_t pLength) 138{ 139 SpaceMapType::iterator it = m_SpaceMap.find(Key(pOffset, pLength)); 140 if (it != m_SpaceMap.end()) 141 return it->second; 142 143 return NULL; 144} 145 146const Space* MemoryArea::find(size_t pOffset, size_t pLength) const 147{ 148 SpaceMapType::const_iterator it = m_SpaceMap.find(Key(pOffset, pLength)); 149 if (it != m_SpaceMap.end()) 150 return it->second; 151 152 return NULL; 153} 154 155