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 //===----------------------------------------------------------------------===// 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 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 //===----------------------------------------------------------------------===// 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 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 107 bool SectionMap::Output::hasContent() const { 108 return m_pSection != NULL && m_pSection->size() != 0; 109 } 110 111 SectionMap::Output::const_dot_iterator 112 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 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 129 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 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 //===----------------------------------------------------------------------===// 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 172 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 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 200 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 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 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 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 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 296 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 324 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 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