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