• 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/common/globals.h"
14 #include "src/snapshot/embedded/embedded-data.h"
15 #include "src/snapshot/embedded/platform-embedded-file-writer-base.h"
16 
17 #if defined(V8_OS_WIN64)
18 #include "src/diagnostics/unwinding-info-win64.h"
19 #endif  // V8_OS_WIN64
20 
21 namespace v8 {
22 namespace internal {
23 
24 static constexpr char kDefaultEmbeddedVariant[] = "Default";
25 
26 struct LabelInfo {
27   int offset;
28   std::string name;
29 };
30 
31 // Detailed source-code information about builtins can only be obtained by
32 // registration on the isolate during compilation.
33 class EmbeddedFileWriterInterface {
34  public:
35   // We maintain a database of filenames to synthetic IDs.
36   virtual int LookupOrAddExternallyCompiledFilename(const char* filename) = 0;
37   virtual const char* GetExternallyCompiledFilename(int index) const = 0;
38   virtual int GetExternallyCompiledFilenameCount() const = 0;
39 
40   // The isolate will call the method below just prior to replacing the
41   // compiled builtin Code objects with trampolines.
42   virtual void PrepareBuiltinSourcePositionMap(Builtins* builtins) = 0;
43 
44   virtual void PrepareBuiltinLabelInfoMap(int create_offset, int invoke_offset,
45                                           int arguments_adaptor_offset) = 0;
46 
47 #if defined(V8_OS_WIN64)
48   virtual void SetBuiltinUnwindData(
49       int builtin_index,
50       const win64_unwindinfo::BuiltinUnwindInfo& unwinding_info) = 0;
51 #endif  // V8_OS_WIN64
52 };
53 
54 // Generates the embedded.S file which is later compiled into the final v8
55 // binary. Its contents are exported through two symbols:
56 //
57 // v8_<variant>_embedded_blob_ (intptr_t):
58 //     a pointer to the start of the embedded blob.
59 // v8_<variant>_embedded_blob_size_ (uint32_t):
60 //     size of the embedded blob in bytes.
61 //
62 // The variant is usually "Default" but can be modified in multisnapshot builds.
63 class EmbeddedFileWriter : public EmbeddedFileWriterInterface {
64  public:
65   int LookupOrAddExternallyCompiledFilename(const char* filename) override;
66   const char* GetExternallyCompiledFilename(int fileid) const override;
67   int GetExternallyCompiledFilenameCount() const override;
68 
69   void PrepareBuiltinSourcePositionMap(Builtins* builtins) override;
70 
71   void PrepareBuiltinLabelInfoMap(int create_offset, int invoke_create,
72                                   int arguments_adaptor_offset) override;
73 
74 #if defined(V8_OS_WIN64)
SetBuiltinUnwindData(int builtin_index,const win64_unwindinfo::BuiltinUnwindInfo & unwinding_info)75   void SetBuiltinUnwindData(
76       int builtin_index,
77       const win64_unwindinfo::BuiltinUnwindInfo& unwinding_info) override {
78     DCHECK_LT(builtin_index, Builtins::builtin_count);
79     unwind_infos_[builtin_index] = unwinding_info;
80   }
81 #endif  // V8_OS_WIN64
82 
SetEmbeddedFile(const char * embedded_src_path)83   void SetEmbeddedFile(const char* embedded_src_path) {
84     embedded_src_path_ = embedded_src_path;
85   }
86 
SetEmbeddedVariant(const char * embedded_variant)87   void SetEmbeddedVariant(const char* embedded_variant) {
88     if (embedded_variant == nullptr) return;
89     embedded_variant_ = embedded_variant;
90   }
91 
SetTargetArch(const char * target_arch)92   void SetTargetArch(const char* target_arch) { target_arch_ = target_arch; }
93 
SetTargetOs(const char * target_os)94   void SetTargetOs(const char* target_os) { target_os_ = target_os; }
95 
WriteEmbedded(const i::EmbeddedData * blob)96   void WriteEmbedded(const i::EmbeddedData* blob) const {
97     MaybeWriteEmbeddedFile(blob);
98   }
99 
100  private:
MaybeWriteEmbeddedFile(const i::EmbeddedData * blob)101   void MaybeWriteEmbeddedFile(const i::EmbeddedData* blob) const {
102     if (embedded_src_path_ == nullptr) return;
103 
104     FILE* fp = GetFileDescriptorOrDie(embedded_src_path_);
105 
106     std::unique_ptr<PlatformEmbeddedFileWriterBase> writer =
107         NewPlatformEmbeddedFileWriter(target_arch_, target_os_);
108     writer->SetFile(fp);
109 
110     WriteFilePrologue(writer.get());
111     WriteExternalFilenames(writer.get());
112     WriteDataSection(writer.get(), blob);
113     WriteCodeSection(writer.get(), blob);
114     WriteFileEpilogue(writer.get(), blob);
115 
116     fclose(fp);
117   }
118 
GetFileDescriptorOrDie(const char * filename)119   static FILE* GetFileDescriptorOrDie(const char* filename) {
120     FILE* fp = v8::base::OS::FOpen(filename, "wb");
121     if (fp == nullptr) {
122       i::PrintF("Unable to open file \"%s\" for writing.\n", filename);
123       exit(1);
124     }
125     return fp;
126   }
127 
WriteFilePrologue(PlatformEmbeddedFileWriterBase * w)128   void WriteFilePrologue(PlatformEmbeddedFileWriterBase* w) const {
129     w->Comment("Autogenerated file. Do not edit.");
130     w->Newline();
131     w->FilePrologue();
132   }
133 
WriteExternalFilenames(PlatformEmbeddedFileWriterBase * w)134   void WriteExternalFilenames(PlatformEmbeddedFileWriterBase* w) const {
135 #ifndef DEBUG
136     // Release builds must not contain debug infos.
137     CHECK_EQ(external_filenames_by_index_.size(), 0);
138 #endif
139 
140     w->Comment(
141         "Source positions in the embedded blob refer to filenames by id.");
142     w->Comment("Assembly directives here map the id to a filename.");
143     w->Newline();
144 
145     // Write external filenames.
146     int size = static_cast<int>(external_filenames_by_index_.size());
147     for (int i = 0; i < size; i++) {
148       w->DeclareExternalFilename(ExternalFilenameIndexToId(i),
149                                  external_filenames_by_index_[i]);
150     }
151   }
152 
153   // Fairly arbitrary but should fit all symbol names.
154   static constexpr int kTemporaryStringLength = 256;
155 
EmbeddedBlobCodeDataSymbol()156   std::string EmbeddedBlobCodeDataSymbol() const {
157     i::EmbeddedVector<char, kTemporaryStringLength>
158         embedded_blob_code_data_symbol;
159     i::SNPrintF(embedded_blob_code_data_symbol,
160                 "v8_%s_embedded_blob_code_data_", embedded_variant_);
161     return std::string{embedded_blob_code_data_symbol.begin()};
162   }
163 
EmbeddedBlobDataDataSymbol()164   std::string EmbeddedBlobDataDataSymbol() const {
165     i::EmbeddedVector<char, kTemporaryStringLength>
166         embedded_blob_data_data_symbol;
167     i::SNPrintF(embedded_blob_data_data_symbol,
168                 "v8_%s_embedded_blob_data_data_", embedded_variant_);
169     return std::string{embedded_blob_data_data_symbol.begin()};
170   }
171 
WriteDataSection(PlatformEmbeddedFileWriterBase * w,const i::EmbeddedData * blob)172   void WriteDataSection(PlatformEmbeddedFileWriterBase* w,
173                         const i::EmbeddedData* blob) const {
174     w->Comment("The embedded blob data section starts here.");
175     w->SectionRoData();
176     w->AlignToDataAlignment();
177     w->DeclareLabel(EmbeddedBlobDataDataSymbol().c_str());
178 
179     WriteBinaryContentsAsInlineAssembly(w, blob->data(), blob->data_size());
180   }
181 
182   void WriteBuiltin(PlatformEmbeddedFileWriterBase* w,
183                     const i::EmbeddedData* blob, const int builtin_id) const;
184 
185   void WriteBuiltinLabels(PlatformEmbeddedFileWriterBase* w,
186                           std::string name) const;
187 
188   void WriteCodeSection(PlatformEmbeddedFileWriterBase* w,
189                         const i::EmbeddedData* blob) const;
190 
191   void WriteFileEpilogue(PlatformEmbeddedFileWriterBase* w,
192                          const i::EmbeddedData* blob) const;
193 
194 #if defined(V8_OS_WIN_X64)
195   void WriteUnwindInfoEntry(PlatformEmbeddedFileWriterBase* w,
196                             uint64_t rva_start, uint64_t rva_end) const;
197 #endif
198 
199   static void WriteBinaryContentsAsInlineAssembly(
200       PlatformEmbeddedFileWriterBase* w, const uint8_t* data, uint32_t size);
201 
202   // In assembly directives, filename ids need to begin with 1.
203   static constexpr int kFirstExternalFilenameId = 1;
ExternalFilenameIndexToId(int index)204   static int ExternalFilenameIndexToId(int index) {
205     return kFirstExternalFilenameId + index;
206   }
ExternalFilenameIdToIndex(int id)207   static int ExternalFilenameIdToIndex(int id) {
208     return id - kFirstExternalFilenameId;
209   }
210 
211  private:
212   std::vector<byte> source_positions_[Builtins::builtin_count];
213   std::vector<LabelInfo> label_info_[Builtins::builtin_count];
214 
215 #if defined(V8_OS_WIN64)
216   win64_unwindinfo::BuiltinUnwindInfo unwind_infos_[Builtins::builtin_count];
217 #endif  // V8_OS_WIN64
218 
219   std::map<const char*, int> external_filenames_;
220   std::vector<const char*> external_filenames_by_index_;
221 
222   // The file to generate or nullptr.
223   const char* embedded_src_path_ = nullptr;
224 
225   // The variant is only used in multi-snapshot builds and otherwise set to
226   // "Default".
227   const char* embedded_variant_ = kDefaultEmbeddedVariant;
228 
229   // {target_arch} and {target_os} control the generated assembly format. Note
230   // these may differ from both host- and target-platforms specified through
231   // e.g. V8_OS_* and V8_TARGET_ARCH_* defines.
232   const char* target_arch_ = nullptr;
233   const char* target_os_ = nullptr;
234 };
235 
236 }  // namespace internal
237 }  // namespace v8
238 
239 #endif  // V8_SNAPSHOT_EMBEDDED_EMBEDDED_FILE_WRITER_H_
240