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 14 namespace { 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 //===----------------------------------------------------------------------===// 22 static llvm::cl::list<std::string> 23 ArgWrapList("wrap", 24 llvm::cl::ZeroOrMore, 25 llvm::cl::desc("Use a wrap function fo symbol."), 26 llvm::cl::value_desc("symbol")); 27 28 static llvm::cl::list<std::string> 29 ArgPortList("portable", 30 llvm::cl::ZeroOrMore, 31 llvm::cl::desc("Use a portable function fo symbol."), 32 llvm::cl::value_desc("symbol")); 33 34 static llvm::cl::list<std::string> 35 ArgAddressMapList("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 41 static llvm::cl::opt<unsigned long long> 42 ArgBssSegAddr("Tbss", 43 llvm::cl::desc("Set the address of the bss segment"), 44 llvm::cl::init(-1U)); 45 46 static llvm::cl::opt<unsigned long long> 47 ArgDataSegAddr("Tdata", 48 llvm::cl::desc("Set the address of the data segment"), 49 llvm::cl::init(-1U)); 50 51 static llvm::cl::opt<unsigned long long> 52 ArgTextSegAddr("Ttext", 53 llvm::cl::desc("Set the address of the text segment"), 54 llvm::cl::init(-1U)); 55 56 static llvm::cl::alias 57 ArgTextSegAddrAlias("Ttext-segment", 58 llvm::cl::desc("alias for -Ttext"), 59 llvm::cl::aliasopt(ArgTextSegAddr)); 60 61 } // anonymous namespace 62 63 using namespace mcld; 64 65 //===----------------------------------------------------------------------===// 66 // ScriptOptions 67 //===----------------------------------------------------------------------===// 68 ScriptOptions::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 77 bool 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