embedded-file-writer.h 7.2 KB
Newer Older
1 2 3 4
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
#ifndef V8_SNAPSHOT_EMBEDDED_EMBEDDED_FILE_WRITER_H_
#define V8_SNAPSHOT_EMBEDDED_EMBEDDED_FILE_WRITER_H_
7

8
#include <cinttypes>
9 10
#include <cstdio>
#include <cstring>
11
#include <memory>
12

13
#include "src/base/strings.h"
14
#include "src/common/globals.h"
15
#include "src/snapshot/embedded/embedded-data.h"
16
#include "src/snapshot/embedded/embedded-file-writer-interface.h"
17
#include "src/snapshot/embedded/platform-embedded-file-writer-base.h"
18

19
#if defined(V8_OS_WIN64)
20
#include "src/base/platform/wrappers.h"
21
#include "src/diagnostics/unwinding-info-win64.h"
22
#endif  // V8_OS_WIN64
23

24 25 26 27 28 29 30 31 32 33 34
namespace v8 {
namespace internal {
// Generates the embedded.S file which is later compiled into the final v8
// binary. Its contents are exported through two symbols:
//
// v8_<variant>_embedded_blob_ (intptr_t):
//     a pointer to the start of the embedded blob.
// v8_<variant>_embedded_blob_size_ (uint32_t):
//     size of the embedded blob in bytes.
//
// The variant is usually "Default" but can be modified in multisnapshot builds.
35
class EmbeddedFileWriter : public EmbeddedFileWriterInterface {
36
 public:
37 38 39
  int LookupOrAddExternallyCompiledFilename(const char* filename) override;
  const char* GetExternallyCompiledFilename(int fileid) const override;
  int GetExternallyCompiledFilenameCount() const override;
40 41 42

  void PrepareBuiltinSourcePositionMap(Builtins* builtins) override;

43 44
  void PrepareBuiltinLabelInfoMap(int create_offset,
                                  int invoke_create) override;
45

46
#if defined(V8_OS_WIN64)
47
  void SetBuiltinUnwindData(
48
      Builtin builtin,
49
      const win64_unwindinfo::BuiltinUnwindInfo& unwinding_info) override {
50 51
    DCHECK_LT(static_cast<int>(builtin), Builtins::kBuiltinCount);
    unwind_infos_[static_cast<int>(builtin)] = unwinding_info;
52
  }
53
#endif  // V8_OS_WIN64
54

55 56
  void SetEmbeddedFile(const char* embedded_src_path) {
    embedded_src_path_ = embedded_src_path;
57 58 59
  }

  void SetEmbeddedVariant(const char* embedded_variant) {
60
    if (embedded_variant == nullptr) return;
61 62 63
    embedded_variant_ = embedded_variant;
  }

64 65 66 67
  void SetTargetArch(const char* target_arch) { target_arch_ = target_arch; }

  void SetTargetOs(const char* target_os) { target_os_ = target_os; }

68 69 70 71 72 73
  void WriteEmbedded(const i::EmbeddedData* blob) const {
    MaybeWriteEmbeddedFile(blob);
  }

 private:
  void MaybeWriteEmbeddedFile(const i::EmbeddedData* blob) const {
74
    if (embedded_src_path_ == nullptr) return;
75

76
    FILE* fp = GetFileDescriptorOrDie(embedded_src_path_);
77

78 79 80
    std::unique_ptr<PlatformEmbeddedFileWriterBase> writer =
        NewPlatformEmbeddedFileWriter(target_arch_, target_os_);
    writer->SetFile(fp);
81

82 83
    WriteFilePrologue(writer.get());
    WriteExternalFilenames(writer.get());
84
    WriteDataSection(writer.get(), blob);
85
    WriteCodeSection(writer.get(), blob);
86
    WriteFileEpilogue(writer.get(), blob);
87

88
    base::Fclose(fp);
89 90 91 92 93 94 95 96 97 98 99
  }

  static FILE* GetFileDescriptorOrDie(const char* filename) {
    FILE* fp = v8::base::OS::FOpen(filename, "wb");
    if (fp == nullptr) {
      i::PrintF("Unable to open file \"%s\" for writing.\n", filename);
      exit(1);
    }
    return fp;
  }

100
  void WriteFilePrologue(PlatformEmbeddedFileWriterBase* w) const {
101 102 103 104 105
    w->Comment("Autogenerated file. Do not edit.");
    w->Newline();
    w->FilePrologue();
  }

106
  void WriteExternalFilenames(PlatformEmbeddedFileWriterBase* w) const {
107 108 109 110 111
#ifndef DEBUG
    // Release builds must not contain debug infos.
    CHECK_EQ(external_filenames_by_index_.size(), 0);
#endif

112 113 114 115 116 117 118 119 120 121 122 123 124
    w->Comment(
        "Source positions in the embedded blob refer to filenames by id.");
    w->Comment("Assembly directives here map the id to a filename.");
    w->Newline();

    // Write external filenames.
    int size = static_cast<int>(external_filenames_by_index_.size());
    for (int i = 0; i < size; i++) {
      w->DeclareExternalFilename(ExternalFilenameIndexToId(i),
                                 external_filenames_by_index_[i]);
    }
  }

125 126 127
  // Fairly arbitrary but should fit all symbol names.
  static constexpr int kTemporaryStringLength = 256;

128
  std::string EmbeddedBlobCodeDataSymbol() const {
129
    base::EmbeddedVector<char, kTemporaryStringLength>
130
        embedded_blob_code_data_symbol;
131 132
    base::SNPrintF(embedded_blob_code_data_symbol,
                   "v8_%s_embedded_blob_code_data_", embedded_variant_);
133 134 135
    return std::string{embedded_blob_code_data_symbol.begin()};
  }

136
  std::string EmbeddedBlobDataDataSymbol() const {
137
    base::EmbeddedVector<char, kTemporaryStringLength>
138
        embedded_blob_data_data_symbol;
139 140
    base::SNPrintF(embedded_blob_data_data_symbol,
                   "v8_%s_embedded_blob_data_data_", embedded_variant_);
141
    return std::string{embedded_blob_data_data_symbol.begin()};
142
  }
143

144 145 146
  void WriteDataSection(PlatformEmbeddedFileWriterBase* w,
                        const i::EmbeddedData* blob) const {
    w->Comment("The embedded blob data section starts here.");
147 148
    w->SectionRoData();
    w->AlignToDataAlignment();
149
    w->DeclareLabel(EmbeddedBlobDataDataSymbol().c_str());
150

151
    WriteBinaryContentsAsInlineAssembly(w, blob->data(), blob->data_size());
152 153
  }

154
  void WriteBuiltin(PlatformEmbeddedFileWriterBase* w,
155
                    const i::EmbeddedData* blob, const Builtin builtin) const;
156

157 158 159
  void WriteBuiltinLabels(PlatformEmbeddedFileWriterBase* w,
                          std::string name) const;

160 161
  void WriteCodeSection(PlatformEmbeddedFileWriterBase* w,
                        const i::EmbeddedData* blob) const;
162

163
  void WriteFileEpilogue(PlatformEmbeddedFileWriterBase* w,
164
                         const i::EmbeddedData* blob) const;
165

166
#if defined(V8_OS_WIN_X64)
167
  void WriteUnwindInfoEntry(PlatformEmbeddedFileWriterBase* w,
168 169 170
                            uint64_t rva_start, uint64_t rva_end) const;
#endif

171
  static void WriteBinaryContentsAsInlineAssembly(
172
      PlatformEmbeddedFileWriterBase* w, const uint8_t* data, uint32_t size);
173

174 175
  // In assembly directives, filename ids need to begin with 1.
  static constexpr int kFirstExternalFilenameId = 1;
176 177 178 179 180 181 182
  static int ExternalFilenameIndexToId(int index) {
    return kFirstExternalFilenameId + index;
  }
  static int ExternalFilenameIdToIndex(int id) {
    return id - kFirstExternalFilenameId;
  }

183
 private:
184 185
  std::vector<byte> source_positions_[Builtins::kBuiltinCount];
  std::vector<LabelInfo> label_info_[Builtins::kBuiltinCount];
186

187
#if defined(V8_OS_WIN64)
188
  win64_unwindinfo::BuiltinUnwindInfo unwind_infos_[Builtins::kBuiltinCount];
189
#endif  // V8_OS_WIN64
190

191 192 193
  std::map<const char*, int> external_filenames_;
  std::vector<const char*> external_filenames_by_index_;

194
  // The file to generate or nullptr.
195
  const char* embedded_src_path_ = nullptr;
196 197 198

  // The variant is only used in multi-snapshot builds and otherwise set to
  // "Default".
199
  const char* embedded_variant_ = kDefaultEmbeddedVariant;
200 201 202 203 204 205

  // {target_arch} and {target_os} control the generated assembly format. Note
  // these may differ from both host- and target-platforms specified through
  // e.g. V8_OS_* and V8_TARGET_ARCH_* defines.
  const char* target_arch_ = nullptr;
  const char* target_os_ = nullptr;
206 207 208 209 210
};

}  // namespace internal
}  // namespace v8

211
#endif  // V8_SNAPSHOT_EMBEDDED_EMBEDDED_FILE_WRITER_H_