1 //===- WasmWriter.cpp -----------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "WasmWriter.h"
10 #include "llvm/BinaryFormat/Wasm.h"
11 #include "llvm/Support/Endian.h"
12 #include "llvm/Support/Errc.h"
13 #include "llvm/Support/LEB128.h"
14 #include "llvm/Support/raw_ostream.h"
20 using namespace object
;
21 using namespace llvm::wasm
;
23 Writer::SectionHeader
Writer::createSectionHeader(const Section
&S
,
24 size_t &SectionSize
) {
26 raw_svector_ostream
OS(Header
);
28 bool HasName
= S
.SectionType
== WASM_SEC_CUSTOM
;
29 SectionSize
= S
.Contents
.size();
31 SectionSize
+= getULEB128Size(S
.Name
.size()) + S
.Name
.size();
32 // If we read this section from an object file, use its original size for the
33 // padding of the LEB value to avoid changing the file size. Otherwise, pad
34 // out to 5 bytes to make it predictable, and match the behavior of clang.
35 unsigned HeaderSecSizeEncodingLen
=
36 S
.HeaderSecSizeEncodingLen
? *S
.HeaderSecSizeEncodingLen
: 5;
37 encodeULEB128(SectionSize
, OS
, HeaderSecSizeEncodingLen
);
39 encodeULEB128(S
.Name
.size(), OS
);
42 // Total section size is the content size plus 1 for the section type and
43 // the LEB-encoded size.
44 SectionSize
= SectionSize
+ 1 + HeaderSecSizeEncodingLen
;
48 size_t Writer::finalize() {
49 size_t ObjectSize
= sizeof(WasmMagic
) + sizeof(WasmVersion
);
50 SectionHeaders
.reserve(Obj
.Sections
.size());
51 // Finalize the headers of each section so we know the total size.
52 for (const Section
&S
: Obj
.Sections
) {
54 SectionHeaders
.push_back(createSectionHeader(S
, SectionSize
));
55 ObjectSize
+= SectionSize
;
60 Error
Writer::write() {
61 size_t TotalSize
= finalize();
62 Out
.reserveExtraSpace(TotalSize
);
65 Out
.write(Obj
.Header
.Magic
.data(), Obj
.Header
.Magic
.size());
67 support::endian::write32le(&Version
, Obj
.Header
.Version
);
68 Out
.write(reinterpret_cast<const char *>(&Version
), sizeof(Version
));
70 // Write each section.
71 for (size_t I
= 0, S
= SectionHeaders
.size(); I
< S
; ++I
) {
72 Out
.write(SectionHeaders
[I
].data(), SectionHeaders
[I
].size());
73 Out
.write(reinterpret_cast<const char *>(Obj
.Sections
[I
].Contents
.data()),
74 Obj
.Sections
[I
].Contents
.size());
77 return Error::success();
80 } // end namespace wasm
81 } // end namespace objcopy
82 } // end namespace llvm