Lines Matching +full:os +full:- +full:data +full:- +full:offset
1 //===- lib/MC/WasmObjectWriter.cpp - Wasm File Writer ---------------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
11 //===----------------------------------------------------------------------===//
16 #include "llvm/Config/llvm-config.h"
57 // A wasm data segment. A wasm binary contains only a single data section
59 // in memory. Each MCSection data created by llvm is modeled as its own
60 // wasm data segment.
65 uint64_t Offset; member
68 SmallVector<char, 4> Data; member
83 // Information about a single item which is part of a COMDAT. For each data
93 uint64_t Offset; // Where is the relocation. member
99 WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol, in WasmRelocationEntry()
102 : Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type), in WasmRelocationEntry()
108 Out << wasm::relocTypetoString(Type) << " Off=" << Offset in print()
110 << ", FixupSection=" << FixupSection->getName(); in print()
118 static const uint32_t InvalidIndex = -1;
133 raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) { in operator <<() argument
134 Rel.print(OS); in operator <<()
135 return OS; in operator <<()
139 // Write Value as an (unsigned) LEB value at offset Offset in Stream, padded
142 void writePatchableULEB(raw_pwrite_stream &Stream, T Value, uint64_t Offset) { in writePatchableULEB() argument
146 Stream.pwrite((char *)Buffer, SizeLen, Offset); in writePatchableULEB()
149 // Write Value as an signed LEB value at offset Offset in Stream, padded
152 void writePatchableSLEB(raw_pwrite_stream &Stream, T Value, uint64_t Offset) { in writePatchableSLEB() argument
156 Stream.pwrite((char *)Buffer, SizeLen, Offset); in writePatchableSLEB()
160 uint64_t Offset) { in writePatchableU32() argument
161 writePatchableULEB<uint32_t, 5>(Stream, Value, Offset); in writePatchableU32()
165 uint64_t Offset) { in writePatchableS32() argument
166 writePatchableSLEB<int32_t, 5>(Stream, Value, Offset); in writePatchableS32()
170 uint64_t Offset) { in writePatchableU64() argument
171 writePatchableSLEB<uint64_t, 10>(Stream, Value, Offset); in writePatchableU64()
175 uint64_t Offset) { in writePatchableS64() argument
176 writePatchableSLEB<int64_t, 10>(Stream, Value, Offset); in writePatchableS64()
179 // Write Value as a plain integer value at offset Offset in Stream.
181 uint64_t Offset) { in patchI32() argument
184 Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset); in patchI32()
188 uint64_t Offset) { in patchI64() argument
191 Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset); in patchI64()
206 // Relocations for fixing up references in the data section.
219 // Maps data symbols to the Wasm segment and offset/size with the segment.
222 // Stores output data (index, relocations, content offset) for custom
249 raw_pwrite_stream *OS = nullptr; member in __anon335a907b0111::WasmObjectWriter
253 bool is64Bit() const { return TargetObjectWriter->is64Bit(); } in is64Bit()
254 bool isEmscripten() const { return TargetObjectWriter->isEmscripten(); } in isEmscripten()
263 : TargetObjectWriter(std::move(MOTW)), OS(&OS_) {} in WasmObjectWriter()
267 : TargetObjectWriter(std::move(MOTW)), IsSplitDwarf(true), OS(&OS_), in WasmObjectWriter()
307 encodeULEB128(Str.size(), W->OS); in writeString()
308 W->OS << Str; in writeString()
316 W->OS.write(Buffer, sizeof(Buffer)); in writeI32()
322 W->OS.write(Buffer, sizeof(Buffer)); in writeI64()
325 void writeValueType(wasm::ValType Ty) { W->OS << static_cast<char>(Ty); } in writeValueType()
369 W->OS << char(SectionId); in startSection()
371 Section.SizeOffset = W->OS.tell(); in startSection()
374 // for any 32-bit value; we'll patch it later. in startSection()
375 encodeULEB128(0, W->OS, 5); in startSection()
378 Section.ContentsOffset = W->OS.tell(); in startSection()
379 Section.PayloadOffset = W->OS.tell(); in startSection()
392 uint64_t Offset = W->OS.tell() + StrSizeLength + Str.size(); in writeStringWithAlignment() local
393 uint64_t Paddings = offsetToAlignment(Offset, Align(Alignment)); in writeStringWithAlignment()
394 Offset += Paddings; in writeStringWithAlignment()
399 encodeSLEB128(Str.size(), W->OS, StrSizeLength + Paddings); in writeStringWithAlignment()
400 W->OS << Str; in writeStringWithAlignment()
402 assert(W->OS.tell() == Offset && "invalid padding"); in writeStringWithAlignment()
411 Section.PayloadOffset = W->OS.tell(); in startCustomSection()
417 // The on-disk hashtable in clangast needs to be aligned by 4 bytes. in startCustomSection()
422 Section.ContentsOffset = W->OS.tell(); in startCustomSection()
428 uint64_t Size = W->OS.tell(); in endSection()
429 // /dev/null doesn't support seek/tell and can report offset of 0. in endSection()
434 Size -= Section.PayloadOffset; in endSection()
442 writePatchableU32(static_cast<raw_pwrite_stream &>(W->OS), Size, in endSection()
448 W->OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic)); in writeHeader()
449 W->write<uint32_t>(wasm::WasmVersion); in writeHeader()
455 // without the reference-types feature, and also function bitcasts in all in executePostLayoutBinding()
461 if (WasmSym->isNoStrip()) in executePostLayoutBinding()
487 const auto &FixupSection = cast<MCSectionWasm>(*Fragment->getParent()); in recordRelocation()
495 const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol()); in recordRelocation()
519 C += FixupOffset - Asm.getSymbolOffset(SymB); in recordRelocation()
524 const auto *SymA = cast<MCSymbolWasm>(&RefA->getSymbol()); in recordRelocation()
526 // The .init_array isn't translated as data, so don't do relocations in it. in recordRelocation()
528 SymA->setUsedInInitArray(); in recordRelocation()
532 if (SymA->isVariable()) { in recordRelocation()
533 const MCExpr *Expr = SymA->getVariableValue(); in recordRelocation()
535 if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) in recordRelocation()
539 // Put any constant offset in an addend. Offsets can be negative, and in recordRelocation()
545 TargetObjectWriter->getRelocType(Target, Fixup, FixupSection, IsLocRel); in recordRelocation()
547 // Absolute offset within a section or a function. in recordRelocation()
553 SymA->isDefined()) { in recordRelocation()
554 // SymA can be a temp data symbol that represents a function (in which case in recordRelocation()
557 // function symbol, in which case it can be left as-is. in recordRelocation()
564 const MCSection &SecA = SymA->getSection(); in recordRelocation()
569 SectionSymbol = SecSymIt->second; in recordRelocation()
593 if (!Sym->isFunctionTable()) in recordRelocation()
596 Sym->setNoStrip(); in recordRelocation()
604 if (SymA->getName().empty()) in recordRelocation()
605 report_fatal_error("relocations against un-named temporaries are not yet " in recordRelocation()
608 SymA->setUsedInReloc(); in recordRelocation()
611 switch (RefA->getKind()) { in recordRelocation()
614 SymA->setUsedInGOT(); in recordRelocation()
643 !RelEntry.Symbol->isGlobal()) { in getProvisionalValue()
658 assert(Base->isFunction()); in getProvisionalValue()
661 return TableIndices[Base] - InitialTableOffset; in getProvisionalValue()
680 if (!RelEntry.Symbol->isDefined()) in getProvisionalValue()
683 static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection()); in getProvisionalValue()
697 // Provisional value is address of the global plus the offset in getProvisionalValue()
699 if (!RelEntry.Symbol->isDefined()) in getProvisionalValue()
704 return Segment.Offset + SymRef.Offset + RelEntry.Addend; in getProvisionalValue()
719 report_fatal_error("only data supported in data sections"); in addData()
722 if (Align->getValueSize() != 1) in addData()
724 // If nops are requested, use zeros, as this is the data section. in addData()
725 uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue(); in addData()
727 std::min<uint64_t>(alignTo(DataBytes.size(), Align->getAlignment()), in addData()
728 DataBytes.size() + Align->getMaxBytesToEmit()); in addData()
732 if (!Fill->getNumValues().evaluateAsAbsolute(NumValues)) in addData()
734 DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues, in addData()
735 Fill->getValue()); in addData()
737 const SmallVectorImpl<char> &Contents = LEB->getContents(); in addData()
746 LLVM_DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n"); in addData()
754 RelEntry.Symbol->getName()); in getRelocationIndexValue()
758 return RelEntry.Symbol->getIndex(); in getRelocationIndexValue()
766 auto &Stream = static_cast<raw_pwrite_stream &>(W->OS); in applyRelocations()
768 uint64_t Offset = ContentsOffset + in applyRelocations() local
769 RelEntry.FixupSection->getSectionOffset() + in applyRelocations()
770 RelEntry.Offset; in applyRelocations()
782 writePatchableU32(Stream, Value, Offset); in applyRelocations()
785 writePatchableU64(Stream, Value, Offset); in applyRelocations()
794 patchI32(Stream, Value, Offset); in applyRelocations()
799 patchI64(Stream, Value, Offset); in applyRelocations()
806 writePatchableS32(Stream, Value, Offset); in applyRelocations()
813 writePatchableS64(Stream, Value, Offset); in applyRelocations()
829 encodeULEB128(Signatures.size(), W->OS); in writeTypeSection()
832 W->OS << char(wasm::WASM_TYPE_FUNC); in writeTypeSection()
833 encodeULEB128(Sig.Params.size(), W->OS); in writeTypeSection()
836 encodeULEB128(Sig.Returns.size(), W->OS); in writeTypeSection()
850 uint64_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize; in writeImportSection()
855 encodeULEB128(Imports.size(), W->OS); in writeImportSection()
859 W->OS << char(Import.Kind); in writeImportSection()
863 encodeULEB128(Import.SigIndex, W->OS); in writeImportSection()
866 W->OS << char(Import.Global.Type); in writeImportSection()
867 W->OS << char(Import.Global.Mutable ? 1 : 0); in writeImportSection()
870 encodeULEB128(Import.Memory.Flags, W->OS); in writeImportSection()
871 encodeULEB128(NumPages, W->OS); // initial in writeImportSection()
874 W->OS << char(Import.Table.ElemType); in writeImportSection()
875 encodeULEB128(Import.Table.Limits.Flags, W->OS); in writeImportSection()
876 encodeULEB128(NumElements, W->OS); // initial in writeImportSection()
879 W->OS << char(0); // Reserved 'attribute' field in writeImportSection()
880 encodeULEB128(Import.SigIndex, W->OS); in writeImportSection()
897 encodeULEB128(Functions.size(), W->OS); in writeFunctionSection()
899 encodeULEB128(Func.SigIndex, W->OS); in writeFunctionSection()
911 encodeULEB128(TagTypes.size(), W->OS); in writeTagSection()
913 W->OS << char(0); // Reserved 'attribute' field in writeTagSection()
914 encodeULEB128(Index, W->OS); in writeTagSection()
927 encodeULEB128(Globals.size(), W->OS); in writeGlobalSection()
929 encodeULEB128(Global.Type.Type, W->OS); in writeGlobalSection()
930 W->OS << char(Global.Type.Mutable); in writeGlobalSection()
934 W->OS << char(Global.InitExpr.Inst.Opcode); in writeGlobalSection()
937 encodeSLEB128(0, W->OS); in writeGlobalSection()
940 encodeSLEB128(0, W->OS); in writeGlobalSection()
955 W->OS << char(wasm::WASM_OPCODE_END); in writeGlobalSection()
968 encodeULEB128(Tables.size(), W->OS); in writeTableSection()
971 "Cannot encode general ref-typed tables"); in writeTableSection()
972 encodeULEB128((uint32_t)Table.Type.ElemType, W->OS); in writeTableSection()
973 encodeULEB128(Table.Type.Limits.Flags, W->OS); in writeTableSection()
974 encodeULEB128(Table.Type.Limits.Minimum, W->OS); in writeTableSection()
976 encodeULEB128(Table.Type.Limits.Maximum, W->OS); in writeTableSection()
988 encodeULEB128(Exports.size(), W->OS); in writeExportSection()
991 W->OS << char(Export.Kind); in writeExportSection()
992 encodeULEB128(Export.Index, W->OS); in writeExportSection()
1008 encodeULEB128(1, W->OS); // number of "segments" in writeElemSection()
1011 uint32_t TableNumber = WasmIndices.find(IndirectFunctionTable)->second; in writeElemSection()
1015 encodeULEB128(Flags, W->OS); in writeElemSection()
1017 encodeULEB128(TableNumber, W->OS); // the table number in writeElemSection()
1019 // init expr for starting offset in writeElemSection()
1020 W->OS << char(is64Bit() ? wasm::WASM_OPCODE_I64_CONST in writeElemSection()
1022 encodeSLEB128(InitialTableOffset, W->OS); in writeElemSection()
1023 W->OS << char(wasm::WASM_OPCODE_END); in writeElemSection()
1029 W->OS << ElemKind; in writeElemSection()
1032 encodeULEB128(TableElems.size(), W->OS); in writeElemSection()
1034 encodeULEB128(Elem, W->OS); in writeElemSection()
1045 encodeULEB128(DataSegments.size(), W->OS); in writeDataCountSection()
1057 encodeULEB128(Functions.size(), W->OS); in writeCodeSection()
1063 encodeULEB128(Size, W->OS); in writeCodeSection()
1064 FuncSection->setSectionOffset(W->OS.tell() - Section.ContentsOffset); in writeCodeSection()
1065 Asm.writeSectionData(W->OS, FuncSection); in writeCodeSection()
1082 encodeULEB128(DataSegments.size(), W->OS); // count in writeDataSection()
1085 encodeULEB128(Segment.InitFlags, W->OS); // flags in writeDataSection()
1087 encodeULEB128(0, W->OS); // memory index in writeDataSection()
1089 W->OS << char(is64Bit() ? wasm::WASM_OPCODE_I64_CONST in writeDataSection()
1091 encodeSLEB128(Segment.Offset, W->OS); // offset in writeDataSection()
1092 W->OS << char(wasm::WASM_OPCODE_END); in writeDataSection()
1094 encodeULEB128(Segment.Data.size(), W->OS); // size in writeDataSection()
1095 Segment.Section->setSectionOffset(W->OS.tell() - Section.ContentsOffset); in writeDataSection()
1096 W->OS << Segment.Data; // data in writeDataSection()
1109 // See: https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md in writeRelocSection()
1115 // First, ensure the relocations are sorted in offset order. In general they in writeRelocSection()
1116 // should already be sorted since `recordRelocation` is called in offset in writeRelocSection()
1122 return (A.Offset + A.FixupSection->getSectionOffset()) < in writeRelocSection()
1123 (B.Offset + B.FixupSection->getSectionOffset()); in writeRelocSection()
1129 encodeULEB128(SectionIndex, W->OS); in writeRelocSection()
1130 encodeULEB128(Relocs.size(), W->OS); in writeRelocSection()
1132 uint64_t Offset = in writeRelocSection() local
1133 RelEntry.Offset + RelEntry.FixupSection->getSectionOffset(); in writeRelocSection()
1136 W->OS << char(RelEntry.Type); in writeRelocSection()
1137 encodeULEB128(Offset, W->OS); in writeRelocSection()
1138 encodeULEB128(Index, W->OS); in writeRelocSection()
1140 encodeSLEB128(RelEntry.Addend, W->OS); in writeRelocSection()
1159 encodeULEB128(wasm::WasmMetadataVersion, W->OS); in writeLinkingMetaDataSection()
1164 encodeULEB128(SymbolInfos.size(), W->OS); in writeLinkingMetaDataSection()
1166 encodeULEB128(Sym.Kind, W->OS); in writeLinkingMetaDataSection()
1167 encodeULEB128(Sym.Flags, W->OS); in writeLinkingMetaDataSection()
1173 encodeULEB128(Sym.ElementIndex, W->OS); in writeLinkingMetaDataSection()
1181 encodeULEB128(Sym.DataRef.Segment, W->OS); in writeLinkingMetaDataSection()
1182 encodeULEB128(Sym.DataRef.Offset, W->OS); in writeLinkingMetaDataSection()
1183 encodeULEB128(Sym.DataRef.Size, W->OS); in writeLinkingMetaDataSection()
1189 encodeULEB128(SectionIndex, W->OS); in writeLinkingMetaDataSection()
1201 encodeULEB128(DataSegments.size(), W->OS); in writeLinkingMetaDataSection()
1204 encodeULEB128(Segment.Alignment, W->OS); in writeLinkingMetaDataSection()
1205 encodeULEB128(Segment.LinkingFlags, W->OS); in writeLinkingMetaDataSection()
1212 encodeULEB128(InitFuncs.size(), W->OS); in writeLinkingMetaDataSection()
1214 encodeULEB128(StartFunc.first, W->OS); // priority in writeLinkingMetaDataSection()
1215 encodeULEB128(StartFunc.second, W->OS); // function index in writeLinkingMetaDataSection()
1222 encodeULEB128(Comdats.size(), W->OS); in writeLinkingMetaDataSection()
1225 encodeULEB128(0, W->OS); // flags for future use in writeLinkingMetaDataSection()
1226 encodeULEB128(C.second.size(), W->OS); in writeLinkingMetaDataSection()
1228 encodeULEB128(Entry.Kind, W->OS); in writeLinkingMetaDataSection()
1229 encodeULEB128(Entry.Index, W->OS); in writeLinkingMetaDataSection()
1244 Sec->setSectionOffset(W->OS.tell() - Section.ContentsOffset); in writeCustomSection()
1245 Asm.writeSectionData(W->OS, Sec); in writeCustomSection()
1275 S.Returns = Sig->Returns; in registerFunctionType()
1276 S.Params = Sig->Params; in registerFunctionType()
1282 TypeIndices[&Symbol] = Pair.first->second; in registerFunctionType()
1286 LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n"); in registerFunctionType()
1296 S.Returns = Sig->Returns; in registerTagType()
1297 S.Params = Sig->Params; in registerTagType()
1303 TypeIndices[&Symbol] = Pair.first->second; in registerTagType()
1307 LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n"); in registerTagType()
1435 support::endian::Writer MainWriter(*OS, llvm::endianness::little); in writeObject()
1450 uint64_t StartOffset = W->OS.tell(); in writeOneObject()
1502 Segment.Offset = DataSize; in writeOneObject()
1504 addData(Segment.Data, Section); in writeOneObject()
1507 DataSize += Segment.Data.size(); in writeOneObject()
1511 Comdats[C->getName()].emplace_back( in writeOneObject()
1520 // For user-defined custom sections, strip the prefix in writeOneObject()
1545 Comdats[C->getName()].emplace_back( in writeOneObject()
1595 Comdats[C->getName()].emplace_back( in writeOneObject()
1608 Index = WasmIndices.find(&WS)->second; in writeOneObject()
1611 LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n"); in writeOneObject()
1618 LLVM_DEBUG(dbgs() << " -> segment index: -1" in writeOneObject()
1624 report_fatal_error("data symbols must have a size set with .size: " + in writeOneObject()
1628 if (!WS.getSize()->evaluateAsAbsolute(Size, Asm)) in writeOneObject()
1633 report_fatal_error("data symbols must live in a data section: " + in writeOneObject()
1636 // For each data symbol, export it in the symtab as a reference to the in writeOneObject()
1637 // corresponding Wasm data segment. in writeOneObject()
1643 LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n"); in writeOneObject()
1676 LLVM_DEBUG(dbgs() << " -> global index: " in writeOneObject()
1677 << WasmIndices.find(&WS)->second << "\n"); in writeOneObject()
1688 LLVM_DEBUG(dbgs() << " -> table index: " in writeOneObject()
1689 << WasmIndices.find(&WS)->second << "\n"); in writeOneObject()
1704 LLVM_DEBUG(dbgs() << " -> tag index: " << WasmIndices.find(&WS)->second in writeOneObject()
1733 if (Base->isFunction()) { in writeOneObject()
1735 uint32_t WasmIndex = WasmIndices.find(Base)->second; in writeOneObject()
1738 LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n"); in writeOneObject()
1739 } else if (Base->isData()) { in writeOneObject()
1741 uint64_t Offset = Asm.getSymbolOffset(S); in writeOneObject() local
1743 // For data symbol alias we use the size of the base symbol as the in writeOneObject()
1744 // size of the alias. When an offset from the base is involved this in writeOneObject()
1745 // can result in a offset + size goes past the end of the data section in writeOneObject()
1747 if (!Base->getSize()->evaluateAsAbsolute(Size, Asm)) in writeOneObject()
1752 std::min(static_cast<uint64_t>(Size), Segment.Data.size() - Offset); in writeOneObject()
1758 LLVM_DEBUG(dbgs() << " -> index:" << Ref.Segment << "\n"); in writeOneObject()
1802 Info.ElementIndex = WasmIndices.find(&WS)->second; in writeOneObject()
1805 Info.DataRef = DataLocations.find(&WS)->second; in writeOneObject()
1815 // ignored by the linker, which re-calculates the relocations itself. in writeOneObject()
1823 assert(Rel.Symbol->isFunction()); in writeOneObject()
1826 uint32_t FunctionIndex = WasmIndices.find(Base)->second; in writeOneObject()
1829 LLVM_DEBUG(dbgs() << " -> adding " << Base->getName() in writeOneObject()
1865 report_fatal_error("only data supported in .init_array section"); in writeOneObject()
1879 P = (const uint8_t *)Contents.data(), in writeOneObject()
1880 *End = (const uint8_t *)Contents.data() + Contents.size(); in writeOneObject()
1883 report_fatal_error("non-symbolic data in .init_array section"); in writeOneObject()
1892 const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol()); in writeOneObject()
1941 writeRelocSection(DataSectionIndex, "DATA", DataRelocations); in writeOneObject()
1950 return W->OS.tell() - StartOffset; in writeOneObject()
1955 raw_pwrite_stream &OS) { in createWasmObjectWriter() argument
1956 return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS); in createWasmObjectWriter()
1961 raw_pwrite_stream &OS, in createWasmDwoObjectWriter() argument
1963 return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS, DwoOS); in createWasmDwoObjectWriter()