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(nullptr, nullptr);
197 }
198 
find(const std::string & pOutputSection) const199 SectionMap::const_iterator SectionMap::find(
200     const std::string& pOutputSection) const {
201   const_iterator out, outBegin = begin(), outEnd = end();
202   for (out = outBegin; out != outEnd; ++out) {
203     if ((*out)->name().compare(pOutputSection) == 0)
204       return out;
205   }
206   return outEnd;
207 }
208 
find(const std::string & pOutputSection)209 SectionMap::iterator SectionMap::find(const std::string& pOutputSection) {
210   iterator out, outBegin = begin(), outEnd = end();
211   for (out = outBegin; out != outEnd; ++out) {
212     if ((*out)->name().compare(pOutputSection) == 0)
213       return out;
214   }
215   return outEnd;
216 }
217 
insert(const std::string & pInputSection,const std::string & pOutputSection,InputSectDesc::KeepPolicy pPolicy)218 std::pair<SectionMap::mapping, bool> SectionMap::insert(
219     const std::string& pInputSection,
220     const std::string& pOutputSection,
221     InputSectDesc::KeepPolicy pPolicy) {
222   iterator out, outBegin = begin(), outEnd = end();
223   for (out = outBegin; out != outEnd; ++out) {
224     if ((*out)->name().compare(pOutputSection) == 0)
225       break;
226   }
227   if (out != end()) {
228     Output::iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end();
229     for (in = inBegin; in != inEnd; ++in) {
230       if ((*in)->getSection()->name().compare(pInputSection) == 0)
231         break;
232     }
233 
234     if (in != (*out)->end()) {
235       return std::make_pair(std::make_pair(*out, *in), false);
236     } else {
237       Input* input = new Input(pInputSection, pPolicy);
238       (*out)->append(input);
239       return std::make_pair(std::make_pair(*out, input), true);
240     }
241   }
242 
243   Output* output = new Output(pOutputSection);
244   m_OutputDescList.push_back(output);
245   Input* input = new Input(pInputSection, pPolicy);
246   output->append(input);
247 
248   return std::make_pair(std::make_pair(output, input), true);
249 }
250 
insert(const InputSectDesc & pInputDesc,const OutputSectDesc & pOutputDesc)251 std::pair<SectionMap::mapping, bool> SectionMap::insert(
252     const InputSectDesc& pInputDesc,
253     const OutputSectDesc& pOutputDesc) {
254   iterator out, outBegin = begin(), outEnd = end();
255   for (out = outBegin; out != outEnd; ++out) {
256     if ((*out)->name().compare(pOutputDesc.name()) == 0 &&
257         (*out)->prolog() == pOutputDesc.prolog() &&
258         (*out)->epilog() == pOutputDesc.epilog())
259       break;
260   }
261 
262   if (out != end()) {
263     Output::iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end();
264     for (in = inBegin; in != inEnd; ++in) {
265       if ((*in)->policy() == pInputDesc.policy() &&
266           (*in)->spec() == pInputDesc.spec())
267         break;
268     }
269 
270     if (in != (*out)->end()) {
271       return std::make_pair(std::make_pair(*out, *in), false);
272     } else {
273       Input* input = new Input(pInputDesc);
274       (*out)->append(input);
275       return std::make_pair(std::make_pair(*out, input), true);
276     }
277   }
278 
279   Output* output = new Output(pOutputDesc);
280   m_OutputDescList.push_back(output);
281   Input* input = new Input(pInputDesc);
282   output->append(input);
283 
284   return std::make_pair(std::make_pair(output, input), true);
285 }
286 
insert(iterator pPosition,LDSection * pSection)287 SectionMap::iterator SectionMap::insert(iterator pPosition,
288                                         LDSection* pSection) {
289   Output* output = new Output(pSection->name());
290   output->append(new Input(pSection->name(), InputSectDesc::NoKeep));
291   output->setSection(pSection);
292   return m_OutputDescList.insert(pPosition, output);
293 }
294 
matched(const SectionMap::Input & pInput,const std::string & pInputFile,const std::string & pInputSection) const295 bool SectionMap::matched(const SectionMap::Input& pInput,
296                          const std::string& pInputFile,
297                          const std::string& pInputSection) const {
298   if (pInput.spec().hasFile() && !matched(pInput.spec().file(), pInputFile))
299     return false;
300 
301   if (pInput.spec().hasExcludeFiles()) {
302     StringList::const_iterator file, fileEnd;
303     fileEnd = pInput.spec().excludeFiles().end();
304     for (file = pInput.spec().excludeFiles().begin(); file != fileEnd; ++file) {
305       if (matched(llvm::cast<WildcardPattern>(**file), pInputFile)) {
306         return false;
307       }
308     }
309   }
310 
311   if (pInput.spec().hasSections()) {
312     StringList::const_iterator sect, sectEnd = pInput.spec().sections().end();
313     for (sect = pInput.spec().sections().begin(); sect != sectEnd; ++sect) {
314       if (matched(llvm::cast<WildcardPattern>(**sect), pInputSection)) {
315         return true;
316       }
317     }
318   }
319 
320   return false;
321 }
322 
matched(const WildcardPattern & pPattern,const std::string & pName) const323 bool SectionMap::matched(const WildcardPattern& pPattern,
324                          const std::string& pName) const {
325   if (pPattern.isPrefix()) {
326     llvm::StringRef name(pName);
327     return name.startswith(pPattern.prefix());
328   } else {
329     return fnmatch0(pPattern.name().c_str(), pName.c_str());
330   }
331 }
332 
333 // fixupDotSymbols - ensure the dot symbols are valid
fixupDotSymbols()334 void SectionMap::fixupDotSymbols() {
335   for (iterator it = begin() + 1, ie = end(); it != ie; ++it) {
336     // fixup the 1st explicit dot assignment if needed
337     if (!(*it)->dotAssignments().empty()) {
338       Output::dot_iterator dot = (*it)->find_first_explicit_dot();
339       if (dot != (*it)->dot_end() && (*dot).symbol().isDot() &&
340           (*dot).getRpnExpr().hasDot()) {
341         Assignment assign(Assignment::OUTPUT_SECTION,
342                           Assignment::DEFAULT,
343                           *SymOperand::create("."),
344                           *RpnExpr::buildHelperExpr(it - 1));
345         Output::dot_iterator ref = (*it)->dotAssignments().insert(dot, assign);
346         for (RpnExpr::iterator tok = (*dot).getRpnExpr().begin(),
347                                tokEnd = (*dot).getRpnExpr().end();
348              tok != tokEnd;
349              ++tok) {
350           if ((*tok)->kind() == ExprToken::OPERAND &&
351               llvm::cast<Operand>(*tok)->isDot())
352             *tok = &((*ref).symbol());
353         }  // for each token in the RHS expr of the dot assignment
354       }
355     }
356 
357     // fixup dot in output VMA if needed
358     if ((*it)->prolog().hasVMA() && (*it)->prolog().vma().hasDot()) {
359       Output::dot_iterator dot = (*it)->find_last_explicit_dot();
360       if (dot == (*it)->dot_end()) {
361         Assignment assign(Assignment::OUTPUT_SECTION,
362                           Assignment::DEFAULT,
363                           *SymOperand::create("."),
364                           *RpnExpr::buildHelperExpr(it - 1));
365         dot = (*it)->dotAssignments().insert(dot, assign);
366       }
367       for (RpnExpr::iterator tok = (*it)->prolog().vma().begin(),
368                              tokEnd = (*it)->prolog().vma().end();
369            tok != tokEnd;
370            ++tok) {
371         if ((*tok)->kind() == ExprToken::OPERAND &&
372             llvm::cast<Operand>(*tok)->isDot())
373           *tok = &((*dot).symbol());
374       }  // for each token in the RHS expr of the dot assignment
375     }
376   }  // for each output section
377 }
378 
379 }  // namespace mcld
380