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