blob: 9cba89559975a381918fd7efc044e4e24e06126d [file] [log] [blame]
Shih-wei Liao22add6f2012-12-15 17:21:00 -08001//===- 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//===----------------------------------------------------------------------===//
Stephen Hines37b74a32014-11-26 18:48:20 -08009#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
Stephen Hines87f34652014-02-14 18:00:16 -080021#include <llvm/Support/Casting.h>
Stephen Hines37b74a32014-11-26 18:48:20 -080022
Shih-wei Liao22add6f2012-12-15 17:21:00 -080023#include <cassert>
24#include <cstring>
Stephen Hines87f34652014-02-14 18:00:16 -080025#include <climits>
26#if !defined(MCLD_ON_WIN32)
27#include <fnmatch.h>
Stephen Hines37b74a32014-11-26 18:48:20 -080028#define fnmatch0(pattern, string) (fnmatch(pattern, string, 0) == 0)
Stephen Hines87f34652014-02-14 18:00:16 -080029#else
30#include <windows.h>
31#include <shlwapi.h>
Stephen Hines37b74a32014-11-26 18:48:20 -080032#define fnmatch0(pattern, string) (PathMatchSpec(string, pattern) == true)
Stephen Hines87f34652014-02-14 18:00:16 -080033#endif
Shih-wei Liao22add6f2012-12-15 17:21:00 -080034
Stephen Hines37b74a32014-11-26 18:48:20 -080035namespace mcld {
36
Shih-wei Liao22add6f2012-12-15 17:21:00 -080037//===----------------------------------------------------------------------===//
Stephen Hines87f34652014-02-14 18:00:16 -080038// SectionMap::Input
Shih-wei Liao22add6f2012-12-15 17:21:00 -080039//===----------------------------------------------------------------------===//
Stephen Hines87f34652014-02-14 18:00:16 -080040SectionMap::Input::Input(const std::string& pName,
41 InputSectDesc::KeepPolicy pPolicy)
Stephen Hines37b74a32014-11-26 18:48:20 -080042 : m_Policy(pPolicy) {
Stephen Hines87f34652014-02-14 18:00:16 -080043 m_Spec.m_pWildcardFile =
Stephen Hines37b74a32014-11-26 18:48:20 -080044 WildcardPattern::create("*", WildcardPattern::SORT_NONE);
Stephen Hines87f34652014-02-14 18:00:16 -080045 m_Spec.m_pExcludeFiles = NULL;
46
47 StringList* sections = StringList::create();
48 sections->push_back(
Stephen Hines37b74a32014-11-26 18:48:20 -080049 WildcardPattern::create(pName, WildcardPattern::SORT_NONE));
Stephen Hines87f34652014-02-14 18:00:16 -080050 m_Spec.m_pWildcardSections = sections;
51
Stephen Hines0dea6bc2014-07-15 18:33:32 -070052 m_pSection = LDSection::Create(pName, LDFileFormat::TEXT, 0, 0);
Stephen Hines87f34652014-02-14 18:00:16 -080053 SectionData* sd = SectionData::Create(*m_pSection);
54 m_pSection->setSectionData(sd);
55 new NullFragment(sd);
56 new NullFragment(sd);
57}
58
59SectionMap::Input::Input(const InputSectDesc& pInputDesc)
Stephen Hines37b74a32014-11-26 18:48:20 -080060 : m_Policy(pInputDesc.policy()) {
Stephen Hines87f34652014-02-14 18:00:16 -080061 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;
Stephen Hines0dea6bc2014-07-15 18:33:32 -070064 m_pSection = LDSection::Create("", LDFileFormat::TEXT, 0, 0);
Stephen Hines87f34652014-02-14 18:00:16 -080065 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//===----------------------------------------------------------------------===//
74SectionMap::Output::Output(const std::string& pName)
Stephen Hines37b74a32014-11-26 18:48:20 -080075 : m_Name(pName), m_Order(UINT_MAX) {
Stephen Hines87f34652014-02-14 18:00:16 -080076 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
Stephen Hines0dea6bc2014-07-15 18:33:32 -070088 m_pSection = LDSection::Create(pName, LDFileFormat::TEXT, 0, 0);
Stephen Hines87f34652014-02-14 18:00:16 -080089 SectionData* sd = SectionData::Create(*m_pSection);
90 m_pSection->setSectionData(sd);
91
92 m_bIsDiscard = pName.compare("/DISCARD/") == 0;
93}
94
95SectionMap::Output::Output(const OutputSectDesc& pOutputDesc)
Stephen Hines37b74a32014-11-26 18:48:20 -080096 : m_Name(pOutputDesc.name()),
97 m_Prolog(pOutputDesc.prolog()),
98 m_Epilog(pOutputDesc.epilog()),
99 m_Order(UINT_MAX) {
Stephen Hines0dea6bc2014-07-15 18:33:32 -0700100 m_pSection = LDSection::Create(m_Name, LDFileFormat::TEXT, 0, 0);
Stephen Hines87f34652014-02-14 18:00:16 -0800101 SectionData* sd = SectionData::Create(*m_pSection);
102 m_pSection->setSectionData(sd);
103
104 m_bIsDiscard = m_Name.compare("/DISCARD/") == 0;
105}
106
Stephen Hines37b74a32014-11-26 18:48:20 -0800107bool SectionMap::Output::hasContent() const {
Stephen Hines87f34652014-02-14 18:00:16 -0800108 return m_pSection != NULL && m_pSection->size() != 0;
109}
110
111SectionMap::Output::const_dot_iterator
Stephen Hines37b74a32014-11-26 18:48:20 -0800112SectionMap::Output::find_first_explicit_dot() const {
Stephen Hines87f34652014-02-14 18:00:16 -0800113 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
Stephen Hines37b74a32014-11-26 18:48:20 -0800120SectionMap::Output::dot_iterator SectionMap::Output::find_first_explicit_dot() {
Stephen Hines87f34652014-02-14 18:00:16 -0800121 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
128SectionMap::Output::const_dot_iterator
Stephen Hines37b74a32014-11-26 18:48:20 -0800129SectionMap::Output::find_last_explicit_dot() const {
Stephen Hines87f34652014-02-14 18:00:16 -0800130 typedef DotAssignments::const_reverse_iterator CONST_RIT;
131 for (CONST_RIT rit = dotAssignments().rbegin(), rie = dotAssignments().rend();
Stephen Hines37b74a32014-11-26 18:48:20 -0800132 rit != rie;
133 ++rit) {
Stephen Hines87f34652014-02-14 18:00:16 -0800134 if ((*rit).type() == Assignment::DEFAULT) {
135 return dot_begin() +
136 (dotAssignments().size() - (rit - dotAssignments().rbegin()) - 1);
137 }
138 }
139 return dot_end();
140}
141
Stephen Hines37b74a32014-11-26 18:48:20 -0800142SectionMap::Output::dot_iterator SectionMap::Output::find_last_explicit_dot() {
Stephen Hines87f34652014-02-14 18:00:16 -0800143 typedef DotAssignments::reverse_iterator RIT;
144 for (RIT rit = dotAssignments().rbegin(), rie = dotAssignments().rend();
Stephen Hines37b74a32014-11-26 18:48:20 -0800145 rit != rie;
146 ++rit) {
Stephen Hines87f34652014-02-14 18:00:16 -0800147 if ((*rit).type() == Assignment::DEFAULT) {
148 return dot_begin() +
149 (dotAssignments().size() - (rit - dotAssignments().rbegin()) - 1);
150 }
151 }
152 return dot_end();
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800153}
154
155//===----------------------------------------------------------------------===//
156// SectionMap
157//===----------------------------------------------------------------------===//
Stephen Hines37b74a32014-11-26 18:48:20 -0800158SectionMap::~SectionMap() {
Stephen Hines87f34652014-02-14 18:00:16 -0800159 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;
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800168 }
169 }
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800170}
171
Stephen Hines37b74a32014-11-26 18:48:20 -0800172SectionMap::const_mapping SectionMap::find(
173 const std::string& pInputFile,
174 const std::string& pInputSection) const {
Stephen Hines87f34652014-02-14 18:00:16 -0800175 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);
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800181 }
182 }
Stephen Hines87f34652014-02-14 18:00:16 -0800183 return std::make_pair((const Output*)NULL, (const Input*)NULL);
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800184}
185
Stephen Hines87f34652014-02-14 18:00:16 -0800186SectionMap::mapping SectionMap::find(const std::string& pInputFile,
Stephen Hines37b74a32014-11-26 18:48:20 -0800187 const std::string& pInputSection) {
Stephen Hines87f34652014-02-14 18:00:16 -0800188 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 }
Colin Cross662e4772022-01-13 15:01:43 -0800196 return std::make_pair(nullptr, nullptr);
Stephen Hines87f34652014-02-14 18:00:16 -0800197}
198
Stephen Hines37b74a32014-11-26 18:48:20 -0800199SectionMap::const_iterator SectionMap::find(
200 const std::string& pOutputSection) const {
Stephen Hines87f34652014-02-14 18:00:16 -0800201 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
Stephen Hines37b74a32014-11-26 18:48:20 -0800209SectionMap::iterator SectionMap::find(const std::string& pOutputSection) {
Stephen Hines87f34652014-02-14 18:00:16 -0800210 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
Stephen Hines37b74a32014-11-26 18:48:20 -0800218std::pair<SectionMap::mapping, bool> SectionMap::insert(
219 const std::string& pInputSection,
220 const std::string& pOutputSection,
221 InputSectDesc::KeepPolicy pPolicy) {
Stephen Hines87f34652014-02-14 18:00:16 -0800222 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 }
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800241 }
242
Stephen Hines87f34652014-02-14 18:00:16 -0800243 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);
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800249}
250
Stephen Hines37b74a32014-11-26 18:48:20 -0800251std::pair<SectionMap::mapping, bool> SectionMap::insert(
252 const InputSectDesc& pInputDesc,
253 const OutputSectDesc& pOutputDesc) {
Stephen Hines87f34652014-02-14 18:00:16 -0800254 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 }
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800261
Stephen Hines87f34652014-02-14 18:00:16 -0800262 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 }
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800269
Stephen Hines87f34652014-02-14 18:00:16 -0800270 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 }
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800278
Stephen Hines87f34652014-02-14 18:00:16 -0800279 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
Stephen Hines37b74a32014-11-26 18:48:20 -0800287SectionMap::iterator SectionMap::insert(iterator pPosition,
288 LDSection* pSection) {
Stephen Hines87f34652014-02-14 18:00:16 -0800289 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
295bool SectionMap::matched(const SectionMap::Input& pInput,
296 const std::string& pInputFile,
Stephen Hines37b74a32014-11-26 18:48:20 -0800297 const std::string& pInputSection) const {
Stephen Hines87f34652014-02-14 18:00:16 -0800298 if (pInput.spec().hasFile() && !matched(pInput.spec().file(), pInputFile))
Stephen Hines37b74a32014-11-26 18:48:20 -0800299 return false;
Stephen Hines87f34652014-02-14 18:00:16 -0800300
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 }
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800318 }
319
320 return false;
321}
322
Stephen Hines87f34652014-02-14 18:00:16 -0800323bool SectionMap::matched(const WildcardPattern& pPattern,
Stephen Hines37b74a32014-11-26 18:48:20 -0800324 const std::string& pName) const {
Stephen Hines87f34652014-02-14 18:00:16 -0800325 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 }
Shih-wei Liao22add6f2012-12-15 17:21:00 -0800331}
332
Stephen Hines87f34652014-02-14 18:00:16 -0800333// fixupDotSymbols - ensure the dot symbols are valid
Stephen Hines37b74a32014-11-26 18:48:20 -0800334void SectionMap::fixupDotSymbols() {
Stephen Hines87f34652014-02-14 18:00:16 -0800335 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();
Stephen Hines37b74a32014-11-26 18:48:20 -0800339 if (dot != (*it)->dot_end() && (*dot).symbol().isDot() &&
Stephen Hines87f34652014-02-14 18:00:16 -0800340 (*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(),
Stephen Hines37b74a32014-11-26 18:48:20 -0800347 tokEnd = (*dot).getRpnExpr().end();
348 tok != tokEnd;
349 ++tok) {
Stephen Hines87f34652014-02-14 18:00:16 -0800350 if ((*tok)->kind() == ExprToken::OPERAND &&
351 llvm::cast<Operand>(*tok)->isDot())
352 *tok = &((*ref).symbol());
Stephen Hines37b74a32014-11-26 18:48:20 -0800353 } // for each token in the RHS expr of the dot assignment
Stephen Hines87f34652014-02-14 18:00:16 -0800354 }
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(),
Stephen Hines37b74a32014-11-26 18:48:20 -0800368 tokEnd = (*it)->prolog().vma().end();
369 tok != tokEnd;
370 ++tok) {
Stephen Hines87f34652014-02-14 18:00:16 -0800371 if ((*tok)->kind() == ExprToken::OPERAND &&
372 llvm::cast<Operand>(*tok)->isDot())
373 *tok = &((*dot).symbol());
Stephen Hines37b74a32014-11-26 18:48:20 -0800374 } // for each token in the RHS expr of the dot assignment
Stephen Hines87f34652014-02-14 18:00:16 -0800375 }
Stephen Hines37b74a32014-11-26 18:48:20 -0800376 } // for each output section
Stephen Hines87f34652014-02-14 18:00:16 -0800377}
Stephen Hines37b74a32014-11-26 18:48:20 -0800378
379} // namespace mcld