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