MemoryArea.cpp revision 5460a1f25d9ddecb5c70667267d66d51af177a99
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 <llvm/Support/ErrorHandling.h>
105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Twine.h>
115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/RegionFactory.h>
135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/MemoryArea.h>
145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/MemoryRegion.h>
155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/FileSystem.h>
165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <cerrno>
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <fcntl.h>
195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <sys/mman.h>
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <sys/stat.h>
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===//
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// MemoryArea
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMemoryArea::MemoryArea(RegionFactory& pRegionFactory)
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  : m_RegionFactory(pRegionFactory),
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_FileDescriptor(-1),
295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_FileSize(0),
305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_AccessFlags(ReadOnly),
315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_State(BadBit) {
325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMemoryArea::~MemoryArea()
355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // truncate the file to real size
375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (isWritable())
385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    truncate(m_FileSize);
395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  unmap();
415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::truncate(size_t pLength)
445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (!isWritable())
465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return;
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (-1 == ::ftruncate(m_FileDescriptor, static_cast<off_t>(pLength))) {
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    llvm::report_fatal_error(llvm::Twine("Cannot truncate `") +
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             m_FilePath.native() +
515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             llvm::Twine("' to size: ") +
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             llvm::Twine(pLength) +
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             llvm::Twine(".\n"));
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::map(const sys::fs::Path& pPath, int pFlags)
585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_AccessFlags = pFlags;
605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_FilePath = pPath;
615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_FileDescriptor = ::open(m_FilePath.c_str(), m_AccessFlags);
625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (-1 == m_FileDescriptor) {
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_State |= FailBit;
655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    struct stat st;
685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int stat_result = ::stat(m_FilePath.native().c_str(), &st);
695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (0x0 == stat_result) {
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_FileSize = static_cast<size_t>(st.st_size);
715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_State = GoodBit;
725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else {
745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_FileSize = 0x0;
755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_State |= FailBit;
765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_State |= BadBit;
775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::map(const sys::fs::Path& pPath, int pFlags, int pMode)
825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_AccessFlags = pFlags;
845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_FilePath = pPath;
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_FileDescriptor = ::open(m_FilePath.c_str(), m_AccessFlags, pMode);
865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (-1 == m_FileDescriptor) {
885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_State |= FailBit;
895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    struct stat st;
925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int stat_result = ::stat(m_FilePath.native().c_str(), &st);
935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (0x0 == stat_result) {
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_FileSize = static_cast<size_t>(st.st_size);
955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_State = GoodBit;
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else {
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_FileSize = 0x0;
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_State |= FailBit;
1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_State |= BadBit;
1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::unmap()
1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (isMapped()) {
1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (-1 == ::close(m_FileDescriptor))
1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_State |= FailBit;
1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else {
1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_FileDescriptor = -1;
1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_AccessFlags = ReadOnly;
1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MemoryArea::isMapped() const
1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return (-1 != m_FileDescriptor);
1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MemoryArea::isGood() const
1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return 0x0 == (m_State & (BadBit | FailBit));
1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MemoryArea::isBad() const
1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return 0x0 != (m_State & BadBit);
1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MemoryArea::isFailed() const
1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return 0x0 != (m_State & FailBit);
1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MemoryArea::isEOF() const
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return 0x0 != (m_State & EOFBit);
1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MemoryArea::isReadable() const
1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return (((m_AccessFlags & AccessMask) == ReadOnly) ||
1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         ((m_AccessFlags & AccessMask) == ReadWrite));
1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MemoryArea::isWritable() const
1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return (((m_AccessFlags & AccessMask) == WriteOnly) ||
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         ((m_AccessFlags & AccessMask) == ReadWrite));
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoint MemoryArea::rdstate() const
1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return m_State;
1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::setState(MemoryArea::IOState pState)
1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_State |= pState;
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::clear(MemoryArea::IOState pState)
1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_State = pState;
1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// The layout of MemorySpace in the virtual memory space
1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// |  : page boundary
1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// [,]: MemoryRegion
1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// -  : fillment
1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// =  : data
1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// |---[=|====|====|==]--|
1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ^   ^              ^  ^
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// |   |              |  |
1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// | r_start      +r_len |
1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// space.data      +space.size
1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// space.file_offset is the offset of the mapped file segment from the start of
1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// the file. if the MemorySpace's type is ALLOCATED_ARRAY, the distances of
1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// (space.data, r_start) and (r_len, space.size) are zero.
1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMemoryRegion* MemoryArea::request(size_t pOffset, size_t pLength)
1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (!isMapped() || !isGood())
1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return NULL;
1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (0x0 == pLength)
1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return NULL;
1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (!isWritable() && (pOffset + pLength) > m_FileSize)
1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return NULL;
1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (isWritable() && (pOffset + pLength) > m_FileSize) {
1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // If the memory area is writable, user can expand the size of file by
1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // request a region larger than the file.
2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // MemoryArea should enlarge the file if the requested region is larger
2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // than the file.
2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_FileSize = page_boundary(pOffset + pLength + 1);
2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    truncate(m_FileSize);
2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Space* space = find(pOffset, pLength);
2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  MemoryArea::Address r_start = 0;
2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (NULL == space) {
2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // the space does not exist, create a new space.
2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    space = new Space(this, pOffset, pLength);
2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_SpaceList.push_back(space);
2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    switch(space->type = policy(pOffset, pLength)) {
2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      case Space::MMAPED: {
2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        int mm_prot, mm_flag;
2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        if (isWritable()) {
2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          mm_prot = PROT_READ | PROT_WRITE;
2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          mm_flag = MAP_FILE | MAP_SHARED;
2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        }
2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        else {
2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          mm_prot = PROT_READ;
2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          mm_flag = MAP_FILE | MAP_PRIVATE;
2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        }
2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        space->file_offset = page_offset(pOffset);
2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        // The space's size may be larger than filesize.
2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        space->size = page_boundary(pLength + pOffset + 1 - space->file_offset);
2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        space->data = (Address) ::mmap(NULL,
2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       space->size,
2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       mm_prot, mm_flag,
2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       m_FileDescriptor,
2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       space->file_offset);
2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        if (space->data == MAP_FAILED) {
2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          llvm::report_fatal_error(llvm::Twine("cannot open memory map file :") +
2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   m_FilePath.native() +
2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   llvm::Twine(" (") +
2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   sys::fs::detail::strerror(errno) +
2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   llvm::Twine(").\n"));
2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        }
2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        r_start = space->data + (pOffset - space->file_offset);
2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        break;
2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      case Space::ALLOCATED_ARRAY: {
2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        // space->offset and space->size are set in constructor. We only need
2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        // to set up data.
2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        space->data = new unsigned char[pLength];
2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        r_start = space->data;
2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        if ((m_AccessFlags & AccessMask) != WriteOnly) {
2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          // Read data from the backend file.
2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          if (!read(*space)) {
2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao            llvm::report_fatal_error(llvm::Twine("Failed to read data from ") +
2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                     m_FilePath.native() +
2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                     llvm::Twine(" (") +
2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                     sys::fs::detail::strerror(errno) +
2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                     llvm::Twine(") at offset ") +
2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                     llvm::Twine(pOffset) +
2595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                     llvm::Twine(" lenght ") +
2605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                     llvm::Twine(pLength) + llvm::Twine(".\n"));
2615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          }
2625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        }
2635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        break;
2645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      } // case
2655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      default: {
2665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        llvm::report_fatal_error("unhandled space type\n");
2675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    } // switch
2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else { // found
2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    off_t distance = pOffset - space->file_offset;
2725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    r_start = space->data + distance;
2735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // now, we have a legal space to hold the new MemoryRegion
2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return m_RegionFactory.produce(space, r_start, pLength);
2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// release - release a MemoryRegion
2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::release(MemoryRegion* pRegion)
2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (!isMapped() || !isGood())
2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return;
2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Space *space = pRegion->parent();
2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_RegionFactory.destruct(pRegion);
2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (0 == space->region_num) {
2895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    write(*space);
2905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_SpaceList.remove(*space);
2915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    release(space);
2925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::clean()
2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_RegionFactory.clear();
2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  SpaceList::iterator sIter, sEnd = m_SpaceList.end();
3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) {
3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    write(*sIter);
3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    release(sIter);
3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_SpaceList.clear();
3055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::sync()
3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  SpaceList::iterator sIter, sEnd = m_SpaceList.end();
3105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) {
3115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    write(*sIter);
3125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMemoryArea::Space* MemoryArea::find(size_t pOffset, size_t pLength)
3165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  SpaceList::iterator sIter, sEnd = m_SpaceList.end();
3185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) {
3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (sIter->file_offset <= pOffset &&
3205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao       (pOffset+pLength) <= (sIter->file_offset+sIter->size) ) { // within
3215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      return sIter;
3225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
3235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return NULL;
3255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::release(MemoryArea::Space* pSpace)
3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  switch (pSpace->type) {
3305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case Space::ALLOCATED_ARRAY: {
3315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      delete [] pSpace->data;
3325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
3345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case Space::MMAPED: {
3355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      ::munmap(pSpace->data, pSpace->size);
3365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
3375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    default:
3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMemoryArea::Space::Type MemoryArea::policy(off_t pOffset, size_t pLength)
3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  const size_t threshold = (PageSize*3)/4; // 3/4 page size in Linux
3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pLength < threshold)
3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return Space::ALLOCATED_ARRAY;
3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else
3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return Space::MMAPED;
3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaossize_t MemoryArea::readToBuffer(sys::fs::detail::Address pBuf,
3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                 size_t pSize, size_t pOffset) {
3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(((m_AccessFlags & AccessMask) != WriteOnly) &&
3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         "Write-only file cannot be read!");
3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ssize_t read_bytes = sys::fs::detail::pread(m_FileDescriptor, pBuf,
3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                              pSize, pOffset);
3595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (static_cast<size_t>(read_bytes) != pSize) {
3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // Some error occurred during pread().
3615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (read_bytes < 0) {
3625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_State |= FailBit;
3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
3645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else if (static_cast<size_t>(read_bytes) < pSize) {
3655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_State |= EOFBit;
3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      if ((m_AccessFlags & AccessMask) != ReadWrite) {
3675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        // Files which is not read-write are not allowed read beyonds the EOF
3685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        // marker.
3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        m_State |= BadBit;
3705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
3715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
3725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else {
3735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_State |= BadBit;
3745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
3755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return read_bytes;
3775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MemoryArea::read(Space& pSpace) {
3805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (!isGood() || !isReadable())
3815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return false;
3825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pSpace.type == Space::ALLOCATED_ARRAY) {
3845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    readToBuffer(pSpace.data, pSpace.size, pSpace.file_offset);
3855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return isGood();
3865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
3885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // Data associated with mmap()'ed space is already at the position the
3895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // pSpace points to.
3905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert((pSpace.type == Space::MMAPED) && "Unknown type of Space!");
3915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return true;
3925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MemoryArea::write(const Space& pSpace)
3975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (!isMapped() || !isGood() || !isWritable())
3995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return;
4005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  switch(pSpace.type) {
4025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case Space::MMAPED: {
4035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      if(-1 == ::msync(pSpace.data, pSpace.size, MS_SYNC))
4045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        m_State |= FailBit;
4055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      return;
4065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
4075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case Space::ALLOCATED_ARRAY: {
4085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      ssize_t write_bytes = sys::fs::detail::pwrite(m_FileDescriptor,
4095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                    pSpace.data,
4105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                    pSpace.size,
4115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                    pSpace.file_offset);
4125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      if (0 > write_bytes) {
4135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        m_State |= FailBit;
4145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        return;
4155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
4165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      if (0 == write_bytes && 0 != pSpace.size)
4175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        m_State |= BadBit;
4185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      if ( pSpace.size > static_cast<size_t>(write_bytes) )
4195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        m_State |= EOFBit;
4205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      return;
4215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
4225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    default:
4235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      return;
4245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
4255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
427