void EmitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) { OS.write(File.Name.data(), File.Name.size()); OS.write('\0'); encodeULEB128(File.DirIdx, OS); encodeULEB128(File.ModTime, OS); encodeULEB128(File.Length, OS); }
void writeCOFF(COFFParser &CP, raw_ostream &OS) { OS << binary_le(CP.Header.Machine) << binary_le(CP.Header.NumberOfSections) << binary_le(CP.Header.TimeDateStamp) << binary_le(CP.Header.PointerToSymbolTable) << binary_le(CP.Header.NumberOfSymbols) << binary_le(CP.Header.SizeOfOptionalHeader) << binary_le(CP.Header.Characteristics); // Output section table. for (std::vector<COFFParser::Section>::const_iterator i = CP.Sections.begin(), e = CP.Sections.end(); i != e; ++i) { OS.write(i->Header.Name, COFF::NameSize); OS << binary_le(i->Header.VirtualSize) << binary_le(i->Header.VirtualAddress) << binary_le(i->Header.SizeOfRawData) << binary_le(i->Header.PointerToRawData) << binary_le(i->Header.PointerToRelocations) << binary_le(i->Header.PointerToLineNumbers) << binary_le(i->Header.NumberOfRelocations) << binary_le(i->Header.NumberOfLineNumbers) << binary_le(i->Header.Characteristics); } // Output section data. for (std::vector<COFFParser::Section>::const_iterator i = CP.Sections.begin(), e = CP.Sections.end(); i != e; ++i) { if (!i->Data.empty()) OS.write(reinterpret_cast<const char*>(&i->Data[0]), i->Data.size()); } // Output symbol table. for (std::vector<COFFParser::Symbol>::const_iterator i = CP.Symbols.begin(), e = CP.Symbols.end(); i != e; ++i) { OS.write(i->Header.Name, COFF::NameSize); OS << binary_le(i->Header.Value) << binary_le(i->Header.SectionNumber) << binary_le(i->Header.Type) << binary_le(i->Header.StorageClass) << binary_le(i->Header.NumberOfAuxSymbols); if (!i->AuxSymbols.empty()) OS.write( reinterpret_cast<const char*>(&i->AuxSymbols[0]) , i->AuxSymbols.size()); } // Output string table. OS.write(&CP.StringTable[0], CP.StringTable.size()); }
void DWARFYAML::EmitPubSection(raw_ostream &OS, const DWARFYAML::PubSection &Sect, bool IsLittleEndian) { writeInteger((uint32_t)Sect.Length, OS, IsLittleEndian); writeInteger((uint16_t)Sect.Version, OS, IsLittleEndian); writeInteger((uint32_t)Sect.UnitOffset, OS, IsLittleEndian); writeInteger((uint32_t)Sect.UnitSize, OS, IsLittleEndian); for (auto Entry : Sect.Entries) { writeInteger((uint32_t)Entry.DieOffset, OS, IsLittleEndian); if (Sect.IsGNUStyle) writeInteger((uint32_t)Entry.Descriptor, OS, IsLittleEndian); OS.write(Entry.Name.data(), Entry.Name.size()); OS.write('\0'); } }
/// Mangle this entity into the given stream. void LinkEntity::mangle(raw_ostream &buffer) const { std::string Old = mangleOld(); std::string New = mangleNew(); std::string Result = NewMangling::selectMangling(Old, New); buffer.write(Result.data(), Result.size()); }
void wpi::write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, optional<size_t> Width) { const size_t kMaxWidth = 128u; size_t W = std::min(kMaxWidth, Width.value_or(0u)); unsigned Nibbles = (64 - countLeadingZeros(N) + 3) / 4; bool Prefix = (Style == HexPrintStyle::PrefixLower || Style == HexPrintStyle::PrefixUpper); bool Upper = (Style == HexPrintStyle::Upper || Style == HexPrintStyle::PrefixUpper); unsigned PrefixChars = Prefix ? 2 : 0; unsigned NumChars = std::max(static_cast<unsigned>(W), std::max(1u, Nibbles) + PrefixChars); char NumberBuffer[kMaxWidth]; ::memset(NumberBuffer, '0', wpi::array_lengthof(NumberBuffer)); if (Prefix) NumberBuffer[1] = 'x'; char *EndPtr = NumberBuffer + NumChars; char *CurPtr = EndPtr; while (N) { unsigned char x = static_cast<unsigned char>(N) % 16; *--CurPtr = hexdigit(x, !Upper); N /= 16; } S.write(NumberBuffer, NumChars); }
int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) { ELFState<ELFT> State(Doc); if (!State.buildSectionIndex()) return 1; std::size_t StartSymIndex = 0; if (!State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Local) || !State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Global) || !State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Weak)) return 1; Elf_Ehdr Header; State.initELFHeader(Header); // TODO: Flesh out section header support. std::vector<Elf_Phdr> PHeaders; State.initProgramHeaders(PHeaders); // XXX: This offset is tightly coupled with the order that we write // things to `OS`. const size_t SectionContentBeginOffset = Header.e_ehsize + Header.e_phentsize * Header.e_phnum + Header.e_shentsize * Header.e_shnum; ContiguousBlobAccumulator CBA(SectionContentBeginOffset); std::vector<Elf_Shdr> SHeaders; if(!State.initSectionHeaders(SHeaders, CBA)) return 1; // Populate SHeaders with implicit sections not present in the Doc for (const auto &Name : State.implicitSectionNames()) if (State.SN2I.get(Name) >= SHeaders.size()) SHeaders.push_back({}); // Initialize the implicit sections auto Index = State.SN2I.get(".symtab"); State.initSymtabSectionHeader(SHeaders[Index], SymtabType::Static, CBA); Index = State.SN2I.get(".strtab"); State.initStrtabSectionHeader(SHeaders[Index], ".strtab", State.DotStrtab, CBA); Index = State.SN2I.get(".shstrtab"); State.initStrtabSectionHeader(SHeaders[Index], ".shstrtab", State.DotShStrtab, CBA); if (State.hasDynamicSymbols()) { Index = State.SN2I.get(".dynsym"); State.initSymtabSectionHeader(SHeaders[Index], SymtabType::Dynamic, CBA); SHeaders[Index].sh_flags |= ELF::SHF_ALLOC; Index = State.SN2I.get(".dynstr"); State.initStrtabSectionHeader(SHeaders[Index], ".dynstr", State.DotDynstr, CBA); SHeaders[Index].sh_flags |= ELF::SHF_ALLOC; } // Now we can decide segment offsets State.setProgramHeaderLayout(PHeaders, SHeaders); OS.write((const char *)&Header, sizeof(Header)); writeArrayData(OS, makeArrayRef(PHeaders)); writeArrayData(OS, makeArrayRef(SHeaders)); CBA.writeBlobToStream(OS); return 0; }
static void writeWithCommas(raw_ostream &S, ArrayRef<char> Buffer) { assert(!Buffer.empty()); ArrayRef<char> ThisGroup; int InitialDigits = ((Buffer.size() - 1) % 3) + 1; ThisGroup = Buffer.take_front(InitialDigits); S.write(ThisGroup.data(), ThisGroup.size()); Buffer = Buffer.drop_front(InitialDigits); assert(Buffer.size() % 3 == 0); while (!Buffer.empty()) { S << ','; ThisGroup = Buffer.take_front(3); S.write(ThisGroup.data(), 3); Buffer = Buffer.drop_front(3); } }
int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) { ELFState<ELFT> State(Doc); if (!State.buildSectionIndex()) return 1; std::size_t StartSymIndex = 0; if (!State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Local) || !State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Global) || !State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Weak)) return 1; Elf_Ehdr Header; State.initELFHeader(Header); // TODO: Flesh out section header support. // TODO: Program headers. // XXX: This offset is tightly coupled with the order that we write // things to `OS`. const size_t SectionContentBeginOffset = Header.e_ehsize + Header.e_shentsize * Header.e_shnum; ContiguousBlobAccumulator CBA(SectionContentBeginOffset); // Doc might not contain .symtab, .strtab and .shstrtab sections, // but we will emit them, so make sure to add them to ShStrTabSHeader. State.DotShStrtab.add(".symtab"); State.DotShStrtab.add(".strtab"); State.DotShStrtab.add(".shstrtab"); std::vector<Elf_Shdr> SHeaders; if(!State.initSectionHeaders(SHeaders, CBA)) return 1; // .symtab section. Elf_Shdr SymtabSHeader; State.initSymtabSectionHeader(SymtabSHeader, CBA); SHeaders.push_back(SymtabSHeader); // .strtab string table header. Elf_Shdr DotStrTabSHeader; State.initStrtabSectionHeader(DotStrTabSHeader, ".strtab", State.DotStrtab, CBA); SHeaders.push_back(DotStrTabSHeader); // .shstrtab string table header. Elf_Shdr ShStrTabSHeader; State.initStrtabSectionHeader(ShStrTabSHeader, ".shstrtab", State.DotShStrtab, CBA); SHeaders.push_back(ShStrTabSHeader); OS.write((const char *)&Header, sizeof(Header)); writeArrayData(OS, makeArrayRef(SHeaders)); CBA.writeBlobToStream(OS); return 0; }
/// \brief Print the given string to a stream, word-wrapping it to /// some number of columns in the process. /// /// \param OS the stream to which the word-wrapping string will be /// emitted. /// \param Str the string to word-wrap and output. /// \param Columns the number of columns to word-wrap to. /// \param Column the column number at which the first character of \p /// Str will be printed. This will be non-zero when part of the first /// line has already been printed. /// \param Bold if the current text should be bold /// \param Indentation the number of spaces to indent any lines beyond /// the first line. /// \returns true if word-wrapping was required, or false if the /// string fit on the first line. static bool printWordWrapped(raw_ostream &OS, StringRef Str, unsigned Columns, unsigned Column = 0, bool Bold = false, unsigned Indentation = WordWrapIndentation) { const unsigned Length = std::min(Str.find('\n'), Str.size()); bool TextNormal = true; // The string used to indent each line. SmallString<16> IndentStr; IndentStr.assign(Indentation, ' '); bool Wrapped = false; for (unsigned WordStart = 0, WordEnd; WordStart < Length; WordStart = WordEnd) { // Find the beginning of the next word. WordStart = skipWhitespace(WordStart, Str, Length); if (WordStart == Length) break; // Find the end of this word. WordEnd = findEndOfWord(WordStart, Str, Length, Column, Columns); // Does this word fit on the current line? unsigned WordLength = WordEnd - WordStart; if (Column + WordLength < Columns) { // This word fits on the current line; print it there. if (WordStart) { OS << ' '; Column += 1; } applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength), TextNormal, Bold); Column += WordLength; continue; } // This word does not fit on the current line, so wrap to the next // line. OS << '\n'; OS.write(&IndentStr[0], Indentation); applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength), TextNormal, Bold); Column = Indentation + WordLength; Wrapped = true; } // Append any remaning text from the message with its existing formatting. applyTemplateHighlighting(OS, Str.substr(Length), TextNormal, Bold); assert(TextNormal && "Text highlighted at end of diagnostic message."); return Wrapped; }
bool RISCVAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { bool HasStdExtC = STI.getFeatureBits()[RISCV::FeatureStdExtC]; unsigned MinNopLen = HasStdExtC ? 2 : 4; if ((Count % MinNopLen) != 0) return false; // The canonical nop on RISC-V is addi x0, x0, 0. uint64_t Nop32Count = Count / 4; for (uint64_t i = Nop32Count; i != 0; --i) OS.write("\x13\0\0\0", 4); // The canonical nop on RVC is c.nop. if (HasStdExtC) { uint64_t Nop16Count = (Count - Nop32Count * 4) / 2; for (uint64_t i = Nop16Count; i != 0; --i) OS.write("\x01\0", 2); } return true; }
bool ARMAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { const uint16_t Thumb1_16bitNopEncoding = 0x46c0; // using MOV r8,r8 const uint16_t Thumb2_16bitNopEncoding = 0xbf00; // NOP const uint32_t ARMv4_NopEncoding = 0xe1a00000; // using MOV r0,r0 const uint32_t ARMv6T2_NopEncoding = 0xe320f000; // NOP if (isThumb()) { const uint16_t nopEncoding = hasNOP() ? Thumb2_16bitNopEncoding : Thumb1_16bitNopEncoding; uint64_t NumNops = Count / 2; for (uint64_t i = 0; i != NumNops; ++i) support::endian::write(OS, nopEncoding, Endian); if (Count & 1) OS << '\0'; return true; } // ARM mode const uint32_t nopEncoding = hasNOP() ? ARMv6T2_NopEncoding : ARMv4_NopEncoding; uint64_t NumNops = Count / 4; for (uint64_t i = 0; i != NumNops; ++i) support::endian::write(OS, nopEncoding, Endian); // FIXME: should this function return false when unable to write exactly // 'Count' bytes with NOP encodings? switch (Count % 4) { default: break; // No leftover bytes to write case 1: OS << '\0'; break; case 2: OS.write("\0\0", 2); break; case 3: OS.write("\0\0\xa0", 3); break; } return true; }
void DWARFYAML::EmitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) { for (auto AbbrevDecl : DI.AbbrevDecls) { encodeULEB128(AbbrevDecl.Code, OS); encodeULEB128(AbbrevDecl.Tag, OS); OS.write(AbbrevDecl.Children); for (auto Attr : AbbrevDecl.Attributes) { encodeULEB128(Attr.Attribute, OS); encodeULEB128(Attr.Form, OS); } encodeULEB128(0, OS); encodeULEB128(0, OS); } }
/// WriteBitcodeToFile - Write the specified module to the specified output /// stream. void llvm::NaClWriteBitcodeToFile(const Module *M, raw_ostream &Out, bool AcceptSupportedOnly) { SmallVector<char, 0> Buffer; Buffer.reserve(256*1024); // Emit the module into the buffer. { NaClBitstreamWriter Stream(Buffer); NaClWriteHeader(Stream, AcceptSupportedOnly); WriteModule(M, Stream); } // Write the generated bitstream to "Out". Out.write((char*)&Buffer.front(), Buffer.size()); }
static void printBSDMemberHeader(raw_ostream &Out, uint64_t Pos, StringRef Name, const sys::TimePoint<std::chrono::seconds> &ModTime, unsigned UID, unsigned GID, unsigned Perms, unsigned Size) { uint64_t PosAfterHeader = Pos + 60 + Name.size(); // Pad so that even 64 bit object files are aligned. unsigned Pad = OffsetToAlignment(PosAfterHeader, 8); unsigned NameWithPadding = Name.size() + Pad; printWithSpacePadding(Out, Twine("#1/") + Twine(NameWithPadding), 16); printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, NameWithPadding + Size); Out << Name; while (Pad--) Out.write(uint8_t(0)); }
void EmitData(raw_ostream &Out, key_type_ref, data_type_ref V, offset_type) { using namespace llvm::support; endian::Writer<little> LE(Out); for (const auto &ProfileData : *V) { const InstrProfRecord &ProfRecord = ProfileData.second; SummaryBuilder->addRecord(ProfRecord); LE.write<uint64_t>(ProfileData.first); // Function hash LE.write<uint64_t>(ProfRecord.Counts.size()); for (uint64_t I : ProfRecord.Counts) LE.write<uint64_t>(I); // Write value data std::unique_ptr<ValueProfData> VDataPtr = ValueProfData::serializeFrom(ProfileData.second); uint32_t S = VDataPtr->getSize(); VDataPtr->swapBytesFromHost(ValueProfDataEndianness); Out.write((const char *)VDataPtr.get(), S); } }
static void write_unsigned_impl(raw_ostream &S, T N, size_t MinDigits, IntegerStyle Style, bool IsNegative) { static_assert(std::is_unsigned<T>::value, "Value is not unsigned!"); char NumberBuffer[128]; std::memset(NumberBuffer, '0', sizeof(NumberBuffer)); size_t Len = 0; Len = format_to_buffer(N, NumberBuffer); if (IsNegative) S << '-'; if (Len < MinDigits && Style != IntegerStyle::Number) { for (size_t I = Len; I < MinDigits; ++I) S << '0'; } if (Style == IntegerStyle::Number) { writeWithCommas(S, ArrayRef<char>(std::end(NumberBuffer) - Len, Len)); } else { S.write(std::end(NumberBuffer) - Len, Len); } }
static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) { using namespace llvm::ELF; typedef typename object::ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr; typedef typename object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr; const ELFYAML::FileHeader &Hdr = Doc.Header; Elf_Ehdr Header; zero(Header); Header.e_ident[EI_MAG0] = 0x7f; Header.e_ident[EI_MAG1] = 'E'; Header.e_ident[EI_MAG2] = 'L'; Header.e_ident[EI_MAG3] = 'F'; Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; bool IsLittleEndian = ELFT::TargetEndianness == support::little; Header.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB; Header.e_ident[EI_VERSION] = EV_CURRENT; Header.e_ident[EI_OSABI] = Hdr.OSABI; Header.e_ident[EI_ABIVERSION] = 0; Header.e_type = Hdr.Type; Header.e_machine = Hdr.Machine; Header.e_version = EV_CURRENT; Header.e_entry = Hdr.Entry; Header.e_flags = Hdr.Flags; Header.e_ehsize = sizeof(Elf_Ehdr); // TODO: Flesh out section header support. // TODO: Program headers. Header.e_shentsize = sizeof(Elf_Shdr); // Immediately following the ELF header. Header.e_shoff = sizeof(Header); const std::vector<ELFYAML::Section> &Sections = Doc.Sections; // "+ 4" for // - SHT_NULL entry (placed first, i.e. 0'th entry) // - symbol table (.symtab) (placed third to last) // - string table (.strtab) (placed second to last) // - section header string table. (placed last) Header.e_shnum = Sections.size() + 4; // Place section header string table last. Header.e_shstrndx = Header.e_shnum - 1; const unsigned DotStrtabSecNo = Header.e_shnum - 2; // XXX: This offset is tightly coupled with the order that we write // things to `OS`. const size_t SectionContentBeginOffset = Header.e_ehsize + Header.e_shentsize * Header.e_shnum; ContiguousBlobAccumulator CBA(SectionContentBeginOffset); SectionNameToIdxMap SN2I; for (unsigned i = 0, e = Sections.size(); i != e; ++i) { StringRef Name = Sections[i].Name; if (Name.empty()) continue; // "+ 1" to take into account the SHT_NULL entry. if (SN2I.addName(Name, i + 1)) { errs() << "error: Repeated section name: '" << Name << "' at YAML section number " << i << ".\n"; return 1; } } ELFState<ELFT> State(CBA, DotStrtabSecNo, SN2I); StringTableBuilder SHStrTab; std::vector<Elf_Shdr> SHeaders; { // Ensure SHN_UNDEF entry is present. An all-zero section header is a // valid SHN_UNDEF entry since SHT_NULL == 0. Elf_Shdr SHdr; zero(SHdr); SHeaders.push_back(SHdr); } for (const auto &Sec : Sections) { Elf_Shdr SHeader; zero(SHeader); SHeader.sh_name = SHStrTab.addString(Sec.Name); SHeader.sh_type = Sec.Type; SHeader.sh_flags = Sec.Flags; SHeader.sh_addr = Sec.Address; Sec.Content.writeAsBinary(CBA.getOSAndAlignedOffset(SHeader.sh_offset)); SHeader.sh_size = Sec.Content.binary_size(); if (!Sec.Link.empty()) { unsigned Index; if (SN2I.lookupSection(Sec.Link, Index)) { errs() << "error: Unknown section referenced: '" << Sec.Link << "' at YAML section '" << Sec.Name << "'.\n"; return 1; } SHeader.sh_link = Index; } SHeader.sh_info = 0; SHeader.sh_addralign = Sec.AddressAlign; SHeader.sh_entsize = 0; SHeaders.push_back(SHeader); } // .symtab section. Elf_Shdr SymtabSHeader; zero(SymtabSHeader); SymtabSHeader.sh_name = SHStrTab.addString(StringRef(".symtab")); handleSymtabSectionHeader<ELFT>(Doc.Symbols, State, SymtabSHeader); SHeaders.push_back(SymtabSHeader); // .strtab string table header. Elf_Shdr DotStrTabSHeader; zero(DotStrTabSHeader); DotStrTabSHeader.sh_name = SHStrTab.addString(StringRef(".strtab")); createStringTableSectionHeader(DotStrTabSHeader, State.getStringTable(), CBA); SHeaders.push_back(DotStrTabSHeader); // Section header string table header. Elf_Shdr SHStrTabSHeader; zero(SHStrTabSHeader); SHStrTabSHeader.sh_name = SHStrTab.addString(StringRef(".shstrtab")); createStringTableSectionHeader(SHStrTabSHeader, SHStrTab, CBA); SHeaders.push_back(SHStrTabSHeader); OS.write((const char *)&Header, sizeof(Header)); writeArrayData(OS, makeArrayRef(SHeaders)); CBA.writeBlobToStream(OS); return 0; }
void HandleTranslationUnit(ASTContext &Ctx) override { auto &SerializedAST = Buffer->Data; OS->write(SerializedAST.data(), SerializedAST.size()); OS->flush(); }
void wasm::writeStr(raw_ostream &OS, StringRef String, const Twine &Msg) { debugWrite(OS.tell(), Msg + " [str[" + Twine(String.size()) + "]: " + String + "]"); encodeULEB128(String.size(), OS); OS.write(String.data(), String.size()); }
static void writeArrayData(raw_ostream &OS, ArrayRef<T> A) { OS.write((const char *)A.data(), arrayDataSize(A)); }
void R600MCCodeEmitter::EmitByte(unsigned int Byte, raw_ostream &OS) const { OS.write((uint8_t) Byte & 0xff); }
void EmitKey(raw_ostream &Out, key_type_ref K, offset_type N) { Out.write(K.data(), N); }
int WasmWriter::writeWasm(raw_ostream &OS) { // Write headers OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic)); writeUint32(OS, Obj.Header.Version); // Write each section for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) { encodeULEB128(Sec->Type, OS); std::string OutString; raw_string_ostream StringStream(OutString); if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) { if (auto Err = writeSectionContent(StringStream, *S)) return Err; } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) { if (auto Err = writeSectionContent(StringStream, *S)) return Err; } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) { if (auto Err = writeSectionContent(StringStream, *S)) return Err; } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) { if (auto Err = writeSectionContent(StringStream, *S)) return Err; } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) { if (auto Err = writeSectionContent(StringStream, *S)) return Err; } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) { if (auto Err = writeSectionContent(StringStream, *S)) return Err; } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) { if (auto Err = writeSectionContent(StringStream, *S)) return Err; } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) { if (auto Err = writeSectionContent(StringStream, *S)) return Err; } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) { if (auto Err = writeSectionContent(StringStream, *S)) return Err; } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) { if (auto Err = writeSectionContent(StringStream, *S)) return Err; } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) { if (auto Err = writeSectionContent(StringStream, *S)) return Err; } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) { if (auto Err = writeSectionContent(StringStream, *S)) return Err; } else { errs() << "Unknown section type: " << Sec->Type << "\n"; return 1; } StringStream.flush(); // Write the section size followed by the content encodeULEB128(OutString.size(), OS); OS << OutString; } // write reloc sections for any section that have relocations for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) { if (Sec->Relocations.empty()) continue; encodeULEB128(wasm::WASM_SEC_CUSTOM, OS); std::string OutString; raw_string_ostream StringStream(OutString); writeRelocSection(StringStream, *Sec); StringStream.flush(); encodeULEB128(OutString.size(), OS); OS << OutString; } return 0; }
static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI, MachineModuleInfo *MMI, int InlineAsmVariant, AsmPrinter *AP, unsigned LocCookie, raw_ostream &OS) { // Switch to the inline assembly variant. OS << "\t.intel_syntax\n\t"; const char *LastEmitted = AsmStr; // One past the last character emitted. unsigned NumOperands = MI->getNumOperands(); while (*LastEmitted) { switch (*LastEmitted) { default: { // Not a special case, emit the string section literally. const char *LiteralEnd = LastEmitted+1; while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' && *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n') ++LiteralEnd; OS.write(LastEmitted, LiteralEnd-LastEmitted); LastEmitted = LiteralEnd; break; } case '\n': ++LastEmitted; // Consume newline character. OS << '\n'; // Indent code with newline. break; case '$': { ++LastEmitted; // Consume '$' character. bool Done = true; // Handle escapes. switch (*LastEmitted) { default: Done = false; break; case '$': ++LastEmitted; // Consume second '$' character. break; } if (Done) break; // If we have ${:foo}, then this is not a real operand reference, it is a // "magic" string reference, just like in .td files. Arrange to call // PrintSpecial. if (LastEmitted[0] == '{' && LastEmitted[1] == ':') { LastEmitted += 2; const char *StrStart = LastEmitted; const char *StrEnd = strchr(StrStart, '}'); if (!StrEnd) report_fatal_error("Unterminated ${:foo} operand in inline asm" " string: '" + Twine(AsmStr) + "'"); std::string Val(StrStart, StrEnd); AP->PrintSpecial(MI, OS, Val.c_str()); LastEmitted = StrEnd+1; break; } const char *IDStart = LastEmitted; const char *IDEnd = IDStart; while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd; unsigned Val; if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val)) report_fatal_error("Bad $ operand number in inline asm string: '" + Twine(AsmStr) + "'"); LastEmitted = IDEnd; if (Val >= NumOperands-1) report_fatal_error("Invalid $ operand number in inline asm string: '" + Twine(AsmStr) + "'"); // Okay, we finally have a value number. Ask the target to print this // operand! unsigned OpNo = InlineAsm::MIOp_FirstOperand; bool Error = false; // Scan to find the machine operand number for the operand. for (; Val; --Val) { if (OpNo >= MI->getNumOperands()) break; unsigned OpFlags = MI->getOperand(OpNo).getImm(); OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1; } // We may have a location metadata attached to the end of the // instruction, and at no point should see metadata at any // other point while processing. It's an error if so. if (OpNo >= MI->getNumOperands() || MI->getOperand(OpNo).isMetadata()) { Error = true; } else { unsigned OpFlags = MI->getOperand(OpNo).getImm(); ++OpNo; // Skip over the ID number. if (InlineAsm::isMemKind(OpFlags)) { Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant, /*Modifier*/ nullptr, OS); } else { Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant, /*Modifier*/ nullptr, OS); } } if (Error) { std::string msg; raw_string_ostream Msg(msg); Msg << "invalid operand in inline asm: '" << AsmStr << "'"; MMI->getModule()->getContext().emitError(LocCookie, Msg.str()); } break; } } } OS << "\n\t.att_syntax\n" << (char)0; // null terminate string. }
static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI, MachineModuleInfo *MMI, int InlineAsmVariant, int AsmPrinterVariant, AsmPrinter *AP, unsigned LocCookie, raw_ostream &OS) { int CurVariant = -1; // The number of the {.|.|.} region we are in. const char *LastEmitted = AsmStr; // One past the last character emitted. unsigned NumOperands = MI->getNumOperands(); OS << '\t'; while (*LastEmitted) { switch (*LastEmitted) { default: { // Not a special case, emit the string section literally. const char *LiteralEnd = LastEmitted+1; while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' && *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n') ++LiteralEnd; if (CurVariant == -1 || CurVariant == AsmPrinterVariant) OS.write(LastEmitted, LiteralEnd-LastEmitted); LastEmitted = LiteralEnd; break; } case '\n': ++LastEmitted; // Consume newline character. OS << '\n'; // Indent code with newline. break; case '$': { ++LastEmitted; // Consume '$' character. bool Done = true; // Handle escapes. switch (*LastEmitted) { default: Done = false; break; case '$': // $$ -> $ if (CurVariant == -1 || CurVariant == AsmPrinterVariant) OS << '$'; ++LastEmitted; // Consume second '$' character. break; case '(': // $( -> same as GCC's { character. ++LastEmitted; // Consume '(' character. if (CurVariant != -1) report_fatal_error("Nested variants found in inline asm string: '" + Twine(AsmStr) + "'"); CurVariant = 0; // We're in the first variant now. break; case '|': ++LastEmitted; // consume '|' character. if (CurVariant == -1) OS << '|'; // this is gcc's behavior for | outside a variant else ++CurVariant; // We're in the next variant. break; case ')': // $) -> same as GCC's } char. ++LastEmitted; // consume ')' character. if (CurVariant == -1) OS << '}'; // this is gcc's behavior for } outside a variant else CurVariant = -1; break; } if (Done) break; bool HasCurlyBraces = false; if (*LastEmitted == '{') { // ${variable} ++LastEmitted; // Consume '{' character. HasCurlyBraces = true; } // If we have ${:foo}, then this is not a real operand reference, it is a // "magic" string reference, just like in .td files. Arrange to call // PrintSpecial. if (HasCurlyBraces && *LastEmitted == ':') { ++LastEmitted; const char *StrStart = LastEmitted; const char *StrEnd = strchr(StrStart, '}'); if (!StrEnd) report_fatal_error("Unterminated ${:foo} operand in inline asm" " string: '" + Twine(AsmStr) + "'"); std::string Val(StrStart, StrEnd); AP->PrintSpecial(MI, OS, Val.c_str()); LastEmitted = StrEnd+1; break; } const char *IDStart = LastEmitted; const char *IDEnd = IDStart; while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd; unsigned Val; if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val)) report_fatal_error("Bad $ operand number in inline asm string: '" + Twine(AsmStr) + "'"); LastEmitted = IDEnd; char Modifier[2] = { 0, 0 }; if (HasCurlyBraces) { // If we have curly braces, check for a modifier character. This // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm. if (*LastEmitted == ':') { ++LastEmitted; // Consume ':' character. if (*LastEmitted == 0) report_fatal_error("Bad ${:} expression in inline asm string: '" + Twine(AsmStr) + "'"); Modifier[0] = *LastEmitted; ++LastEmitted; // Consume modifier character. } if (*LastEmitted != '}') report_fatal_error("Bad ${} expression in inline asm string: '" + Twine(AsmStr) + "'"); ++LastEmitted; // Consume '}' character. } if (Val >= NumOperands-1) report_fatal_error("Invalid $ operand number in inline asm string: '" + Twine(AsmStr) + "'"); // Okay, we finally have a value number. Ask the target to print this // operand! if (CurVariant == -1 || CurVariant == AsmPrinterVariant) { unsigned OpNo = InlineAsm::MIOp_FirstOperand; bool Error = false; // Scan to find the machine operand number for the operand. for (; Val; --Val) { if (OpNo >= MI->getNumOperands()) break; unsigned OpFlags = MI->getOperand(OpNo).getImm(); OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1; } // We may have a location metadata attached to the end of the // instruction, and at no point should see metadata at any // other point while processing. It's an error if so. if (OpNo >= MI->getNumOperands() || MI->getOperand(OpNo).isMetadata()) { Error = true; } else { unsigned OpFlags = MI->getOperand(OpNo).getImm(); ++OpNo; // Skip over the ID number. if (Modifier[0] == 'l') { // Labels are target independent. if (MI->getOperand(OpNo).isBlockAddress()) { const BlockAddress *BA = MI->getOperand(OpNo).getBlockAddress(); MCSymbol *Sym = AP->GetBlockAddressSymbol(BA); Sym->print(OS, AP->MAI); } else if (MI->getOperand(OpNo).isMBB()) { const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol(); Sym->print(OS, AP->MAI); } else { Error = true; } } else { if (InlineAsm::isMemKind(OpFlags)) { Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant, Modifier[0] ? Modifier : nullptr, OS); } else { Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant, Modifier[0] ? Modifier : nullptr, OS); } } } if (Error) { std::string msg; raw_string_ostream Msg(msg); Msg << "invalid operand in inline asm: '" << AsmStr << "'"; MMI->getModule()->getContext().emitError(LocCookie, Msg.str()); } } break; } } } OS << '\n' << (char)0; // null terminate string. }
static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind, bool Deterministic, ArrayRef<MemberData> Members, StringRef StringTable) { // We don't write a symbol table on an archive with no members -- except on // Darwin, where the linker will abort unless the archive has a symbol table. if (StringTable.empty() && !isDarwin(Kind)) return; unsigned NumSyms = 0; for (const MemberData &M : Members) NumSyms += M.Symbols.size(); unsigned Size = 0; unsigned OffsetSize = is64BitKind(Kind) ? sizeof(uint64_t) : sizeof(uint32_t); Size += OffsetSize; // Number of entries if (isBSDLike(Kind)) Size += NumSyms * OffsetSize * 2; // Table else Size += NumSyms * OffsetSize; // Table if (isBSDLike(Kind)) Size += OffsetSize; // byte count Size += StringTable.size(); // ld64 expects the members to be 8-byte aligned for 64-bit content and at // least 4-byte aligned for 32-bit content. Opt for the larger encoding // uniformly. // We do this for all bsd formats because it simplifies aligning members. unsigned Alignment = isBSDLike(Kind) ? 8 : 2; unsigned Pad = OffsetToAlignment(Size, Alignment); Size += Pad; if (isBSDLike(Kind)) { const char *Name = is64BitKind(Kind) ? "__.SYMDEF_64" : "__.SYMDEF"; printBSDMemberHeader(Out, Out.tell(), Name, now(Deterministic), 0, 0, 0, Size); } else { const char *Name = is64BitKind(Kind) ? "/SYM64" : ""; printGNUSmallMemberHeader(Out, Name, now(Deterministic), 0, 0, 0, Size); } uint64_t Pos = Out.tell() + Size; if (isBSDLike(Kind)) printNBits(Out, Kind, NumSyms * 2 * OffsetSize); else printNBits(Out, Kind, NumSyms); for (const MemberData &M : Members) { for (unsigned StringOffset : M.Symbols) { if (isBSDLike(Kind)) printNBits(Out, Kind, StringOffset); printNBits(Out, Kind, Pos); // member offset } Pos += M.Header.size() + M.Data.size() + M.Padding.size(); } if (isBSDLike(Kind)) // byte count of the string table printNBits(Out, Kind, StringTable.size()); Out << StringTable; while (Pad--) Out.write(uint8_t(0)); }
static int writeUint32(raw_ostream &OS, uint32_t Value) { char Data[sizeof(Value)]; support::endian::write32le(Data, Value); OS.write(Data, sizeof(Data)); return 0; }
static int writeUint8(raw_ostream &OS, uint8_t Value) { char Data[sizeof(Value)]; memcpy(Data, &Value, sizeof(Data)); OS.write(Data, sizeof(Data)); return 0; }
/// Mangle this entity into the given stream. void LinkEntity::mangle(raw_ostream &buffer) const { std::string Result = mangleAsString(); buffer.write(Result.data(), Result.size()); }
bool writeCOFF(COFFParser &CP, raw_ostream &OS) { OS << binary_le(CP.Obj.Header.Machine) << binary_le(CP.Obj.Header.NumberOfSections) << binary_le(CP.Obj.Header.TimeDateStamp) << binary_le(CP.Obj.Header.PointerToSymbolTable) << binary_le(CP.Obj.Header.NumberOfSymbols) << binary_le(CP.Obj.Header.SizeOfOptionalHeader) << binary_le(CP.Obj.Header.Characteristics); // Output section table. for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(), e = CP.Obj.Sections.end(); i != e; ++i) { OS.write(i->Header.Name, COFF::NameSize); OS << binary_le(i->Header.VirtualSize) << binary_le(i->Header.VirtualAddress) << binary_le(i->Header.SizeOfRawData) << binary_le(i->Header.PointerToRawData) << binary_le(i->Header.PointerToRelocations) << binary_le(i->Header.PointerToLineNumbers) << binary_le(i->Header.NumberOfRelocations) << binary_le(i->Header.NumberOfLineNumbers) << binary_le(i->Header.Characteristics); } unsigned CurSymbol = 0; StringMap<unsigned> SymbolTableIndexMap; for (std::vector<COFFYAML::Symbol>::iterator I = CP.Obj.Symbols.begin(), E = CP.Obj.Symbols.end(); I != E; ++I) { SymbolTableIndexMap[I->Name] = CurSymbol; CurSymbol += 1 + I->Header.NumberOfAuxSymbols; } // Output section data. for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(), e = CP.Obj.Sections.end(); i != e; ++i) { i->SectionData.writeAsBinary(OS); for (unsigned I2 = 0, E2 = i->Relocations.size(); I2 != E2; ++I2) { const COFFYAML::Relocation &R = i->Relocations[I2]; uint32_t SymbolTableIndex = SymbolTableIndexMap[R.SymbolName]; OS << binary_le(R.VirtualAddress) << binary_le(SymbolTableIndex) << binary_le(R.Type); } } // Output symbol table. for (std::vector<COFFYAML::Symbol>::const_iterator i = CP.Obj.Symbols.begin(), e = CP.Obj.Symbols.end(); i != e; ++i) { OS.write(i->Header.Name, COFF::NameSize); OS << binary_le(i->Header.Value) << binary_le(i->Header.SectionNumber) << binary_le(i->Header.Type) << binary_le(i->Header.StorageClass) << binary_le(i->Header.NumberOfAuxSymbols); if (i->FunctionDefinition) OS << binary_le(i->FunctionDefinition->TagIndex) << binary_le(i->FunctionDefinition->TotalSize) << binary_le(i->FunctionDefinition->PointerToLinenumber) << binary_le(i->FunctionDefinition->PointerToNextFunction) << zeros(i->FunctionDefinition->unused); if (i->bfAndefSymbol) OS << zeros(i->bfAndefSymbol->unused1) << binary_le(i->bfAndefSymbol->Linenumber) << zeros(i->bfAndefSymbol->unused2) << binary_le(i->bfAndefSymbol->PointerToNextFunction) << zeros(i->bfAndefSymbol->unused3); if (i->WeakExternal) OS << binary_le(i->WeakExternal->TagIndex) << binary_le(i->WeakExternal->Characteristics) << zeros(i->WeakExternal->unused); if (!i->File.empty()) { uint32_t NumberOfAuxRecords = (i->File.size() + COFF::SymbolSize - 1) / COFF::SymbolSize; uint32_t NumberOfAuxBytes = NumberOfAuxRecords * COFF::SymbolSize; uint32_t NumZeros = NumberOfAuxBytes - i->File.size(); OS.write(i->File.data(), i->File.size()); for (uint32_t Padding = 0; Padding < NumZeros; ++Padding) OS.write(0); } if (i->SectionDefinition) OS << binary_le(i->SectionDefinition->Length) << binary_le(i->SectionDefinition->NumberOfRelocations) << binary_le(i->SectionDefinition->NumberOfLinenumbers) << binary_le(i->SectionDefinition->CheckSum) << binary_le(i->SectionDefinition->Number) << binary_le(i->SectionDefinition->Selection) << zeros(i->SectionDefinition->unused); if (i->CLRToken) OS << binary_le(i->CLRToken->AuxType) << zeros(i->CLRToken->unused1) << binary_le(i->CLRToken->SymbolTableIndex) << zeros(i->CLRToken->unused2); } // Output string table. OS.write(&CP.StringTable[0], CP.StringTable.size()); return true; }