1//===- ScriptOptions.cpp --------------------------------------------------===// 2// 3// The MCLinker Project 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9#include <mcld/ScriptOptions.h> 10#include <mcld/LinkerScript.h> 11#include <mcld/ADT/StringEntry.h> 12#include <mcld/Support/MsgHandling.h> 13 14namespace { 15 16//===----------------------------------------------------------------------===// 17// Script Options 18// Script options are used to modify the default link script. Some positional 19// options, such as --defsym, also can modify default link script is not listed 20// here. These special options belong to Positional Options. 21//===----------------------------------------------------------------------===// 22static llvm::cl::list<std::string> 23ArgWrapList("wrap", 24 llvm::cl::ZeroOrMore, 25 llvm::cl::desc("Use a wrap function fo symbol."), 26 llvm::cl::value_desc("symbol")); 27 28static llvm::cl::list<std::string> 29ArgPortList("portable", 30 llvm::cl::ZeroOrMore, 31 llvm::cl::desc("Use a portable function fo symbol."), 32 llvm::cl::value_desc("symbol")); 33 34static llvm::cl::list<std::string> 35ArgAddressMapList("section-start", 36 llvm::cl::ZeroOrMore, 37 llvm::cl::desc("Locate a output section at the given absolute address"), 38 llvm::cl::value_desc("Set address of section"), 39 llvm::cl::Prefix); 40 41static llvm::cl::opt<unsigned long long> 42ArgBssSegAddr("Tbss", 43 llvm::cl::desc("Set the address of the bss segment"), 44 llvm::cl::init(-1U)); 45 46static llvm::cl::opt<unsigned long long> 47ArgDataSegAddr("Tdata", 48 llvm::cl::desc("Set the address of the data segment"), 49 llvm::cl::init(-1U)); 50 51static llvm::cl::opt<unsigned long long> 52ArgTextSegAddr("Ttext", 53 llvm::cl::desc("Set the address of the text segment"), 54 llvm::cl::init(-1U)); 55 56static llvm::cl::alias 57ArgTextSegAddrAlias("Ttext-segment", 58 llvm::cl::desc("alias for -Ttext"), 59 llvm::cl::aliasopt(ArgTextSegAddr)); 60 61} // anonymous namespace 62 63using namespace mcld; 64 65//===----------------------------------------------------------------------===// 66// ScriptOptions 67//===----------------------------------------------------------------------===// 68ScriptOptions::ScriptOptions() 69 : m_WrapList(ArgWrapList), 70 m_PortList(ArgPortList), 71 m_AddressMapList(ArgAddressMapList), 72 m_BssSegAddr(ArgBssSegAddr), 73 m_DataSegAddr(ArgDataSegAddr), 74 m_TextSegAddr(ArgTextSegAddr) { 75} 76 77bool ScriptOptions::parse(LinkerScript& pScript) 78{ 79 // set up rename map, for --wrap 80 llvm::cl::list<std::string>::iterator wname; 81 llvm::cl::list<std::string>::iterator wnameEnd = ArgWrapList.end(); 82 for (wname = ArgWrapList.begin(); wname != wnameEnd; ++wname) { 83 bool exist = false; 84 85 // add wname -> __wrap_wname 86 StringEntry<llvm::StringRef>* to_wrap = 87 pScript.renameMap().insert(*wname, exist); 88 89 std::string to_wrap_str = "__wrap_" + *wname; 90 to_wrap->setValue(to_wrap_str); 91 92 if (exist) 93 warning(mcld::diag::rewrap) << *wname << to_wrap_str; 94 95 // add __real_wname -> wname 96 std::string from_real_str = "__real_" + *wname; 97 StringEntry<llvm::StringRef>* from_real = 98 pScript.renameMap().insert(from_real_str, exist); 99 from_real->setValue(*wname); 100 if (exist) 101 mcld::warning(mcld::diag::rewrap) << *wname << from_real_str; 102 } 103 104 // set up rename map, for --portable 105 llvm::cl::list<std::string>::iterator pname; 106 llvm::cl::list<std::string>::iterator pnameEnd = ArgPortList.end(); 107 for (pname = ArgPortList.begin(); pname != pnameEnd; ++pname) { 108 bool exist = false; 109 110 // add pname -> pname_portable 111 StringEntry<llvm::StringRef>* to_port = 112 pScript.renameMap().insert(*pname, exist); 113 114 std::string to_port_str = *pname + "_portable"; 115 to_port->setValue(to_port_str); 116 117 if (exist) 118 warning(mcld::diag::rewrap) << *pname << to_port_str; 119 120 // add __real_pname -> pname 121 std::string from_real_str = "__real_" + *pname; 122 StringEntry<llvm::StringRef>* from_real = 123 pScript.renameMap().insert(from_real_str, exist); 124 125 from_real->setValue(*pname); 126 if (exist) 127 warning(mcld::diag::rewrap) << *pname << from_real_str; 128 } // end of for 129 130 // set --section-start SECTION=ADDRESS 131 for (llvm::cl::list<std::string>::iterator 132 it = ArgAddressMapList.begin(), ie = ArgAddressMapList.end(); 133 it != ie; ++it) { 134 // FIXME: Add a cl::parser 135 size_t pos = (*it).find_last_of('='); 136 llvm::StringRef script(*it); 137 uint64_t address = 0x0; 138 script.substr(pos + 1).getAsInteger(0, address); 139 bool exist = false; 140 StringEntry<uint64_t>* addr_mapping = 141 pScript.addressMap().insert(script.substr(0, pos), exist); 142 addr_mapping->setValue(address); 143 } 144 145 // set -Tbss [address] 146 if (-1U != ArgBssSegAddr) { 147 bool exist = false; 148 StringEntry<uint64_t>* bss_mapping = 149 pScript.addressMap().insert(".bss", exist); 150 bss_mapping->setValue(ArgBssSegAddr); 151 } 152 153 // set -Tdata [address] 154 if (-1U != ArgDataSegAddr) { 155 bool exist = false; 156 StringEntry<uint64_t>* data_mapping = 157 pScript.addressMap().insert(".data", exist); 158 data_mapping->setValue(ArgDataSegAddr); 159 } 160 161 // set -Ttext [address] 162 if (-1U != ArgTextSegAddr) { 163 bool exist = false; 164 StringEntry<uint64_t>* text_mapping = 165 pScript.addressMap().insert(".text", exist); 166 text_mapping->setValue(ArgTextSegAddr); 167 } 168 169 return true; 170} 171 172