ObjectBuilder.cpp revision 37b74a387bb3993387029859c2d9d051c41c724e
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 25namespace mcld { 26 27//===----------------------------------------------------------------------===// 28// ObjectBuilder 29//===----------------------------------------------------------------------===// 30ObjectBuilder::ObjectBuilder(Module& pTheModule) : 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 // 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 55LDSection* 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 130bool 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 166void 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 172void 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. 179uint64_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