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