//===- SectionMap.cpp -----------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "mcld/Object/SectionMap.h" #include "mcld/Fragment/NullFragment.h" #include "mcld/LD/LDSection.h" #include "mcld/LD/SectionData.h" #include "mcld/Script/Assignment.h" #include "mcld/Script/Operand.h" #include "mcld/Script/Operator.h" #include "mcld/Script/RpnExpr.h" #include "mcld/Script/StringList.h" #include "mcld/Script/WildcardPattern.h" #include #include #include #include #if !defined(MCLD_ON_WIN32) #include #define fnmatch0(pattern, string) (fnmatch(pattern, string, 0) == 0) #else #include #include #define fnmatch0(pattern, string) (PathMatchSpec(string, pattern) == true) #endif namespace mcld { //===----------------------------------------------------------------------===// // SectionMap::Input //===----------------------------------------------------------------------===// SectionMap::Input::Input(const std::string& pName, InputSectDesc::KeepPolicy pPolicy) : m_Policy(pPolicy) { m_Spec.m_pWildcardFile = WildcardPattern::create("*", WildcardPattern::SORT_NONE); m_Spec.m_pExcludeFiles = NULL; StringList* sections = StringList::create(); sections->push_back( WildcardPattern::create(pName, WildcardPattern::SORT_NONE)); m_Spec.m_pWildcardSections = sections; m_pSection = LDSection::Create(pName, LDFileFormat::TEXT, 0, 0); SectionData* sd = SectionData::Create(*m_pSection); m_pSection->setSectionData(sd); new NullFragment(sd); new NullFragment(sd); } SectionMap::Input::Input(const InputSectDesc& pInputDesc) : m_Policy(pInputDesc.policy()) { m_Spec.m_pWildcardFile = pInputDesc.spec().m_pWildcardFile; m_Spec.m_pExcludeFiles = pInputDesc.spec().m_pExcludeFiles; m_Spec.m_pWildcardSections = pInputDesc.spec().m_pWildcardSections; m_pSection = LDSection::Create("", LDFileFormat::TEXT, 0, 0); SectionData* sd = SectionData::Create(*m_pSection); m_pSection->setSectionData(sd); new NullFragment(sd); new NullFragment(sd); } //===----------------------------------------------------------------------===// // SectionMap::Output //===----------------------------------------------------------------------===// SectionMap::Output::Output(const std::string& pName) : m_Name(pName), m_Order(UINT_MAX) { m_Prolog.m_pVMA = NULL; m_Prolog.m_Type = OutputSectDesc::LOAD; m_Prolog.m_pLMA = NULL; m_Prolog.m_pAlign = NULL; m_Prolog.m_pSubAlign = NULL; m_Prolog.m_Constraint = OutputSectDesc::NO_CONSTRAINT; m_Epilog.m_pRegion = NULL; m_Epilog.m_pLMARegion = NULL; m_Epilog.m_pPhdrs = NULL; m_Epilog.m_pFillExp = NULL; m_pSection = LDSection::Create(pName, LDFileFormat::TEXT, 0, 0); SectionData* sd = SectionData::Create(*m_pSection); m_pSection->setSectionData(sd); m_bIsDiscard = pName.compare("/DISCARD/") == 0; } SectionMap::Output::Output(const OutputSectDesc& pOutputDesc) : m_Name(pOutputDesc.name()), m_Prolog(pOutputDesc.prolog()), m_Epilog(pOutputDesc.epilog()), m_Order(UINT_MAX) { m_pSection = LDSection::Create(m_Name, LDFileFormat::TEXT, 0, 0); SectionData* sd = SectionData::Create(*m_pSection); m_pSection->setSectionData(sd); m_bIsDiscard = m_Name.compare("/DISCARD/") == 0; } bool SectionMap::Output::hasContent() const { return m_pSection != NULL && m_pSection->size() != 0; } SectionMap::Output::const_dot_iterator SectionMap::Output::find_first_explicit_dot() const { for (const_dot_iterator it = dot_begin(), ie = dot_end(); it != ie; ++it) { if ((*it).type() == Assignment::DEFAULT) return it; } return dot_end(); } SectionMap::Output::dot_iterator SectionMap::Output::find_first_explicit_dot() { for (dot_iterator it = dot_begin(), ie = dot_end(); it != ie; ++it) { if ((*it).type() == Assignment::DEFAULT) return it; } return dot_end(); } SectionMap::Output::const_dot_iterator SectionMap::Output::find_last_explicit_dot() const { typedef DotAssignments::const_reverse_iterator CONST_RIT; for (CONST_RIT rit = dotAssignments().rbegin(), rie = dotAssignments().rend(); rit != rie; ++rit) { if ((*rit).type() == Assignment::DEFAULT) { return dot_begin() + (dotAssignments().size() - (rit - dotAssignments().rbegin()) - 1); } } return dot_end(); } SectionMap::Output::dot_iterator SectionMap::Output::find_last_explicit_dot() { typedef DotAssignments::reverse_iterator RIT; for (RIT rit = dotAssignments().rbegin(), rie = dotAssignments().rend(); rit != rie; ++rit) { if ((*rit).type() == Assignment::DEFAULT) { return dot_begin() + (dotAssignments().size() - (rit - dotAssignments().rbegin()) - 1); } } return dot_end(); } //===----------------------------------------------------------------------===// // SectionMap //===----------------------------------------------------------------------===// SectionMap::~SectionMap() { iterator out, outBegin = begin(), outEnd = end(); for (out = outBegin; out != outEnd; ++out) { if (*out != NULL) { Output::iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end(); for (in = inBegin; in != inEnd; ++in) { if (*in != NULL) delete *in; } delete *out; } } } SectionMap::const_mapping SectionMap::find( const std::string& pInputFile, const std::string& pInputSection) const { const_iterator out, outBegin = begin(), outEnd = end(); for (out = outBegin; out != outEnd; ++out) { Output::const_iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end(); for (in = inBegin; in != inEnd; ++in) { if (matched(**in, pInputFile, pInputSection)) return std::make_pair(*out, *in); } } return std::make_pair((const Output*)NULL, (const Input*)NULL); } SectionMap::mapping SectionMap::find(const std::string& pInputFile, const std::string& pInputSection) { iterator out, outBegin = begin(), outEnd = end(); for (out = outBegin; out != outEnd; ++out) { Output::iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end(); for (in = inBegin; in != inEnd; ++in) { if (matched(**in, pInputFile, pInputSection)) return std::make_pair(*out, *in); } } return std::make_pair(reinterpret_cast(NULL), reinterpret_cast(NULL)); } SectionMap::const_iterator SectionMap::find( const std::string& pOutputSection) const { const_iterator out, outBegin = begin(), outEnd = end(); for (out = outBegin; out != outEnd; ++out) { if ((*out)->name().compare(pOutputSection) == 0) return out; } return outEnd; } SectionMap::iterator SectionMap::find(const std::string& pOutputSection) { iterator out, outBegin = begin(), outEnd = end(); for (out = outBegin; out != outEnd; ++out) { if ((*out)->name().compare(pOutputSection) == 0) return out; } return outEnd; } std::pair SectionMap::insert( const std::string& pInputSection, const std::string& pOutputSection, InputSectDesc::KeepPolicy pPolicy) { iterator out, outBegin = begin(), outEnd = end(); for (out = outBegin; out != outEnd; ++out) { if ((*out)->name().compare(pOutputSection) == 0) break; } if (out != end()) { Output::iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end(); for (in = inBegin; in != inEnd; ++in) { if ((*in)->getSection()->name().compare(pInputSection) == 0) break; } if (in != (*out)->end()) { return std::make_pair(std::make_pair(*out, *in), false); } else { Input* input = new Input(pInputSection, pPolicy); (*out)->append(input); return std::make_pair(std::make_pair(*out, input), true); } } Output* output = new Output(pOutputSection); m_OutputDescList.push_back(output); Input* input = new Input(pInputSection, pPolicy); output->append(input); return std::make_pair(std::make_pair(output, input), true); } std::pair SectionMap::insert( const InputSectDesc& pInputDesc, const OutputSectDesc& pOutputDesc) { iterator out, outBegin = begin(), outEnd = end(); for (out = outBegin; out != outEnd; ++out) { if ((*out)->name().compare(pOutputDesc.name()) == 0 && (*out)->prolog() == pOutputDesc.prolog() && (*out)->epilog() == pOutputDesc.epilog()) break; } if (out != end()) { Output::iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end(); for (in = inBegin; in != inEnd; ++in) { if ((*in)->policy() == pInputDesc.policy() && (*in)->spec() == pInputDesc.spec()) break; } if (in != (*out)->end()) { return std::make_pair(std::make_pair(*out, *in), false); } else { Input* input = new Input(pInputDesc); (*out)->append(input); return std::make_pair(std::make_pair(*out, input), true); } } Output* output = new Output(pOutputDesc); m_OutputDescList.push_back(output); Input* input = new Input(pInputDesc); output->append(input); return std::make_pair(std::make_pair(output, input), true); } SectionMap::iterator SectionMap::insert(iterator pPosition, LDSection* pSection) { Output* output = new Output(pSection->name()); output->append(new Input(pSection->name(), InputSectDesc::NoKeep)); output->setSection(pSection); return m_OutputDescList.insert(pPosition, output); } bool SectionMap::matched(const SectionMap::Input& pInput, const std::string& pInputFile, const std::string& pInputSection) const { if (pInput.spec().hasFile() && !matched(pInput.spec().file(), pInputFile)) return false; if (pInput.spec().hasExcludeFiles()) { StringList::const_iterator file, fileEnd; fileEnd = pInput.spec().excludeFiles().end(); for (file = pInput.spec().excludeFiles().begin(); file != fileEnd; ++file) { if (matched(llvm::cast(**file), pInputFile)) { return false; } } } if (pInput.spec().hasSections()) { StringList::const_iterator sect, sectEnd = pInput.spec().sections().end(); for (sect = pInput.spec().sections().begin(); sect != sectEnd; ++sect) { if (matched(llvm::cast(**sect), pInputSection)) { return true; } } } return false; } bool SectionMap::matched(const WildcardPattern& pPattern, const std::string& pName) const { if (pPattern.isPrefix()) { llvm::StringRef name(pName); return name.startswith(pPattern.prefix()); } else { return fnmatch0(pPattern.name().c_str(), pName.c_str()); } } // fixupDotSymbols - ensure the dot symbols are valid void SectionMap::fixupDotSymbols() { for (iterator it = begin() + 1, ie = end(); it != ie; ++it) { // fixup the 1st explicit dot assignment if needed if (!(*it)->dotAssignments().empty()) { Output::dot_iterator dot = (*it)->find_first_explicit_dot(); if (dot != (*it)->dot_end() && (*dot).symbol().isDot() && (*dot).getRpnExpr().hasDot()) { Assignment assign(Assignment::OUTPUT_SECTION, Assignment::DEFAULT, *SymOperand::create("."), *RpnExpr::buildHelperExpr(it - 1)); Output::dot_iterator ref = (*it)->dotAssignments().insert(dot, assign); for (RpnExpr::iterator tok = (*dot).getRpnExpr().begin(), tokEnd = (*dot).getRpnExpr().end(); tok != tokEnd; ++tok) { if ((*tok)->kind() == ExprToken::OPERAND && llvm::cast(*tok)->isDot()) *tok = &((*ref).symbol()); } // for each token in the RHS expr of the dot assignment } } // fixup dot in output VMA if needed if ((*it)->prolog().hasVMA() && (*it)->prolog().vma().hasDot()) { Output::dot_iterator dot = (*it)->find_last_explicit_dot(); if (dot == (*it)->dot_end()) { Assignment assign(Assignment::OUTPUT_SECTION, Assignment::DEFAULT, *SymOperand::create("."), *RpnExpr::buildHelperExpr(it - 1)); dot = (*it)->dotAssignments().insert(dot, assign); } for (RpnExpr::iterator tok = (*it)->prolog().vma().begin(), tokEnd = (*it)->prolog().vma().end(); tok != tokEnd; ++tok) { if ((*tok)->kind() == ExprToken::OPERAND && llvm::cast(*tok)->isDot()) *tok = &((*dot).symbol()); } // for each token in the RHS expr of the dot assignment } } // for each output section } } // namespace mcld