1 /*
2  * Copyright 2018 WebAssembly Community Group participants
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/binary.h"
18 #include "src/binary-reader.h"
19 #include "src/binary-reader-nop.h"
20 #include "src/error-formatter.h"
21 #include "src/leb128.h"
22 #include "src/option-parser.h"
23 #include "src/stream.h"
24 
25 using namespace wabt;
26 
27 static std::string s_filename;
28 
29 static const char s_description[] =
30 R"(  Remove sections of a WebAssembly binary file.
31 
32 examples:
33   # Remove all custom sections from test.wasm
34   $ wasm-strip test.wasm
35 )";
36 
ParseOptions(int argc,char ** argv)37 static void ParseOptions(int argc, char** argv) {
38   OptionParser parser("wasm-strip", s_description);
39 
40   parser.AddArgument("filename", OptionParser::ArgumentCount::One,
41                      [](const char* argument) {
42                        s_filename = argument;
43                        ConvertBackslashToSlash(&s_filename);
44                      });
45   parser.Parse(argc, argv);
46 }
47 
48 class BinaryReaderStrip : public BinaryReaderNop {
49  public:
BinaryReaderStrip(Errors * errors)50   explicit BinaryReaderStrip(Errors* errors)
51       : errors_(errors) {
52     stream_.WriteU32(WABT_BINARY_MAGIC, "WASM_BINARY_MAGIC");
53     stream_.WriteU32(WABT_BINARY_VERSION, "WASM_BINARY_VERSION");
54   }
55 
OnError(const Error & error)56   bool OnError(const Error& error) override {
57     errors_->push_back(error);
58     return true;
59   }
60 
BeginSection(Index section_index,BinarySection section_type,Offset size)61   Result BeginSection(Index section_index,
62                       BinarySection section_type,
63                       Offset size) override {
64     if (section_type == BinarySection::Custom) {
65       return Result::Ok;
66     }
67     stream_.WriteU8Enum(section_type, "section code");
68     WriteU32Leb128(&stream_, size, "section size");
69     stream_.WriteData(state->data + state->offset, size, "section data");
70     return Result::Ok;
71   }
72 
WriteToFile(string_view filename)73   Result WriteToFile(string_view filename) {
74     return stream_.WriteToFile(filename);
75   }
76 
77  private:
78   MemoryStream stream_;
79   Errors* errors_;
80 };
81 
ProgramMain(int argc,char ** argv)82 int ProgramMain(int argc, char** argv) {
83   Result result;
84 
85   InitStdio();
86   ParseOptions(argc, argv);
87 
88   std::vector<uint8_t> file_data;
89   result = ReadFile(s_filename.c_str(), &file_data);
90   if (Succeeded(result)) {
91     Errors errors;
92     Features features;
93     const bool kReadDebugNames = false;
94     const bool kStopOnFirstError = true;
95     const bool kFailOnCustomSectionError = false;
96     ReadBinaryOptions options(features, nullptr, kReadDebugNames,
97                               kStopOnFirstError, kFailOnCustomSectionError);
98 
99     BinaryReaderStrip reader(&errors);
100     result = ReadBinary(file_data.data(), file_data.size(), &reader, options);
101     FormatErrorsToFile(errors, Location::Type::Binary);
102 
103     if (Succeeded(result)) {
104       result = reader.WriteToFile(s_filename);
105     }
106   }
107   return result != Result::Ok;
108 }
109 
main(int argc,char ** argv)110 int main(int argc, char** argv) {
111   WABT_TRY
112   return ProgramMain(argc, argv);
113   WABT_CATCH_BAD_ALLOC_AND_EXIT
114 }
115