1 // Copyright 2019 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 #include "src/snapshot/embedded/platform-embedded-file-writer-generic.h"
6
7 #include <algorithm>
8 #include <cinttypes>
9
10 #include "src/common/globals.h"
11 #include "src/objects/code.h"
12
13 namespace v8 {
14 namespace internal {
15
16 #define SYMBOL_PREFIX ""
17
18 namespace {
19
DirectiveAsString(DataDirective directive)20 const char* DirectiveAsString(DataDirective directive) {
21 switch (directive) {
22 case kByte:
23 return ".byte";
24 case kLong:
25 return ".long";
26 case kQuad:
27 return ".quad";
28 case kOcta:
29 return ".octa";
30 }
31 UNREACHABLE();
32 }
33
34 } // namespace
35
SectionText()36 void PlatformEmbeddedFileWriterGeneric::SectionText() {
37 if (target_os_ == EmbeddedTargetOs::kChromeOS) {
38 fprintf(fp_, ".section .text.hot.embedded\n");
39 } else {
40 fprintf(fp_, ".section .text\n");
41 }
42 }
43
SectionData()44 void PlatformEmbeddedFileWriterGeneric::SectionData() {
45 fprintf(fp_, ".section .data\n");
46 }
47
SectionRoData()48 void PlatformEmbeddedFileWriterGeneric::SectionRoData() {
49 fprintf(fp_, ".section .rodata\n");
50 }
51
DeclareUint32(const char * name,uint32_t value)52 void PlatformEmbeddedFileWriterGeneric::DeclareUint32(const char* name,
53 uint32_t value) {
54 DeclareSymbolGlobal(name);
55 DeclareLabel(name);
56 IndentedDataDirective(kLong);
57 fprintf(fp_, "%d", value);
58 Newline();
59 }
60
DeclarePointerToSymbol(const char * name,const char * target)61 void PlatformEmbeddedFileWriterGeneric::DeclarePointerToSymbol(
62 const char* name, const char* target) {
63 DeclareSymbolGlobal(name);
64 DeclareLabel(name);
65 fprintf(fp_, " %s %s%s\n", DirectiveAsString(PointerSizeDirective()),
66 SYMBOL_PREFIX, target);
67 }
68
DeclareSymbolGlobal(const char * name)69 void PlatformEmbeddedFileWriterGeneric::DeclareSymbolGlobal(const char* name) {
70 fprintf(fp_, ".global %s%s\n", SYMBOL_PREFIX, name);
71 // These symbols are not visible outside of the final binary, this allows for
72 // reduced binary size, and less work for the dynamic linker.
73 fprintf(fp_, ".hidden %s\n", name);
74 }
75
AlignToCodeAlignment()76 void PlatformEmbeddedFileWriterGeneric::AlignToCodeAlignment() {
77 STATIC_ASSERT(32 >= kCodeAlignment);
78 fprintf(fp_, ".balign 32\n");
79 }
80
AlignToDataAlignment()81 void PlatformEmbeddedFileWriterGeneric::AlignToDataAlignment() {
82 // On Windows ARM64, s390, PPC and possibly more platforms, aligned load
83 // instructions are used to retrieve v8_Default_embedded_blob_ and/or
84 // v8_Default_embedded_blob_size_. The generated instructions require the
85 // load target to be aligned at 8 bytes (2^3).
86 STATIC_ASSERT(8 >= Code::kMetadataAlignment);
87 fprintf(fp_, ".balign 8\n");
88 }
89
Comment(const char * string)90 void PlatformEmbeddedFileWriterGeneric::Comment(const char* string) {
91 fprintf(fp_, "// %s\n", string);
92 }
93
DeclareLabel(const char * name)94 void PlatformEmbeddedFileWriterGeneric::DeclareLabel(const char* name) {
95 fprintf(fp_, "%s%s:\n", SYMBOL_PREFIX, name);
96 }
97
SourceInfo(int fileid,const char * filename,int line)98 void PlatformEmbeddedFileWriterGeneric::SourceInfo(int fileid,
99 const char* filename,
100 int line) {
101 fprintf(fp_, ".loc %d %d\n", fileid, line);
102 }
103
DeclareFunctionBegin(const char * name,uint32_t size)104 void PlatformEmbeddedFileWriterGeneric::DeclareFunctionBegin(const char* name,
105 uint32_t size) {
106 if (ENABLE_CONTROL_FLOW_INTEGRITY_BOOL) {
107 DeclareSymbolGlobal(name);
108 }
109
110 DeclareLabel(name);
111
112 if (target_arch_ == EmbeddedTargetArch::kArm ||
113 target_arch_ == EmbeddedTargetArch::kArm64) {
114 // ELF format binaries on ARM use ".type <function name>, %function"
115 // to create a DWARF subprogram entry.
116 fprintf(fp_, ".type %s, %%function\n", name);
117 } else {
118 // Other ELF Format binaries use ".type <function name>, @function"
119 // to create a DWARF subprogram entry.
120 fprintf(fp_, ".type %s, @function\n", name);
121 }
122 fprintf(fp_, ".size %s, %u\n", name, size);
123 }
124
DeclareFunctionEnd(const char * name)125 void PlatformEmbeddedFileWriterGeneric::DeclareFunctionEnd(const char* name) {}
126
FilePrologue()127 void PlatformEmbeddedFileWriterGeneric::FilePrologue() {
128 // TODO(v8:10026): Add ELF note required for BTI.
129 }
130
DeclareExternalFilename(int fileid,const char * filename)131 void PlatformEmbeddedFileWriterGeneric::DeclareExternalFilename(
132 int fileid, const char* filename) {
133 // Replace any Windows style paths (backslashes) with forward
134 // slashes.
135 std::string fixed_filename(filename);
136 std::replace(fixed_filename.begin(), fixed_filename.end(), '\\', '/');
137 fprintf(fp_, ".file %d \"%s\"\n", fileid, fixed_filename.c_str());
138 }
139
FileEpilogue()140 void PlatformEmbeddedFileWriterGeneric::FileEpilogue() {
141 // Omitting this section can imply an executable stack, which is usually
142 // a linker warning/error. C++ compilers add these automatically, but
143 // compiling assembly requires the .note.GNU-stack section to be inserted
144 // manually.
145 // Additional documentation:
146 // https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart
147 fprintf(fp_, ".section .note.GNU-stack,\"\",%%progbits\n");
148 }
149
IndentedDataDirective(DataDirective directive)150 int PlatformEmbeddedFileWriterGeneric::IndentedDataDirective(
151 DataDirective directive) {
152 return fprintf(fp_, " %s ", DirectiveAsString(directive));
153 }
154
ByteChunkDataDirective() const155 DataDirective PlatformEmbeddedFileWriterGeneric::ByteChunkDataDirective()
156 const {
157 #if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)
158 // MIPS uses a fixed 4 byte instruction set, using .long
159 // to prevent any unnecessary padding.
160 return kLong;
161 #else
162 // Other ISAs just listen to the base
163 return PlatformEmbeddedFileWriterBase::ByteChunkDataDirective();
164 #endif
165 }
166
167 #undef SYMBOL_PREFIX
168
169 } // namespace internal
170 } // namespace v8
171