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