ObjectBuilder.cpp revision 551ae4ebd3e9d137ea668fb83ae4a55b8cfba451
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/// UpdateSectionAlign - 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/// UpdateSectionAlign - update alignment for input section 164void ObjectBuilder::UpdateSectionAlign(LDSection& pSection, 165 uint32_t pAlignConstraint) 166{ 167 if (pSection.align() < pAlignConstraint) 168 pSection.setAlign(pAlignConstraint); 169} 170 171/// AppendFragment - To append pFrag to the given SectionData pSD. 172uint64_t ObjectBuilder::AppendFragment(Fragment& pFrag, 173 SectionData& pSD, 174 uint32_t pAlignConstraint) 175{ 176 // get initial offset. 177 uint64_t offset = 0; 178 if (!pSD.empty()) 179 offset = pSD.back().getOffset() + pSD.back().size(); 180 181 AlignFragment* align = NULL; 182 if (pAlignConstraint > 1) { 183 // if the align constraint is larger than 1, append an alignment 184 align = new AlignFragment(pAlignConstraint, // alignment 185 0x0, // the filled value 186 1u, // the size of filled value 187 pAlignConstraint - 1 // max bytes to emit 188 ); 189 align->setOffset(offset); 190 align->setParent(&pSD); 191 pSD.getFragmentList().push_back(align); 192 offset += align->size(); 193 } 194 195 // append the fragment 196 pFrag.setParent(&pSD); 197 pFrag.setOffset(offset); 198 pSD.getFragmentList().push_back(&pFrag); 199 200 // append the null fragment 201 offset += pFrag.size(); 202 NullFragment* null = new NullFragment(&pSD); 203 null->setOffset(offset); 204 205 if (NULL != align) 206 return align->size() + pFrag.size(); 207 else 208 return pFrag.size(); 209} 210 211