• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_SNAPSHOT_EMBEDDED_EMBEDDED_FILE_WRITER_H_
6 #define V8_SNAPSHOT_EMBEDDED_EMBEDDED_FILE_WRITER_H_
7 
8 #include <cinttypes>
9 #include <cstdio>
10 #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 namespace v8 {
25 namespace internal {
26 // Generates the embedded.S file which is later compiled into the final v8
27 // binary. Its contents are exported through two symbols:
28 //
29 // v8_<variant>_embedded_blob_ (intptr_t):
30 //     a pointer to the start of the embedded blob.
31 // v8_<variant>_embedded_blob_size_ (uint32_t):
32 //     size of the embedded blob in bytes.
33 //
34 // The variant is usually "Default" but can be modified in multisnapshot builds.
35 class EmbeddedFileWriter : public EmbeddedFileWriterInterface {
36  public:
37   int LookupOrAddExternallyCompiledFilename(const char* filename) override;
38   const char* GetExternallyCompiledFilename(int fileid) const override;
39   int GetExternallyCompiledFilenameCount() const override;
40 
41   void PrepareBuiltinSourcePositionMap(Builtins* builtins) override;
42 
43   void PrepareBuiltinLabelInfoMap(int create_offset,
44                                   int invoke_create) override;
45 
46 #if defined(V8_OS_WIN64)
SetBuiltinUnwindData(Builtin builtin,const win64_unwindinfo::BuiltinUnwindInfo & unwinding_info)47   void SetBuiltinUnwindData(
48       Builtin builtin,
49       const win64_unwindinfo::BuiltinUnwindInfo& unwinding_info) override {
50     DCHECK_LT(static_cast<int>(builtin), Builtins::kBuiltinCount);
51     unwind_infos_[static_cast<int>(builtin)] = unwinding_info;
52   }
53 #endif  // V8_OS_WIN64
54 
SetEmbeddedFile(const char * embedded_src_path)55   void SetEmbeddedFile(const char* embedded_src_path) {
56     embedded_src_path_ = embedded_src_path;
57   }
58 
SetEmbeddedVariant(const char * embedded_variant)59   void SetEmbeddedVariant(const char* embedded_variant) {
60     if (embedded_variant == nullptr) return;
61     embedded_variant_ = embedded_variant;
62   }
63 
SetTargetArch(const char * target_arch)64   void SetTargetArch(const char* target_arch) { target_arch_ = target_arch; }
65 
SetTargetOs(const char * target_os)66   void SetTargetOs(const char* target_os) { target_os_ = target_os; }
67 
WriteEmbedded(const i::EmbeddedData * blob)68   void WriteEmbedded(const i::EmbeddedData* blob) const {
69     MaybeWriteEmbeddedFile(blob);
70   }
71 
72  private:
MaybeWriteEmbeddedFile(const i::EmbeddedData * blob)73   void MaybeWriteEmbeddedFile(const i::EmbeddedData* blob) const {
74     if (embedded_src_path_ == nullptr) return;
75 
76     FILE* fp = GetFileDescriptorOrDie(embedded_src_path_);
77 
78     std::unique_ptr<PlatformEmbeddedFileWriterBase> writer =
79         NewPlatformEmbeddedFileWriter(target_arch_, target_os_);
80     writer->SetFile(fp);
81 
82     WriteFilePrologue(writer.get());
83     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 
GetFileDescriptorOrDie(const char * filename)91   static FILE* GetFileDescriptorOrDie(const char* filename) {
92     FILE* fp = v8::base::OS::FOpen(filename, "wb");
93     if (fp == nullptr) {
94       i::PrintF("Unable to open file \"%s\" for writing.\n", filename);
95       exit(1);
96     }
97     return fp;
98   }
99 
WriteFilePrologue(PlatformEmbeddedFileWriterBase * w)100   void WriteFilePrologue(PlatformEmbeddedFileWriterBase* w) const {
101     w->Comment("Autogenerated file. Do not edit.");
102     w->Newline();
103     w->FilePrologue();
104   }
105 
WriteExternalFilenames(PlatformEmbeddedFileWriterBase * w)106   void WriteExternalFilenames(PlatformEmbeddedFileWriterBase* w) const {
107 #ifndef DEBUG
108     // Release builds must not contain debug infos.
109     CHECK_EQ(external_filenames_by_index_.size(), 0);
110 #endif
111 
112     w->Comment(
113         "Source positions in the embedded blob refer to filenames by id.");
114     w->Comment("Assembly directives here map the id to a filename.");
115     w->Newline();
116 
117     // Write external filenames.
118     int size = static_cast<int>(external_filenames_by_index_.size());
119     for (int i = 0; i < size; i++) {
120       w->DeclareExternalFilename(ExternalFilenameIndexToId(i),
121                                  external_filenames_by_index_[i]);
122     }
123   }
124 
125   // Fairly arbitrary but should fit all symbol names.
126   static constexpr int kTemporaryStringLength = 256;
127 
EmbeddedBlobCodeDataSymbol()128   std::string EmbeddedBlobCodeDataSymbol() const {
129     base::EmbeddedVector<char, kTemporaryStringLength>
130         embedded_blob_code_data_symbol;
131     base::SNPrintF(embedded_blob_code_data_symbol,
132                    "v8_%s_embedded_blob_code_data_", embedded_variant_);
133     return std::string{embedded_blob_code_data_symbol.begin()};
134   }
135 
EmbeddedBlobDataDataSymbol()136   std::string EmbeddedBlobDataDataSymbol() const {
137     base::EmbeddedVector<char, kTemporaryStringLength>
138         embedded_blob_data_data_symbol;
139     base::SNPrintF(embedded_blob_data_data_symbol,
140                    "v8_%s_embedded_blob_data_data_", embedded_variant_);
141     return std::string{embedded_blob_data_data_symbol.begin()};
142   }
143 
WriteDataSection(PlatformEmbeddedFileWriterBase * w,const i::EmbeddedData * blob)144   void WriteDataSection(PlatformEmbeddedFileWriterBase* w,
145                         const i::EmbeddedData* blob) const {
146     w->Comment("The embedded blob data section starts here.");
147     w->SectionRoData();
148     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   void WriteBuiltinLabels(PlatformEmbeddedFileWriterBase* w,
158                           std::string name) const;
159 
160   void WriteCodeSection(PlatformEmbeddedFileWriterBase* w,
161                         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                             uint64_t rva_start, uint64_t rva_end) const;
169 #endif
170 
171   static void WriteBinaryContentsAsInlineAssembly(
172       PlatformEmbeddedFileWriterBase* w, const uint8_t* data, uint32_t size);
173 
174   // In assembly directives, filename ids need to begin with 1.
175   static constexpr int kFirstExternalFilenameId = 1;
ExternalFilenameIndexToId(int index)176   static int ExternalFilenameIndexToId(int index) {
177     return kFirstExternalFilenameId + index;
178   }
ExternalFilenameIdToIndex(int id)179   static int ExternalFilenameIdToIndex(int id) {
180     return id - kFirstExternalFilenameId;
181   }
182 
183  private:
184   std::vector<byte> source_positions_[Builtins::kBuiltinCount];
185   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   std::map<const char*, int> external_filenames_;
192   std::vector<const char*> external_filenames_by_index_;
193 
194   // The file to generate or nullptr.
195   const char* embedded_src_path_ = nullptr;
196 
197   // The variant is only used in multi-snapshot builds and otherwise set to
198   // "Default".
199   const char* embedded_variant_ = kDefaultEmbeddedVariant;
200 
201   // {target_arch} and {target_os} control the generated assembly format. Note
202   // these may differ from both host- and target-platforms specified through
203   // e.g. V8_OS_* and V8_TARGET_ARCH_* defines.
204   const char* target_arch_ = nullptr;
205   const char* target_os_ = nullptr;
206 };
207 
208 }  // namespace internal
209 }  // namespace v8
210 
211 #endif  // V8_SNAPSHOT_EMBEDDED_EMBEDDED_FILE_WRITER_H_
212