1 //===- MemoryAreaFactory.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/MemoryAreaFactory.h>
10 #include <mcld/Support/MsgHandling.h>
11 #include <mcld/Support/RegionFactory.h>
12 #include <mcld/Support/SystemUtils.h>
13 #include <mcld/Support/Space.h>
14
15 using namespace mcld;
16
17 //===----------------------------------------------------------------------===//
18 // MemoryAreaFactory
MemoryAreaFactory(size_t pNum)19 MemoryAreaFactory::MemoryAreaFactory(size_t pNum)
20 : GCFactory<MemoryArea, 0>(pNum) {
21 // For each loaded file, MCLinker must load ELF header, section header,
22 // symbol table, and string table. So, we set the size of chunk quadruple
23 // larger than the number of input files.
24 m_pRegionFactory = new RegionFactory(pNum*4);
25 }
26
~MemoryAreaFactory()27 MemoryAreaFactory::~MemoryAreaFactory()
28 {
29 HandleToArea::iterator rec, rEnd = m_HandleToArea.end();
30 for (rec = m_HandleToArea.begin(); rec != rEnd; ++rec) {
31 if (rec->handle->isOpened()) {
32 rec->handle->close();
33 }
34 delete rec->handle;
35 }
36
37 delete m_pRegionFactory;
38 }
39
40 MemoryArea*
produce(const sys::fs::Path & pPath,FileHandle::OpenMode pMode)41 MemoryAreaFactory::produce(const sys::fs::Path& pPath,
42 FileHandle::OpenMode pMode)
43 {
44 HandleToArea::Result map_result = m_HandleToArea.findFirst(pPath);
45 if (NULL == map_result.area) {
46 // can not found
47 FileHandle* handler = new FileHandle();
48 if (!handler->open(pPath, pMode)) {
49 error(diag::err_cannot_open_file) << pPath
50 << sys::strerror(handler->error());
51 }
52
53 MemoryArea* result = allocate();
54 new (result) MemoryArea(*m_pRegionFactory, *handler);
55
56 m_HandleToArea.push_back(handler, result);
57 return result;
58 }
59
60 return map_result.area;
61 }
62
63 MemoryArea*
produce(const sys::fs::Path & pPath,FileHandle::OpenMode pMode,FileHandle::Permission pPerm)64 MemoryAreaFactory::produce(const sys::fs::Path& pPath,
65 FileHandle::OpenMode pMode,
66 FileHandle::Permission pPerm)
67 {
68 HandleToArea::Result map_result = m_HandleToArea.findFirst(pPath);
69 if (NULL == map_result.area) {
70 // can not found
71 FileHandle* handler = new FileHandle();
72 if (!handler->open(pPath, pMode, pPerm)) {
73 error(diag::err_cannot_open_file) << pPath
74 << sys::strerror(handler->error());
75 }
76
77 MemoryArea* result = allocate();
78 new (result) MemoryArea(*m_pRegionFactory, *handler);
79
80 m_HandleToArea.push_back(handler, result);
81 return result;
82 }
83
84 return map_result.area;
85 }
86
destruct(MemoryArea * pArea)87 void MemoryAreaFactory::destruct(MemoryArea* pArea)
88 {
89 m_HandleToArea.erase(pArea);
90 pArea->clear();
91 pArea->handler()->close();
92 destroy(pArea);
93 deallocate(pArea);
94 }
95
96 MemoryArea*
create(void * pMemBuffer,size_t pSize)97 MemoryAreaFactory::create(void* pMemBuffer, size_t pSize)
98 {
99 Space* space = new Space(Space::EXTERNAL, pMemBuffer, pSize);
100 MemoryArea* result = allocate();
101 new (result) MemoryArea(*m_pRegionFactory, *space);
102 return result;
103 }
104
105 MemoryArea*
create(int pFD,FileHandle::OpenMode pMode)106 MemoryAreaFactory::create(int pFD, FileHandle::OpenMode pMode)
107 {
108 FileHandle* handler = new FileHandle();
109 handler->delegate(pFD, pMode);
110
111 MemoryArea* result = allocate();
112 new (result) MemoryArea(*m_pRegionFactory, *handler);
113
114 return result;
115 }
116
117