1 //===- ELFDynamic.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/LD/ELFFileFormat.h" 10 #include "mcld/Support/MsgHandling.h" 11 #include "mcld/Target/ELFDynamic.h" 12 #include "mcld/Target/GNULDBackend.h" 13 #include "mcld/LinkerConfig.h" 14 15 #include <llvm/Support/ErrorHandling.h> 16 #include <llvm/Support/Host.h> 17 18 namespace mcld { 19 namespace elf_dynamic { 20 21 //===----------------------------------------------------------------------===// 22 // elf_dynamic::EntryIF 23 //===----------------------------------------------------------------------===// 24 EntryIF::EntryIF() { 25 } 26 27 EntryIF::~EntryIF() { 28 } 29 30 } // namespace elf_dynamic 31 32 //===----------------------------------------------------------------------===// 33 // ELFDynamic 34 //===----------------------------------------------------------------------===// 35 ELFDynamic::ELFDynamic(const GNULDBackend& pParent, const LinkerConfig& pConfig) 36 : m_pEntryFactory(NULL), m_Backend(pParent), m_Config(pConfig), m_Idx(0) { 37 // FIXME: support big-endian machine. 38 if (m_Config.targets().is32Bits()) { 39 if (m_Config.targets().isLittleEndian()) 40 m_pEntryFactory = new elf_dynamic::Entry<32, true>(); 41 } else if (m_Config.targets().is64Bits()) { 42 if (m_Config.targets().isLittleEndian()) 43 m_pEntryFactory = new elf_dynamic::Entry<64, true>(); 44 } else { 45 fatal(diag::unsupported_bitclass) << m_Config.targets().triple().str() 46 << m_Config.targets().bitclass(); 47 } 48 } 49 50 ELFDynamic::~ELFDynamic() { 51 if (m_pEntryFactory != NULL) 52 delete m_pEntryFactory; 53 54 EntryListType::iterator entry, entryEnd = m_EntryList.end(); 55 for (entry = m_EntryList.begin(); entry != entryEnd; ++entry) { 56 if (*entry != NULL) 57 delete (*entry); 58 } 59 60 entryEnd = m_NeedList.end(); 61 for (entry = m_NeedList.begin(); entry != entryEnd; ++entry) { 62 if (*entry != NULL) 63 delete (*entry); 64 } 65 } 66 67 size_t ELFDynamic::size() const { 68 return (m_NeedList.size() + m_EntryList.size()); 69 } 70 71 size_t ELFDynamic::numOfBytes() const { 72 return size() * entrySize(); 73 } 74 75 size_t ELFDynamic::entrySize() const { 76 return m_pEntryFactory->size(); 77 } 78 79 void ELFDynamic::reserveOne(uint64_t pTag) { 80 assert(m_pEntryFactory != NULL); 81 m_EntryList.push_back(m_pEntryFactory->clone()); 82 } 83 84 void ELFDynamic::applyOne(uint64_t pTag, uint64_t pValue) { 85 assert(m_Idx < m_EntryList.size()); 86 m_EntryList[m_Idx]->setValue(pTag, pValue); 87 ++m_Idx; 88 } 89 90 /// reserveEntries - reserve entries 91 void ELFDynamic::reserveEntries(const ELFFileFormat& pFormat) { 92 if (LinkerConfig::DynObj == m_Config.codeGenType()) { 93 reserveOne(llvm::ELF::DT_SONAME); 94 95 if (m_Config.options().Bsymbolic()) 96 reserveOne(llvm::ELF::DT_SYMBOLIC); 97 } 98 99 if (pFormat.hasInit()) 100 reserveOne(llvm::ELF::DT_INIT); 101 102 if (pFormat.hasFini()) 103 reserveOne(llvm::ELF::DT_FINI); 104 105 if (pFormat.hasPreInitArray()) { 106 reserveOne(llvm::ELF::DT_PREINIT_ARRAY); 107 reserveOne(llvm::ELF::DT_PREINIT_ARRAYSZ); 108 } 109 110 if (pFormat.hasInitArray()) { 111 reserveOne(llvm::ELF::DT_INIT_ARRAY); 112 reserveOne(llvm::ELF::DT_INIT_ARRAYSZ); 113 } 114 115 if (pFormat.hasFiniArray()) { 116 reserveOne(llvm::ELF::DT_FINI_ARRAY); 117 reserveOne(llvm::ELF::DT_FINI_ARRAYSZ); 118 } 119 120 if (pFormat.hasHashTab()) 121 reserveOne(llvm::ELF::DT_HASH); 122 123 if (pFormat.hasGNUHashTab()) 124 reserveOne(llvm::ELF::DT_GNU_HASH); 125 126 if (pFormat.hasDynSymTab()) { 127 reserveOne(llvm::ELF::DT_SYMTAB); 128 reserveOne(llvm::ELF::DT_SYMENT); 129 } 130 131 if (pFormat.hasDynStrTab()) { 132 reserveOne(llvm::ELF::DT_STRTAB); 133 reserveOne(llvm::ELF::DT_STRSZ); 134 } 135 136 reserveTargetEntries(pFormat); 137 138 if (pFormat.hasRelPlt() || pFormat.hasRelaPlt()) { 139 reserveOne(llvm::ELF::DT_PLTREL); 140 reserveOne(llvm::ELF::DT_JMPREL); 141 reserveOne(llvm::ELF::DT_PLTRELSZ); 142 } 143 144 if (pFormat.hasRelDyn()) { 145 reserveOne(llvm::ELF::DT_REL); 146 reserveOne(llvm::ELF::DT_RELSZ); 147 reserveOne(llvm::ELF::DT_RELENT); 148 } 149 150 if (pFormat.hasRelaDyn()) { 151 reserveOne(llvm::ELF::DT_RELA); 152 reserveOne(llvm::ELF::DT_RELASZ); 153 reserveOne(llvm::ELF::DT_RELAENT); 154 } 155 156 uint64_t dt_flags = 0x0; 157 if (m_Config.options().hasOrigin()) 158 dt_flags |= llvm::ELF::DF_ORIGIN; 159 if (m_Config.options().Bsymbolic()) 160 dt_flags |= llvm::ELF::DF_SYMBOLIC; 161 if (m_Config.options().hasNow()) 162 dt_flags |= llvm::ELF::DF_BIND_NOW; 163 if (m_Backend.hasTextRel()) 164 dt_flags |= llvm::ELF::DF_TEXTREL; 165 if (m_Backend.hasStaticTLS() && 166 (LinkerConfig::DynObj == m_Config.codeGenType())) 167 dt_flags |= llvm::ELF::DF_STATIC_TLS; 168 169 if ((m_Config.options().hasNewDTags() && dt_flags != 0x0) || 170 (dt_flags & llvm::ELF::DF_STATIC_TLS) != 0x0) 171 reserveOne(llvm::ELF::DT_FLAGS); 172 173 if (m_Backend.hasTextRel()) 174 reserveOne(llvm::ELF::DT_TEXTREL); 175 176 if (m_Config.options().hasNow() || m_Config.options().hasLoadFltr() || 177 m_Config.options().hasOrigin() || m_Config.options().hasInterPose() || 178 m_Config.options().hasNoDefaultLib() || m_Config.options().hasNoDump() || 179 m_Config.options().Bgroup() || 180 ((LinkerConfig::DynObj == m_Config.codeGenType()) && 181 (m_Config.options().hasNoDelete() || m_Config.options().hasInitFirst() || 182 m_Config.options().hasNoDLOpen()))) { 183 reserveOne(llvm::ELF::DT_FLAGS_1); 184 } 185 186 unsigned num_spare_dtags = m_Config.options().getNumSpareDTags(); 187 for (unsigned i = 0; i < num_spare_dtags; ++i) { 188 reserveOne(llvm::ELF::DT_NULL); 189 } 190 } 191 192 /// applyEntries - apply entries 193 void ELFDynamic::applyEntries(const ELFFileFormat& pFormat) { 194 if (LinkerConfig::DynObj == m_Config.codeGenType() && 195 m_Config.options().Bsymbolic()) { 196 applyOne(llvm::ELF::DT_SYMBOLIC, 0x0); 197 } 198 199 if (pFormat.hasInit()) 200 applyOne(llvm::ELF::DT_INIT, pFormat.getInit().addr()); 201 202 if (pFormat.hasFini()) 203 applyOne(llvm::ELF::DT_FINI, pFormat.getFini().addr()); 204 205 if (pFormat.hasPreInitArray()) { 206 applyOne(llvm::ELF::DT_PREINIT_ARRAY, pFormat.getPreInitArray().addr()); 207 applyOne(llvm::ELF::DT_PREINIT_ARRAYSZ, pFormat.getPreInitArray().size()); 208 } 209 210 if (pFormat.hasInitArray()) { 211 applyOne(llvm::ELF::DT_INIT_ARRAY, pFormat.getInitArray().addr()); 212 applyOne(llvm::ELF::DT_INIT_ARRAYSZ, pFormat.getInitArray().size()); 213 } 214 215 if (pFormat.hasFiniArray()) { 216 applyOne(llvm::ELF::DT_FINI_ARRAY, pFormat.getFiniArray().addr()); 217 applyOne(llvm::ELF::DT_FINI_ARRAYSZ, pFormat.getFiniArray().size()); 218 } 219 220 if (pFormat.hasHashTab()) 221 applyOne(llvm::ELF::DT_HASH, pFormat.getHashTab().addr()); 222 223 if (pFormat.hasGNUHashTab()) 224 applyOne(llvm::ELF::DT_GNU_HASH, pFormat.getGNUHashTab().addr()); 225 226 if (pFormat.hasDynSymTab()) { 227 applyOne(llvm::ELF::DT_SYMTAB, pFormat.getDynSymTab().addr()); 228 applyOne(llvm::ELF::DT_SYMENT, symbolSize()); 229 } 230 231 if (pFormat.hasDynStrTab()) { 232 applyOne(llvm::ELF::DT_STRTAB, pFormat.getDynStrTab().addr()); 233 applyOne(llvm::ELF::DT_STRSZ, pFormat.getDynStrTab().size()); 234 } 235 236 applyTargetEntries(pFormat); 237 238 if (pFormat.hasRelPlt()) { 239 applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_REL); 240 applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelPlt().addr()); 241 applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelPlt().size()); 242 } else if (pFormat.hasRelaPlt()) { 243 applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_RELA); 244 applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelaPlt().addr()); 245 applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelaPlt().size()); 246 } 247 248 if (pFormat.hasRelDyn()) { 249 applyOne(llvm::ELF::DT_REL, pFormat.getRelDyn().addr()); 250 applyOne(llvm::ELF::DT_RELSZ, pFormat.getRelDyn().size()); 251 applyOne(llvm::ELF::DT_RELENT, m_pEntryFactory->relSize()); 252 } 253 254 if (pFormat.hasRelaDyn()) { 255 applyOne(llvm::ELF::DT_RELA, pFormat.getRelaDyn().addr()); 256 applyOne(llvm::ELF::DT_RELASZ, pFormat.getRelaDyn().size()); 257 applyOne(llvm::ELF::DT_RELAENT, m_pEntryFactory->relaSize()); 258 } 259 260 if (m_Backend.hasTextRel()) { 261 applyOne(llvm::ELF::DT_TEXTREL, 0x0); 262 263 if (m_Config.options().warnSharedTextrel() && 264 LinkerConfig::DynObj == m_Config.codeGenType()) 265 mcld::warning(mcld::diag::warn_shared_textrel); 266 } 267 268 uint64_t dt_flags = 0x0; 269 if (m_Config.options().hasOrigin()) 270 dt_flags |= llvm::ELF::DF_ORIGIN; 271 if (m_Config.options().Bsymbolic()) 272 dt_flags |= llvm::ELF::DF_SYMBOLIC; 273 if (m_Config.options().hasNow()) 274 dt_flags |= llvm::ELF::DF_BIND_NOW; 275 if (m_Backend.hasTextRel()) 276 dt_flags |= llvm::ELF::DF_TEXTREL; 277 if (m_Backend.hasStaticTLS() && 278 (LinkerConfig::DynObj == m_Config.codeGenType())) 279 dt_flags |= llvm::ELF::DF_STATIC_TLS; 280 281 if ((m_Config.options().hasNewDTags() && dt_flags != 0x0) || 282 (dt_flags & llvm::ELF::DF_STATIC_TLS) != 0) 283 applyOne(llvm::ELF::DT_FLAGS, dt_flags); 284 285 uint64_t dt_flags_1 = 0x0; 286 if (m_Config.options().hasNow()) 287 dt_flags_1 |= llvm::ELF::DF_1_NOW; 288 if (m_Config.options().hasLoadFltr()) 289 dt_flags_1 |= llvm::ELF::DF_1_LOADFLTR; 290 if (m_Config.options().hasOrigin()) 291 dt_flags_1 |= llvm::ELF::DF_1_ORIGIN; 292 if (m_Config.options().hasInterPose()) 293 dt_flags_1 |= llvm::ELF::DF_1_INTERPOSE; 294 if (m_Config.options().hasNoDefaultLib()) 295 dt_flags_1 |= llvm::ELF::DF_1_NODEFLIB; 296 if (m_Config.options().hasNoDump()) 297 dt_flags_1 |= llvm::ELF::DF_1_NODUMP; 298 if (m_Config.options().Bgroup()) 299 dt_flags_1 |= llvm::ELF::DF_1_GROUP; 300 if (LinkerConfig::DynObj == m_Config.codeGenType()) { 301 if (m_Config.options().hasNoDelete()) 302 dt_flags_1 |= llvm::ELF::DF_1_NODELETE; 303 if (m_Config.options().hasInitFirst()) 304 dt_flags_1 |= llvm::ELF::DF_1_INITFIRST; 305 if (m_Config.options().hasNoDLOpen()) 306 dt_flags_1 |= llvm::ELF::DF_1_NOOPEN; 307 } 308 if (dt_flags_1 != 0x0) 309 applyOne(llvm::ELF::DT_FLAGS_1, dt_flags_1); 310 311 unsigned num_spare_dtags = m_Config.options().getNumSpareDTags(); 312 for (unsigned i = 0; i < num_spare_dtags; ++i) { 313 applyOne(llvm::ELF::DT_NULL, 0x0); 314 } 315 } 316 317 /// symbolSize 318 size_t ELFDynamic::symbolSize() const { 319 return m_pEntryFactory->symbolSize(); 320 } 321 322 /// reserveNeedEntry - reserve on DT_NEED entry. 323 void ELFDynamic::reserveNeedEntry() { 324 m_NeedList.push_back(m_pEntryFactory->clone()); 325 } 326 327 /// emit 328 void ELFDynamic::emit(const LDSection& pSection, MemoryRegion& pRegion) const { 329 if (pRegion.size() < pSection.size()) { 330 llvm::report_fatal_error(llvm::Twine("the given memory is smaller") + 331 llvm::Twine(" than the section's demaind.\n")); 332 } 333 334 uint8_t* address = reinterpret_cast<uint8_t*>(pRegion.begin()); 335 EntryListType::const_iterator entry, entryEnd = m_NeedList.end(); 336 for (entry = m_NeedList.begin(); entry != entryEnd; ++entry) 337 address += (*entry)->emit(address); 338 339 entryEnd = m_EntryList.end(); 340 for (entry = m_EntryList.begin(); entry != entryEnd; ++entry) 341 address += (*entry)->emit(address); 342 } 343 344 void ELFDynamic::applySoname(uint64_t pStrTabIdx) { 345 applyOne(llvm::ELF::DT_SONAME, pStrTabIdx); 346 } 347 348 } // namespace mcld 349