//===- 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; }