WasmObjectWriter.cpp 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981
  1. //===- lib/MC/WasmObjectWriter.cpp - Wasm File Writer ---------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements Wasm object file writer information.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "llvm/ADT/STLExtras.h"
  13. #include "llvm/ADT/SmallPtrSet.h"
  14. #include "llvm/BinaryFormat/Wasm.h"
  15. #include "llvm/BinaryFormat/WasmTraits.h"
  16. #include "llvm/Config/llvm-config.h"
  17. #include "llvm/MC/MCAsmBackend.h"
  18. #include "llvm/MC/MCAsmLayout.h"
  19. #include "llvm/MC/MCAssembler.h"
  20. #include "llvm/MC/MCContext.h"
  21. #include "llvm/MC/MCExpr.h"
  22. #include "llvm/MC/MCFixupKindInfo.h"
  23. #include "llvm/MC/MCObjectWriter.h"
  24. #include "llvm/MC/MCSectionWasm.h"
  25. #include "llvm/MC/MCSymbolWasm.h"
  26. #include "llvm/MC/MCValue.h"
  27. #include "llvm/MC/MCWasmObjectWriter.h"
  28. #include "llvm/Support/Casting.h"
  29. #include "llvm/Support/Debug.h"
  30. #include "llvm/Support/EndianStream.h"
  31. #include "llvm/Support/ErrorHandling.h"
  32. #include "llvm/Support/LEB128.h"
  33. #include "llvm/Support/StringSaver.h"
  34. #include <vector>
  35. using namespace llvm;
  36. #define DEBUG_TYPE "mc"
  37. namespace {
  38. // When we create the indirect function table we start at 1, so that there is
  39. // and empty slot at 0 and therefore calling a null function pointer will trap.
  40. static const uint32_t InitialTableOffset = 1;
  41. // For patching purposes, we need to remember where each section starts, both
  42. // for patching up the section size field, and for patching up references to
  43. // locations within the section.
  44. struct SectionBookkeeping {
  45. // Where the size of the section is written.
  46. uint64_t SizeOffset;
  47. // Where the section header ends (without custom section name).
  48. uint64_t PayloadOffset;
  49. // Where the contents of the section starts.
  50. uint64_t ContentsOffset;
  51. uint32_t Index;
  52. };
  53. // A wasm data segment. A wasm binary contains only a single data section
  54. // but that can contain many segments, each with their own virtual location
  55. // in memory. Each MCSection data created by llvm is modeled as its own
  56. // wasm data segment.
  57. struct WasmDataSegment {
  58. MCSectionWasm *Section;
  59. StringRef Name;
  60. uint32_t InitFlags;
  61. uint64_t Offset;
  62. uint32_t Alignment;
  63. uint32_t LinkingFlags;
  64. SmallVector<char, 4> Data;
  65. };
  66. // A wasm function to be written into the function section.
  67. struct WasmFunction {
  68. uint32_t SigIndex;
  69. const MCSymbolWasm *Sym;
  70. };
  71. // A wasm global to be written into the global section.
  72. struct WasmGlobal {
  73. wasm::WasmGlobalType Type;
  74. uint64_t InitialValue;
  75. };
  76. // Information about a single item which is part of a COMDAT. For each data
  77. // segment or function which is in the COMDAT, there is a corresponding
  78. // WasmComdatEntry.
  79. struct WasmComdatEntry {
  80. unsigned Kind;
  81. uint32_t Index;
  82. };
  83. // Information about a single relocation.
  84. struct WasmRelocationEntry {
  85. uint64_t Offset; // Where is the relocation.
  86. const MCSymbolWasm *Symbol; // The symbol to relocate with.
  87. int64_t Addend; // A value to add to the symbol.
  88. unsigned Type; // The type of the relocation.
  89. const MCSectionWasm *FixupSection; // The section the relocation is targeting.
  90. WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol,
  91. int64_t Addend, unsigned Type,
  92. const MCSectionWasm *FixupSection)
  93. : Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type),
  94. FixupSection(FixupSection) {}
  95. bool hasAddend() const { return wasm::relocTypeHasAddend(Type); }
  96. void print(raw_ostream &Out) const {
  97. Out << wasm::relocTypetoString(Type) << " Off=" << Offset
  98. << ", Sym=" << *Symbol << ", Addend=" << Addend
  99. << ", FixupSection=" << FixupSection->getName();
  100. }
  101. #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  102. LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
  103. #endif
  104. };
  105. static const uint32_t InvalidIndex = -1;
  106. struct WasmCustomSection {
  107. StringRef Name;
  108. MCSectionWasm *Section;
  109. uint32_t OutputContentsOffset;
  110. uint32_t OutputIndex;
  111. WasmCustomSection(StringRef Name, MCSectionWasm *Section)
  112. : Name(Name), Section(Section), OutputContentsOffset(0),
  113. OutputIndex(InvalidIndex) {}
  114. };
  115. #if !defined(NDEBUG)
  116. raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) {
  117. Rel.print(OS);
  118. return OS;
  119. }
  120. #endif
  121. // Write Value as an (unsigned) LEB value at offset Offset in Stream, padded
  122. // to allow patching.
  123. template <typename T, int W>
  124. void writePatchableULEB(raw_pwrite_stream &Stream, T Value, uint64_t Offset) {
  125. uint8_t Buffer[W];
  126. unsigned SizeLen = encodeULEB128(Value, Buffer, W);
  127. assert(SizeLen == W);
  128. Stream.pwrite((char *)Buffer, SizeLen, Offset);
  129. }
  130. // Write Value as an signed LEB value at offset Offset in Stream, padded
  131. // to allow patching.
  132. template <typename T, int W>
  133. void writePatchableSLEB(raw_pwrite_stream &Stream, T Value, uint64_t Offset) {
  134. uint8_t Buffer[W];
  135. unsigned SizeLen = encodeSLEB128(Value, Buffer, W);
  136. assert(SizeLen == W);
  137. Stream.pwrite((char *)Buffer, SizeLen, Offset);
  138. }
  139. static void writePatchableU32(raw_pwrite_stream &Stream, uint32_t Value,
  140. uint64_t Offset) {
  141. writePatchableULEB<uint32_t, 5>(Stream, Value, Offset);
  142. }
  143. static void writePatchableS32(raw_pwrite_stream &Stream, int32_t Value,
  144. uint64_t Offset) {
  145. writePatchableSLEB<int32_t, 5>(Stream, Value, Offset);
  146. }
  147. static void writePatchableU64(raw_pwrite_stream &Stream, uint64_t Value,
  148. uint64_t Offset) {
  149. writePatchableSLEB<uint64_t, 10>(Stream, Value, Offset);
  150. }
  151. static void writePatchableS64(raw_pwrite_stream &Stream, int64_t Value,
  152. uint64_t Offset) {
  153. writePatchableSLEB<int64_t, 10>(Stream, Value, Offset);
  154. }
  155. // Write Value as a plain integer value at offset Offset in Stream.
  156. static void patchI32(raw_pwrite_stream &Stream, uint32_t Value,
  157. uint64_t Offset) {
  158. uint8_t Buffer[4];
  159. support::endian::write32le(Buffer, Value);
  160. Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
  161. }
  162. static void patchI64(raw_pwrite_stream &Stream, uint64_t Value,
  163. uint64_t Offset) {
  164. uint8_t Buffer[8];
  165. support::endian::write64le(Buffer, Value);
  166. Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
  167. }
  168. bool isDwoSection(const MCSection &Sec) {
  169. return Sec.getName().endswith(".dwo");
  170. }
  171. class WasmObjectWriter : public MCObjectWriter {
  172. support::endian::Writer *W;
  173. /// The target specific Wasm writer instance.
  174. std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
  175. // Relocations for fixing up references in the code section.
  176. std::vector<WasmRelocationEntry> CodeRelocations;
  177. // Relocations for fixing up references in the data section.
  178. std::vector<WasmRelocationEntry> DataRelocations;
  179. // Index values to use for fixing up call_indirect type indices.
  180. // Maps function symbols to the index of the type of the function
  181. DenseMap<const MCSymbolWasm *, uint32_t> TypeIndices;
  182. // Maps function symbols to the table element index space. Used
  183. // for TABLE_INDEX relocation types (i.e. address taken functions).
  184. DenseMap<const MCSymbolWasm *, uint32_t> TableIndices;
  185. // Maps function/global/table symbols to the
  186. // function/global/table/tag/section index space.
  187. DenseMap<const MCSymbolWasm *, uint32_t> WasmIndices;
  188. DenseMap<const MCSymbolWasm *, uint32_t> GOTIndices;
  189. // Maps data symbols to the Wasm segment and offset/size with the segment.
  190. DenseMap<const MCSymbolWasm *, wasm::WasmDataReference> DataLocations;
  191. // Stores output data (index, relocations, content offset) for custom
  192. // section.
  193. std::vector<WasmCustomSection> CustomSections;
  194. std::unique_ptr<WasmCustomSection> ProducersSection;
  195. std::unique_ptr<WasmCustomSection> TargetFeaturesSection;
  196. // Relocations for fixing up references in the custom sections.
  197. DenseMap<const MCSectionWasm *, std::vector<WasmRelocationEntry>>
  198. CustomSectionsRelocations;
  199. // Map from section to defining function symbol.
  200. DenseMap<const MCSection *, const MCSymbol *> SectionFunctions;
  201. DenseMap<wasm::WasmSignature, uint32_t> SignatureIndices;
  202. SmallVector<wasm::WasmSignature, 4> Signatures;
  203. SmallVector<WasmDataSegment, 4> DataSegments;
  204. unsigned NumFunctionImports = 0;
  205. unsigned NumGlobalImports = 0;
  206. unsigned NumTableImports = 0;
  207. unsigned NumTagImports = 0;
  208. uint32_t SectionCount = 0;
  209. enum class DwoMode {
  210. AllSections,
  211. NonDwoOnly,
  212. DwoOnly,
  213. };
  214. bool IsSplitDwarf = false;
  215. raw_pwrite_stream *OS = nullptr;
  216. raw_pwrite_stream *DwoOS = nullptr;
  217. // TargetObjectWriter wranppers.
  218. bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
  219. bool isEmscripten() const { return TargetObjectWriter->isEmscripten(); }
  220. void startSection(SectionBookkeeping &Section, unsigned SectionId);
  221. void startCustomSection(SectionBookkeeping &Section, StringRef Name);
  222. void endSection(SectionBookkeeping &Section);
  223. public:
  224. WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
  225. raw_pwrite_stream &OS_)
  226. : TargetObjectWriter(std::move(MOTW)), OS(&OS_) {}
  227. WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
  228. raw_pwrite_stream &OS_, raw_pwrite_stream &DwoOS_)
  229. : TargetObjectWriter(std::move(MOTW)), IsSplitDwarf(true), OS(&OS_),
  230. DwoOS(&DwoOS_) {}
  231. private:
  232. void reset() override {
  233. CodeRelocations.clear();
  234. DataRelocations.clear();
  235. TypeIndices.clear();
  236. WasmIndices.clear();
  237. GOTIndices.clear();
  238. TableIndices.clear();
  239. DataLocations.clear();
  240. CustomSections.clear();
  241. ProducersSection.reset();
  242. TargetFeaturesSection.reset();
  243. CustomSectionsRelocations.clear();
  244. SignatureIndices.clear();
  245. Signatures.clear();
  246. DataSegments.clear();
  247. SectionFunctions.clear();
  248. NumFunctionImports = 0;
  249. NumGlobalImports = 0;
  250. NumTableImports = 0;
  251. MCObjectWriter::reset();
  252. }
  253. void writeHeader(const MCAssembler &Asm);
  254. void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
  255. const MCFragment *Fragment, const MCFixup &Fixup,
  256. MCValue Target, uint64_t &FixedValue) override;
  257. void executePostLayoutBinding(MCAssembler &Asm,
  258. const MCAsmLayout &Layout) override;
  259. void prepareImports(SmallVectorImpl<wasm::WasmImport> &Imports,
  260. MCAssembler &Asm, const MCAsmLayout &Layout);
  261. uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
  262. uint64_t writeOneObject(MCAssembler &Asm, const MCAsmLayout &Layout,
  263. DwoMode Mode);
  264. void writeString(const StringRef Str) {
  265. encodeULEB128(Str.size(), W->OS);
  266. W->OS << Str;
  267. }
  268. void writeStringWithAlignment(const StringRef Str, unsigned Alignment);
  269. void writeI32(int32_t val) {
  270. char Buffer[4];
  271. support::endian::write32le(Buffer, val);
  272. W->OS.write(Buffer, sizeof(Buffer));
  273. }
  274. void writeI64(int64_t val) {
  275. char Buffer[8];
  276. support::endian::write64le(Buffer, val);
  277. W->OS.write(Buffer, sizeof(Buffer));
  278. }
  279. void writeValueType(wasm::ValType Ty) { W->OS << static_cast<char>(Ty); }
  280. void writeTypeSection(ArrayRef<wasm::WasmSignature> Signatures);
  281. void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint64_t DataSize,
  282. uint32_t NumElements);
  283. void writeFunctionSection(ArrayRef<WasmFunction> Functions);
  284. void writeExportSection(ArrayRef<wasm::WasmExport> Exports);
  285. void writeElemSection(const MCSymbolWasm *IndirectFunctionTable,
  286. ArrayRef<uint32_t> TableElems);
  287. void writeDataCountSection();
  288. uint32_t writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
  289. ArrayRef<WasmFunction> Functions);
  290. uint32_t writeDataSection(const MCAsmLayout &Layout);
  291. void writeTagSection(ArrayRef<uint32_t> TagTypes);
  292. void writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals);
  293. void writeTableSection(ArrayRef<wasm::WasmTable> Tables);
  294. void writeRelocSection(uint32_t SectionIndex, StringRef Name,
  295. std::vector<WasmRelocationEntry> &Relocations);
  296. void writeLinkingMetaDataSection(
  297. ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
  298. ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
  299. const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats);
  300. void writeCustomSection(WasmCustomSection &CustomSection,
  301. const MCAssembler &Asm, const MCAsmLayout &Layout);
  302. void writeCustomRelocSections();
  303. uint64_t getProvisionalValue(const WasmRelocationEntry &RelEntry,
  304. const MCAsmLayout &Layout);
  305. void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
  306. uint64_t ContentsOffset, const MCAsmLayout &Layout);
  307. uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);
  308. uint32_t getFunctionType(const MCSymbolWasm &Symbol);
  309. uint32_t getTagType(const MCSymbolWasm &Symbol);
  310. void registerFunctionType(const MCSymbolWasm &Symbol);
  311. void registerTagType(const MCSymbolWasm &Symbol);
  312. };
  313. } // end anonymous namespace
  314. // Write out a section header and a patchable section size field.
  315. void WasmObjectWriter::startSection(SectionBookkeeping &Section,
  316. unsigned SectionId) {
  317. LLVM_DEBUG(dbgs() << "startSection " << SectionId << "\n");
  318. W->OS << char(SectionId);
  319. Section.SizeOffset = W->OS.tell();
  320. // The section size. We don't know the size yet, so reserve enough space
  321. // for any 32-bit value; we'll patch it later.
  322. encodeULEB128(0, W->OS, 5);
  323. // The position where the section starts, for measuring its size.
  324. Section.ContentsOffset = W->OS.tell();
  325. Section.PayloadOffset = W->OS.tell();
  326. Section.Index = SectionCount++;
  327. }
  328. // Write a string with extra paddings for trailing alignment
  329. // TODO: support alignment at asm and llvm level?
  330. void WasmObjectWriter::writeStringWithAlignment(const StringRef Str,
  331. unsigned Alignment) {
  332. // Calculate the encoded size of str length and add pads based on it and
  333. // alignment.
  334. raw_null_ostream NullOS;
  335. uint64_t StrSizeLength = encodeULEB128(Str.size(), NullOS);
  336. uint64_t Offset = W->OS.tell() + StrSizeLength + Str.size();
  337. uint64_t Paddings = offsetToAlignment(Offset, Align(Alignment));
  338. Offset += Paddings;
  339. // LEB128 greater than 5 bytes is invalid
  340. assert((StrSizeLength + Paddings) <= 5 && "too long string to align");
  341. encodeSLEB128(Str.size(), W->OS, StrSizeLength + Paddings);
  342. W->OS << Str;
  343. assert(W->OS.tell() == Offset && "invalid padding");
  344. }
  345. void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
  346. StringRef Name) {
  347. LLVM_DEBUG(dbgs() << "startCustomSection " << Name << "\n");
  348. startSection(Section, wasm::WASM_SEC_CUSTOM);
  349. // The position where the section header ends, for measuring its size.
  350. Section.PayloadOffset = W->OS.tell();
  351. // Custom sections in wasm also have a string identifier.
  352. if (Name != "__clangast") {
  353. writeString(Name);
  354. } else {
  355. // The on-disk hashtable in clangast needs to be aligned by 4 bytes.
  356. writeStringWithAlignment(Name, 4);
  357. }
  358. // The position where the custom section starts.
  359. Section.ContentsOffset = W->OS.tell();
  360. }
  361. // Now that the section is complete and we know how big it is, patch up the
  362. // section size field at the start of the section.
  363. void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
  364. uint64_t Size = W->OS.tell();
  365. // /dev/null doesn't support seek/tell and can report offset of 0.
  366. // Simply skip this patching in that case.
  367. if (!Size)
  368. return;
  369. Size -= Section.PayloadOffset;
  370. if (uint32_t(Size) != Size)
  371. report_fatal_error("section size does not fit in a uint32_t");
  372. LLVM_DEBUG(dbgs() << "endSection size=" << Size << "\n");
  373. // Write the final section size to the payload_len field, which follows
  374. // the section id byte.
  375. writePatchableU32(static_cast<raw_pwrite_stream &>(W->OS), Size,
  376. Section.SizeOffset);
  377. }
  378. // Emit the Wasm header.
  379. void WasmObjectWriter::writeHeader(const MCAssembler &Asm) {
  380. W->OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
  381. W->write<uint32_t>(wasm::WasmVersion);
  382. }
  383. void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
  384. const MCAsmLayout &Layout) {
  385. // Some compilation units require the indirect function table to be present
  386. // but don't explicitly reference it. This is the case for call_indirect
  387. // without the reference-types feature, and also function bitcasts in all
  388. // cases. In those cases the __indirect_function_table has the
  389. // WASM_SYMBOL_NO_STRIP attribute. Here we make sure this symbol makes it to
  390. // the assembler, if needed.
  391. if (auto *Sym = Asm.getContext().lookupSymbol("__indirect_function_table")) {
  392. const auto *WasmSym = static_cast<const MCSymbolWasm *>(Sym);
  393. if (WasmSym->isNoStrip())
  394. Asm.registerSymbol(*Sym);
  395. }
  396. // Build a map of sections to the function that defines them, for use
  397. // in recordRelocation.
  398. for (const MCSymbol &S : Asm.symbols()) {
  399. const auto &WS = static_cast<const MCSymbolWasm &>(S);
  400. if (WS.isDefined() && WS.isFunction() && !WS.isVariable()) {
  401. const auto &Sec = static_cast<const MCSectionWasm &>(S.getSection());
  402. auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &S));
  403. if (!Pair.second)
  404. report_fatal_error("section already has a defining function: " +
  405. Sec.getName());
  406. }
  407. }
  408. }
  409. void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
  410. const MCAsmLayout &Layout,
  411. const MCFragment *Fragment,
  412. const MCFixup &Fixup, MCValue Target,
  413. uint64_t &FixedValue) {
  414. // The WebAssembly backend should never generate FKF_IsPCRel fixups
  415. assert(!(Asm.getBackend().getFixupKindInfo(Fixup.getKind()).Flags &
  416. MCFixupKindInfo::FKF_IsPCRel));
  417. const auto &FixupSection = cast<MCSectionWasm>(*Fragment->getParent());
  418. uint64_t C = Target.getConstant();
  419. uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
  420. MCContext &Ctx = Asm.getContext();
  421. bool IsLocRel = false;
  422. if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
  423. const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol());
  424. if (FixupSection.getKind().isText()) {
  425. Ctx.reportError(Fixup.getLoc(),
  426. Twine("symbol '") + SymB.getName() +
  427. "' unsupported subtraction expression used in "
  428. "relocation in code section.");
  429. return;
  430. }
  431. if (SymB.isUndefined()) {
  432. Ctx.reportError(Fixup.getLoc(),
  433. Twine("symbol '") + SymB.getName() +
  434. "' can not be undefined in a subtraction expression");
  435. return;
  436. }
  437. const MCSection &SecB = SymB.getSection();
  438. if (&SecB != &FixupSection) {
  439. Ctx.reportError(Fixup.getLoc(),
  440. Twine("symbol '") + SymB.getName() +
  441. "' can not be placed in a different section");
  442. return;
  443. }
  444. IsLocRel = true;
  445. C += FixupOffset - Layout.getSymbolOffset(SymB);
  446. }
  447. // We either rejected the fixup or folded B into C at this point.
  448. const MCSymbolRefExpr *RefA = Target.getSymA();
  449. const auto *SymA = cast<MCSymbolWasm>(&RefA->getSymbol());
  450. // The .init_array isn't translated as data, so don't do relocations in it.
  451. if (FixupSection.getName().startswith(".init_array")) {
  452. SymA->setUsedInInitArray();
  453. return;
  454. }
  455. if (SymA->isVariable()) {
  456. const MCExpr *Expr = SymA->getVariableValue();
  457. if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr))
  458. if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
  459. llvm_unreachable("weakref used in reloc not yet implemented");
  460. }
  461. // Put any constant offset in an addend. Offsets can be negative, and
  462. // LLVM expects wrapping, in contrast to wasm's immediates which can't
  463. // be negative and don't wrap.
  464. FixedValue = 0;
  465. unsigned Type =
  466. TargetObjectWriter->getRelocType(Target, Fixup, FixupSection, IsLocRel);
  467. // Absolute offset within a section or a function.
  468. // Currently only supported for for metadata sections.
  469. // See: test/MC/WebAssembly/blockaddress.ll
  470. if ((Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
  471. Type == wasm::R_WASM_FUNCTION_OFFSET_I64 ||
  472. Type == wasm::R_WASM_SECTION_OFFSET_I32) &&
  473. SymA->isDefined()) {
  474. // SymA can be a temp data symbol that represents a function (in which case
  475. // it needs to be replaced by the section symbol), [XXX and it apparently
  476. // later gets changed again to a func symbol?] or it can be a real
  477. // function symbol, in which case it can be left as-is.
  478. if (!FixupSection.getKind().isMetadata())
  479. report_fatal_error("relocations for function or section offsets are "
  480. "only supported in metadata sections");
  481. const MCSymbol *SectionSymbol = nullptr;
  482. const MCSection &SecA = SymA->getSection();
  483. if (SecA.getKind().isText()) {
  484. auto SecSymIt = SectionFunctions.find(&SecA);
  485. if (SecSymIt == SectionFunctions.end())
  486. report_fatal_error("section doesn\'t have defining symbol");
  487. SectionSymbol = SecSymIt->second;
  488. } else {
  489. SectionSymbol = SecA.getBeginSymbol();
  490. }
  491. if (!SectionSymbol)
  492. report_fatal_error("section symbol is required for relocation");
  493. C += Layout.getSymbolOffset(*SymA);
  494. SymA = cast<MCSymbolWasm>(SectionSymbol);
  495. }
  496. if (Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB ||
  497. Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64 ||
  498. Type == wasm::R_WASM_TABLE_INDEX_SLEB ||
  499. Type == wasm::R_WASM_TABLE_INDEX_SLEB64 ||
  500. Type == wasm::R_WASM_TABLE_INDEX_I32 ||
  501. Type == wasm::R_WASM_TABLE_INDEX_I64) {
  502. // TABLE_INDEX relocs implicitly use the default indirect function table.
  503. // We require the function table to have already been defined.
  504. auto TableName = "__indirect_function_table";
  505. MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(TableName));
  506. if (!Sym) {
  507. report_fatal_error("missing indirect function table symbol");
  508. } else {
  509. if (!Sym->isFunctionTable())
  510. report_fatal_error("__indirect_function_table symbol has wrong type");
  511. // Ensure that __indirect_function_table reaches the output.
  512. Sym->setNoStrip();
  513. Asm.registerSymbol(*Sym);
  514. }
  515. }
  516. // Relocation other than R_WASM_TYPE_INDEX_LEB are required to be
  517. // against a named symbol.
  518. if (Type != wasm::R_WASM_TYPE_INDEX_LEB) {
  519. if (SymA->getName().empty())
  520. report_fatal_error("relocations against un-named temporaries are not yet "
  521. "supported by wasm");
  522. SymA->setUsedInReloc();
  523. }
  524. switch (RefA->getKind()) {
  525. case MCSymbolRefExpr::VK_GOT:
  526. case MCSymbolRefExpr::VK_WASM_GOT_TLS:
  527. SymA->setUsedInGOT();
  528. break;
  529. default:
  530. break;
  531. }
  532. WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
  533. LLVM_DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
  534. if (FixupSection.isWasmData()) {
  535. DataRelocations.push_back(Rec);
  536. } else if (FixupSection.getKind().isText()) {
  537. CodeRelocations.push_back(Rec);
  538. } else if (FixupSection.getKind().isMetadata()) {
  539. CustomSectionsRelocations[&FixupSection].push_back(Rec);
  540. } else {
  541. llvm_unreachable("unexpected section type");
  542. }
  543. }
  544. // Compute a value to write into the code at the location covered
  545. // by RelEntry. This value isn't used by the static linker; it just serves
  546. // to make the object format more readable and more likely to be directly
  547. // useable.
  548. uint64_t
  549. WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry,
  550. const MCAsmLayout &Layout) {
  551. if ((RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB ||
  552. RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_I32) &&
  553. !RelEntry.Symbol->isGlobal()) {
  554. assert(GOTIndices.count(RelEntry.Symbol) > 0 && "symbol not found in GOT index space");
  555. return GOTIndices[RelEntry.Symbol];
  556. }
  557. switch (RelEntry.Type) {
  558. case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
  559. case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
  560. case wasm::R_WASM_TABLE_INDEX_SLEB:
  561. case wasm::R_WASM_TABLE_INDEX_SLEB64:
  562. case wasm::R_WASM_TABLE_INDEX_I32:
  563. case wasm::R_WASM_TABLE_INDEX_I64: {
  564. // Provisional value is table address of the resolved symbol itself
  565. const MCSymbolWasm *Base =
  566. cast<MCSymbolWasm>(Layout.getBaseSymbol(*RelEntry.Symbol));
  567. assert(Base->isFunction());
  568. if (RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB ||
  569. RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
  570. return TableIndices[Base] - InitialTableOffset;
  571. else
  572. return TableIndices[Base];
  573. }
  574. case wasm::R_WASM_TYPE_INDEX_LEB:
  575. // Provisional value is same as the index
  576. return getRelocationIndexValue(RelEntry);
  577. case wasm::R_WASM_FUNCTION_INDEX_LEB:
  578. case wasm::R_WASM_GLOBAL_INDEX_LEB:
  579. case wasm::R_WASM_GLOBAL_INDEX_I32:
  580. case wasm::R_WASM_TAG_INDEX_LEB:
  581. case wasm::R_WASM_TABLE_NUMBER_LEB:
  582. // Provisional value is function/global/tag Wasm index
  583. assert(WasmIndices.count(RelEntry.Symbol) > 0 && "symbol not found in wasm index space");
  584. return WasmIndices[RelEntry.Symbol];
  585. case wasm::R_WASM_FUNCTION_OFFSET_I32:
  586. case wasm::R_WASM_FUNCTION_OFFSET_I64:
  587. case wasm::R_WASM_SECTION_OFFSET_I32: {
  588. if (!RelEntry.Symbol->isDefined())
  589. return 0;
  590. const auto &Section =
  591. static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection());
  592. return Section.getSectionOffset() + RelEntry.Addend;
  593. }
  594. case wasm::R_WASM_MEMORY_ADDR_LEB:
  595. case wasm::R_WASM_MEMORY_ADDR_LEB64:
  596. case wasm::R_WASM_MEMORY_ADDR_SLEB:
  597. case wasm::R_WASM_MEMORY_ADDR_SLEB64:
  598. case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
  599. case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
  600. case wasm::R_WASM_MEMORY_ADDR_I32:
  601. case wasm::R_WASM_MEMORY_ADDR_I64:
  602. case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
  603. case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
  604. case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: {
  605. // Provisional value is address of the global plus the offset
  606. // For undefined symbols, use zero
  607. if (!RelEntry.Symbol->isDefined())
  608. return 0;
  609. const wasm::WasmDataReference &SymRef = DataLocations[RelEntry.Symbol];
  610. const WasmDataSegment &Segment = DataSegments[SymRef.Segment];
  611. // Ignore overflow. LLVM allows address arithmetic to silently wrap.
  612. return Segment.Offset + SymRef.Offset + RelEntry.Addend;
  613. }
  614. default:
  615. llvm_unreachable("invalid relocation type");
  616. }
  617. }
  618. static void addData(SmallVectorImpl<char> &DataBytes,
  619. MCSectionWasm &DataSection) {
  620. LLVM_DEBUG(errs() << "addData: " << DataSection.getName() << "\n");
  621. DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
  622. for (const MCFragment &Frag : DataSection) {
  623. if (Frag.hasInstructions())
  624. report_fatal_error("only data supported in data sections");
  625. if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
  626. if (Align->getValueSize() != 1)
  627. report_fatal_error("only byte values supported for alignment");
  628. // If nops are requested, use zeros, as this is the data section.
  629. uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
  630. uint64_t Size =
  631. std::min<uint64_t>(alignTo(DataBytes.size(), Align->getAlignment()),
  632. DataBytes.size() + Align->getMaxBytesToEmit());
  633. DataBytes.resize(Size, Value);
  634. } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
  635. int64_t NumValues;
  636. if (!Fill->getNumValues().evaluateAsAbsolute(NumValues))
  637. llvm_unreachable("The fill should be an assembler constant");
  638. DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues,
  639. Fill->getValue());
  640. } else if (auto *LEB = dyn_cast<MCLEBFragment>(&Frag)) {
  641. const SmallVectorImpl<char> &Contents = LEB->getContents();
  642. llvm::append_range(DataBytes, Contents);
  643. } else {
  644. const auto &DataFrag = cast<MCDataFragment>(Frag);
  645. const SmallVectorImpl<char> &Contents = DataFrag.getContents();
  646. llvm::append_range(DataBytes, Contents);
  647. }
  648. }
  649. LLVM_DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n");
  650. }
  651. uint32_t
  652. WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) {
  653. if (RelEntry.Type == wasm::R_WASM_TYPE_INDEX_LEB) {
  654. if (!TypeIndices.count(RelEntry.Symbol))
  655. report_fatal_error("symbol not found in type index space: " +
  656. RelEntry.Symbol->getName());
  657. return TypeIndices[RelEntry.Symbol];
  658. }
  659. return RelEntry.Symbol->getIndex();
  660. }
  661. // Apply the portions of the relocation records that we can handle ourselves
  662. // directly.
  663. void WasmObjectWriter::applyRelocations(
  664. ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset,
  665. const MCAsmLayout &Layout) {
  666. auto &Stream = static_cast<raw_pwrite_stream &>(W->OS);
  667. for (const WasmRelocationEntry &RelEntry : Relocations) {
  668. uint64_t Offset = ContentsOffset +
  669. RelEntry.FixupSection->getSectionOffset() +
  670. RelEntry.Offset;
  671. LLVM_DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
  672. uint64_t Value = getProvisionalValue(RelEntry, Layout);
  673. switch (RelEntry.Type) {
  674. case wasm::R_WASM_FUNCTION_INDEX_LEB:
  675. case wasm::R_WASM_TYPE_INDEX_LEB:
  676. case wasm::R_WASM_GLOBAL_INDEX_LEB:
  677. case wasm::R_WASM_MEMORY_ADDR_LEB:
  678. case wasm::R_WASM_TAG_INDEX_LEB:
  679. case wasm::R_WASM_TABLE_NUMBER_LEB:
  680. writePatchableU32(Stream, Value, Offset);
  681. break;
  682. case wasm::R_WASM_MEMORY_ADDR_LEB64:
  683. writePatchableU64(Stream, Value, Offset);
  684. break;
  685. case wasm::R_WASM_TABLE_INDEX_I32:
  686. case wasm::R_WASM_MEMORY_ADDR_I32:
  687. case wasm::R_WASM_FUNCTION_OFFSET_I32:
  688. case wasm::R_WASM_SECTION_OFFSET_I32:
  689. case wasm::R_WASM_GLOBAL_INDEX_I32:
  690. case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
  691. patchI32(Stream, Value, Offset);
  692. break;
  693. case wasm::R_WASM_TABLE_INDEX_I64:
  694. case wasm::R_WASM_MEMORY_ADDR_I64:
  695. case wasm::R_WASM_FUNCTION_OFFSET_I64:
  696. patchI64(Stream, Value, Offset);
  697. break;
  698. case wasm::R_WASM_TABLE_INDEX_SLEB:
  699. case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
  700. case wasm::R_WASM_MEMORY_ADDR_SLEB:
  701. case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
  702. case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
  703. writePatchableS32(Stream, Value, Offset);
  704. break;
  705. case wasm::R_WASM_TABLE_INDEX_SLEB64:
  706. case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
  707. case wasm::R_WASM_MEMORY_ADDR_SLEB64:
  708. case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
  709. case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
  710. writePatchableS64(Stream, Value, Offset);
  711. break;
  712. default:
  713. llvm_unreachable("invalid relocation type");
  714. }
  715. }
  716. }
  717. void WasmObjectWriter::writeTypeSection(
  718. ArrayRef<wasm::WasmSignature> Signatures) {
  719. if (Signatures.empty())
  720. return;
  721. SectionBookkeeping Section;
  722. startSection(Section, wasm::WASM_SEC_TYPE);
  723. encodeULEB128(Signatures.size(), W->OS);
  724. for (const wasm::WasmSignature &Sig : Signatures) {
  725. W->OS << char(wasm::WASM_TYPE_FUNC);
  726. encodeULEB128(Sig.Params.size(), W->OS);
  727. for (wasm::ValType Ty : Sig.Params)
  728. writeValueType(Ty);
  729. encodeULEB128(Sig.Returns.size(), W->OS);
  730. for (wasm::ValType Ty : Sig.Returns)
  731. writeValueType(Ty);
  732. }
  733. endSection(Section);
  734. }
  735. void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
  736. uint64_t DataSize,
  737. uint32_t NumElements) {
  738. if (Imports.empty())
  739. return;
  740. uint64_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
  741. SectionBookkeeping Section;
  742. startSection(Section, wasm::WASM_SEC_IMPORT);
  743. encodeULEB128(Imports.size(), W->OS);
  744. for (const wasm::WasmImport &Import : Imports) {
  745. writeString(Import.Module);
  746. writeString(Import.Field);
  747. W->OS << char(Import.Kind);
  748. switch (Import.Kind) {
  749. case wasm::WASM_EXTERNAL_FUNCTION:
  750. encodeULEB128(Import.SigIndex, W->OS);
  751. break;
  752. case wasm::WASM_EXTERNAL_GLOBAL:
  753. W->OS << char(Import.Global.Type);
  754. W->OS << char(Import.Global.Mutable ? 1 : 0);
  755. break;
  756. case wasm::WASM_EXTERNAL_MEMORY:
  757. encodeULEB128(Import.Memory.Flags, W->OS);
  758. encodeULEB128(NumPages, W->OS); // initial
  759. break;
  760. case wasm::WASM_EXTERNAL_TABLE:
  761. W->OS << char(Import.Table.ElemType);
  762. encodeULEB128(0, W->OS); // flags
  763. encodeULEB128(NumElements, W->OS); // initial
  764. break;
  765. case wasm::WASM_EXTERNAL_TAG:
  766. W->OS << char(0); // Reserved 'attribute' field
  767. encodeULEB128(Import.SigIndex, W->OS);
  768. break;
  769. default:
  770. llvm_unreachable("unsupported import kind");
  771. }
  772. }
  773. endSection(Section);
  774. }
  775. void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) {
  776. if (Functions.empty())
  777. return;
  778. SectionBookkeeping Section;
  779. startSection(Section, wasm::WASM_SEC_FUNCTION);
  780. encodeULEB128(Functions.size(), W->OS);
  781. for (const WasmFunction &Func : Functions)
  782. encodeULEB128(Func.SigIndex, W->OS);
  783. endSection(Section);
  784. }
  785. void WasmObjectWriter::writeTagSection(ArrayRef<uint32_t> TagTypes) {
  786. if (TagTypes.empty())
  787. return;
  788. SectionBookkeeping Section;
  789. startSection(Section, wasm::WASM_SEC_TAG);
  790. encodeULEB128(TagTypes.size(), W->OS);
  791. for (uint32_t Index : TagTypes) {
  792. W->OS << char(0); // Reserved 'attribute' field
  793. encodeULEB128(Index, W->OS);
  794. }
  795. endSection(Section);
  796. }
  797. void WasmObjectWriter::writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals) {
  798. if (Globals.empty())
  799. return;
  800. SectionBookkeeping Section;
  801. startSection(Section, wasm::WASM_SEC_GLOBAL);
  802. encodeULEB128(Globals.size(), W->OS);
  803. for (const wasm::WasmGlobal &Global : Globals) {
  804. encodeULEB128(Global.Type.Type, W->OS);
  805. W->OS << char(Global.Type.Mutable);
  806. W->OS << char(Global.InitExpr.Opcode);
  807. switch (Global.Type.Type) {
  808. case wasm::WASM_TYPE_I32:
  809. encodeSLEB128(0, W->OS);
  810. break;
  811. case wasm::WASM_TYPE_I64:
  812. encodeSLEB128(0, W->OS);
  813. break;
  814. case wasm::WASM_TYPE_F32:
  815. writeI32(0);
  816. break;
  817. case wasm::WASM_TYPE_F64:
  818. writeI64(0);
  819. break;
  820. case wasm::WASM_TYPE_EXTERNREF:
  821. writeValueType(wasm::ValType::EXTERNREF);
  822. break;
  823. default:
  824. llvm_unreachable("unexpected type");
  825. }
  826. W->OS << char(wasm::WASM_OPCODE_END);
  827. }
  828. endSection(Section);
  829. }
  830. void WasmObjectWriter::writeTableSection(ArrayRef<wasm::WasmTable> Tables) {
  831. if (Tables.empty())
  832. return;
  833. SectionBookkeeping Section;
  834. startSection(Section, wasm::WASM_SEC_TABLE);
  835. encodeULEB128(Tables.size(), W->OS);
  836. for (const wasm::WasmTable &Table : Tables) {
  837. encodeULEB128(Table.Type.ElemType, W->OS);
  838. encodeULEB128(Table.Type.Limits.Flags, W->OS);
  839. encodeULEB128(Table.Type.Limits.Minimum, W->OS);
  840. if (Table.Type.Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
  841. encodeULEB128(Table.Type.Limits.Maximum, W->OS);
  842. }
  843. endSection(Section);
  844. }
  845. void WasmObjectWriter::writeExportSection(ArrayRef<wasm::WasmExport> Exports) {
  846. if (Exports.empty())
  847. return;
  848. SectionBookkeeping Section;
  849. startSection(Section, wasm::WASM_SEC_EXPORT);
  850. encodeULEB128(Exports.size(), W->OS);
  851. for (const wasm::WasmExport &Export : Exports) {
  852. writeString(Export.Name);
  853. W->OS << char(Export.Kind);
  854. encodeULEB128(Export.Index, W->OS);
  855. }
  856. endSection(Section);
  857. }
  858. void WasmObjectWriter::writeElemSection(
  859. const MCSymbolWasm *IndirectFunctionTable, ArrayRef<uint32_t> TableElems) {
  860. if (TableElems.empty())
  861. return;
  862. assert(IndirectFunctionTable);
  863. SectionBookkeeping Section;
  864. startSection(Section, wasm::WASM_SEC_ELEM);
  865. encodeULEB128(1, W->OS); // number of "segments"
  866. assert(WasmIndices.count(IndirectFunctionTable));
  867. uint32_t TableNumber = WasmIndices.find(IndirectFunctionTable)->second;
  868. uint32_t Flags = 0;
  869. if (TableNumber)
  870. Flags |= wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER;
  871. encodeULEB128(Flags, W->OS);
  872. if (Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
  873. encodeULEB128(TableNumber, W->OS); // the table number
  874. // init expr for starting offset
  875. W->OS << char(wasm::WASM_OPCODE_I32_CONST);
  876. encodeSLEB128(InitialTableOffset, W->OS);
  877. W->OS << char(wasm::WASM_OPCODE_END);
  878. if (Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
  879. // We only write active function table initializers, for which the elem kind
  880. // is specified to be written as 0x00 and interpreted to mean "funcref".
  881. const uint8_t ElemKind = 0;
  882. W->OS << ElemKind;
  883. }
  884. encodeULEB128(TableElems.size(), W->OS);
  885. for (uint32_t Elem : TableElems)
  886. encodeULEB128(Elem, W->OS);
  887. endSection(Section);
  888. }
  889. void WasmObjectWriter::writeDataCountSection() {
  890. if (DataSegments.empty())
  891. return;
  892. SectionBookkeeping Section;
  893. startSection(Section, wasm::WASM_SEC_DATACOUNT);
  894. encodeULEB128(DataSegments.size(), W->OS);
  895. endSection(Section);
  896. }
  897. uint32_t WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
  898. const MCAsmLayout &Layout,
  899. ArrayRef<WasmFunction> Functions) {
  900. if (Functions.empty())
  901. return 0;
  902. SectionBookkeeping Section;
  903. startSection(Section, wasm::WASM_SEC_CODE);
  904. encodeULEB128(Functions.size(), W->OS);
  905. for (const WasmFunction &Func : Functions) {
  906. auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection());
  907. int64_t Size = 0;
  908. if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
  909. report_fatal_error(".size expression must be evaluatable");
  910. encodeULEB128(Size, W->OS);
  911. FuncSection.setSectionOffset(W->OS.tell() - Section.ContentsOffset);
  912. Asm.writeSectionData(W->OS, &FuncSection, Layout);
  913. }
  914. // Apply fixups.
  915. applyRelocations(CodeRelocations, Section.ContentsOffset, Layout);
  916. endSection(Section);
  917. return Section.Index;
  918. }
  919. uint32_t WasmObjectWriter::writeDataSection(const MCAsmLayout &Layout) {
  920. if (DataSegments.empty())
  921. return 0;
  922. SectionBookkeeping Section;
  923. startSection(Section, wasm::WASM_SEC_DATA);
  924. encodeULEB128(DataSegments.size(), W->OS); // count
  925. for (const WasmDataSegment &Segment : DataSegments) {
  926. encodeULEB128(Segment.InitFlags, W->OS); // flags
  927. if (Segment.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
  928. encodeULEB128(0, W->OS); // memory index
  929. if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
  930. W->OS << char(is64Bit() ? wasm::WASM_OPCODE_I64_CONST
  931. : wasm::WASM_OPCODE_I32_CONST);
  932. encodeSLEB128(Segment.Offset, W->OS); // offset
  933. W->OS << char(wasm::WASM_OPCODE_END);
  934. }
  935. encodeULEB128(Segment.Data.size(), W->OS); // size
  936. Segment.Section->setSectionOffset(W->OS.tell() - Section.ContentsOffset);
  937. W->OS << Segment.Data; // data
  938. }
  939. // Apply fixups.
  940. applyRelocations(DataRelocations, Section.ContentsOffset, Layout);
  941. endSection(Section);
  942. return Section.Index;
  943. }
  944. void WasmObjectWriter::writeRelocSection(
  945. uint32_t SectionIndex, StringRef Name,
  946. std::vector<WasmRelocationEntry> &Relocs) {
  947. // See: https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md
  948. // for descriptions of the reloc sections.
  949. if (Relocs.empty())
  950. return;
  951. // First, ensure the relocations are sorted in offset order. In general they
  952. // should already be sorted since `recordRelocation` is called in offset
  953. // order, but for the code section we combine many MC sections into single
  954. // wasm section, and this order is determined by the order of Asm.Symbols()
  955. // not the sections order.
  956. llvm::stable_sort(
  957. Relocs, [](const WasmRelocationEntry &A, const WasmRelocationEntry &B) {
  958. return (A.Offset + A.FixupSection->getSectionOffset()) <
  959. (B.Offset + B.FixupSection->getSectionOffset());
  960. });
  961. SectionBookkeeping Section;
  962. startCustomSection(Section, std::string("reloc.") + Name.str());
  963. encodeULEB128(SectionIndex, W->OS);
  964. encodeULEB128(Relocs.size(), W->OS);
  965. for (const WasmRelocationEntry &RelEntry : Relocs) {
  966. uint64_t Offset =
  967. RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
  968. uint32_t Index = getRelocationIndexValue(RelEntry);
  969. W->OS << char(RelEntry.Type);
  970. encodeULEB128(Offset, W->OS);
  971. encodeULEB128(Index, W->OS);
  972. if (RelEntry.hasAddend())
  973. encodeSLEB128(RelEntry.Addend, W->OS);
  974. }
  975. endSection(Section);
  976. }
  977. void WasmObjectWriter::writeCustomRelocSections() {
  978. for (const auto &Sec : CustomSections) {
  979. auto &Relocations = CustomSectionsRelocations[Sec.Section];
  980. writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
  981. }
  982. }
  983. void WasmObjectWriter::writeLinkingMetaDataSection(
  984. ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
  985. ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
  986. const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats) {
  987. SectionBookkeeping Section;
  988. startCustomSection(Section, "linking");
  989. encodeULEB128(wasm::WasmMetadataVersion, W->OS);
  990. SectionBookkeeping SubSection;
  991. if (SymbolInfos.size() != 0) {
  992. startSection(SubSection, wasm::WASM_SYMBOL_TABLE);
  993. encodeULEB128(SymbolInfos.size(), W->OS);
  994. for (const wasm::WasmSymbolInfo &Sym : SymbolInfos) {
  995. encodeULEB128(Sym.Kind, W->OS);
  996. encodeULEB128(Sym.Flags, W->OS);
  997. switch (Sym.Kind) {
  998. case wasm::WASM_SYMBOL_TYPE_FUNCTION:
  999. case wasm::WASM_SYMBOL_TYPE_GLOBAL:
  1000. case wasm::WASM_SYMBOL_TYPE_TAG:
  1001. case wasm::WASM_SYMBOL_TYPE_TABLE:
  1002. encodeULEB128(Sym.ElementIndex, W->OS);
  1003. if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
  1004. (Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
  1005. writeString(Sym.Name);
  1006. break;
  1007. case wasm::WASM_SYMBOL_TYPE_DATA:
  1008. writeString(Sym.Name);
  1009. if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
  1010. encodeULEB128(Sym.DataRef.Segment, W->OS);
  1011. encodeULEB128(Sym.DataRef.Offset, W->OS);
  1012. encodeULEB128(Sym.DataRef.Size, W->OS);
  1013. }
  1014. break;
  1015. case wasm::WASM_SYMBOL_TYPE_SECTION: {
  1016. const uint32_t SectionIndex =
  1017. CustomSections[Sym.ElementIndex].OutputIndex;
  1018. encodeULEB128(SectionIndex, W->OS);
  1019. break;
  1020. }
  1021. default:
  1022. llvm_unreachable("unexpected kind");
  1023. }
  1024. }
  1025. endSection(SubSection);
  1026. }
  1027. if (DataSegments.size()) {
  1028. startSection(SubSection, wasm::WASM_SEGMENT_INFO);
  1029. encodeULEB128(DataSegments.size(), W->OS);
  1030. for (const WasmDataSegment &Segment : DataSegments) {
  1031. writeString(Segment.Name);
  1032. encodeULEB128(Segment.Alignment, W->OS);
  1033. encodeULEB128(Segment.LinkingFlags, W->OS);
  1034. }
  1035. endSection(SubSection);
  1036. }
  1037. if (!InitFuncs.empty()) {
  1038. startSection(SubSection, wasm::WASM_INIT_FUNCS);
  1039. encodeULEB128(InitFuncs.size(), W->OS);
  1040. for (auto &StartFunc : InitFuncs) {
  1041. encodeULEB128(StartFunc.first, W->OS); // priority
  1042. encodeULEB128(StartFunc.second, W->OS); // function index
  1043. }
  1044. endSection(SubSection);
  1045. }
  1046. if (Comdats.size()) {
  1047. startSection(SubSection, wasm::WASM_COMDAT_INFO);
  1048. encodeULEB128(Comdats.size(), W->OS);
  1049. for (const auto &C : Comdats) {
  1050. writeString(C.first);
  1051. encodeULEB128(0, W->OS); // flags for future use
  1052. encodeULEB128(C.second.size(), W->OS);
  1053. for (const WasmComdatEntry &Entry : C.second) {
  1054. encodeULEB128(Entry.Kind, W->OS);
  1055. encodeULEB128(Entry.Index, W->OS);
  1056. }
  1057. }
  1058. endSection(SubSection);
  1059. }
  1060. endSection(Section);
  1061. }
  1062. void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
  1063. const MCAssembler &Asm,
  1064. const MCAsmLayout &Layout) {
  1065. SectionBookkeeping Section;
  1066. auto *Sec = CustomSection.Section;
  1067. startCustomSection(Section, CustomSection.Name);
  1068. Sec->setSectionOffset(W->OS.tell() - Section.ContentsOffset);
  1069. Asm.writeSectionData(W->OS, Sec, Layout);
  1070. CustomSection.OutputContentsOffset = Section.ContentsOffset;
  1071. CustomSection.OutputIndex = Section.Index;
  1072. endSection(Section);
  1073. // Apply fixups.
  1074. auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
  1075. applyRelocations(Relocations, CustomSection.OutputContentsOffset, Layout);
  1076. }
  1077. uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm &Symbol) {
  1078. assert(Symbol.isFunction());
  1079. assert(TypeIndices.count(&Symbol));
  1080. return TypeIndices[&Symbol];
  1081. }
  1082. uint32_t WasmObjectWriter::getTagType(const MCSymbolWasm &Symbol) {
  1083. assert(Symbol.isTag());
  1084. assert(TypeIndices.count(&Symbol));
  1085. return TypeIndices[&Symbol];
  1086. }
  1087. void WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) {
  1088. assert(Symbol.isFunction());
  1089. wasm::WasmSignature S;
  1090. if (auto *Sig = Symbol.getSignature()) {
  1091. S.Returns = Sig->Returns;
  1092. S.Params = Sig->Params;
  1093. }
  1094. auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
  1095. if (Pair.second)
  1096. Signatures.push_back(S);
  1097. TypeIndices[&Symbol] = Pair.first->second;
  1098. LLVM_DEBUG(dbgs() << "registerFunctionType: " << Symbol
  1099. << " new:" << Pair.second << "\n");
  1100. LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
  1101. }
  1102. void WasmObjectWriter::registerTagType(const MCSymbolWasm &Symbol) {
  1103. assert(Symbol.isTag());
  1104. // TODO Currently we don't generate imported exceptions, but if we do, we
  1105. // should have a way of infering types of imported exceptions.
  1106. wasm::WasmSignature S;
  1107. if (auto *Sig = Symbol.getSignature()) {
  1108. S.Returns = Sig->Returns;
  1109. S.Params = Sig->Params;
  1110. }
  1111. auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
  1112. if (Pair.second)
  1113. Signatures.push_back(S);
  1114. TypeIndices[&Symbol] = Pair.first->second;
  1115. LLVM_DEBUG(dbgs() << "registerTagType: " << Symbol << " new:" << Pair.second
  1116. << "\n");
  1117. LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
  1118. }
  1119. static bool isInSymtab(const MCSymbolWasm &Sym) {
  1120. if (Sym.isUsedInReloc() || Sym.isUsedInInitArray())
  1121. return true;
  1122. if (Sym.isComdat() && !Sym.isDefined())
  1123. return false;
  1124. if (Sym.isTemporary())
  1125. return false;
  1126. if (Sym.isSection())
  1127. return false;
  1128. if (Sym.omitFromLinkingSection())
  1129. return false;
  1130. return true;
  1131. }
  1132. void WasmObjectWriter::prepareImports(
  1133. SmallVectorImpl<wasm::WasmImport> &Imports, MCAssembler &Asm,
  1134. const MCAsmLayout &Layout) {
  1135. // For now, always emit the memory import, since loads and stores are not
  1136. // valid without it. In the future, we could perhaps be more clever and omit
  1137. // it if there are no loads or stores.
  1138. wasm::WasmImport MemImport;
  1139. MemImport.Module = "env";
  1140. MemImport.Field = "__linear_memory";
  1141. MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY;
  1142. MemImport.Memory.Flags = is64Bit() ? wasm::WASM_LIMITS_FLAG_IS_64
  1143. : wasm::WASM_LIMITS_FLAG_NONE;
  1144. Imports.push_back(MemImport);
  1145. // Populate SignatureIndices, and Imports and WasmIndices for undefined
  1146. // symbols. This must be done before populating WasmIndices for defined
  1147. // symbols.
  1148. for (const MCSymbol &S : Asm.symbols()) {
  1149. const auto &WS = static_cast<const MCSymbolWasm &>(S);
  1150. // Register types for all functions, including those with private linkage
  1151. // (because wasm always needs a type signature).
  1152. if (WS.isFunction()) {
  1153. const auto *BS = Layout.getBaseSymbol(S);
  1154. if (!BS)
  1155. report_fatal_error(Twine(S.getName()) +
  1156. ": absolute addressing not supported!");
  1157. registerFunctionType(*cast<MCSymbolWasm>(BS));
  1158. }
  1159. if (WS.isTag())
  1160. registerTagType(WS);
  1161. if (WS.isTemporary())
  1162. continue;
  1163. // If the symbol is not defined in this translation unit, import it.
  1164. if (!WS.isDefined() && !WS.isComdat()) {
  1165. if (WS.isFunction()) {
  1166. wasm::WasmImport Import;
  1167. Import.Module = WS.getImportModule();
  1168. Import.Field = WS.getImportName();
  1169. Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
  1170. Import.SigIndex = getFunctionType(WS);
  1171. Imports.push_back(Import);
  1172. assert(WasmIndices.count(&WS) == 0);
  1173. WasmIndices[&WS] = NumFunctionImports++;
  1174. } else if (WS.isGlobal()) {
  1175. if (WS.isWeak())
  1176. report_fatal_error("undefined global symbol cannot be weak");
  1177. wasm::WasmImport Import;
  1178. Import.Field = WS.getImportName();
  1179. Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
  1180. Import.Module = WS.getImportModule();
  1181. Import.Global = WS.getGlobalType();
  1182. Imports.push_back(Import);
  1183. assert(WasmIndices.count(&WS) == 0);
  1184. WasmIndices[&WS] = NumGlobalImports++;
  1185. } else if (WS.isTag()) {
  1186. if (WS.isWeak())
  1187. report_fatal_error("undefined tag symbol cannot be weak");
  1188. wasm::WasmImport Import;
  1189. Import.Module = WS.getImportModule();
  1190. Import.Field = WS.getImportName();
  1191. Import.Kind = wasm::WASM_EXTERNAL_TAG;
  1192. Import.SigIndex = getTagType(WS);
  1193. Imports.push_back(Import);
  1194. assert(WasmIndices.count(&WS) == 0);
  1195. WasmIndices[&WS] = NumTagImports++;
  1196. } else if (WS.isTable()) {
  1197. if (WS.isWeak())
  1198. report_fatal_error("undefined table symbol cannot be weak");
  1199. wasm::WasmImport Import;
  1200. Import.Module = WS.getImportModule();
  1201. Import.Field = WS.getImportName();
  1202. Import.Kind = wasm::WASM_EXTERNAL_TABLE;
  1203. Import.Table = WS.getTableType();
  1204. Imports.push_back(Import);
  1205. assert(WasmIndices.count(&WS) == 0);
  1206. WasmIndices[&WS] = NumTableImports++;
  1207. }
  1208. }
  1209. }
  1210. // Add imports for GOT globals
  1211. for (const MCSymbol &S : Asm.symbols()) {
  1212. const auto &WS = static_cast<const MCSymbolWasm &>(S);
  1213. if (WS.isUsedInGOT()) {
  1214. wasm::WasmImport Import;
  1215. if (WS.isFunction())
  1216. Import.Module = "GOT.func";
  1217. else
  1218. Import.Module = "GOT.mem";
  1219. Import.Field = WS.getName();
  1220. Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
  1221. Import.Global = {wasm::WASM_TYPE_I32, true};
  1222. Imports.push_back(Import);
  1223. assert(GOTIndices.count(&WS) == 0);
  1224. GOTIndices[&WS] = NumGlobalImports++;
  1225. }
  1226. }
  1227. }
  1228. uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
  1229. const MCAsmLayout &Layout) {
  1230. support::endian::Writer MainWriter(*OS, support::little);
  1231. W = &MainWriter;
  1232. if (IsSplitDwarf) {
  1233. uint64_t TotalSize = writeOneObject(Asm, Layout, DwoMode::NonDwoOnly);
  1234. assert(DwoOS);
  1235. support::endian::Writer DwoWriter(*DwoOS, support::little);
  1236. W = &DwoWriter;
  1237. return TotalSize + writeOneObject(Asm, Layout, DwoMode::DwoOnly);
  1238. } else {
  1239. return writeOneObject(Asm, Layout, DwoMode::AllSections);
  1240. }
  1241. }
  1242. uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
  1243. const MCAsmLayout &Layout,
  1244. DwoMode Mode) {
  1245. uint64_t StartOffset = W->OS.tell();
  1246. SectionCount = 0;
  1247. CustomSections.clear();
  1248. LLVM_DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
  1249. // Collect information from the available symbols.
  1250. SmallVector<WasmFunction, 4> Functions;
  1251. SmallVector<uint32_t, 4> TableElems;
  1252. SmallVector<wasm::WasmImport, 4> Imports;
  1253. SmallVector<wasm::WasmExport, 4> Exports;
  1254. SmallVector<uint32_t, 2> TagTypes;
  1255. SmallVector<wasm::WasmGlobal, 1> Globals;
  1256. SmallVector<wasm::WasmTable, 1> Tables;
  1257. SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos;
  1258. SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs;
  1259. std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
  1260. uint64_t DataSize = 0;
  1261. if (Mode != DwoMode::DwoOnly) {
  1262. prepareImports(Imports, Asm, Layout);
  1263. }
  1264. // Populate DataSegments and CustomSections, which must be done before
  1265. // populating DataLocations.
  1266. for (MCSection &Sec : Asm) {
  1267. auto &Section = static_cast<MCSectionWasm &>(Sec);
  1268. StringRef SectionName = Section.getName();
  1269. if (Mode == DwoMode::NonDwoOnly && isDwoSection(Sec))
  1270. continue;
  1271. if (Mode == DwoMode::DwoOnly && !isDwoSection(Sec))
  1272. continue;
  1273. LLVM_DEBUG(dbgs() << "Processing Section " << SectionName << " group "
  1274. << Section.getGroup() << "\n";);
  1275. // .init_array sections are handled specially elsewhere.
  1276. if (SectionName.startswith(".init_array"))
  1277. continue;
  1278. // Code is handled separately
  1279. if (Section.getKind().isText())
  1280. continue;
  1281. if (Section.isWasmData()) {
  1282. uint32_t SegmentIndex = DataSegments.size();
  1283. DataSize = alignTo(DataSize, Section.getAlignment());
  1284. DataSegments.emplace_back();
  1285. WasmDataSegment &Segment = DataSegments.back();
  1286. Segment.Name = SectionName;
  1287. Segment.InitFlags = Section.getPassive()
  1288. ? (uint32_t)wasm::WASM_DATA_SEGMENT_IS_PASSIVE
  1289. : 0;
  1290. Segment.Offset = DataSize;
  1291. Segment.Section = &Section;
  1292. addData(Segment.Data, Section);
  1293. Segment.Alignment = Log2_32(Section.getAlignment());
  1294. Segment.LinkingFlags = Section.getSegmentFlags();
  1295. DataSize += Segment.Data.size();
  1296. Section.setSegmentIndex(SegmentIndex);
  1297. if (const MCSymbolWasm *C = Section.getGroup()) {
  1298. Comdats[C->getName()].emplace_back(
  1299. WasmComdatEntry{wasm::WASM_COMDAT_DATA, SegmentIndex});
  1300. }
  1301. } else {
  1302. // Create custom sections
  1303. assert(Sec.getKind().isMetadata());
  1304. StringRef Name = SectionName;
  1305. // For user-defined custom sections, strip the prefix
  1306. if (Name.startswith(".custom_section."))
  1307. Name = Name.substr(strlen(".custom_section."));
  1308. MCSymbol *Begin = Sec.getBeginSymbol();
  1309. if (Begin) {
  1310. assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0);
  1311. WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
  1312. }
  1313. // Separate out the producers and target features sections
  1314. if (Name == "producers") {
  1315. ProducersSection = std::make_unique<WasmCustomSection>(Name, &Section);
  1316. continue;
  1317. }
  1318. if (Name == "target_features") {
  1319. TargetFeaturesSection =
  1320. std::make_unique<WasmCustomSection>(Name, &Section);
  1321. continue;
  1322. }
  1323. // Custom sections can also belong to COMDAT groups. In this case the
  1324. // decriptor's "index" field is the section index (in the final object
  1325. // file), but that is not known until after layout, so it must be fixed up
  1326. // later
  1327. if (const MCSymbolWasm *C = Section.getGroup()) {
  1328. Comdats[C->getName()].emplace_back(
  1329. WasmComdatEntry{wasm::WASM_COMDAT_SECTION,
  1330. static_cast<uint32_t>(CustomSections.size())});
  1331. }
  1332. CustomSections.emplace_back(Name, &Section);
  1333. }
  1334. }
  1335. if (Mode != DwoMode::DwoOnly) {
  1336. // Populate WasmIndices and DataLocations for defined symbols.
  1337. for (const MCSymbol &S : Asm.symbols()) {
  1338. // Ignore unnamed temporary symbols, which aren't ever exported, imported,
  1339. // or used in relocations.
  1340. if (S.isTemporary() && S.getName().empty())
  1341. continue;
  1342. const auto &WS = static_cast<const MCSymbolWasm &>(S);
  1343. LLVM_DEBUG(dbgs()
  1344. << "MCSymbol: "
  1345. << toString(WS.getType().getValueOr(wasm::WASM_SYMBOL_TYPE_DATA))
  1346. << " '" << S << "'"
  1347. << " isDefined=" << S.isDefined() << " isExternal="
  1348. << S.isExternal() << " isTemporary=" << S.isTemporary()
  1349. << " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden()
  1350. << " isVariable=" << WS.isVariable() << "\n");
  1351. if (WS.isVariable())
  1352. continue;
  1353. if (WS.isComdat() && !WS.isDefined())
  1354. continue;
  1355. if (WS.isFunction()) {
  1356. unsigned Index;
  1357. if (WS.isDefined()) {
  1358. if (WS.getOffset() != 0)
  1359. report_fatal_error(
  1360. "function sections must contain one function each");
  1361. if (WS.getSize() == nullptr)
  1362. report_fatal_error(
  1363. "function symbols must have a size set with .size");
  1364. // A definition. Write out the function body.
  1365. Index = NumFunctionImports + Functions.size();
  1366. WasmFunction Func;
  1367. Func.SigIndex = getFunctionType(WS);
  1368. Func.Sym = &WS;
  1369. assert(WasmIndices.count(&WS) == 0);
  1370. WasmIndices[&WS] = Index;
  1371. Functions.push_back(Func);
  1372. auto &Section = static_cast<MCSectionWasm &>(WS.getSection());
  1373. if (const MCSymbolWasm *C = Section.getGroup()) {
  1374. Comdats[C->getName()].emplace_back(
  1375. WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index});
  1376. }
  1377. if (WS.hasExportName()) {
  1378. wasm::WasmExport Export;
  1379. Export.Name = WS.getExportName();
  1380. Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
  1381. Export.Index = Index;
  1382. Exports.push_back(Export);
  1383. }
  1384. } else {
  1385. // An import; the index was assigned above.
  1386. Index = WasmIndices.find(&WS)->second;
  1387. }
  1388. LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n");
  1389. } else if (WS.isData()) {
  1390. if (!isInSymtab(WS))
  1391. continue;
  1392. if (!WS.isDefined()) {
  1393. LLVM_DEBUG(dbgs() << " -> segment index: -1"
  1394. << "\n");
  1395. continue;
  1396. }
  1397. if (!WS.getSize())
  1398. report_fatal_error("data symbols must have a size set with .size: " +
  1399. WS.getName());
  1400. int64_t Size = 0;
  1401. if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
  1402. report_fatal_error(".size expression must be evaluatable");
  1403. auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
  1404. if (!DataSection.isWasmData())
  1405. report_fatal_error("data symbols must live in a data section: " +
  1406. WS.getName());
  1407. // For each data symbol, export it in the symtab as a reference to the
  1408. // corresponding Wasm data segment.
  1409. wasm::WasmDataReference Ref = wasm::WasmDataReference{
  1410. DataSection.getSegmentIndex(), Layout.getSymbolOffset(WS),
  1411. static_cast<uint64_t>(Size)};
  1412. assert(DataLocations.count(&WS) == 0);
  1413. DataLocations[&WS] = Ref;
  1414. LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n");
  1415. } else if (WS.isGlobal()) {
  1416. // A "true" Wasm global (currently just __stack_pointer)
  1417. if (WS.isDefined()) {
  1418. wasm::WasmGlobal Global;
  1419. Global.Type = WS.getGlobalType();
  1420. Global.Index = NumGlobalImports + Globals.size();
  1421. switch (Global.Type.Type) {
  1422. case wasm::WASM_TYPE_I32:
  1423. Global.InitExpr.Opcode = wasm::WASM_OPCODE_I32_CONST;
  1424. break;
  1425. case wasm::WASM_TYPE_I64:
  1426. Global.InitExpr.Opcode = wasm::WASM_OPCODE_I64_CONST;
  1427. break;
  1428. case wasm::WASM_TYPE_F32:
  1429. Global.InitExpr.Opcode = wasm::WASM_OPCODE_F32_CONST;
  1430. break;
  1431. case wasm::WASM_TYPE_F64:
  1432. Global.InitExpr.Opcode = wasm::WASM_OPCODE_F64_CONST;
  1433. break;
  1434. case wasm::WASM_TYPE_EXTERNREF:
  1435. Global.InitExpr.Opcode = wasm::WASM_OPCODE_REF_NULL;
  1436. break;
  1437. default:
  1438. llvm_unreachable("unexpected type");
  1439. }
  1440. assert(WasmIndices.count(&WS) == 0);
  1441. WasmIndices[&WS] = Global.Index;
  1442. Globals.push_back(Global);
  1443. } else {
  1444. // An import; the index was assigned above
  1445. LLVM_DEBUG(dbgs() << " -> global index: "
  1446. << WasmIndices.find(&WS)->second << "\n");
  1447. }
  1448. } else if (WS.isTable()) {
  1449. if (WS.isDefined()) {
  1450. wasm::WasmTable Table;
  1451. Table.Index = NumTableImports + Tables.size();
  1452. Table.Type = WS.getTableType();
  1453. assert(WasmIndices.count(&WS) == 0);
  1454. WasmIndices[&WS] = Table.Index;
  1455. Tables.push_back(Table);
  1456. }
  1457. LLVM_DEBUG(dbgs() << " -> table index: "
  1458. << WasmIndices.find(&WS)->second << "\n");
  1459. } else if (WS.isTag()) {
  1460. // C++ exception symbol (__cpp_exception) or longjmp symbol
  1461. // (__c_longjmp)
  1462. unsigned Index;
  1463. if (WS.isDefined()) {
  1464. Index = NumTagImports + TagTypes.size();
  1465. uint32_t SigIndex = getTagType(WS);
  1466. assert(WasmIndices.count(&WS) == 0);
  1467. WasmIndices[&WS] = Index;
  1468. TagTypes.push_back(SigIndex);
  1469. } else {
  1470. // An import; the index was assigned above.
  1471. assert(WasmIndices.count(&WS) > 0);
  1472. }
  1473. LLVM_DEBUG(dbgs() << " -> tag index: " << WasmIndices.find(&WS)->second
  1474. << "\n");
  1475. } else {
  1476. assert(WS.isSection());
  1477. }
  1478. }
  1479. // Populate WasmIndices and DataLocations for aliased symbols. We need to
  1480. // process these in a separate pass because we need to have processed the
  1481. // target of the alias before the alias itself and the symbols are not
  1482. // necessarily ordered in this way.
  1483. for (const MCSymbol &S : Asm.symbols()) {
  1484. if (!S.isVariable())
  1485. continue;
  1486. assert(S.isDefined());
  1487. const auto *BS = Layout.getBaseSymbol(S);
  1488. if (!BS)
  1489. report_fatal_error(Twine(S.getName()) +
  1490. ": absolute addressing not supported!");
  1491. const MCSymbolWasm *Base = cast<MCSymbolWasm>(BS);
  1492. // Find the target symbol of this weak alias and export that index
  1493. const auto &WS = static_cast<const MCSymbolWasm &>(S);
  1494. LLVM_DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *Base
  1495. << "'\n");
  1496. if (Base->isFunction()) {
  1497. assert(WasmIndices.count(Base) > 0);
  1498. uint32_t WasmIndex = WasmIndices.find(Base)->second;
  1499. assert(WasmIndices.count(&WS) == 0);
  1500. WasmIndices[&WS] = WasmIndex;
  1501. LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n");
  1502. } else if (Base->isData()) {
  1503. auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
  1504. uint64_t Offset = Layout.getSymbolOffset(S);
  1505. int64_t Size = 0;
  1506. // For data symbol alias we use the size of the base symbol as the
  1507. // size of the alias. When an offset from the base is involved this
  1508. // can result in a offset + size goes past the end of the data section
  1509. // which out object format doesn't support. So we must clamp it.
  1510. if (!Base->getSize()->evaluateAsAbsolute(Size, Layout))
  1511. report_fatal_error(".size expression must be evaluatable");
  1512. const WasmDataSegment &Segment =
  1513. DataSegments[DataSection.getSegmentIndex()];
  1514. Size =
  1515. std::min(static_cast<uint64_t>(Size), Segment.Data.size() - Offset);
  1516. wasm::WasmDataReference Ref = wasm::WasmDataReference{
  1517. DataSection.getSegmentIndex(),
  1518. static_cast<uint32_t>(Layout.getSymbolOffset(S)),
  1519. static_cast<uint32_t>(Size)};
  1520. DataLocations[&WS] = Ref;
  1521. LLVM_DEBUG(dbgs() << " -> index:" << Ref.Segment << "\n");
  1522. } else {
  1523. report_fatal_error("don't yet support global/tag aliases");
  1524. }
  1525. }
  1526. }
  1527. // Finally, populate the symbol table itself, in its "natural" order.
  1528. for (const MCSymbol &S : Asm.symbols()) {
  1529. const auto &WS = static_cast<const MCSymbolWasm &>(S);
  1530. if (!isInSymtab(WS)) {
  1531. WS.setIndex(InvalidIndex);
  1532. continue;
  1533. }
  1534. LLVM_DEBUG(dbgs() << "adding to symtab: " << WS << "\n");
  1535. uint32_t Flags = 0;
  1536. if (WS.isWeak())
  1537. Flags |= wasm::WASM_SYMBOL_BINDING_WEAK;
  1538. if (WS.isHidden())
  1539. Flags |= wasm::WASM_SYMBOL_VISIBILITY_HIDDEN;
  1540. if (!WS.isExternal() && WS.isDefined())
  1541. Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
  1542. if (WS.isUndefined())
  1543. Flags |= wasm::WASM_SYMBOL_UNDEFINED;
  1544. if (WS.isNoStrip()) {
  1545. Flags |= wasm::WASM_SYMBOL_NO_STRIP;
  1546. if (isEmscripten()) {
  1547. Flags |= wasm::WASM_SYMBOL_EXPORTED;
  1548. }
  1549. }
  1550. if (WS.hasImportName())
  1551. Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME;
  1552. if (WS.hasExportName())
  1553. Flags |= wasm::WASM_SYMBOL_EXPORTED;
  1554. if (WS.isTLS())
  1555. Flags |= wasm::WASM_SYMBOL_TLS;
  1556. wasm::WasmSymbolInfo Info;
  1557. Info.Name = WS.getName();
  1558. Info.Kind = WS.getType().getValueOr(wasm::WASM_SYMBOL_TYPE_DATA);
  1559. Info.Flags = Flags;
  1560. if (!WS.isData()) {
  1561. assert(WasmIndices.count(&WS) > 0);
  1562. Info.ElementIndex = WasmIndices.find(&WS)->second;
  1563. } else if (WS.isDefined()) {
  1564. assert(DataLocations.count(&WS) > 0);
  1565. Info.DataRef = DataLocations.find(&WS)->second;
  1566. }
  1567. WS.setIndex(SymbolInfos.size());
  1568. SymbolInfos.emplace_back(Info);
  1569. }
  1570. {
  1571. auto HandleReloc = [&](const WasmRelocationEntry &Rel) {
  1572. // Functions referenced by a relocation need to put in the table. This is
  1573. // purely to make the object file's provisional values readable, and is
  1574. // ignored by the linker, which re-calculates the relocations itself.
  1575. if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
  1576. Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&
  1577. Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
  1578. Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&
  1579. Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB &&
  1580. Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
  1581. return;
  1582. assert(Rel.Symbol->isFunction());
  1583. const MCSymbolWasm *Base =
  1584. cast<MCSymbolWasm>(Layout.getBaseSymbol(*Rel.Symbol));
  1585. uint32_t FunctionIndex = WasmIndices.find(Base)->second;
  1586. uint32_t TableIndex = TableElems.size() + InitialTableOffset;
  1587. if (TableIndices.try_emplace(Base, TableIndex).second) {
  1588. LLVM_DEBUG(dbgs() << " -> adding " << Base->getName()
  1589. << " to table: " << TableIndex << "\n");
  1590. TableElems.push_back(FunctionIndex);
  1591. registerFunctionType(*Base);
  1592. }
  1593. };
  1594. for (const WasmRelocationEntry &RelEntry : CodeRelocations)
  1595. HandleReloc(RelEntry);
  1596. for (const WasmRelocationEntry &RelEntry : DataRelocations)
  1597. HandleReloc(RelEntry);
  1598. }
  1599. // Translate .init_array section contents into start functions.
  1600. for (const MCSection &S : Asm) {
  1601. const auto &WS = static_cast<const MCSectionWasm &>(S);
  1602. if (WS.getName().startswith(".fini_array"))
  1603. report_fatal_error(".fini_array sections are unsupported");
  1604. if (!WS.getName().startswith(".init_array"))
  1605. continue;
  1606. if (WS.getFragmentList().empty())
  1607. continue;
  1608. // init_array is expected to contain a single non-empty data fragment
  1609. if (WS.getFragmentList().size() != 3)
  1610. report_fatal_error("only one .init_array section fragment supported");
  1611. auto IT = WS.begin();
  1612. const MCFragment &EmptyFrag = *IT;
  1613. if (EmptyFrag.getKind() != MCFragment::FT_Data)
  1614. report_fatal_error(".init_array section should be aligned");
  1615. IT = std::next(IT);
  1616. const MCFragment &AlignFrag = *IT;
  1617. if (AlignFrag.getKind() != MCFragment::FT_Align)
  1618. report_fatal_error(".init_array section should be aligned");
  1619. if (cast<MCAlignFragment>(AlignFrag).getAlignment() != (is64Bit() ? 8 : 4))
  1620. report_fatal_error(".init_array section should be aligned for pointers");
  1621. const MCFragment &Frag = *std::next(IT);
  1622. if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
  1623. report_fatal_error("only data supported in .init_array section");
  1624. uint16_t Priority = UINT16_MAX;
  1625. unsigned PrefixLength = strlen(".init_array");
  1626. if (WS.getName().size() > PrefixLength) {
  1627. if (WS.getName()[PrefixLength] != '.')
  1628. report_fatal_error(
  1629. ".init_array section priority should start with '.'");
  1630. if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
  1631. report_fatal_error("invalid .init_array section priority");
  1632. }
  1633. const auto &DataFrag = cast<MCDataFragment>(Frag);
  1634. const SmallVectorImpl<char> &Contents = DataFrag.getContents();
  1635. for (const uint8_t *
  1636. P = (const uint8_t *)Contents.data(),
  1637. *End = (const uint8_t *)Contents.data() + Contents.size();
  1638. P != End; ++P) {
  1639. if (*P != 0)
  1640. report_fatal_error("non-symbolic data in .init_array section");
  1641. }
  1642. for (const MCFixup &Fixup : DataFrag.getFixups()) {
  1643. assert(Fixup.getKind() ==
  1644. MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
  1645. const MCExpr *Expr = Fixup.getValue();
  1646. auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
  1647. if (!SymRef)
  1648. report_fatal_error("fixups in .init_array should be symbol references");
  1649. const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
  1650. if (TargetSym.getIndex() == InvalidIndex)
  1651. report_fatal_error("symbols in .init_array should exist in symtab");
  1652. if (!TargetSym.isFunction())
  1653. report_fatal_error("symbols in .init_array should be for functions");
  1654. InitFuncs.push_back(
  1655. std::make_pair(Priority, TargetSym.getIndex()));
  1656. }
  1657. }
  1658. // Write out the Wasm header.
  1659. writeHeader(Asm);
  1660. uint32_t CodeSectionIndex, DataSectionIndex;
  1661. if (Mode != DwoMode::DwoOnly) {
  1662. writeTypeSection(Signatures);
  1663. writeImportSection(Imports, DataSize, TableElems.size());
  1664. writeFunctionSection(Functions);
  1665. writeTableSection(Tables);
  1666. // Skip the "memory" section; we import the memory instead.
  1667. writeTagSection(TagTypes);
  1668. writeGlobalSection(Globals);
  1669. writeExportSection(Exports);
  1670. const MCSymbol *IndirectFunctionTable =
  1671. Asm.getContext().lookupSymbol("__indirect_function_table");
  1672. writeElemSection(cast_or_null<const MCSymbolWasm>(IndirectFunctionTable),
  1673. TableElems);
  1674. writeDataCountSection();
  1675. CodeSectionIndex = writeCodeSection(Asm, Layout, Functions);
  1676. DataSectionIndex = writeDataSection(Layout);
  1677. }
  1678. // The Sections in the COMDAT list have placeholder indices (their index among
  1679. // custom sections, rather than among all sections). Fix them up here.
  1680. for (auto &Group : Comdats) {
  1681. for (auto &Entry : Group.second) {
  1682. if (Entry.Kind == wasm::WASM_COMDAT_SECTION) {
  1683. Entry.Index += SectionCount;
  1684. }
  1685. }
  1686. }
  1687. for (auto &CustomSection : CustomSections)
  1688. writeCustomSection(CustomSection, Asm, Layout);
  1689. if (Mode != DwoMode::DwoOnly) {
  1690. writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
  1691. writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations);
  1692. writeRelocSection(DataSectionIndex, "DATA", DataRelocations);
  1693. }
  1694. writeCustomRelocSections();
  1695. if (ProducersSection)
  1696. writeCustomSection(*ProducersSection, Asm, Layout);
  1697. if (TargetFeaturesSection)
  1698. writeCustomSection(*TargetFeaturesSection, Asm, Layout);
  1699. // TODO: Translate the .comment section to the output.
  1700. return W->OS.tell() - StartOffset;
  1701. }
  1702. std::unique_ptr<MCObjectWriter>
  1703. llvm::createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
  1704. raw_pwrite_stream &OS) {
  1705. return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS);
  1706. }
  1707. std::unique_ptr<MCObjectWriter>
  1708. llvm::createWasmDwoObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
  1709. raw_pwrite_stream &OS,
  1710. raw_pwrite_stream &DwoOS) {
  1711. return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS, DwoOS);
  1712. }