1 //===- LinkerConfig.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 10 #include "alone/Support/LinkerConfig.h" 11 #include "alone/Support/Log.h" 12 13 #include <llvm/Support/Signals.h> 14 15 #include <mcld/MC/MCLDDirectory.h> 16 #include <mcld/MC/ZOption.h> 17 #include <mcld/LD/TextDiagnosticPrinter.h> 18 #include <mcld/Support/Path.h> 19 #include <mcld/Support/MsgHandling.h> 20 #include <mcld/Support/raw_ostream.h> 21 22 using namespace alone; 23 24 LinkerConfig::LinkerConfig(const std::string &pTriple) 25 : mTriple(pTriple), mSOName(), mTarget(NULL), mLDConfig(NULL), 26 mLDScript(NULL), mDiagLineInfo(NULL), mDiagPrinter(NULL) { 27 28 initializeTarget(); 29 initializeLDScript(); 30 initializeLDInfo(); 31 initializeDiagnostic(); 32 } 33 34 LinkerConfig::~LinkerConfig() { 35 delete mLDConfig; 36 37 if (mDiagPrinter->getNumErrors() != 0) { 38 // If here, the program failed ungracefully. Run the interrupt handlers to 39 // ensure any other cleanups (e.g., files that registered by 40 // RemoveFileOnSignal(...)) getting done before exit. 41 llvm::sys::RunInterruptHandlers(); 42 } 43 mDiagPrinter->finish(); 44 45 delete mLDScript; 46 delete mDiagLineInfo; 47 delete mDiagPrinter; 48 } 49 50 bool LinkerConfig::initializeTarget() { 51 std::string error; 52 mTarget = mcld::TargetRegistry::lookupTarget(mTriple, error); 53 if (NULL != mTarget) { 54 return true; 55 } else { 56 ALOGE("Cannot initialize mcld::Target for given triple '%s'! (%s)\n", 57 mTriple.c_str(), error.c_str()); 58 return false; 59 } 60 } 61 62 bool LinkerConfig::initializeLDInfo() { 63 if (NULL != mLDConfig) { 64 ALOGE("Cannot initialize mcld::MCLDInfo for given triple '%s!\n", 65 mTriple.c_str()); 66 return false; 67 } 68 69 mLDConfig = new mcld::LinkerConfig(getTriple()); 70 mLDConfig->setCodeGenType(mcld::LinkerConfig::Exec); 71 72 struct NameMap { 73 const char* from; 74 const char* to; 75 }; 76 77 static const NameMap map[] = 78 { 79 {".text", ".text"}, 80 {".rodata", ".rodata"}, 81 {".data.rel.ro.local", ".data.rel.ro.local"}, 82 {".data.rel.ro", ".data.rel.ro"}, 83 {".data", ".data"}, 84 {".bss", ".bss"}, 85 {".tdata", ".tdata"}, 86 {".tbss", ".tbss"}, 87 {".init_array", ".init_array"}, 88 {".fini_array", ".fini_array"}, 89 // TODO: Support DT_INIT_ARRAY for all constructors? 90 {".ctors", ".ctors"}, 91 {".dtors", ".dtors"}, 92 // FIXME: in GNU ld, if we are creating a shared object .sdata2 and .sbss2 93 // sections would be handled differently. 94 {".sdata2", ".sdata"}, 95 {".sbss2", ".sbss"}, 96 {".sdata", ".sdata"}, 97 {".sbss", ".sbss"}, 98 {".lrodata", ".lrodata"}, 99 {".ldata", ".ldata"}, 100 {".lbss", ".lbss"}, 101 {".gcc_except_table", ".gcc_except_table"}, 102 {".gnu.linkonce.d.rel.ro.local", ".data.rel.ro.local"}, 103 {".gnu.linkonce.d.rel.ro", ".data.rel.ro"}, 104 {".gnu.linkonce.r", ".rodata"}, 105 {".gnu.linkonce.d", ".data"}, 106 {".gnu.linkonce.b", ".bss"}, 107 {".gnu.linkonce.sb2", ".sbss"}, 108 {".gnu.linkonce.sb", ".sbss"}, 109 {".gnu.linkonce.s2", ".sdata"}, 110 {".gnu.linkonce.s", ".sdata"}, 111 {".gnu.linkonce.wi", ".debug_info"}, 112 {".gnu.linkonce.td", ".tdata"}, 113 {".gnu.linkonce.tb", ".tbss"}, 114 {".gnu.linkonce.t", ".text"}, 115 {".gnu.linkonce.lr", ".lrodata"}, 116 {".gnu.linkonce.lb", ".lbss"}, 117 {".gnu.linkonce.l", ".ldata"}, 118 }; 119 120 if (mLDConfig->codeGenType() != mcld::LinkerConfig::Object) { 121 const unsigned int map_size = (sizeof(map) / sizeof(map[0]) ); 122 for (unsigned int i = 0; i < map_size; ++i) { 123 bool exist = false; 124 mLDScript->sectionMap().append(map[i].from, 125 map[i].to, 126 exist); 127 } 128 } 129 return true; 130 } 131 132 bool LinkerConfig::initializeLDScript() { 133 mLDScript = new mcld::LinkerScript(); 134 return true; 135 } 136 137 bool LinkerConfig::initializeDiagnostic() { 138 // Set up MsgHandler. 139 mDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *mLDConfig); 140 141 mcld::InitializeDiagnosticEngine(*mLDConfig, mDiagPrinter); 142 143 mDiagLineInfo = mTarget->createDiagnosticLineInfo(*mTarget, mTriple); 144 145 mcld::getDiagnosticEngine().setLineInfo(*mDiagLineInfo); 146 return true; 147 } 148 149 bool LinkerConfig::isShared() const { 150 return (mcld::LinkerConfig::DynObj == mLDConfig->codeGenType()); 151 } 152 153 void LinkerConfig::setShared(bool pEnable) { 154 if (pEnable) 155 mLDConfig->setCodeGenType(mcld::LinkerConfig::DynObj); 156 else 157 mLDConfig->setCodeGenType(mcld::LinkerConfig::Exec); 158 return; 159 } 160 161 void LinkerConfig::setBsymbolic(bool pEnable) { 162 mLDConfig->options().setBsymbolic(pEnable); 163 return; 164 } 165 166 void LinkerConfig::setDefineCommon(bool pEnable) { 167 mLDConfig->options().setDefineCommon(pEnable); 168 return; 169 } 170 171 void LinkerConfig::setSOName(const std::string &pSOName) { 172 mLDConfig->options().setSOName(pSOName); 173 return; 174 } 175 176 void LinkerConfig::setDyld(const std::string &pDyld) { 177 mLDConfig->options().setDyld(pDyld); 178 return; 179 } 180 181 void LinkerConfig::setSysRoot(const std::string &pSysRoot) { 182 mLDScript->setSysroot(mcld::sys::fs::Path(pSysRoot)); 183 return; 184 } 185 186 void LinkerConfig::setZOption(unsigned int pOptions) { 187 mcld::ZOption option; 188 if (pOptions & kCombReloc) { 189 option.setKind(mcld::ZOption::CombReloc); 190 mLDConfig->options().addZOption(option); 191 } 192 else { 193 option.setKind(mcld::ZOption::NoCombReloc); 194 mLDConfig->options().addZOption(option); 195 } 196 197 if (pOptions & kDefs) { 198 option.setKind(mcld::ZOption::Defs); 199 mLDConfig->options().addZOption(option); 200 } 201 202 if (pOptions & kExecStack) { 203 option.setKind(mcld::ZOption::ExecStack); 204 mLDConfig->options().addZOption(option); 205 } 206 else { 207 option.setKind(mcld::ZOption::NoExecStack); 208 mLDConfig->options().addZOption(option); 209 } 210 211 if (pOptions & kInitFirst) { 212 option.setKind(mcld::ZOption::InitFirst); 213 mLDConfig->options().addZOption(option); 214 } 215 216 if (pOptions & kInterPose) { 217 option.setKind(mcld::ZOption::InterPose); 218 mLDConfig->options().addZOption(option); 219 } 220 221 if (pOptions & kLoadFltr) { 222 option.setKind(mcld::ZOption::LoadFltr); 223 mLDConfig->options().addZOption(option); 224 } 225 226 if (pOptions & kMulDefs) { 227 option.setKind(mcld::ZOption::MulDefs); 228 mLDConfig->options().addZOption(option); 229 } 230 231 if (pOptions & kNoCopyReloc) { 232 option.setKind(mcld::ZOption::NoCopyReloc); 233 mLDConfig->options().addZOption(option); 234 } 235 236 if (pOptions & kNoDefaultLib) { 237 option.setKind(mcld::ZOption::NoDefaultLib); 238 mLDConfig->options().addZOption(option); 239 } 240 241 if (pOptions & kNoDelete) { 242 option.setKind(mcld::ZOption::NoDelete); 243 mLDConfig->options().addZOption(option); 244 } 245 246 if (pOptions & kNoDLOpen) { 247 option.setKind(mcld::ZOption::NoDLOpen); 248 mLDConfig->options().addZOption(option); 249 } 250 251 if (pOptions & kNoDump) { 252 option.setKind(mcld::ZOption::NoDump); 253 mLDConfig->options().addZOption(option); 254 } 255 256 if (pOptions & kRelro) { 257 option.setKind(mcld::ZOption::Relro); 258 mLDConfig->options().addZOption(option); 259 } 260 else { 261 option.setKind(mcld::ZOption::NoRelro); 262 mLDConfig->options().addZOption(option); 263 } 264 265 if (pOptions & kLazy) { 266 option.setKind(mcld::ZOption::Lazy); 267 mLDConfig->options().addZOption(option); 268 } 269 else { 270 option.setKind(mcld::ZOption::Now); 271 mLDConfig->options().addZOption(option); 272 } 273 274 if (pOptions & kOrigin) { 275 option.setKind(mcld::ZOption::Origin); 276 mLDConfig->options().addZOption(option); 277 } 278 } 279 280 void LinkerConfig::addWrap(const std::string &pWrapSymbol) { 281 bool exist = false; 282 283 // Add wname -> __wrap_wname. 284 mcld::StringEntry<llvm::StringRef>* to_wrap = 285 mLDScript->renameMap().insert(pWrapSymbol, exist); 286 287 std::string to_wrap_str = "__wrap_" + pWrapSymbol; 288 to_wrap->setValue(to_wrap_str); 289 290 if (exist) { 291 mcld::warning(mcld::diag::rewrap) << pWrapSymbol << to_wrap_str; 292 } 293 294 // Add __real_wname -> wname. 295 std::string from_real_str = "__real_" + pWrapSymbol; 296 mcld::StringEntry<llvm::StringRef>* from_real = 297 mLDScript->renameMap().insert(from_real_str, exist); 298 from_real->setValue(pWrapSymbol); 299 300 if (exist) { 301 mcld::warning(mcld::diag::rewrap) << pWrapSymbol << from_real_str; 302 } 303 304 return; 305 } 306 307 void LinkerConfig::addPortable(const std::string &pPortableSymbol) { 308 bool exist = false; 309 310 // Add pname -> pname_portable. 311 mcld::StringEntry<llvm::StringRef>* to_port = 312 mLDScript->renameMap().insert(pPortableSymbol, exist); 313 314 std::string to_port_str = pPortableSymbol + "_portable"; 315 to_port->setValue(to_port_str); 316 317 if (exist) { 318 mcld::warning(mcld::diag::rewrap) << pPortableSymbol << to_port_str; 319 } 320 321 // Add __real_pname -> pname. 322 std::string from_real_str = "__real_" + pPortableSymbol; 323 mcld::StringEntry<llvm::StringRef>* from_real = 324 mLDScript->renameMap().insert(from_real_str, exist); 325 326 from_real->setValue(pPortableSymbol); 327 328 if (exist) { 329 mcld::warning(mcld::diag::rewrap) << pPortableSymbol << from_real_str; 330 } 331 332 return; 333 } 334 335 void LinkerConfig::addSearchDir(const std::string &pDirPath) { 336 // SearchDirs will remove the created MCLDDirectory. 337 if (!mLDScript->directories().insert(pDirPath)) { 338 mcld::warning(mcld::diag::warn_cannot_open_search_dir) << pDirPath; 339 } 340 } 341