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