summaryrefslogtreecommitdiff
path: root/src/tools/wasm-link-metadata.cpp
blob: 1ca64880f26b954f7eaf6f78e21431801cad38dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*
 * Copyright 2017 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//
// wasm-link-metadata console tool
// Reads wasm .o file and emits .json metadata
//

#include <exception>

#include "abi/wasm-object.h"
#include "ir/trapping.h"
#include "support/colors.h"
#include "support/command-line.h"
#include "support/file.h"
#include "wasm-binary.h"
#include "wasm-emscripten.h"
#include "wasm-io.h"
#include "wasm-linker.h"
#include "wasm-printing.h"
#include "wasm-validator.h"

using namespace cashew;
using namespace wasm;

void parseLinkingSection(std::vector<char> const& data, uint32_t &dataSize) {
  unsigned idx = 0;
  auto get = [&idx, &data](){ return data[idx++]; };
  auto readNext = [get](){
    U32LEB leb;
    leb.read(get);
    return leb.value;
  };

  while (idx < data.size()) {
    ABI::LinkType type = static_cast<ABI::LinkType>(readNext());
    uint32_t size = readNext();
    uint32_t startIdx = idx;

    switch(type) {
    case ABI::WASM_DATA_SIZE: {
      dataSize = readNext();
      break;
    }
    default: {
      break;
    }
    }
    // Always go to the end of the subsection based on size, not contents.
    idx = startIdx + size;
  }
}

int main(int argc, const char *argv[]) {
  std::string infile;
  std::string outfile;
  Options options("wasm-link-metadata",
                  "Reads wasm .o file and emits .json metadata");
  options
      .add("--output", "-o", "Output file",
           Options::Arguments::One,
           [&outfile](Options *o, const std::string &argument) {
             outfile = argument;
             Colors::disable();
           })
      .add_positional("INFILE", Options::Arguments::One,
                      [&infile](Options *o, const std::string &argument) {
                        infile = argument;
                      });
  options.parse(argc, argv);

  if (infile == "") {
    Fatal() << "Need to specify an infile\n";
  }

  Module wasm;
  try {
    ModuleReader reader;
    reader.readBinary(infile, wasm);
  } catch (ParseException& p) {
    p.dump(std::cerr);
    Fatal() << "error in parsing wasm binary";
  }

  if (options.debug) {
    WasmPrinter::printModule(&wasm, std::cerr);
  }

  uint32_t dataSize = 0;
  for (auto &section : wasm.userSections) {
    if (section.name == "linking") {
      parseLinkingSection(section.data, dataSize);
    }
  }

  std::vector<Name> initializerFunctions;
  initializerFunctions.push_back("__wasm_call_ctors");

  EmscriptenGlueGenerator generator(wasm);
  std::string metadata = generator.generateEmscriptenMetadata(dataSize, initializerFunctions);
  Output output(outfile, Flags::Text, Flags::Release);
  output << metadata;

  return 0;
}