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