blob: 611acd1d8eeb970edc6afe66002673e3f427d8d3 [file] [log] [blame]
//===- 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;
}