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 //===----------------------------------------------------------------------===// 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 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 //===----------------------------------------------------------------------===// 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 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 108 bool SectionMap::Output::hasContent() const 109 { 110 return m_pSection != NULL && m_pSection->size() != 0; 111 } 112 113 SectionMap::Output::const_dot_iterator 114 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 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 133 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 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 //===----------------------------------------------------------------------===// 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 178 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 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 207 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 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> 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> 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 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 308 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 337 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 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