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