C++程序  |  112行  |  3.19 KB

//===- SectionRules.cpp ---------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <mcld/LD/SectionRules.h>

#include <cassert>
#include <cstring>

#include <mcld/Module.h>
#include <mcld/LinkerConfig.h>
#include <mcld/Object/SectionMap.h>
#include <mcld/ADT/StringHash.h>

using namespace mcld;

namespace {
  static StringHash<ES> hash_func;
} // end anonymous namespace

//===----------------------------------------------------------------------===//
// SectionRules::Rule
//===----------------------------------------------------------------------===//
SectionRules::Rule::Rule(const std::string& pSubStr, LDSection* pSection)
  : substr(pSubStr), target(pSection) {
  hash = hash_func(pSubStr);
}

//===----------------------------------------------------------------------===//
// SectionRules
//===----------------------------------------------------------------------===//
SectionRules::SectionRules(const LinkerConfig& pConfig, Module& pModule)
  : m_SectionNameMap(pConfig.scripts().sectionMap()),
    m_Module(pModule) {
}

SectionRules::~SectionRules()
{
}

SectionRules::iterator SectionRules::find(const std::string& pName)
{
  uint32_t hash = hash_func(pName);
  RuleList::iterator rule, rEnd = m_RuleList.end();
  for (rule = m_RuleList.begin(); rule != rEnd; ++rule) {
    if (pName.size() < rule->substr.size())
      continue;
    if (!StringHash<ES>::may_include(rule->hash, hash))
      continue;

    if (0 == strncmp(pName.c_str(), rule->substr.c_str(), rule->substr.size()))
      return rule;
  }
  return rule;
}

SectionRules::const_iterator SectionRules::find(const std::string& pName) const
{
  uint32_t hash = hash_func(pName);
  RuleList::const_iterator rule, rEnd = m_RuleList.end();
  for (rule = m_RuleList.begin(); rule != rEnd; ++rule) {
    if (pName.size() < rule->substr.size())
      continue;
    if (!StringHash<ES>::may_include(rule->hash, hash))
      continue;

    if (0 == strncmp(pName.c_str(), rule->substr.c_str(), rule->substr.size()))
      return rule;
  }
  return rule;
}

LDSection* SectionRules::getMatchedSection(const std::string& pName) const
{
  LDSection* section;
  const_iterator it = find(pName);

  // check if we can find a matched LDSection.
  // If not, we need to find it in output context. But this should be rare.
  if (it != m_RuleList.end())
    section = (*it).target;
  else
    section = m_Module.getSection(pName);

  return section;
}

void SectionRules::append(const std::string& pName, LDSection& pSection)
{
  iterator it = find(pName);
  if (it != m_RuleList.end()) {
    assert(NULL == (*it).target);
    (*it).target = &pSection;
  }
}

void SectionRules::initOutputSectMap()
{
  // Based on SectionMap to initialize the map from a input substr to its 
  // associated output LDSection*
  SectionMap::const_iterator it;
  for (it = m_SectionNameMap.begin(); it != m_SectionNameMap.end(); ++it) {
    Rule rule(it->from, NULL);
    m_RuleList.push_back(rule);
  }
  assert(m_SectionNameMap.size() == m_RuleList.size());
}