llvm.org GIT mirror llvm / be2ec9b
[yaml2obj][ELF] Convert some static functions into class members to reduce number of arguments. No functional changes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205434 91177308-0d34-0410-b5e6-96231b3b80d8 Simon Atanasyan 5 years ago
1 changed file(s) with 168 addition(s) and 158 deletion(s). Raw diff Collapse all Expand all
133133 memset(&Obj, 0, sizeof(Obj));
134134 }
135135
136 /// \brief Create a string table in `SHeader`, which we assume is already
137 /// zero'd.
138 template
139 static void createStringTableSectionHeader(Elf_Shdr &SHeader,
140 StringTableBuilder &STB,
141 ContiguousBlobAccumulator &CBA) {
142 SHeader.sh_type = ELF::SHT_STRTAB;
143 STB.writeToStream(CBA.getOSAndAlignedOffset(SHeader.sh_offset));
144 SHeader.sh_size = STB.size();
145 SHeader.sh_addralign = 1;
146 }
147
148136 namespace {
149137 /// \brief "Single point of truth" for the ELF file construction.
150138 /// TODO: This class still has a ways to go before it is truly a "single
151139 /// point of truth".
152140 template
153141 class ELFState {
142 typedef typename object::ELFFile::Elf_Ehdr Elf_Ehdr;
143 typedef typename object::ELFFile::Elf_Shdr Elf_Shdr;
144 typedef typename object::ELFFile::Elf_Sym Elf_Sym;
145
154146 /// \brief The future ".strtab" section.
155147 StringTableBuilder DotStrtab;
156148
149 /// \brief The future ".shstrtab" section.
150 StringTableBuilder DotShStrtab;
151
157152 SectionNameToIdxMap SN2I;
158153 const ELFYAML::Object &Doc;
159154
160 public:
161 ELFState(const ELFYAML::Object &D) : Doc(D) {}
155 bool buildSectionIndex();
156 void initELFHeader(Elf_Ehdr &Header);
157 bool initSectionHeaders(std::vector &SHeaders,
158 ContiguousBlobAccumulator &CBA);
159 void initSymtabSectionHeader(Elf_Shdr &SHeader,
160 ContiguousBlobAccumulator &CBA);
161 void initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
162 StringTableBuilder &STB,
163 ContiguousBlobAccumulator &CBA);
164 void addSymbols(const std::vector &Symbols,
165 std::vector &Syms, unsigned SymbolBinding);
162166
163167 // - SHT_NULL entry (placed first, i.e. 0'th entry)
164168 // - symbol table (.symtab) (placed third to last)
169173 unsigned getDotShStrTabSecNo() const { return Doc.Sections.size() + 3; }
170174 unsigned getSectionCount() const { return Doc.Sections.size() + 4; }
171175
172 StringTableBuilder &getStringTable() { return DotStrtab; }
173 SectionNameToIdxMap &getSN2I() { return SN2I; }
174
175 bool buildSectionIndex() {
176 SN2I.addName(".symtab", getDotSymTabSecNo());
177 SN2I.addName(".strtab", getDotStrTabSecNo());
178 SN2I.addName(".shstrtab", getDotShStrTabSecNo());
179
180 for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) {
181 StringRef Name = Doc.Sections[i].Name;
182 if (Name.empty())
183 continue;
184 // "+ 1" to take into account the SHT_NULL entry.
185 if (SN2I.addName(Name, i + 1)) {
186 errs() << "error: Repeated section name: '" << Name
187 << "' at YAML section number " << i << ".\n";
188 return false;
189 }
190 }
191 return true;
192 }
176 ELFState(const ELFYAML::Object &D) : Doc(D) {}
177
178 public:
179 static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc);
193180 };
194181 } // end anonymous namespace
195182
196 // FIXME: At this point it is fairly clear that we need to refactor these
197 // static functions into methods of a class sharing some typedefs. These
198 // ELF type names are insane.
199 template
200 static void
201 addSymbols(const std::vector &Symbols, ELFState &State,
202 std::vector::Elf_Sym> &Syms,
203 unsigned SymbolBinding) {
204 typedef typename object::ELFFile::Elf_Sym Elf_Sym;
183 template
184 void ELFState::initELFHeader(Elf_Ehdr &Header) {
185 using namespace llvm::ELF;
186 zero(Header);
187 Header.e_ident[EI_MAG0] = 0x7f;
188 Header.e_ident[EI_MAG1] = 'E';
189 Header.e_ident[EI_MAG2] = 'L';
190 Header.e_ident[EI_MAG3] = 'F';
191 Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
192 bool IsLittleEndian = ELFT::TargetEndianness == support::little;
193 Header.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
194 Header.e_ident[EI_VERSION] = EV_CURRENT;
195 Header.e_ident[EI_OSABI] = Doc.Header.OSABI;
196 Header.e_ident[EI_ABIVERSION] = 0;
197 Header.e_type = Doc.Header.Type;
198 Header.e_machine = Doc.Header.Machine;
199 Header.e_version = EV_CURRENT;
200 Header.e_entry = Doc.Header.Entry;
201 Header.e_flags = Doc.Header.Flags;
202 Header.e_ehsize = sizeof(Elf_Ehdr);
203 Header.e_shentsize = sizeof(Elf_Shdr);
204 // Immediately following the ELF header.
205 Header.e_shoff = sizeof(Header);
206 Header.e_shnum = getSectionCount();
207 Header.e_shstrndx = getDotShStrTabSecNo();
208 }
209
210 template
211 bool ELFState::initSectionHeaders(std::vector &SHeaders,
212 ContiguousBlobAccumulator &CBA) {
213 // Ensure SHN_UNDEF entry is present. An all-zero section header is a
214 // valid SHN_UNDEF entry since SHT_NULL == 0.
215 Elf_Shdr SHeader;
216 zero(SHeader);
217 SHeaders.push_back(SHeader);
218
219 for (const auto &Sec : Doc.Sections) {
220 zero(SHeader);
221 SHeader.sh_name = DotShStrtab.addString(Sec.Name);
222 SHeader.sh_type = Sec.Type;
223 SHeader.sh_flags = Sec.Flags;
224 SHeader.sh_addr = Sec.Address;
225
226 Sec.Content.writeAsBinary(CBA.getOSAndAlignedOffset(SHeader.sh_offset));
227 SHeader.sh_size = Sec.Content.binary_size();
228
229 if (!Sec.Link.empty()) {
230 unsigned Index;
231 if (SN2I.lookupSection(Sec.Link, Index)) {
232 errs() << "error: Unknown section referenced: '" << Sec.Link
233 << "' at YAML section '" << Sec.Name << "'.\n";
234 return false;;
235 }
236 SHeader.sh_link = Index;
237 }
238 SHeader.sh_info = 0;
239 SHeader.sh_addralign = Sec.AddressAlign;
240 SHeader.sh_entsize = 0;
241 SHeaders.push_back(SHeader);
242 }
243 return true;
244 }
245
246 template
247 void ELFState::initSymtabSectionHeader(Elf_Shdr &SHeader,
248 ContiguousBlobAccumulator &CBA) {
249 zero(SHeader);
250 SHeader.sh_name = DotShStrtab.addString(StringRef(".symtab"));
251 SHeader.sh_type = ELF::SHT_SYMTAB;
252 SHeader.sh_link = getDotStrTabSecNo();
253 // One greater than symbol table index of the last local symbol.
254 SHeader.sh_info = Doc.Symbols.Local.size() + 1;
255 SHeader.sh_entsize = sizeof(Elf_Sym);
256
257 std::vector Syms;
258 {
259 // Ensure STN_UNDEF is present
260 Elf_Sym Sym;
261 zero(Sym);
262 Syms.push_back(Sym);
263 }
264 addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL);
265 addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL);
266 addSymbols(Doc.Symbols.Weak, Syms, ELF::STB_WEAK);
267
268 writeArrayData(CBA.getOSAndAlignedOffset(SHeader.sh_offset),
269 makeArrayRef(Syms));
270 SHeader.sh_size = arrayDataSize(makeArrayRef(Syms));
271 }
272
273 template
274 void ELFState::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
275 StringTableBuilder &STB,
276 ContiguousBlobAccumulator &CBA) {
277 zero(SHeader);
278 SHeader.sh_name = DotShStrtab.addString(Name);
279 SHeader.sh_type = ELF::SHT_STRTAB;
280 STB.writeToStream(CBA.getOSAndAlignedOffset(SHeader.sh_offset));
281 SHeader.sh_size = STB.size();
282 SHeader.sh_addralign = 1;
283 }
284
285 template
286 void ELFState::addSymbols(const std::vector &Symbols,
287 std::vector &Syms,
288 unsigned SymbolBinding) {
205289 for (const auto &Sym : Symbols) {
206290 Elf_Sym Symbol;
207291 zero(Symbol);
208292 if (!Sym.Name.empty())
209 Symbol.st_name = State.getStringTable().addString(Sym.Name);
293 Symbol.st_name = DotStrtab.addString(Sym.Name);
210294 Symbol.setBindingAndType(SymbolBinding, Sym.Type);
211295 if (!Sym.Section.empty()) {
212296 unsigned Index;
213 if (State.getSN2I().lookupSection(Sym.Section, Index)) {
297 if (SN2I.lookupSection(Sym.Section, Index)) {
214298 errs() << "error: Unknown section referenced: '" << Sym.Section
215299 << "' by YAML symbol " << Sym.Name << ".\n";
216300 exit(1);
223307 }
224308 }
225309
226 template
227 static void
228 handleSymtabSectionHeader(const ELFYAML::LocalGlobalWeakSymbols &Symbols,
229 ELFState &State,
230 typename object::ELFFile::Elf_Shdr &SHeader,
231 ContiguousBlobAccumulator &CBA) {
232
233 typedef typename object::ELFFile::Elf_Sym Elf_Sym;
234 SHeader.sh_type = ELF::SHT_SYMTAB;
235 SHeader.sh_link = State.getDotStrTabSecNo();
236 // One greater than symbol table index of the last local symbol.
237 SHeader.sh_info = Symbols.Local.size() + 1;
238 SHeader.sh_entsize = sizeof(Elf_Sym);
239
240 std::vector Syms;
241 {
242 // Ensure STN_UNDEF is present
243 Elf_Sym Sym;
244 zero(Sym);
245 Syms.push_back(Sym);
246 }
247 addSymbols(Symbols.Local, State, Syms, ELF::STB_LOCAL);
248 addSymbols(Symbols.Global, State, Syms, ELF::STB_GLOBAL);
249 addSymbols(Symbols.Weak, State, Syms, ELF::STB_WEAK);
250
251 writeArrayData(CBA.getOSAndAlignedOffset(SHeader.sh_offset),
252 makeArrayRef(Syms));
253 SHeader.sh_size = arrayDataSize(makeArrayRef(Syms));
254 }
255
256 template
257 static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
258 using namespace llvm::ELF;
259 typedef typename object::ELFFile::Elf_Ehdr Elf_Ehdr;
260 typedef typename object::ELFFile::Elf_Shdr Elf_Shdr;
261
310 template bool ELFState::buildSectionIndex() {
311 SN2I.addName(".symtab", getDotSymTabSecNo());
312 SN2I.addName(".strtab", getDotStrTabSecNo());
313 SN2I.addName(".shstrtab", getDotShStrTabSecNo());
314
315 for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) {
316 StringRef Name = Doc.Sections[i].Name;
317 if (Name.empty())
318 continue;
319 // "+ 1" to take into account the SHT_NULL entry.
320 if (SN2I.addName(Name, i + 1)) {
321 errs() << "error: Repeated section name: '" << Name
322 << "' at YAML section number " << i << ".\n";
323 return false;
324 }
325 }
326 return true;
327 }
328
329 template
330 int ELFState::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
262331 ELFState State(Doc);
263332 if (!State.buildSectionIndex())
264333 return 1;
265334
266 const ELFYAML::FileHeader &Hdr = Doc.Header;
267
268335 Elf_Ehdr Header;
269 zero(Header);
270 Header.e_ident[EI_MAG0] = 0x7f;
271 Header.e_ident[EI_MAG1] = 'E';
272 Header.e_ident[EI_MAG2] = 'L';
273 Header.e_ident[EI_MAG3] = 'F';
274 Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
275 bool IsLittleEndian = ELFT::TargetEndianness == support::little;
276 Header.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
277 Header.e_ident[EI_VERSION] = EV_CURRENT;
278 Header.e_ident[EI_OSABI] = Hdr.OSABI;
279 Header.e_ident[EI_ABIVERSION] = 0;
280 Header.e_type = Hdr.Type;
281 Header.e_machine = Hdr.Machine;
282 Header.e_version = EV_CURRENT;
283 Header.e_entry = Hdr.Entry;
284 Header.e_flags = Hdr.Flags;
285 Header.e_ehsize = sizeof(Elf_Ehdr);
336 State.initELFHeader(Header);
286337
287338 // TODO: Flesh out section header support.
288339 // TODO: Program headers.
289
290 Header.e_shentsize = sizeof(Elf_Shdr);
291 // Immediately following the ELF header.
292 Header.e_shoff = sizeof(Header);
293 Header.e_shnum = State.getSectionCount();
294 Header.e_shstrndx = State.getDotShStrTabSecNo();
295340
296341 // XXX: This offset is tightly coupled with the order that we write
297342 // things to `OS`.
299344 Header.e_ehsize + Header.e_shentsize * Header.e_shnum;
300345 ContiguousBlobAccumulator CBA(SectionContentBeginOffset);
301346
302 StringTableBuilder SHStrTab;
303347 std::vector SHeaders;
304 {
305 // Ensure SHN_UNDEF entry is present. An all-zero section header is a
306 // valid SHN_UNDEF entry since SHT_NULL == 0.
307 Elf_Shdr SHdr;
308 zero(SHdr);
309 SHeaders.push_back(SHdr);
310 }
311 for (const auto &Sec : Doc.Sections) {
312 Elf_Shdr SHeader;
313 zero(SHeader);
314 SHeader.sh_name = SHStrTab.addString(Sec.Name);
315 SHeader.sh_type = Sec.Type;
316 SHeader.sh_flags = Sec.Flags;
317 SHeader.sh_addr = Sec.Address;
318
319 Sec.Content.writeAsBinary(CBA.getOSAndAlignedOffset(SHeader.sh_offset));
320 SHeader.sh_size = Sec.Content.binary_size();
321
322 if (!Sec.Link.empty()) {
323 unsigned Index;
324 if (State.getSN2I().lookupSection(Sec.Link, Index)) {
325 errs() << "error: Unknown section referenced: '" << Sec.Link
326 << "' at YAML section '" << Sec.Name << "'.\n";
327 return 1;
328 }
329 SHeader.sh_link = Index;
330 }
331 SHeader.sh_info = 0;
332 SHeader.sh_addralign = Sec.AddressAlign;
333 SHeader.sh_entsize = 0;
334 SHeaders.push_back(SHeader);
335 }
348 if(!State.initSectionHeaders(SHeaders, CBA))
349 return 1;
336350
337351 // .symtab section.
338352 Elf_Shdr SymtabSHeader;
339 zero(SymtabSHeader);
340 SymtabSHeader.sh_name = SHStrTab.addString(StringRef(".symtab"));
341 handleSymtabSectionHeader(Doc.Symbols, State, SymtabSHeader, CBA);
353 State.initSymtabSectionHeader(SymtabSHeader, CBA);
342354 SHeaders.push_back(SymtabSHeader);
343355
344356 // .strtab string table header.
345357 Elf_Shdr DotStrTabSHeader;
346 zero(DotStrTabSHeader);
347 DotStrTabSHeader.sh_name = SHStrTab.addString(StringRef(".strtab"));
348 createStringTableSectionHeader(DotStrTabSHeader, State.getStringTable(), CBA);
358 State.initStrtabSectionHeader(DotStrTabSHeader, ".strtab", State.DotStrtab,
359 CBA);
349360 SHeaders.push_back(DotStrTabSHeader);
350361
351 // Section header string table header.
352 Elf_Shdr SHStrTabSHeader;
353 zero(SHStrTabSHeader);
354 SHStrTabSHeader.sh_name = SHStrTab.addString(StringRef(".shstrtab"));
355 createStringTableSectionHeader(SHStrTabSHeader, SHStrTab, CBA);
356 SHeaders.push_back(SHStrTabSHeader);
362 // .shstrtab string table header.
363 Elf_Shdr ShStrTabSHeader;
364 State.initStrtabSectionHeader(ShStrTabSHeader, ".shstrtab", State.DotShStrtab,
365 CBA);
366 SHeaders.push_back(ShStrTabSHeader);
357367
358368 OS.write((const char *)&Header, sizeof(Header));
359369 writeArrayData(OS, makeArrayRef(SHeaders));
384394 typedef ELFType BE32;
385395 if (is64Bit(Doc)) {
386396 if (isLittleEndian(Doc))
387 return writeELF(outs(), Doc);
397 return ELFState::writeELF(outs(), Doc);
388398 else
389 return writeELF(outs(), Doc);
399 return ELFState::writeELF(outs(), Doc);
390400 } else {
391401 if (isLittleEndian(Doc))
392 return writeELF(outs(), Doc);
402 return ELFState::writeELF(outs(), Doc);
393403 else
394 return writeELF(outs(), Doc);
395 }
396 }
404 return ELFState::writeELF(outs(), Doc);
405 }
406 }