1//===- ARMException.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 10#include "ARMException.h" 11 12#include "ARMLDBackend.h" 13 14#include "mcld/ADT/ilist_sort.h" 15#include "mcld/Fragment/RegionFragment.h" 16#include "mcld/LD/ELFFileFormat.h" 17#include "mcld/LD/LDContext.h" 18#include "mcld/Support/MsgHandling.h" 19 20#include <memory> 21 22static const char g_CantUnwindEntry[8] = { 23 // Relocation to text section. 24 0, 0, 0, 0, 25 // EXIDX_CANTUNWIND (little endian.) 26 1, 0, 0, 0, 27}; 28 29namespace mcld { 30 31void ARMExData::addInputMap(Input* pInput, 32 std::unique_ptr<ARMInputExMap>&& pExMap) { 33 assert(m_Inputs.find(pInput) == m_Inputs.end() && 34 "multiple maps for an input"); 35 36 ARMInputExMap* exMap = pExMap.get(); 37 38 // Add mapping to the input-to-exdata map. 39 m_Inputs.insert(std::make_pair(pInput, std::move(pExMap))); 40 41 // Add mapping to the fragment-to-exdata map. 42 for (ARMInputExMap::iterator it = exMap->begin(), end = exMap->end(); 43 it != end; ++it) { 44 ARMExSectionTuple* exTuple = it->second.get(); 45 m_ExIdxToTuple[exTuple->getExIdxFragment()] = exTuple; 46 } 47} 48 49void ARMGNULDBackend::scanInputExceptionSections(Module& pModule) { 50 for (Module::obj_iterator it = pModule.obj_begin(), 51 end = pModule.obj_end(); it != end; ++it) { 52 Input* input = *it; 53 scanInputExceptionSections(pModule, *input); 54 } 55} 56 57static RegionFragment* findRegionFragment(LDSection& pSection) { 58 SectionData* sectData = pSection.getSectionData(); 59 for (SectionData::iterator it = sectData->begin(), 60 end = sectData->end(); it != end; ++it) { 61 if (it->getKind() == Fragment::Region) { 62 return static_cast<RegionFragment*>(&*it); 63 } 64 } 65 return NULL; 66} 67 68void ARMGNULDBackend::scanInputExceptionSections(Module& pModule, 69 Input& pInput) { 70 std::unique_ptr<ARMInputExMap> exMap(new ARMInputExMap()); 71 72 // Scan the input and collect all related sections. 73 LDContext* ctx = pInput.context(); 74 for (LDContext::sect_iterator it = ctx->sectBegin(), 75 end = ctx->sectEnd(); it != end; ++it) { 76 LDSection* sect = *it; 77 llvm::StringRef name(sect->name()); 78 79 if (name.startswith(".ARM.exidx")) { 80 ARMExSectionTuple* exTuple = exMap->getOrCreateByExSection(name); 81 exTuple->setExIdxSection(sect); 82 exTuple->setTextSection(sect->getLink()); 83 } else if (name.startswith(".ARM.extab")) { 84 ARMExSectionTuple* exTuple = exMap->getOrCreateByExSection(name); 85 exTuple->setExTabSection(sect); 86 } else if (name.startswith(".rel.ARM.exidx")) { 87 ARMExSectionTuple* exTuple = exMap->getOrCreateByRelExSection(name); 88 exTuple->setRelExIdxSection(sect); 89 } else if (name.startswith(".rel.ARM.extab")) { 90 ARMExSectionTuple* exTuple = exMap->getOrCreateByRelExSection(name); 91 exTuple->setRelExIdxSection(sect); 92 } 93 } 94 95 // Remove the invalid exception tuples and convert LDSection to RegionFragment 96 // or RelocData. 97 ARMInputExMap::iterator it = exMap->begin(); 98 ARMInputExMap::iterator end = exMap->end(); 99 while (it != end) { 100 ARMExSectionTuple* exTuple = it->second.get(); 101 LDSection* const text = exTuple->getTextSection(); 102 LDSection* const exIdx = exTuple->getExIdxSection(); 103 LDSection* const exTab = exTuple->getExTabSection(); 104 LDSection* const relExIdx = exTuple->getRelExIdxSection(); 105 LDSection* const relExTab = exTuple->getRelExTabSection(); 106 107 // Check the .ARM.exidx section. 108 if (!exIdx) { 109 if (exTab) { 110 fatal(diag::eh_missing_exidx_section) << exTab->name() << pInput.name(); 111 } else if (relExIdx) { 112 fatal(diag::eh_missing_exidx_section) << relExIdx->name() 113 << pInput.name(); 114 } else if (relExTab) { 115 fatal(diag::eh_missing_exidx_section) << relExTab->name() 116 << pInput.name(); 117 } else { 118 llvm_unreachable("unexpected bad exception tuple"); 119 } 120 } 121 122 // Check the text section. 123 if (!text) { 124 fatal(diag::eh_missing_text_section) << exIdx->name() << pInput.name(); 125 } 126 127 // Ignore the exception section if the text section is ignored. 128 if ((text->kind() == LDFileFormat::Ignore) || 129 (text->kind() == LDFileFormat::Folded)) { 130 // Set the related exception sections as LDFileFormat::Ignore. 131 exIdx->setKind(LDFileFormat::Ignore); 132 if (exTab) { 133 exTab->setKind(LDFileFormat::Ignore); 134 } 135 // Remove this tuple from the input exception map. 136 exMap->erase(it++); 137 continue; 138 } 139 140 // Get RegionFragment from ".text", ".ARM.exidx", and ".ARM.extab" sections. 141 RegionFragment* textFrag = findRegionFragment(*text); 142 RegionFragment* exIdxFrag = findRegionFragment(*exIdx); 143 RegionFragment* exTabFrag = exTab ? findRegionFragment(*exTab) : NULL; 144 145 exTuple->setTextFragment(textFrag); 146 exTuple->setExIdxFragment(exIdxFrag); 147 exTuple->setExTabFragment(exTabFrag); 148 149 // Get the RelocData from ".rel.ARM.exidx" and ".rel.ARM.extab" sections. 150 RelocData* exIdxRD = relExIdx ? relExIdx->getRelocData() : NULL; 151 RelocData* exTabRD = relExTab ? relExTab->getRelocData() : NULL; 152 153 exTuple->setExIdxRelocData(exIdxRD); 154 exTuple->setExTabRelocData(exTabRD); 155 156 // If there is no region fragment in the .ARM.extab section, then we can 157 // skip this tuple. 158 if (!exIdxFrag) { 159 exMap->erase(it++); 160 continue; 161 } 162 163 // TODO: Sort the RelocData w.r.t. the fixup offset. 164 165 // Check next tuple 166 ++it; 167 } 168 169 // Add input map 170 m_ExData.addInputMap(&pInput, std::move(exMap)); 171} 172 173class ExIdxFragmentComparator { 174 private: 175 const ARMExData& m_ExData; 176 177 public: 178 explicit ExIdxFragmentComparator(const ARMExData& pExData) 179 : m_ExData(pExData) { 180 } 181 182 bool operator()(const Fragment& a, const Fragment& b) { 183 ARMExSectionTuple* tupleA = m_ExData.getTupleByExIdx(&a); 184 ARMExSectionTuple* tupleB = m_ExData.getTupleByExIdx(&b); 185 186 Fragment* textFragA = tupleA->getTextFragment(); 187 Fragment* textFragB = tupleB->getTextFragment(); 188 189 uint64_t addrA = textFragA->getParent()->getSection().addr() + 190 textFragA->getOffset(); 191 uint64_t addrB = textFragB->getParent()->getSection().addr() + 192 textFragB->getOffset(); 193 return (addrA < addrB); 194 } 195}; 196 197static mcld::ResolveInfo* 198CreateLocalSymbolToFragmentEnd(mcld::Module& pModule, mcld::Fragment& pFrag) { 199 // Create and add symbol to the name pool. 200 mcld::ResolveInfo* resolveInfo = 201 pModule.getNamePool().createSymbol(/* pName */"", 202 /* pIsDyn */false, 203 mcld::ResolveInfo::Section, 204 mcld::ResolveInfo::Define, 205 mcld::ResolveInfo::Local, 206 /* pSize */0, 207 mcld::ResolveInfo::Hidden); 208 if (resolveInfo == nullptr) { 209 return nullptr; 210 } 211 212 // Create input symbol. 213 mcld::LDSymbol* inputSym = mcld::LDSymbol::Create(*resolveInfo); 214 if (inputSym == nullptr) { 215 return nullptr; 216 } 217 218 inputSym->setFragmentRef(mcld::FragmentRef::Create(pFrag, pFrag.size())); 219 inputSym->setValue(/* pValue */0); 220 221 // The output symbol is simply an alias to the input symbol. 222 resolveInfo->setSymPtr(inputSym); 223 224 return resolveInfo; 225} 226 227void ARMGNULDBackend::rewriteARMExIdxSection(Module& pModule) { 228 if (!m_pEXIDX->hasSectionData()) { 229 // Return if this is empty section. 230 return; 231 } 232 233 SectionData* sectData = m_pEXIDX->getSectionData(); 234 SectionData::FragmentListType& list = sectData->getFragmentList(); 235 236 // Move the first fragment (align fragment) and last fragment (null fragment) 237 // to temporary list because we would only like to sort the region fragment. 238 SectionData::FragmentListType tmp; 239 { 240 SectionData::iterator first = sectData->begin(); 241 SectionData::iterator last = sectData->end(); 242 --last; 243 244 assert(first->getKind() == Fragment::Alignment); 245 assert(last->getKind() == Fragment::Null); 246 247 tmp.splice(tmp.end(), list, first); 248 tmp.splice(tmp.end(), list, last); 249 } 250 251 // Sort the region fragments in the .ARM.exidx output section. 252 sort(list, ExIdxFragmentComparator(m_ExData)); 253 254 // Fix the coverage of the .ARM.exidx table. 255 llvm::StringRef cantUnwindRegion(g_CantUnwindEntry, 256 sizeof(g_CantUnwindEntry)); 257 258 SectionData::FragmentListType::iterator it = list.begin(); 259 if (it != list.end()) { 260 Fragment* prevTextFrag = m_ExData.getTupleByExIdx(it)->getTextFragment(); 261 uint64_t prevTextEnd = prevTextFrag->getParent()->getSection().addr() + 262 prevTextFrag->getOffset() + 263 prevTextFrag->size(); 264 ++it; 265 while (it != list.end()) { 266 Fragment* currTextFrag = m_ExData.getTupleByExIdx(it)->getTextFragment(); 267 uint64_t currTextBegin = currTextFrag->getParent()->getSection().addr() + 268 currTextFrag->getOffset(); 269 270 if (currTextBegin > prevTextEnd) { 271 // Found a gap. Insert a can't unwind entry. 272 RegionFragment* frag = new RegionFragment(cantUnwindRegion, nullptr); 273 frag->setParent(sectData); 274 list.insert(it, frag); 275 276 // Add PREL31 reference to the beginning of the uncovered region. 277 Relocation* reloc = 278 Relocation::Create(static_cast<uint32_t>(llvm::ELF::R_ARM_PREL31), 279 *FragmentRef::Create(*frag, /* pOffset */0), 280 /* pAddend */0); 281 reloc->setSymInfo( 282 CreateLocalSymbolToFragmentEnd(pModule, *prevTextFrag)); 283 addExtraRelocation(reloc); 284 } 285 286 prevTextEnd = currTextBegin + currTextFrag->size(); 287 prevTextFrag = currTextFrag; 288 ++it; 289 } 290 291 // Add a can't unwind entry to terminate .ARM.exidx section. 292 RegionFragment* frag = new RegionFragment(cantUnwindRegion, nullptr); 293 frag->setParent(sectData); 294 list.push_back(frag); 295 296 // Add PREL31 reference to the end of the .text section. 297 Relocation* reloc = 298 Relocation::Create(static_cast<uint32_t>(llvm::ELF::R_ARM_PREL31), 299 *FragmentRef::Create(*frag, /* pOffset */0), 300 /* pAddend */0); 301 reloc->setSymInfo(CreateLocalSymbolToFragmentEnd(pModule, *prevTextFrag)); 302 addExtraRelocation(reloc); 303 } 304 305 // Add the first and the last fragment back. 306 list.splice(list.begin(), tmp, tmp.begin()); 307 list.splice(list.end(), tmp, tmp.begin()); 308 309 // Update the fragment offsets. 310 uint64_t offset = 0; 311 for (SectionData::iterator it = sectData->begin(), end = sectData->end(); 312 it != end; ++it) { 313 it->setOffset(offset); 314 offset += it->size(); 315 } 316 317 // Update the section size. 318 m_pEXIDX->setSize(offset); 319 320 // Rebuild the section header. 321 setOutputSectionAddress(pModule); 322} 323 324} // namespace mcld 325