1//===- yaml2elf - Convert YAML to a ELF object file -----------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9/// 10/// \file 11/// \brief The ELF component of yaml2obj. 12/// 13//===----------------------------------------------------------------------===// 14 15#include "yaml2obj.h" 16#include "llvm/ADT/ArrayRef.h" 17#include "llvm/MC/StringTableBuilder.h" 18#include "llvm/Object/ELFObjectFile.h" 19#include "llvm/ObjectYAML/ELFYAML.h" 20#include "llvm/Support/ELF.h" 21#include "llvm/Support/MemoryBuffer.h" 22#include "llvm/Support/YAMLTraits.h" 23#include "llvm/Support/raw_ostream.h" 24 25using namespace llvm; 26 27// This class is used to build up a contiguous binary blob while keeping 28// track of an offset in the output (which notionally begins at 29// `InitialOffset`). 30namespace { 31class ContiguousBlobAccumulator { 32 const uint64_t InitialOffset; 33 SmallVector<char, 128> Buf; 34 raw_svector_ostream OS; 35 36 /// \returns The new offset. 37 uint64_t padToAlignment(unsigned Align) { 38 if (Align == 0) 39 Align = 1; 40 uint64_t CurrentOffset = InitialOffset + OS.tell(); 41 uint64_t AlignedOffset = alignTo(CurrentOffset, Align); 42 for (; CurrentOffset != AlignedOffset; ++CurrentOffset) 43 OS.write('\0'); 44 return AlignedOffset; // == CurrentOffset; 45 } 46 47public: 48 ContiguousBlobAccumulator(uint64_t InitialOffset_) 49 : InitialOffset(InitialOffset_), Buf(), OS(Buf) {} 50 template <class Integer> 51 raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align) { 52 Offset = padToAlignment(Align); 53 return OS; 54 } 55 void writeBlobToStream(raw_ostream &Out) { Out << OS.str(); } 56}; 57} // end anonymous namespace 58 59// Used to keep track of section and symbol names, so that in the YAML file 60// sections and symbols can be referenced by name instead of by index. 61namespace { 62class NameToIdxMap { 63 StringMap<int> Map; 64public: 65 /// \returns true if name is already present in the map. 66 bool addName(StringRef Name, unsigned i) { 67 return !Map.insert(std::make_pair(Name, (int)i)).second; 68 } 69 /// \returns true if name is not present in the map 70 bool lookup(StringRef Name, unsigned &Idx) const { 71 StringMap<int>::const_iterator I = Map.find(Name); 72 if (I == Map.end()) 73 return true; 74 Idx = I->getValue(); 75 return false; 76 } 77}; 78} // end anonymous namespace 79 80template <class T> 81static size_t arrayDataSize(ArrayRef<T> A) { 82 return A.size() * sizeof(T); 83} 84 85template <class T> 86static void writeArrayData(raw_ostream &OS, ArrayRef<T> A) { 87 OS.write((const char *)A.data(), arrayDataSize(A)); 88} 89 90template <class T> 91static void zero(T &Obj) { 92 memset(&Obj, 0, sizeof(Obj)); 93} 94 95namespace { 96/// \brief "Single point of truth" for the ELF file construction. 97/// TODO: This class still has a ways to go before it is truly a "single 98/// point of truth". 99template <class ELFT> 100class ELFState { 101 typedef typename object::ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr; 102 typedef typename object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr; 103 typedef typename object::ELFFile<ELFT>::Elf_Sym Elf_Sym; 104 typedef typename object::ELFFile<ELFT>::Elf_Rel Elf_Rel; 105 typedef typename object::ELFFile<ELFT>::Elf_Rela Elf_Rela; 106 107 /// \brief The future ".strtab" section. 108 StringTableBuilder DotStrtab{StringTableBuilder::ELF}; 109 110 /// \brief The future ".shstrtab" section. 111 StringTableBuilder DotShStrtab{StringTableBuilder::ELF}; 112 113 NameToIdxMap SN2I; 114 NameToIdxMap SymN2I; 115 const ELFYAML::Object &Doc; 116 117 bool buildSectionIndex(); 118 bool buildSymbolIndex(std::size_t &StartIndex, 119 const std::vector<ELFYAML::Symbol> &Symbols); 120 void initELFHeader(Elf_Ehdr &Header); 121 bool initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, 122 ContiguousBlobAccumulator &CBA); 123 void initSymtabSectionHeader(Elf_Shdr &SHeader, 124 ContiguousBlobAccumulator &CBA); 125 void initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name, 126 StringTableBuilder &STB, 127 ContiguousBlobAccumulator &CBA); 128 void addSymbols(const std::vector<ELFYAML::Symbol> &Symbols, 129 std::vector<Elf_Sym> &Syms, unsigned SymbolBinding); 130 void writeSectionContent(Elf_Shdr &SHeader, 131 const ELFYAML::RawContentSection &Section, 132 ContiguousBlobAccumulator &CBA); 133 bool writeSectionContent(Elf_Shdr &SHeader, 134 const ELFYAML::RelocationSection &Section, 135 ContiguousBlobAccumulator &CBA); 136 bool writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::Group &Group, 137 ContiguousBlobAccumulator &CBA); 138 bool writeSectionContent(Elf_Shdr &SHeader, 139 const ELFYAML::MipsABIFlags &Section, 140 ContiguousBlobAccumulator &CBA); 141 142 // - SHT_NULL entry (placed first, i.e. 0'th entry) 143 // - symbol table (.symtab) (placed third to last) 144 // - string table (.strtab) (placed second to last) 145 // - section header string table (.shstrtab) (placed last) 146 unsigned getDotSymTabSecNo() const { return Doc.Sections.size() + 1; } 147 unsigned getDotStrTabSecNo() const { return Doc.Sections.size() + 2; } 148 unsigned getDotShStrTabSecNo() const { return Doc.Sections.size() + 3; } 149 unsigned getSectionCount() const { return Doc.Sections.size() + 4; } 150 151 ELFState(const ELFYAML::Object &D) : Doc(D) {} 152 153public: 154 static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc); 155}; 156} // end anonymous namespace 157 158template <class ELFT> 159void ELFState<ELFT>::initELFHeader(Elf_Ehdr &Header) { 160 using namespace llvm::ELF; 161 zero(Header); 162 Header.e_ident[EI_MAG0] = 0x7f; 163 Header.e_ident[EI_MAG1] = 'E'; 164 Header.e_ident[EI_MAG2] = 'L'; 165 Header.e_ident[EI_MAG3] = 'F'; 166 Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; 167 bool IsLittleEndian = ELFT::TargetEndianness == support::little; 168 Header.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB; 169 Header.e_ident[EI_VERSION] = EV_CURRENT; 170 Header.e_ident[EI_OSABI] = Doc.Header.OSABI; 171 Header.e_ident[EI_ABIVERSION] = 0; 172 Header.e_type = Doc.Header.Type; 173 Header.e_machine = Doc.Header.Machine; 174 Header.e_version = EV_CURRENT; 175 Header.e_entry = Doc.Header.Entry; 176 Header.e_flags = Doc.Header.Flags; 177 Header.e_ehsize = sizeof(Elf_Ehdr); 178 Header.e_shentsize = sizeof(Elf_Shdr); 179 // Immediately following the ELF header. 180 Header.e_shoff = sizeof(Header); 181 Header.e_shnum = getSectionCount(); 182 Header.e_shstrndx = getDotShStrTabSecNo(); 183} 184 185template <class ELFT> 186bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, 187 ContiguousBlobAccumulator &CBA) { 188 // Ensure SHN_UNDEF entry is present. An all-zero section header is a 189 // valid SHN_UNDEF entry since SHT_NULL == 0. 190 Elf_Shdr SHeader; 191 zero(SHeader); 192 SHeaders.push_back(SHeader); 193 194 for (const auto &Sec : Doc.Sections) 195 DotShStrtab.add(Sec->Name); 196 DotShStrtab.finalize(); 197 198 for (const auto &Sec : Doc.Sections) { 199 zero(SHeader); 200 SHeader.sh_name = DotShStrtab.getOffset(Sec->Name); 201 SHeader.sh_type = Sec->Type; 202 SHeader.sh_flags = Sec->Flags; 203 SHeader.sh_addr = Sec->Address; 204 SHeader.sh_addralign = Sec->AddressAlign; 205 206 if (!Sec->Link.empty()) { 207 unsigned Index; 208 if (SN2I.lookup(Sec->Link, Index)) { 209 errs() << "error: Unknown section referenced: '" << Sec->Link 210 << "' at YAML section '" << Sec->Name << "'.\n"; 211 return false; 212 } 213 SHeader.sh_link = Index; 214 } 215 216 if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec.get())) 217 writeSectionContent(SHeader, *S, CBA); 218 else if (auto S = dyn_cast<ELFYAML::RelocationSection>(Sec.get())) { 219 if (S->Link.empty()) 220 // For relocation section set link to .symtab by default. 221 SHeader.sh_link = getDotSymTabSecNo(); 222 223 unsigned Index; 224 if (SN2I.lookup(S->Info, Index)) { 225 if (S->Info.getAsInteger(0, Index)) { 226 errs() << "error: Unknown section referenced: '" << S->Info 227 << "' at YAML section '" << S->Name << "'.\n"; 228 return false; 229 } 230 } 231 SHeader.sh_info = Index; 232 233 if (!writeSectionContent(SHeader, *S, CBA)) 234 return false; 235 } else if (auto S = dyn_cast<ELFYAML::Group>(Sec.get())) { 236 unsigned SymIdx; 237 if (SymN2I.lookup(S->Info, SymIdx)) { 238 errs() << "error: Unknown symbol referenced: '" << S->Info 239 << "' at YAML section '" << S->Name << "'.\n"; 240 return false; 241 } 242 SHeader.sh_info = SymIdx; 243 if (!writeSectionContent(SHeader, *S, CBA)) 244 return false; 245 } else if (auto S = dyn_cast<ELFYAML::MipsABIFlags>(Sec.get())) { 246 if (!writeSectionContent(SHeader, *S, CBA)) 247 return false; 248 } else if (auto S = dyn_cast<ELFYAML::NoBitsSection>(Sec.get())) { 249 SHeader.sh_entsize = 0; 250 SHeader.sh_size = S->Size; 251 // SHT_NOBITS section does not have content 252 // so just to setup the section offset. 253 CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); 254 } else 255 llvm_unreachable("Unknown section type"); 256 257 SHeaders.push_back(SHeader); 258 } 259 return true; 260} 261 262template <class ELFT> 263void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader, 264 ContiguousBlobAccumulator &CBA) { 265 zero(SHeader); 266 SHeader.sh_name = DotShStrtab.getOffset(".symtab"); 267 SHeader.sh_type = ELF::SHT_SYMTAB; 268 SHeader.sh_link = getDotStrTabSecNo(); 269 // One greater than symbol table index of the last local symbol. 270 SHeader.sh_info = Doc.Symbols.Local.size() + 1; 271 SHeader.sh_entsize = sizeof(Elf_Sym); 272 SHeader.sh_addralign = 8; 273 274 std::vector<Elf_Sym> Syms; 275 { 276 // Ensure STN_UNDEF is present 277 Elf_Sym Sym; 278 zero(Sym); 279 Syms.push_back(Sym); 280 } 281 282 // Add symbol names to .strtab. 283 for (const auto &Sym : Doc.Symbols.Local) 284 DotStrtab.add(Sym.Name); 285 for (const auto &Sym : Doc.Symbols.Global) 286 DotStrtab.add(Sym.Name); 287 for (const auto &Sym : Doc.Symbols.Weak) 288 DotStrtab.add(Sym.Name); 289 DotStrtab.finalize(); 290 291 addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL); 292 addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL); 293 addSymbols(Doc.Symbols.Weak, Syms, ELF::STB_WEAK); 294 295 writeArrayData( 296 CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign), 297 makeArrayRef(Syms)); 298 SHeader.sh_size = arrayDataSize(makeArrayRef(Syms)); 299} 300 301template <class ELFT> 302void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name, 303 StringTableBuilder &STB, 304 ContiguousBlobAccumulator &CBA) { 305 zero(SHeader); 306 SHeader.sh_name = DotShStrtab.getOffset(Name); 307 SHeader.sh_type = ELF::SHT_STRTAB; 308 CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign) 309 << STB.data(); 310 SHeader.sh_size = STB.data().size(); 311 SHeader.sh_addralign = 1; 312} 313 314template <class ELFT> 315void ELFState<ELFT>::addSymbols(const std::vector<ELFYAML::Symbol> &Symbols, 316 std::vector<Elf_Sym> &Syms, 317 unsigned SymbolBinding) { 318 for (const auto &Sym : Symbols) { 319 Elf_Sym Symbol; 320 zero(Symbol); 321 if (!Sym.Name.empty()) 322 Symbol.st_name = DotStrtab.getOffset(Sym.Name); 323 Symbol.setBindingAndType(SymbolBinding, Sym.Type); 324 if (!Sym.Section.empty()) { 325 unsigned Index; 326 if (SN2I.lookup(Sym.Section, Index)) { 327 errs() << "error: Unknown section referenced: '" << Sym.Section 328 << "' by YAML symbol " << Sym.Name << ".\n"; 329 exit(1); 330 } 331 Symbol.st_shndx = Index; 332 } // else Symbol.st_shndex == SHN_UNDEF (== 0), since it was zero'd earlier. 333 Symbol.st_value = Sym.Value; 334 Symbol.st_other = Sym.Other; 335 Symbol.st_size = Sym.Size; 336 Syms.push_back(Symbol); 337 } 338} 339 340template <class ELFT> 341void 342ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, 343 const ELFYAML::RawContentSection &Section, 344 ContiguousBlobAccumulator &CBA) { 345 assert(Section.Size >= Section.Content.binary_size() && 346 "Section size and section content are inconsistent"); 347 raw_ostream &OS = 348 CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); 349 Section.Content.writeAsBinary(OS); 350 for (auto i = Section.Content.binary_size(); i < Section.Size; ++i) 351 OS.write(0); 352 SHeader.sh_entsize = 0; 353 SHeader.sh_size = Section.Size; 354} 355 356static bool isMips64EL(const ELFYAML::Object &Doc) { 357 return Doc.Header.Machine == ELFYAML::ELF_EM(llvm::ELF::EM_MIPS) && 358 Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64) && 359 Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB); 360} 361 362template <class ELFT> 363bool 364ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, 365 const ELFYAML::RelocationSection &Section, 366 ContiguousBlobAccumulator &CBA) { 367 assert((Section.Type == llvm::ELF::SHT_REL || 368 Section.Type == llvm::ELF::SHT_RELA) && 369 "Section type is not SHT_REL nor SHT_RELA"); 370 371 bool IsRela = Section.Type == llvm::ELF::SHT_RELA; 372 SHeader.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); 373 SHeader.sh_size = SHeader.sh_entsize * Section.Relocations.size(); 374 375 auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); 376 377 for (const auto &Rel : Section.Relocations) { 378 unsigned SymIdx = 0; 379 // Some special relocation, R_ARM_v4BX for instance, does not have 380 // an external reference. So it ignores the return value of lookup() 381 // here. 382 SymN2I.lookup(Rel.Symbol, SymIdx); 383 384 if (IsRela) { 385 Elf_Rela REntry; 386 zero(REntry); 387 REntry.r_offset = Rel.Offset; 388 REntry.r_addend = Rel.Addend; 389 REntry.setSymbolAndType(SymIdx, Rel.Type, isMips64EL(Doc)); 390 OS.write((const char *)&REntry, sizeof(REntry)); 391 } else { 392 Elf_Rel REntry; 393 zero(REntry); 394 REntry.r_offset = Rel.Offset; 395 REntry.setSymbolAndType(SymIdx, Rel.Type, isMips64EL(Doc)); 396 OS.write((const char *)&REntry, sizeof(REntry)); 397 } 398 } 399 return true; 400} 401 402template <class ELFT> 403bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, 404 const ELFYAML::Group &Section, 405 ContiguousBlobAccumulator &CBA) { 406 typedef typename object::ELFFile<ELFT>::Elf_Word Elf_Word; 407 assert(Section.Type == llvm::ELF::SHT_GROUP && 408 "Section type is not SHT_GROUP"); 409 410 SHeader.sh_entsize = sizeof(Elf_Word); 411 SHeader.sh_size = SHeader.sh_entsize * Section.Members.size(); 412 413 auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); 414 415 for (auto member : Section.Members) { 416 Elf_Word SIdx; 417 unsigned int sectionIndex = 0; 418 if (member.sectionNameOrType == "GRP_COMDAT") 419 sectionIndex = llvm::ELF::GRP_COMDAT; 420 else if (SN2I.lookup(member.sectionNameOrType, sectionIndex)) { 421 errs() << "error: Unknown section referenced: '" 422 << member.sectionNameOrType << "' at YAML section' " 423 << Section.Name << "\n"; 424 return false; 425 } 426 SIdx = sectionIndex; 427 OS.write((const char *)&SIdx, sizeof(SIdx)); 428 } 429 return true; 430} 431 432template <class ELFT> 433bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, 434 const ELFYAML::MipsABIFlags &Section, 435 ContiguousBlobAccumulator &CBA) { 436 assert(Section.Type == llvm::ELF::SHT_MIPS_ABIFLAGS && 437 "Section type is not SHT_MIPS_ABIFLAGS"); 438 439 object::Elf_Mips_ABIFlags<ELFT> Flags; 440 zero(Flags); 441 SHeader.sh_entsize = sizeof(Flags); 442 SHeader.sh_size = SHeader.sh_entsize; 443 444 auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); 445 Flags.version = Section.Version; 446 Flags.isa_level = Section.ISALevel; 447 Flags.isa_rev = Section.ISARevision; 448 Flags.gpr_size = Section.GPRSize; 449 Flags.cpr1_size = Section.CPR1Size; 450 Flags.cpr2_size = Section.CPR2Size; 451 Flags.fp_abi = Section.FpABI; 452 Flags.isa_ext = Section.ISAExtension; 453 Flags.ases = Section.ASEs; 454 Flags.flags1 = Section.Flags1; 455 Flags.flags2 = Section.Flags2; 456 OS.write((const char *)&Flags, sizeof(Flags)); 457 458 return true; 459} 460 461template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() { 462 SN2I.addName(".symtab", getDotSymTabSecNo()); 463 SN2I.addName(".strtab", getDotStrTabSecNo()); 464 SN2I.addName(".shstrtab", getDotShStrTabSecNo()); 465 466 for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) { 467 StringRef Name = Doc.Sections[i]->Name; 468 if (Name.empty()) 469 continue; 470 // "+ 1" to take into account the SHT_NULL entry. 471 if (SN2I.addName(Name, i + 1)) { 472 errs() << "error: Repeated section name: '" << Name 473 << "' at YAML section number " << i << ".\n"; 474 return false; 475 } 476 } 477 return true; 478} 479 480template <class ELFT> 481bool 482ELFState<ELFT>::buildSymbolIndex(std::size_t &StartIndex, 483 const std::vector<ELFYAML::Symbol> &Symbols) { 484 for (const auto &Sym : Symbols) { 485 ++StartIndex; 486 if (Sym.Name.empty()) 487 continue; 488 if (SymN2I.addName(Sym.Name, StartIndex)) { 489 errs() << "error: Repeated symbol name: '" << Sym.Name << "'.\n"; 490 return false; 491 } 492 } 493 return true; 494} 495 496template <class ELFT> 497int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) { 498 ELFState<ELFT> State(Doc); 499 if (!State.buildSectionIndex()) 500 return 1; 501 502 std::size_t StartSymIndex = 0; 503 if (!State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Local) || 504 !State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Global) || 505 !State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Weak)) 506 return 1; 507 508 Elf_Ehdr Header; 509 State.initELFHeader(Header); 510 511 // TODO: Flesh out section header support. 512 // TODO: Program headers. 513 514 // XXX: This offset is tightly coupled with the order that we write 515 // things to `OS`. 516 const size_t SectionContentBeginOffset = 517 Header.e_ehsize + Header.e_shentsize * Header.e_shnum; 518 ContiguousBlobAccumulator CBA(SectionContentBeginOffset); 519 520 // Doc might not contain .symtab, .strtab and .shstrtab sections, 521 // but we will emit them, so make sure to add them to ShStrTabSHeader. 522 State.DotShStrtab.add(".symtab"); 523 State.DotShStrtab.add(".strtab"); 524 State.DotShStrtab.add(".shstrtab"); 525 526 std::vector<Elf_Shdr> SHeaders; 527 if(!State.initSectionHeaders(SHeaders, CBA)) 528 return 1; 529 530 // .symtab section. 531 Elf_Shdr SymtabSHeader; 532 State.initSymtabSectionHeader(SymtabSHeader, CBA); 533 SHeaders.push_back(SymtabSHeader); 534 535 // .strtab string table header. 536 Elf_Shdr DotStrTabSHeader; 537 State.initStrtabSectionHeader(DotStrTabSHeader, ".strtab", State.DotStrtab, 538 CBA); 539 SHeaders.push_back(DotStrTabSHeader); 540 541 // .shstrtab string table header. 542 Elf_Shdr ShStrTabSHeader; 543 State.initStrtabSectionHeader(ShStrTabSHeader, ".shstrtab", State.DotShStrtab, 544 CBA); 545 SHeaders.push_back(ShStrTabSHeader); 546 547 OS.write((const char *)&Header, sizeof(Header)); 548 writeArrayData(OS, makeArrayRef(SHeaders)); 549 CBA.writeBlobToStream(OS); 550 return 0; 551} 552 553static bool is64Bit(const ELFYAML::Object &Doc) { 554 return Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64); 555} 556 557static bool isLittleEndian(const ELFYAML::Object &Doc) { 558 return Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB); 559} 560 561int yaml2elf(llvm::ELFYAML::Object &Doc, raw_ostream &Out) { 562 using object::ELFType; 563 typedef ELFType<support::little, true> LE64; 564 typedef ELFType<support::big, true> BE64; 565 typedef ELFType<support::little, false> LE32; 566 typedef ELFType<support::big, false> BE32; 567 if (is64Bit(Doc)) { 568 if (isLittleEndian(Doc)) 569 return ELFState<LE64>::writeELF(Out, Doc); 570 else 571 return ELFState<BE64>::writeELF(Out, Doc); 572 } else { 573 if (isLittleEndian(Doc)) 574 return ELFState<LE32>::writeELF(Out, Doc); 575 else 576 return ELFState<BE32>::writeELF(Out, Doc); 577 } 578} 579