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