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 17 using namespace mcld; 18 using namespace elf_dynamic; 19 20 //===----------------------------------------------------------------------===// 21 // elf_dynamic::EntryIF 22 EntryIF::EntryIF() 23 { 24 } 25 26 EntryIF::~EntryIF() 27 { 28 } 29 30 //===----------------------------------------------------------------------===// 31 // ELFDynamic 32 ELFDynamic::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 41 ELFDynamic::~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 59 size_t ELFDynamic::size() const 60 { 61 return (m_NeedList.size() + m_EntryList.size()); 62 } 63 64 size_t ELFDynamic::numOfBytes() const 65 { 66 return size()*entrySize(); 67 } 68 69 size_t ELFDynamic::entrySize() const 70 { 71 return m_pEntryFactory->size(); 72 } 73 74 void ELFDynamic::reserveOne(uint64_t pTag) 75 { 76 assert(NULL != m_pEntryFactory); 77 m_EntryList.push_back(new elf_dynamic::Entry<32, true>()); 78 } 79 80 void 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 88 /// reserveEntries - reserve entries 89 void ELFDynamic::reserveEntries(const MCLDInfo& pLDInfo, 90 const ELFFileFormat& pFormat) 91 { 92 if (pLDInfo.output().type() == Output::DynObj) { 93 reserveOne(llvm::ELF::DT_SONAME); // DT_SONAME 94 95 if (pLDInfo.options().Bsymbolic()) 96 reserveOne(llvm::ELF::DT_SYMBOLIC); // DT_SYMBOLIC 97 } 98 99 if (pFormat.hasInit()) 100 reserveOne(llvm::ELF::DT_INIT); // DT_INIT 101 102 if (pFormat.hasFini()) 103 reserveOne(llvm::ELF::DT_FINI); // DT_FINI 104 105 if (pFormat.hasInitArray()) { 106 reserveOne(llvm::ELF::DT_INIT_ARRAY); // DT_INIT_ARRAY 107 reserveOne(llvm::ELF::DT_INIT_ARRAYSZ); // DT_INIT_ARRAYSZ 108 } 109 110 if (pFormat.hasFiniArray()) { 111 reserveOne(llvm::ELF::DT_FINI_ARRAY); // DT_FINI_ARRAY 112 reserveOne(llvm::ELF::DT_FINI_ARRAYSZ); // DT_FINI_ARRAYSZ 113 } 114 115 if (pFormat.hasHashTab()) 116 reserveOne(llvm::ELF::DT_HASH); // DT_HASH 117 118 if (pFormat.hasDynSymTab()) { 119 reserveOne(llvm::ELF::DT_SYMTAB); // DT_SYMTAB 120 reserveOne(llvm::ELF::DT_SYMENT); // DT_SYMENT 121 } 122 123 if (pFormat.hasDynStrTab()) { 124 reserveOne(llvm::ELF::DT_STRTAB); // DT_STRTAB 125 reserveOne(llvm::ELF::DT_STRSZ); // DT_STRSZ 126 } 127 128 reserveTargetEntries(pFormat); // DT_PLTGOT 129 130 if (pFormat.hasRelPlt() || pFormat.hasRelaPlt()) 131 reserveOne(llvm::ELF::DT_PLTREL); // DT_PLTREL 132 133 if (pFormat.hasPLT()) { 134 reserveOne(llvm::ELF::DT_JMPREL); // DT_JMPREL 135 reserveOne(llvm::ELF::DT_PLTRELSZ); // DT_PLTRELSZ 136 } 137 138 if (pFormat.hasRelDyn()) { 139 reserveOne(llvm::ELF::DT_REL); // DT_REL 140 reserveOne(llvm::ELF::DT_RELSZ); // DT_RELSZ 141 reserveOne(llvm::ELF::DT_RELENT); // DT_RELENT 142 } 143 144 if (pFormat.hasRelaDyn()) { 145 reserveOne(llvm::ELF::DT_RELA); // DT_RELA 146 reserveOne(llvm::ELF::DT_RELASZ); // DT_RELASZ 147 reserveOne(llvm::ELF::DT_RELAENT); // DT_RELAENT 148 } 149 reserveOne(llvm::ELF::DT_NULL); // for DT_NULL 150 } 151 152 /// applyEntries - apply entries 153 void ELFDynamic::applyEntries(const MCLDInfo& pInfo, 154 const ELFFileFormat& pFormat) 155 { 156 if (pInfo.output().type() == Output::DynObj && 157 pInfo.options().Bsymbolic()) { 158 applyOne(llvm::ELF::DT_SYMBOLIC, 0x0); // DT_SYMBOLIC 159 } 160 161 if (pFormat.hasInit()) 162 applyOne(llvm::ELF::DT_INIT, pFormat.getInit().addr()); // DT_INIT 163 164 if (pFormat.hasFini()) 165 applyOne(llvm::ELF::DT_FINI, pFormat.getFini().addr()); // DT_FINI 166 167 if (pFormat.hasInitArray()) { 168 // DT_INIT_ARRAY 169 applyOne(llvm::ELF::DT_INIT_ARRAY, pFormat.getInitArray().addr()); 170 171 // DT_INIT_ARRAYSZ 172 applyOne(llvm::ELF::DT_INIT_ARRAYSZ, pFormat.getInitArray().size()); 173 } 174 175 if (pFormat.hasFiniArray()) { 176 // DT_FINI_ARRAY 177 applyOne(llvm::ELF::DT_FINI_ARRAY, pFormat.getFiniArray().addr()); 178 179 // DT_FINI_ARRAYSZ 180 applyOne(llvm::ELF::DT_FINI_ARRAYSZ, pFormat.getFiniArray().size()); 181 } 182 183 if (pFormat.hasHashTab()) 184 applyOne(llvm::ELF::DT_HASH, pFormat.getHashTab().addr()); // DT_HASH 185 186 if (pFormat.hasDynSymTab()) { 187 applyOne(llvm::ELF::DT_SYMTAB, pFormat.getDynSymTab().addr()); // DT_SYMTAB 188 applyOne(llvm::ELF::DT_SYMENT, symbolSize()); // DT_SYMENT 189 } 190 191 if (pFormat.hasDynStrTab()) { 192 applyOne(llvm::ELF::DT_STRTAB, pFormat.getDynStrTab().addr()); // DT_STRTAB 193 applyOne(llvm::ELF::DT_STRSZ, pFormat.getDynStrTab().size()); // DT_STRSZ 194 } 195 196 applyTargetEntries(pFormat); // DT_PLTGOT 197 198 if (pFormat.hasRelPlt()) 199 applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_REL); // DT_PLTREL 200 else if (pFormat.hasRelaPlt()) 201 applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_RELA); // DT_PLTREL 202 203 if (pFormat.hasRelPlt()) { 204 applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelPlt().addr()); // DT_JMPREL 205 applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelPlt().size()); // DT_PLTRELSZ 206 } 207 208 if (pFormat.hasRelDyn()) { 209 applyOne(llvm::ELF::DT_REL, pFormat.getRelDyn().addr()); // DT_REL 210 applyOne(llvm::ELF::DT_RELSZ, pFormat.getRelDyn().size()); // DT_RELSZ 211 applyOne(llvm::ELF::DT_RELENT, m_pEntryFactory->relSize()); // DT_RELENT 212 } 213 214 if (pFormat.hasRelaDyn()) { 215 applyOne(llvm::ELF::DT_RELA, pFormat.getRelaDyn().addr()); // DT_RELA 216 applyOne(llvm::ELF::DT_RELASZ, pFormat.getRelaDyn().size()); // DT_RELASZ 217 applyOne(llvm::ELF::DT_RELAENT, m_pEntryFactory->relaSize()); // DT_RELAENT 218 } 219 220 applyOne(llvm::ELF::DT_NULL, 0x0); // for DT_NULL 221 } 222 223 /// symbolSize 224 size_t ELFDynamic::symbolSize() const 225 { 226 return m_pEntryFactory->symbolSize(); 227 } 228 229 /// reserveNeedEntry - reserve on DT_NEED entry. 230 void ELFDynamic::reserveNeedEntry() 231 { 232 m_NeedList.push_back(m_pEntryFactory->clone()); 233 } 234 235 /// emit 236 void ELFDynamic::emit(const LDSection& pSection, MemoryRegion& pRegion) const 237 { 238 if (pRegion.size() < pSection.size()) { 239 llvm::report_fatal_error(llvm::Twine("the given memory is smaller") + 240 llvm::Twine(" than the section's demaind.\n")); 241 } 242 243 uint8_t* address = (uint8_t*)pRegion.start(); 244 EntryListType::const_iterator entry, entryEnd = m_NeedList.end(); 245 for (entry = m_NeedList.begin(); entry != entryEnd; ++entry) 246 address += (*entry)->emit(address); 247 248 entryEnd = m_EntryList.end(); 249 for (entry = m_EntryList.begin(); entry != entryEnd; ++entry) 250 address += (*entry)->emit(address); 251 } 252 253 void ELFDynamic::applySoname(uint64_t pStrTabIdx) 254 { 255 applyOne(llvm::ELF::DT_SONAME, pStrTabIdx); // DT_SONAME 256 } 257 258