1a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines//===- ARMException.cpp ---------------------------------------------------===// 2a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines// 3a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines// The MCLinker Project 4a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines// 5a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines// This file is distributed under the University of Illinois Open Source 6a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines// License. See LICENSE.TXT for details. 7a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines// 8a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines//===----------------------------------------------------------------------===// 9a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 10a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines#include "ARMException.h" 11a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 12a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines#include "ARMLDBackend.h" 13a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 14a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines#include "mcld/ADT/ilist_sort.h" 15a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines#include "mcld/Fragment/RegionFragment.h" 16a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines#include "mcld/LD/ELFFileFormat.h" 17a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines#include "mcld/LD/LDContext.h" 18a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines#include "mcld/Support/MsgHandling.h" 19a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 20a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines#include <memory> 21a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 2204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hinesstatic const char g_CantUnwindEntry[8] = { 2304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines // Relocation to text section. 2404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines 0, 0, 0, 0, 2504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines // EXIDX_CANTUNWIND (little endian.) 2604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines 1, 0, 0, 0, 2704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines}; 2804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines 29a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesnamespace mcld { 30a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 31a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesvoid ARMExData::addInputMap(Input* pInput, 32a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines std::unique_ptr<ARMInputExMap>&& pExMap) { 33a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines assert(m_Inputs.find(pInput) == m_Inputs.end() && 34a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines "multiple maps for an input"); 35a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 36a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines ARMInputExMap* exMap = pExMap.get(); 37a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 38a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Add mapping to the input-to-exdata map. 39a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines m_Inputs.insert(std::make_pair(pInput, std::move(pExMap))); 40a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 41a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Add mapping to the fragment-to-exdata map. 42a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines for (ARMInputExMap::iterator it = exMap->begin(), end = exMap->end(); 43a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines it != end; ++it) { 44a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines ARMExSectionTuple* exTuple = it->second.get(); 45a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines m_ExIdxToTuple[exTuple->getExIdxFragment()] = exTuple; 46a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 47a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines} 48a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 49a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesvoid ARMGNULDBackend::scanInputExceptionSections(Module& pModule) { 50a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines for (Module::obj_iterator it = pModule.obj_begin(), 51a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines end = pModule.obj_end(); it != end; ++it) { 52a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines Input* input = *it; 53a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines scanInputExceptionSections(pModule, *input); 54a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 55a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines} 56a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 57a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesstatic RegionFragment* findRegionFragment(LDSection& pSection) { 58a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines SectionData* sectData = pSection.getSectionData(); 59a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines for (SectionData::iterator it = sectData->begin(), 60a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines end = sectData->end(); it != end; ++it) { 61a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines if (it->getKind() == Fragment::Region) { 62a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines return static_cast<RegionFragment*>(&*it); 63a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 64a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 65a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines return NULL; 66a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines} 67a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 68a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesvoid ARMGNULDBackend::scanInputExceptionSections(Module& pModule, 69a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines Input& pInput) { 70a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines std::unique_ptr<ARMInputExMap> exMap(new ARMInputExMap()); 71a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 72a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Scan the input and collect all related sections. 73a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines LDContext* ctx = pInput.context(); 74a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines for (LDContext::sect_iterator it = ctx->sectBegin(), 75a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines end = ctx->sectEnd(); it != end; ++it) { 76a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines LDSection* sect = *it; 77a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines llvm::StringRef name(sect->name()); 78a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 79a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines if (name.startswith(".ARM.exidx")) { 80a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines ARMExSectionTuple* exTuple = exMap->getOrCreateByExSection(name); 81a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines exTuple->setExIdxSection(sect); 82a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines exTuple->setTextSection(sect->getLink()); 83a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } else if (name.startswith(".ARM.extab")) { 84a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines ARMExSectionTuple* exTuple = exMap->getOrCreateByExSection(name); 85a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines exTuple->setExTabSection(sect); 86a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } else if (name.startswith(".rel.ARM.exidx")) { 87a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines ARMExSectionTuple* exTuple = exMap->getOrCreateByRelExSection(name); 88a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines exTuple->setRelExIdxSection(sect); 89a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } else if (name.startswith(".rel.ARM.extab")) { 90a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines ARMExSectionTuple* exTuple = exMap->getOrCreateByRelExSection(name); 91a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines exTuple->setRelExIdxSection(sect); 92a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 93a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 94a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 95a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Remove the invalid exception tuples and convert LDSection to RegionFragment 96a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // or RelocData. 97a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines ARMInputExMap::iterator it = exMap->begin(); 98a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines ARMInputExMap::iterator end = exMap->end(); 99a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines while (it != end) { 100a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines ARMExSectionTuple* exTuple = it->second.get(); 101a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines LDSection* const text = exTuple->getTextSection(); 102a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines LDSection* const exIdx = exTuple->getExIdxSection(); 103a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines LDSection* const exTab = exTuple->getExTabSection(); 104a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines LDSection* const relExIdx = exTuple->getRelExIdxSection(); 105a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines LDSection* const relExTab = exTuple->getRelExTabSection(); 106a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 107a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Check the .ARM.exidx section. 108a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines if (!exIdx) { 109a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines if (exTab) { 110a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines fatal(diag::eh_missing_exidx_section) << exTab->name() << pInput.name(); 111a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } else if (relExIdx) { 112a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines fatal(diag::eh_missing_exidx_section) << relExIdx->name() 113a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines << pInput.name(); 114a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } else if (relExTab) { 115a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines fatal(diag::eh_missing_exidx_section) << relExTab->name() 116a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines << pInput.name(); 117a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } else { 118a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines llvm_unreachable("unexpected bad exception tuple"); 119a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 120a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 121a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 122a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Check the text section. 123a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines if (!text) { 124a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines fatal(diag::eh_missing_text_section) << exIdx->name() << pInput.name(); 125a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 126a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 127a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Ignore the exception section if the text section is ignored. 128a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines if ((text->kind() == LDFileFormat::Ignore) || 129a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines (text->kind() == LDFileFormat::Folded)) { 130a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Set the related exception sections as LDFileFormat::Ignore. 131a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines exIdx->setKind(LDFileFormat::Ignore); 132a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines if (exTab) { 133a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines exTab->setKind(LDFileFormat::Ignore); 134a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 135a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Remove this tuple from the input exception map. 136a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines exMap->erase(it++); 137a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines continue; 138a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 139a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 140a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Get RegionFragment from ".text", ".ARM.exidx", and ".ARM.extab" sections. 141a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines RegionFragment* textFrag = findRegionFragment(*text); 142a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines RegionFragment* exIdxFrag = findRegionFragment(*exIdx); 143a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines RegionFragment* exTabFrag = exTab ? findRegionFragment(*exTab) : NULL; 144a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 145a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines exTuple->setTextFragment(textFrag); 146a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines exTuple->setExIdxFragment(exIdxFrag); 147a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines exTuple->setExTabFragment(exTabFrag); 148a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 149a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Get the RelocData from ".rel.ARM.exidx" and ".rel.ARM.extab" sections. 150a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines RelocData* exIdxRD = relExIdx ? relExIdx->getRelocData() : NULL; 151a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines RelocData* exTabRD = relExTab ? relExTab->getRelocData() : NULL; 152a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 153a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines exTuple->setExIdxRelocData(exIdxRD); 154a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines exTuple->setExTabRelocData(exTabRD); 155a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 156a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // If there is no region fragment in the .ARM.extab section, then we can 157a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // skip this tuple. 158a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines if (!exIdxFrag) { 159a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines exMap->erase(it++); 160a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines continue; 161a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 162a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 163a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // TODO: Sort the RelocData w.r.t. the fixup offset. 164a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 165a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Check next tuple 166a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines ++it; 167a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 168a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 169a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Add input map 170a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines m_ExData.addInputMap(&pInput, std::move(exMap)); 171a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines} 172a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 173a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesclass ExIdxFragmentComparator { 174a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines private: 175a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines const ARMExData& m_ExData; 176a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 177a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines public: 17804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines explicit ExIdxFragmentComparator(const ARMExData& pExData) 179a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines : m_ExData(pExData) { 180a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 181a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 182a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines bool operator()(const Fragment& a, const Fragment& b) { 183a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines ARMExSectionTuple* tupleA = m_ExData.getTupleByExIdx(&a); 184a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines ARMExSectionTuple* tupleB = m_ExData.getTupleByExIdx(&b); 185a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 186a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines Fragment* textFragA = tupleA->getTextFragment(); 187a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines Fragment* textFragB = tupleB->getTextFragment(); 188a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 189a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines uint64_t addrA = textFragA->getParent()->getSection().addr() + 190a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines textFragA->getOffset(); 191a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines uint64_t addrB = textFragB->getParent()->getSection().addr() + 192a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines textFragB->getOffset(); 193a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines return (addrA < addrB); 194a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 195a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}; 196a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 19704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hinesstatic mcld::ResolveInfo* 19804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen HinesCreateLocalSymbolToFragmentEnd(mcld::Module& pModule, mcld::Fragment& pFrag) { 19904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines // Create and add symbol to the name pool. 20004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines mcld::ResolveInfo* resolveInfo = 20104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines pModule.getNamePool().createSymbol(/* pName */"", 20204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines /* pIsDyn */false, 20304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines mcld::ResolveInfo::Section, 20404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines mcld::ResolveInfo::Define, 20504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines mcld::ResolveInfo::Local, 20604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines /* pSize */0, 20704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines mcld::ResolveInfo::Hidden); 20804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines if (resolveInfo == nullptr) { 20904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines return nullptr; 21004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines } 21104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines 21204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines // Create input symbol. 21304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines mcld::LDSymbol* inputSym = mcld::LDSymbol::Create(*resolveInfo); 21404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines if (inputSym == nullptr) { 21504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines return nullptr; 21604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines } 21704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines 21804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines inputSym->setFragmentRef(mcld::FragmentRef::Create(pFrag, pFrag.size())); 21904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines inputSym->setValue(/* pValue */0); 22004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines 22104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines // The output symbol is simply an alias to the input symbol. 22204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines resolveInfo->setSymPtr(inputSym); 22304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines 22404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines return resolveInfo; 22504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines} 22604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines 227a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesvoid ARMGNULDBackend::rewriteARMExIdxSection(Module& pModule) { 228a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines if (!m_pEXIDX->hasSectionData()) { 229a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Return if this is empty section. 230a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines return; 231a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 232a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 233a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines SectionData* sectData = m_pEXIDX->getSectionData(); 234a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines SectionData::FragmentListType& list = sectData->getFragmentList(); 235a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 23604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines // Move the first fragment (align fragment) and last fragment (null fragment) 23704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines // to temporary list because we would only like to sort the region fragment. 238a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines SectionData::FragmentListType tmp; 239a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines { 240a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines SectionData::iterator first = sectData->begin(); 241a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines SectionData::iterator last = sectData->end(); 242a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines --last; 243a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 244a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines assert(first->getKind() == Fragment::Alignment); 245a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines assert(last->getKind() == Fragment::Null); 246a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 247a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines tmp.splice(tmp.end(), list, first); 248a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines tmp.splice(tmp.end(), list, last); 249a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 250a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 251a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Sort the region fragments in the .ARM.exidx output section. 252a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines sort(list, ExIdxFragmentComparator(m_ExData)); 253a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 25404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines // Fix the coverage of the .ARM.exidx table. 25504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines llvm::StringRef cantUnwindRegion(g_CantUnwindEntry, 25604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines sizeof(g_CantUnwindEntry)); 25704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines 25804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines SectionData::FragmentListType::iterator it = list.begin(); 25904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines if (it != list.end()) { 26004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines Fragment* prevTextFrag = m_ExData.getTupleByExIdx(it)->getTextFragment(); 26104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines uint64_t prevTextEnd = prevTextFrag->getParent()->getSection().addr() + 26204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines prevTextFrag->getOffset() + 26304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines prevTextFrag->size(); 26404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines ++it; 26504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines while (it != list.end()) { 26604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines Fragment* currTextFrag = m_ExData.getTupleByExIdx(it)->getTextFragment(); 26704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines uint64_t currTextBegin = currTextFrag->getParent()->getSection().addr() + 26804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines currTextFrag->getOffset(); 26904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines 27004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines if (currTextBegin > prevTextEnd) { 27104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines // Found a gap. Insert a can't unwind entry. 27204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines RegionFragment* frag = new RegionFragment(cantUnwindRegion, nullptr); 27304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines frag->setParent(sectData); 27404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines list.insert(it, frag); 27504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines 27604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines // Add PREL31 reference to the beginning of the uncovered region. 27704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines Relocation* reloc = 27804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines Relocation::Create(static_cast<uint32_t>(llvm::ELF::R_ARM_PREL31), 27904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines *FragmentRef::Create(*frag, /* pOffset */0), 28004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines /* pAddend */0); 28104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines reloc->setSymInfo( 28204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines CreateLocalSymbolToFragmentEnd(pModule, *prevTextFrag)); 28304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines addExtraRelocation(reloc); 28404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines } 28504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines 28604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines prevTextEnd = currTextBegin + currTextFrag->size(); 28704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines prevTextFrag = currTextFrag; 28804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines ++it; 28904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines } 29004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines 29104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines // Add a can't unwind entry to terminate .ARM.exidx section. 29204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines RegionFragment* frag = new RegionFragment(cantUnwindRegion, nullptr); 29304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines frag->setParent(sectData); 29404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines list.push_back(frag); 29504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines 29604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines // Add PREL31 reference to the end of the .text section. 29704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines Relocation* reloc = 29804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines Relocation::Create(static_cast<uint32_t>(llvm::ELF::R_ARM_PREL31), 29904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines *FragmentRef::Create(*frag, /* pOffset */0), 30004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines /* pAddend */0); 30104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines reloc->setSymInfo(CreateLocalSymbolToFragmentEnd(pModule, *prevTextFrag)); 30204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines addExtraRelocation(reloc); 30304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines } 30404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines 30504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines // Add the first and the last fragment back. 306a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines list.splice(list.begin(), tmp, tmp.begin()); 307a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines list.splice(list.end(), tmp, tmp.begin()); 308a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 309a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Update the fragment offsets. 310a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines uint64_t offset = 0; 311a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines for (SectionData::iterator it = sectData->begin(), end = sectData->end(); 312a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines it != end; ++it) { 313a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines it->setOffset(offset); 314a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines offset += it->size(); 315a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines } 316a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 31704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines // Update the section size. 31804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines m_pEXIDX->setSize(offset); 31904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines 320a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines // Rebuild the section header. 321a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines setOutputSectionAddress(pModule); 322a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines} 323a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines 324a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines} // namespace mcld 325