1 //===- SectionMap.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/Object/SectionMap.h"
10
11 #include "mcld/Fragment/NullFragment.h"
12 #include "mcld/LD/LDSection.h"
13 #include "mcld/LD/SectionData.h"
14 #include "mcld/Script/Assignment.h"
15 #include "mcld/Script/Operand.h"
16 #include "mcld/Script/Operator.h"
17 #include "mcld/Script/RpnExpr.h"
18 #include "mcld/Script/StringList.h"
19 #include "mcld/Script/WildcardPattern.h"
20
21 #include <llvm/Support/Casting.h>
22
23 #include <cassert>
24 #include <cstring>
25 #include <climits>
26 #if !defined(MCLD_ON_WIN32)
27 #include <fnmatch.h>
28 #define fnmatch0(pattern, string) (fnmatch(pattern, string, 0) == 0)
29 #else
30 #include <windows.h>
31 #include <shlwapi.h>
32 #define fnmatch0(pattern, string) (PathMatchSpec(string, pattern) == true)
33 #endif
34
35 namespace mcld {
36
37 //===----------------------------------------------------------------------===//
38 // SectionMap::Input
39 //===----------------------------------------------------------------------===//
Input(const std::string & pName,InputSectDesc::KeepPolicy pPolicy)40 SectionMap::Input::Input(const std::string& pName,
41 InputSectDesc::KeepPolicy pPolicy)
42 : m_Policy(pPolicy) {
43 m_Spec.m_pWildcardFile =
44 WildcardPattern::create("*", WildcardPattern::SORT_NONE);
45 m_Spec.m_pExcludeFiles = NULL;
46
47 StringList* sections = StringList::create();
48 sections->push_back(
49 WildcardPattern::create(pName, WildcardPattern::SORT_NONE));
50 m_Spec.m_pWildcardSections = sections;
51
52 m_pSection = LDSection::Create(pName, LDFileFormat::TEXT, 0, 0);
53 SectionData* sd = SectionData::Create(*m_pSection);
54 m_pSection->setSectionData(sd);
55 new NullFragment(sd);
56 new NullFragment(sd);
57 }
58
Input(const InputSectDesc & pInputDesc)59 SectionMap::Input::Input(const InputSectDesc& pInputDesc)
60 : m_Policy(pInputDesc.policy()) {
61 m_Spec.m_pWildcardFile = pInputDesc.spec().m_pWildcardFile;
62 m_Spec.m_pExcludeFiles = pInputDesc.spec().m_pExcludeFiles;
63 m_Spec.m_pWildcardSections = pInputDesc.spec().m_pWildcardSections;
64 m_pSection = LDSection::Create("", LDFileFormat::TEXT, 0, 0);
65 SectionData* sd = SectionData::Create(*m_pSection);
66 m_pSection->setSectionData(sd);
67 new NullFragment(sd);
68 new NullFragment(sd);
69 }
70
71 //===----------------------------------------------------------------------===//
72 // SectionMap::Output
73 //===----------------------------------------------------------------------===//
Output(const std::string & pName)74 SectionMap::Output::Output(const std::string& pName)
75 : m_Name(pName), m_Order(UINT_MAX) {
76 m_Prolog.m_pVMA = NULL;
77 m_Prolog.m_Type = OutputSectDesc::LOAD;
78 m_Prolog.m_pLMA = NULL;
79 m_Prolog.m_pAlign = NULL;
80 m_Prolog.m_pSubAlign = NULL;
81 m_Prolog.m_Constraint = OutputSectDesc::NO_CONSTRAINT;
82
83 m_Epilog.m_pRegion = NULL;
84 m_Epilog.m_pLMARegion = NULL;
85 m_Epilog.m_pPhdrs = NULL;
86 m_Epilog.m_pFillExp = NULL;
87
88 m_pSection = LDSection::Create(pName, LDFileFormat::TEXT, 0, 0);
89 SectionData* sd = SectionData::Create(*m_pSection);
90 m_pSection->setSectionData(sd);
91
92 m_bIsDiscard = pName.compare("/DISCARD/") == 0;
93 }
94
Output(const OutputSectDesc & pOutputDesc)95 SectionMap::Output::Output(const OutputSectDesc& pOutputDesc)
96 : m_Name(pOutputDesc.name()),
97 m_Prolog(pOutputDesc.prolog()),
98 m_Epilog(pOutputDesc.epilog()),
99 m_Order(UINT_MAX) {
100 m_pSection = LDSection::Create(m_Name, LDFileFormat::TEXT, 0, 0);
101 SectionData* sd = SectionData::Create(*m_pSection);
102 m_pSection->setSectionData(sd);
103
104 m_bIsDiscard = m_Name.compare("/DISCARD/") == 0;
105 }
106
hasContent() const107 bool SectionMap::Output::hasContent() const {
108 return m_pSection != NULL && m_pSection->size() != 0;
109 }
110
111 SectionMap::Output::const_dot_iterator
find_first_explicit_dot() const112 SectionMap::Output::find_first_explicit_dot() const {
113 for (const_dot_iterator it = dot_begin(), ie = dot_end(); it != ie; ++it) {
114 if ((*it).type() == Assignment::DEFAULT)
115 return it;
116 }
117 return dot_end();
118 }
119
find_first_explicit_dot()120 SectionMap::Output::dot_iterator SectionMap::Output::find_first_explicit_dot() {
121 for (dot_iterator it = dot_begin(), ie = dot_end(); it != ie; ++it) {
122 if ((*it).type() == Assignment::DEFAULT)
123 return it;
124 }
125 return dot_end();
126 }
127
128 SectionMap::Output::const_dot_iterator
find_last_explicit_dot() const129 SectionMap::Output::find_last_explicit_dot() const {
130 typedef DotAssignments::const_reverse_iterator CONST_RIT;
131 for (CONST_RIT rit = dotAssignments().rbegin(), rie = dotAssignments().rend();
132 rit != rie;
133 ++rit) {
134 if ((*rit).type() == Assignment::DEFAULT) {
135 return dot_begin() +
136 (dotAssignments().size() - (rit - dotAssignments().rbegin()) - 1);
137 }
138 }
139 return dot_end();
140 }
141
find_last_explicit_dot()142 SectionMap::Output::dot_iterator SectionMap::Output::find_last_explicit_dot() {
143 typedef DotAssignments::reverse_iterator RIT;
144 for (RIT rit = dotAssignments().rbegin(), rie = dotAssignments().rend();
145 rit != rie;
146 ++rit) {
147 if ((*rit).type() == Assignment::DEFAULT) {
148 return dot_begin() +
149 (dotAssignments().size() - (rit - dotAssignments().rbegin()) - 1);
150 }
151 }
152 return dot_end();
153 }
154
155 //===----------------------------------------------------------------------===//
156 // SectionMap
157 //===----------------------------------------------------------------------===//
~SectionMap()158 SectionMap::~SectionMap() {
159 iterator out, outBegin = begin(), outEnd = end();
160 for (out = outBegin; out != outEnd; ++out) {
161 if (*out != NULL) {
162 Output::iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end();
163 for (in = inBegin; in != inEnd; ++in) {
164 if (*in != NULL)
165 delete *in;
166 }
167 delete *out;
168 }
169 }
170 }
171
find(const std::string & pInputFile,const std::string & pInputSection) const172 SectionMap::const_mapping SectionMap::find(
173 const std::string& pInputFile,
174 const std::string& pInputSection) const {
175 const_iterator out, outBegin = begin(), outEnd = end();
176 for (out = outBegin; out != outEnd; ++out) {
177 Output::const_iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end();
178 for (in = inBegin; in != inEnd; ++in) {
179 if (matched(**in, pInputFile, pInputSection))
180 return std::make_pair(*out, *in);
181 }
182 }
183 return std::make_pair((const Output*)NULL, (const Input*)NULL);
184 }
185
find(const std::string & pInputFile,const std::string & pInputSection)186 SectionMap::mapping SectionMap::find(const std::string& pInputFile,
187 const std::string& pInputSection) {
188 iterator out, outBegin = begin(), outEnd = end();
189 for (out = outBegin; out != outEnd; ++out) {
190 Output::iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end();
191 for (in = inBegin; in != inEnd; ++in) {
192 if (matched(**in, pInputFile, pInputSection))
193 return std::make_pair(*out, *in);
194 }
195 }
196 return std::make_pair(reinterpret_cast<Output*>(NULL),
197 reinterpret_cast<Input*>(NULL));
198 }
199
find(const std::string & pOutputSection) const200 SectionMap::const_iterator SectionMap::find(
201 const std::string& pOutputSection) const {
202 const_iterator out, outBegin = begin(), outEnd = end();
203 for (out = outBegin; out != outEnd; ++out) {
204 if ((*out)->name().compare(pOutputSection) == 0)
205 return out;
206 }
207 return outEnd;
208 }
209
find(const std::string & pOutputSection)210 SectionMap::iterator SectionMap::find(const std::string& pOutputSection) {
211 iterator out, outBegin = begin(), outEnd = end();
212 for (out = outBegin; out != outEnd; ++out) {
213 if ((*out)->name().compare(pOutputSection) == 0)
214 return out;
215 }
216 return outEnd;
217 }
218
insert(const std::string & pInputSection,const std::string & pOutputSection,InputSectDesc::KeepPolicy pPolicy)219 std::pair<SectionMap::mapping, bool> SectionMap::insert(
220 const std::string& pInputSection,
221 const std::string& pOutputSection,
222 InputSectDesc::KeepPolicy pPolicy) {
223 iterator out, outBegin = begin(), outEnd = end();
224 for (out = outBegin; out != outEnd; ++out) {
225 if ((*out)->name().compare(pOutputSection) == 0)
226 break;
227 }
228 if (out != end()) {
229 Output::iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end();
230 for (in = inBegin; in != inEnd; ++in) {
231 if ((*in)->getSection()->name().compare(pInputSection) == 0)
232 break;
233 }
234
235 if (in != (*out)->end()) {
236 return std::make_pair(std::make_pair(*out, *in), false);
237 } else {
238 Input* input = new Input(pInputSection, pPolicy);
239 (*out)->append(input);
240 return std::make_pair(std::make_pair(*out, input), true);
241 }
242 }
243
244 Output* output = new Output(pOutputSection);
245 m_OutputDescList.push_back(output);
246 Input* input = new Input(pInputSection, pPolicy);
247 output->append(input);
248
249 return std::make_pair(std::make_pair(output, input), true);
250 }
251
insert(const InputSectDesc & pInputDesc,const OutputSectDesc & pOutputDesc)252 std::pair<SectionMap::mapping, bool> SectionMap::insert(
253 const InputSectDesc& pInputDesc,
254 const OutputSectDesc& pOutputDesc) {
255 iterator out, outBegin = begin(), outEnd = end();
256 for (out = outBegin; out != outEnd; ++out) {
257 if ((*out)->name().compare(pOutputDesc.name()) == 0 &&
258 (*out)->prolog() == pOutputDesc.prolog() &&
259 (*out)->epilog() == pOutputDesc.epilog())
260 break;
261 }
262
263 if (out != end()) {
264 Output::iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end();
265 for (in = inBegin; in != inEnd; ++in) {
266 if ((*in)->policy() == pInputDesc.policy() &&
267 (*in)->spec() == pInputDesc.spec())
268 break;
269 }
270
271 if (in != (*out)->end()) {
272 return std::make_pair(std::make_pair(*out, *in), false);
273 } else {
274 Input* input = new Input(pInputDesc);
275 (*out)->append(input);
276 return std::make_pair(std::make_pair(*out, input), true);
277 }
278 }
279
280 Output* output = new Output(pOutputDesc);
281 m_OutputDescList.push_back(output);
282 Input* input = new Input(pInputDesc);
283 output->append(input);
284
285 return std::make_pair(std::make_pair(output, input), true);
286 }
287
insert(iterator pPosition,LDSection * pSection)288 SectionMap::iterator SectionMap::insert(iterator pPosition,
289 LDSection* pSection) {
290 Output* output = new Output(pSection->name());
291 output->append(new Input(pSection->name(), InputSectDesc::NoKeep));
292 output->setSection(pSection);
293 return m_OutputDescList.insert(pPosition, output);
294 }
295
matched(const SectionMap::Input & pInput,const std::string & pInputFile,const std::string & pInputSection) const296 bool SectionMap::matched(const SectionMap::Input& pInput,
297 const std::string& pInputFile,
298 const std::string& pInputSection) const {
299 if (pInput.spec().hasFile() && !matched(pInput.spec().file(), pInputFile))
300 return false;
301
302 if (pInput.spec().hasExcludeFiles()) {
303 StringList::const_iterator file, fileEnd;
304 fileEnd = pInput.spec().excludeFiles().end();
305 for (file = pInput.spec().excludeFiles().begin(); file != fileEnd; ++file) {
306 if (matched(llvm::cast<WildcardPattern>(**file), pInputFile)) {
307 return false;
308 }
309 }
310 }
311
312 if (pInput.spec().hasSections()) {
313 StringList::const_iterator sect, sectEnd = pInput.spec().sections().end();
314 for (sect = pInput.spec().sections().begin(); sect != sectEnd; ++sect) {
315 if (matched(llvm::cast<WildcardPattern>(**sect), pInputSection)) {
316 return true;
317 }
318 }
319 }
320
321 return false;
322 }
323
matched(const WildcardPattern & pPattern,const std::string & pName) const324 bool SectionMap::matched(const WildcardPattern& pPattern,
325 const std::string& pName) const {
326 if (pPattern.isPrefix()) {
327 llvm::StringRef name(pName);
328 return name.startswith(pPattern.prefix());
329 } else {
330 return fnmatch0(pPattern.name().c_str(), pName.c_str());
331 }
332 }
333
334 // fixupDotSymbols - ensure the dot symbols are valid
fixupDotSymbols()335 void SectionMap::fixupDotSymbols() {
336 for (iterator it = begin() + 1, ie = end(); it != ie; ++it) {
337 // fixup the 1st explicit dot assignment if needed
338 if (!(*it)->dotAssignments().empty()) {
339 Output::dot_iterator dot = (*it)->find_first_explicit_dot();
340 if (dot != (*it)->dot_end() && (*dot).symbol().isDot() &&
341 (*dot).getRpnExpr().hasDot()) {
342 Assignment assign(Assignment::OUTPUT_SECTION,
343 Assignment::DEFAULT,
344 *SymOperand::create("."),
345 *RpnExpr::buildHelperExpr(it - 1));
346 Output::dot_iterator ref = (*it)->dotAssignments().insert(dot, assign);
347 for (RpnExpr::iterator tok = (*dot).getRpnExpr().begin(),
348 tokEnd = (*dot).getRpnExpr().end();
349 tok != tokEnd;
350 ++tok) {
351 if ((*tok)->kind() == ExprToken::OPERAND &&
352 llvm::cast<Operand>(*tok)->isDot())
353 *tok = &((*ref).symbol());
354 } // for each token in the RHS expr of the dot assignment
355 }
356 }
357
358 // fixup dot in output VMA if needed
359 if ((*it)->prolog().hasVMA() && (*it)->prolog().vma().hasDot()) {
360 Output::dot_iterator dot = (*it)->find_last_explicit_dot();
361 if (dot == (*it)->dot_end()) {
362 Assignment assign(Assignment::OUTPUT_SECTION,
363 Assignment::DEFAULT,
364 *SymOperand::create("."),
365 *RpnExpr::buildHelperExpr(it - 1));
366 dot = (*it)->dotAssignments().insert(dot, assign);
367 }
368 for (RpnExpr::iterator tok = (*it)->prolog().vma().begin(),
369 tokEnd = (*it)->prolog().vma().end();
370 tok != tokEnd;
371 ++tok) {
372 if ((*tok)->kind() == ExprToken::OPERAND &&
373 llvm::cast<Operand>(*tok)->isDot())
374 *tok = &((*dot).symbol());
375 } // for each token in the RHS expr of the dot assignment
376 }
377 } // for each output section
378 }
379
380 } // namespace mcld
381