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