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