C++程序  |  172行  |  5.78 KB

//===- ScriptOptions.cpp --------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <mcld/ScriptOptions.h>
#include <mcld/LinkerScript.h>
#include <mcld/ADT/StringEntry.h>
#include <mcld/Support/MsgHandling.h>

namespace {

//===----------------------------------------------------------------------===//
// Script Options
// Script options are used to modify the default link script. Some positional
// options, such as --defsym, also can modify default link script is not listed
// here. These special options belong to Positional Options.
//===----------------------------------------------------------------------===//
static llvm::cl::list<std::string>
ArgWrapList("wrap",
            llvm::cl::ZeroOrMore,
            llvm::cl::desc("Use a wrap function fo symbol."),
            llvm::cl::value_desc("symbol"));

static llvm::cl::list<std::string>
ArgPortList("portable",
            llvm::cl::ZeroOrMore,
            llvm::cl::desc("Use a portable function fo symbol."),
            llvm::cl::value_desc("symbol"));

static llvm::cl::list<std::string>
ArgAddressMapList("section-start",
                  llvm::cl::ZeroOrMore,
                  llvm::cl::desc("Locate a output section at the given absolute address"),
                  llvm::cl::value_desc("Set address of section"),
                  llvm::cl::Prefix);

static llvm::cl::opt<unsigned long long>
ArgBssSegAddr("Tbss",
              llvm::cl::desc("Set the address of the bss segment"),
              llvm::cl::init(-1U));

static llvm::cl::opt<unsigned long long>
ArgDataSegAddr("Tdata",
               llvm::cl::desc("Set the address of the data segment"),
               llvm::cl::init(-1U));

static llvm::cl::opt<unsigned long long>
ArgTextSegAddr("Ttext",
               llvm::cl::desc("Set the address of the text segment"),
               llvm::cl::init(-1U));

static llvm::cl::alias
ArgTextSegAddrAlias("Ttext-segment",
                    llvm::cl::desc("alias for -Ttext"),
                    llvm::cl::aliasopt(ArgTextSegAddr));

} // anonymous namespace

using namespace mcld;

//===----------------------------------------------------------------------===//
// ScriptOptions
//===----------------------------------------------------------------------===//
ScriptOptions::ScriptOptions()
  : m_WrapList(ArgWrapList),
    m_PortList(ArgPortList),
    m_AddressMapList(ArgAddressMapList),
    m_BssSegAddr(ArgBssSegAddr),
    m_DataSegAddr(ArgDataSegAddr),
    m_TextSegAddr(ArgTextSegAddr) {
}

bool ScriptOptions::parse(LinkerScript& pScript)
{
  // set up rename map, for --wrap
  llvm::cl::list<std::string>::iterator wname;
  llvm::cl::list<std::string>::iterator wnameEnd = ArgWrapList.end();
  for (wname = ArgWrapList.begin(); wname != wnameEnd; ++wname) {
    bool exist = false;

    // add wname -> __wrap_wname
    StringEntry<llvm::StringRef>* to_wrap =
                                     pScript.renameMap().insert(*wname, exist);

    std::string to_wrap_str = "__wrap_" + *wname;
    to_wrap->setValue(to_wrap_str);

    if (exist)
      warning(mcld::diag::rewrap) << *wname << to_wrap_str;

    // add __real_wname -> wname
    std::string from_real_str = "__real_" + *wname;
    StringEntry<llvm::StringRef>* from_real =
                              pScript.renameMap().insert(from_real_str, exist);
    from_real->setValue(*wname);
    if (exist)
      mcld::warning(mcld::diag::rewrap) << *wname << from_real_str;
  }

  // set up rename map, for --portable
  llvm::cl::list<std::string>::iterator pname;
  llvm::cl::list<std::string>::iterator pnameEnd = ArgPortList.end();
  for (pname = ArgPortList.begin(); pname != pnameEnd; ++pname) {
    bool exist = false;

    // add pname -> pname_portable
    StringEntry<llvm::StringRef>* to_port =
                                     pScript.renameMap().insert(*pname, exist);

    std::string to_port_str = *pname + "_portable";
    to_port->setValue(to_port_str);

    if (exist)
      warning(mcld::diag::rewrap) << *pname << to_port_str;

    // add __real_pname -> pname
    std::string from_real_str = "__real_" + *pname;
    StringEntry<llvm::StringRef>* from_real =
                              pScript.renameMap().insert(from_real_str, exist);

    from_real->setValue(*pname);
    if (exist)
      warning(mcld::diag::rewrap) << *pname << from_real_str;
  } // end of for

  // set --section-start SECTION=ADDRESS
  for (llvm::cl::list<std::string>::iterator
       it = ArgAddressMapList.begin(), ie = ArgAddressMapList.end();
       it != ie; ++it) {
    // FIXME: Add a cl::parser
    size_t pos = (*it).find_last_of('=');
    llvm::StringRef script(*it);
    uint64_t address = 0x0;
    script.substr(pos + 1).getAsInteger(0, address);
    bool exist = false;
    StringEntry<uint64_t>* addr_mapping =
                     pScript.addressMap().insert(script.substr(0, pos), exist);
    addr_mapping->setValue(address);
  }

  // set -Tbss [address]
  if (-1U != ArgBssSegAddr) {
    bool exist = false;
    StringEntry<uint64_t>* bss_mapping =
                                    pScript.addressMap().insert(".bss", exist);
    bss_mapping->setValue(ArgBssSegAddr);
  }

  // set -Tdata [address]
  if (-1U != ArgDataSegAddr) {
    bool exist = false;
    StringEntry<uint64_t>* data_mapping =
                                   pScript.addressMap().insert(".data", exist);
    data_mapping->setValue(ArgDataSegAddr);
  }

  // set -Ttext [address]
  if (-1U != ArgTextSegAddr) {
    bool exist = false;
    StringEntry<uint64_t>* text_mapping =
                                   pScript.addressMap().insert(".text", exist);
    text_mapping->setValue(ArgTextSegAddr);
  }

  return true;
}