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