//===- MemoryAreaFactory.cpp ----------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include <mcld/Support/MemoryAreaFactory.h> #include <mcld/Support/MsgHandling.h> #include <mcld/Support/RegionFactory.h> #include <mcld/Support/SystemUtils.h> #include <mcld/Support/Space.h> using namespace mcld; //===----------------------------------------------------------------------===// // MemoryAreaFactory MemoryAreaFactory::MemoryAreaFactory(size_t pNum) : GCFactory<MemoryArea, 0>(pNum) { // For each loaded file, MCLinker must load ELF header, section header, // symbol table, and string table. So, we set the size of chunk quadruple // larger than the number of input files. m_pRegionFactory = new RegionFactory(pNum*4); } MemoryAreaFactory::~MemoryAreaFactory() { HandleToArea::iterator rec, rEnd = m_HandleToArea.end(); for (rec = m_HandleToArea.begin(); rec != rEnd; ++rec) { if (rec->handle->isOpened()) { rec->handle->close(); } delete rec->handle; } delete m_pRegionFactory; } MemoryArea* MemoryAreaFactory::produce(const sys::fs::Path& pPath, FileHandle::OpenMode pMode) { HandleToArea::Result map_result = m_HandleToArea.findFirst(pPath); if (NULL == map_result.area) { // can not found FileHandle* handler = new FileHandle(); if (!handler->open(pPath, pMode)) { error(diag::err_cannot_open_file) << pPath << sys::strerror(handler->error()); } MemoryArea* result = allocate(); new (result) MemoryArea(*m_pRegionFactory, *handler); m_HandleToArea.push_back(handler, result); return result; } return map_result.area; } MemoryArea* MemoryAreaFactory::produce(const sys::fs::Path& pPath, FileHandle::OpenMode pMode, FileHandle::Permission pPerm) { HandleToArea::Result map_result = m_HandleToArea.findFirst(pPath); if (NULL == map_result.area) { // can not found FileHandle* handler = new FileHandle(); if (!handler->open(pPath, pMode, pPerm)) { error(diag::err_cannot_open_file) << pPath << sys::strerror(handler->error()); } MemoryArea* result = allocate(); new (result) MemoryArea(*m_pRegionFactory, *handler); m_HandleToArea.push_back(handler, result); return result; } return map_result.area; } void MemoryAreaFactory::destruct(MemoryArea* pArea) { m_HandleToArea.erase(pArea); pArea->clear(); pArea->handler()->close(); destroy(pArea); deallocate(pArea); } MemoryArea* MemoryAreaFactory::create(void* pMemBuffer, size_t pSize) { Space* space = new Space(Space::EXTERNAL, pMemBuffer, pSize); MemoryArea* result = allocate(); new (result) MemoryArea(*m_pRegionFactory, *space); return result; } MemoryArea* MemoryAreaFactory::create(int pFD, FileHandle::OpenMode pMode) { FileHandle* handler = new FileHandle(); handler->delegate(pFD, pMode); MemoryArea* result = allocate(); new (result) MemoryArea(*m_pRegionFactory, *handler); return result; }