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