15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- MemoryArea.cpp -----------------------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/MemoryArea.h>
1022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Support/Space.h>
115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/MemoryRegion.h>
12affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/FileHandle.h>
13affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===//
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// MemoryArea
1967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
20affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// MemoryArea - special constructor
21affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// This constructor is used for *SPECIAL* situation. I'm sorry I can not
22affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// reveal what is the special situation.
2322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoMemoryArea::MemoryArea(Space& pUniverse)
2422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  : m_pFileHandle(NULL) {
2522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  m_SpaceMap.insert(std::make_pair(Key(pUniverse.start(), pUniverse.size()),
2622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                   &pUniverse));
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoMemoryArea::MemoryArea(FileHandle& pFileHandle)
3022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  : m_pFileHandle(&pFileHandle) {
315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
33affc150dc44fab1911775a49636d0ce85333b634Zonr ChangMemoryArea::~MemoryArea()
345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// The layout of MemorySpace in the virtual memory space
385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// |  : page boundary
405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// [,]: MemoryRegion
415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// -  : fillment
425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// =  : data
435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// |---[=|====|====|==]--|
455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ^   ^              ^  ^
465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// |   |              |  |
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// | r_start      +r_len |
485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// space.data      +space.size
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// space.file_offset is the offset of the mapped file segment from the start of
515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// the file. if the MemorySpace's type is ALLOCATED_ARRAY, the distances of
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// (space.data, r_start) and (r_len, space.size) are zero.
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMemoryRegion* MemoryArea::request(size_t pOffset, size_t pLength)
555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Space* space = find(pOffset, pLength);
575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (NULL == space) {
58affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // not found
59affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (NULL == m_pFileHandle) {
60affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      // if m_pFileHandle is NULL, clients delegate us an universal Space and
61affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      // we never remove it. In that way, space can not be NULL.
6267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao      unreachable(diag::err_out_of_range_region) << pOffset << pLength;
63affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    space = Space::Create(*m_pFileHandle, pOffset, pLength);
666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_SpaceMap.insert(std::make_pair(Key(space->start(), space->size()), space));
675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
69affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // adjust r_start
70affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  off_t distance = pOffset - space->start();
71affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  void* r_start = space->memory() + distance;
72affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // now, we have a legal space to hold the new MemoryRegion
7422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return MemoryRegion::Create(r_start, pLength, *space);
755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// release - release a MemoryRegion
785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::release(MemoryRegion* pRegion)
795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
80affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (NULL == pRegion)
815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return;
825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Space *space = pRegion->parent();
8422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  MemoryRegion::Destroy(pRegion);
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
86affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (0 == space->numOfRegions()) {
87affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
88affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (NULL != m_pFileHandle) {
89affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      // if m_pFileHandle is NULL, clients delegate us an universal Space and
90affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      // we never remove it. Otherwise, we have to synchronize and release
91affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      // Space.
92affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      if (m_pFileHandle->isWritable()) {
93affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        // synchronize writable space before we release it.
9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        Space::Sync(space, *m_pFileHandle);
95affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      std::pair<SpaceMapType::iterator, SpaceMapType::iterator> range =
986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        m_SpaceMap.equal_range(Key(space->start(), space->size()));
996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      SpaceMapType::iterator it;
1006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      for (it = range.first; it != range.second; ++it) {
1016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        if (space == it->second)
1026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines          break;
1036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      }
1046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_SpaceMap.erase(it);
1056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      Space::Release(space, *m_pFileHandle);
1076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      assert(NULL != space);
1086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      Space::Destroy(space);
109affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
113affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// clear - release all MemoryRegions
114affc150dc44fab1911775a49636d0ce85333b634Zonr Changvoid MemoryArea::clear()
1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
116affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (NULL == m_pFileHandle)
117affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return;
1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  SpaceMapType::iterator space, sEnd = m_SpaceMap.end();
120affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (m_pFileHandle->isWritable()) {
12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    for (space = m_SpaceMap.begin(); space != sEnd; ++space) {
12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      Space::Sync(space->second, *m_pFileHandle);
12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      Space::Release(space->second, *m_pFileHandle);
1246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      assert(NULL != space->second);
1256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      Space::Destroy(space->second);
126affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
128affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  else {
1296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    for (space = m_SpaceMap.begin(); space != sEnd; ++space) {
13022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      Space::Release(space->second, *m_pFileHandle);
1316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      assert(NULL != space->second);
13222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      Space::Destroy(space->second);
1336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
1356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
13622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  m_SpaceMap.clear();
1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
139affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===--------------------------------------------------------------------===//
140affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// SpaceList methods
14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===--------------------------------------------------------------------===//
142affc150dc44fab1911775a49636d0ce85333b634Zonr ChangSpace* MemoryArea::find(size_t pOffset, size_t pLength)
1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
144f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  std::pair<SpaceMapType::iterator, SpaceMapType::iterator> range =
145f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_SpaceMap.equal_range(Key(pOffset, pLength));
146f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  SpaceMapType::iterator it;
147f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  for (it = range.first; it != range.second; ++it) {
148f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if ((it->second->start() <= pOffset) &&
149f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        ((pOffset + pLength) <= (it->second->start() + it->second->size())))
150f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return it->second;
151f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return NULL;
1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
155affc150dc44fab1911775a49636d0ce85333b634Zonr Changconst Space* MemoryArea::find(size_t pOffset, size_t pLength) const
1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
157f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  std::pair<SpaceMapType::const_iterator, SpaceMapType::const_iterator> range =
158f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_SpaceMap.equal_range(Key(pOffset, pLength));
159f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  SpaceMapType::const_iterator it;
160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  for (it = range.first; it != range.second; ++it) {
161f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if ((it->second->start() <= pOffset) &&
162f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        ((pOffset + pLength) <= (it->second->start() + it->second->size())))
163f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return it->second;
164f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
165affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return NULL;
1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
168