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