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