1 //===- ObjectBuilder.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 <mcld/Object/ObjectBuilder.h> 10 11 #include <mcld/Module.h> 12 #include <mcld/LinkerConfig.h> 13 #include <mcld/IRBuilder.h> 14 #include <mcld/Object/SectionMap.h> 15 #include <mcld/LD/LDSection.h> 16 #include <mcld/LD/SectionData.h> 17 #include <mcld/LD/RelocData.h> 18 #include <mcld/LD/EhFrame.h> 19 #include <mcld/Fragment/Relocation.h> 20 #include <mcld/Fragment/AlignFragment.h> 21 #include <mcld/Fragment/NullFragment.h> 22 #include <mcld/Fragment/FillFragment.h> 23 24 #include <llvm/Support/Casting.h> 25 26 using namespace mcld; 27 28 //===----------------------------------------------------------------------===// 29 // ObjectBuilder 30 //===----------------------------------------------------------------------===// 31 ObjectBuilder::ObjectBuilder(const LinkerConfig& pConfig, Module& pTheModule) 32 : m_Config(pConfig), m_Module(pTheModule) { 33 } 34 35 /// CreateSection - create an output section. 36 LDSection* ObjectBuilder::CreateSection(const std::string& pName, 37 LDFileFormat::Kind pKind, 38 uint32_t pType, 39 uint32_t pFlag, 40 uint32_t pAlign) 41 { 42 // try to get one from output LDSection 43 const SectionMap::NamePair& pair = m_Module.getScript().sectionMap().find(pName); 44 std::string output_name = (pair.isNull())?pName:pair.to; 45 LDSection* output_sect = LDSection::Create(output_name, pKind, pType, pFlag); 46 output_sect->setAlign(pAlign); 47 m_Module.getSectionTable().push_back(output_sect); 48 return output_sect; 49 } 50 51 /// MergeSection - merge the pInput section to the pOutput section 52 LDSection* ObjectBuilder::MergeSection(LDSection& pInputSection) 53 { 54 const SectionMap::NamePair& pair = 55 m_Module.getScript().sectionMap().find(pInputSection.name()); 56 std::string output_name = (pair.isNull())?pInputSection.name():pair.to; 57 LDSection* target = m_Module.getSection(output_name); 58 59 if (NULL == target) { 60 target = LDSection::Create(output_name, 61 pInputSection.kind(), 62 pInputSection.type(), 63 pInputSection.flag()); 64 target->setAlign(pInputSection.align()); 65 m_Module.getSectionTable().push_back(target); 66 } 67 68 switch (target->kind()) { 69 // Some *OUTPUT sections should not be merged. 70 case LDFileFormat::Relocation: 71 case LDFileFormat::NamePool: 72 /** do nothing **/ 73 return target; 74 case LDFileFormat::EhFrame: { 75 EhFrame* eh_frame = NULL; 76 if (target->hasEhFrame()) 77 eh_frame = target->getEhFrame(); 78 else 79 eh_frame = IRBuilder::CreateEhFrame(*target); 80 81 eh_frame->merge(*pInputSection.getEhFrame()); 82 UpdateSectionAlign(*target, pInputSection); 83 return target; 84 } 85 default: { 86 SectionData* data = NULL; 87 if (target->hasSectionData()) 88 data = target->getSectionData(); 89 else 90 data = IRBuilder::CreateSectionData(*target); 91 92 if (MoveSectionData(*pInputSection.getSectionData(), *data)) { 93 UpdateSectionAlign(*target, pInputSection); 94 return target; 95 } 96 return NULL; 97 } 98 } 99 return target; 100 } 101 102 /// MoveSectionData - move the fragments of pTO section data to pTo 103 bool ObjectBuilder::MoveSectionData(SectionData& pFrom, SectionData& pTo) 104 { 105 assert(&pFrom != &pTo && "Cannot move section data to itself!"); 106 107 uint32_t offset = pTo.getSection().size(); 108 AlignFragment* align = NULL; 109 if (pFrom.getSection().align() > 1) { 110 // if the align constraint is larger than 1, append an alignment 111 align = new AlignFragment(pFrom.getSection().align(), // alignment 112 0x0, // the filled value 113 1u, // the size of filled value 114 pFrom.getSection().align() - 1 // max bytes to emit 115 ); 116 align->setOffset(offset); 117 align->setParent(&pTo); 118 pTo.getFragmentList().push_back(align); 119 offset += align->size(); 120 } 121 122 // move fragments from pFrom to pTO 123 SectionData::FragmentListType& from_list = pFrom.getFragmentList(); 124 SectionData::FragmentListType& to_list = pTo.getFragmentList(); 125 SectionData::FragmentListType::iterator frag, fragEnd = from_list.end(); 126 for (frag = from_list.begin(); frag != fragEnd; ++frag) { 127 frag->setParent(&pTo); 128 frag->setOffset(offset); 129 offset += frag->size(); 130 } 131 to_list.splice(to_list.end(), from_list); 132 133 // set up pTo's header 134 pTo.getSection().setSize(offset); 135 136 return true; 137 } 138 139 /// UpdateSectionFlags - update alignment for input section 140 void ObjectBuilder::UpdateSectionAlign(LDSection& pTo, const LDSection& pFrom) 141 { 142 if (pFrom.align() > pTo.align()) 143 pTo.setAlign(pFrom.align()); 144 } 145 146 /// AppendFragment - To append pFrag to the given SectionData pSD. 147 uint64_t ObjectBuilder::AppendFragment(Fragment& pFrag, 148 SectionData& pSD, 149 uint32_t pAlignConstraint) 150 { 151 // get initial offset. 152 uint32_t offset = 0; 153 if (!pSD.empty()) 154 offset = pSD.back().getOffset() + pSD.back().size(); 155 156 AlignFragment* align = NULL; 157 if (pAlignConstraint > 1) { 158 // if the align constraint is larger than 1, append an alignment 159 align = new AlignFragment(pAlignConstraint, // alignment 160 0x0, // the filled value 161 1u, // the size of filled value 162 pAlignConstraint - 1 // max bytes to emit 163 ); 164 align->setOffset(offset); 165 align->setParent(&pSD); 166 pSD.getFragmentList().push_back(align); 167 offset += align->size(); 168 } 169 170 // append the fragment 171 pFrag.setParent(&pSD); 172 pFrag.setOffset(offset); 173 pSD.getFragmentList().push_back(&pFrag); 174 175 // append the null fragment 176 offset += pFrag.size(); 177 NullFragment* null = new NullFragment(&pSD); 178 null->setOffset(offset); 179 180 if (NULL != align) 181 return align->size() + pFrag.size(); 182 else 183 return pFrag.size(); 184 } 185 186