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 13namespace v8 { 14namespace internal { 15 16#define SYMBOL_PREFIX "" 17 18namespace { 19 20const 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 36void 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 44void PlatformEmbeddedFileWriterGeneric::SectionData() { 45 fprintf(fp_, ".section .data\n"); 46} 47 48void PlatformEmbeddedFileWriterGeneric::SectionRoData() { 49 fprintf(fp_, ".section .rodata\n"); 50} 51 52void 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 61void 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 69void 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 76void PlatformEmbeddedFileWriterGeneric::AlignToCodeAlignment() { 77#if V8_TARGET_ARCH_X64 78 // On x64 use 64-bytes code alignment to allow 64-bytes loop header alignment. 79 STATIC_ASSERT(64 >= kCodeAlignment); 80 fprintf(fp_, ".balign 64\n"); 81#elif V8_TARGET_ARCH_PPC64 82 // 64 byte alignment is needed on ppc64 to make sure p10 prefixed instructions 83 // don't cross 64-byte boundaries. 84 STATIC_ASSERT(64 >= kCodeAlignment); 85 fprintf(fp_, ".balign 64\n"); 86#else 87 STATIC_ASSERT(32 >= kCodeAlignment); 88 fprintf(fp_, ".balign 32\n"); 89#endif 90} 91 92void PlatformEmbeddedFileWriterGeneric::AlignToDataAlignment() { 93 // On Windows ARM64, s390, PPC and possibly more platforms, aligned load 94 // instructions are used to retrieve v8_Default_embedded_blob_ and/or 95 // v8_Default_embedded_blob_size_. The generated instructions require the 96 // load target to be aligned at 8 bytes (2^3). 97 STATIC_ASSERT(8 >= Code::kMetadataAlignment); 98 fprintf(fp_, ".balign 8\n"); 99} 100 101void PlatformEmbeddedFileWriterGeneric::Comment(const char* string) { 102 fprintf(fp_, "// %s\n", string); 103} 104 105void PlatformEmbeddedFileWriterGeneric::DeclareLabel(const char* name) { 106 fprintf(fp_, "%s%s:\n", SYMBOL_PREFIX, name); 107} 108 109void PlatformEmbeddedFileWriterGeneric::SourceInfo(int fileid, 110 const char* filename, 111 int line) { 112 fprintf(fp_, ".loc %d %d\n", fileid, line); 113} 114 115void PlatformEmbeddedFileWriterGeneric::DeclareFunctionBegin(const char* name, 116 uint32_t size) { 117 if (ENABLE_CONTROL_FLOW_INTEGRITY_BOOL) { 118 DeclareSymbolGlobal(name); 119 } 120 121 DeclareLabel(name); 122 123 if (target_arch_ == EmbeddedTargetArch::kArm || 124 target_arch_ == EmbeddedTargetArch::kArm64) { 125 // ELF format binaries on ARM use ".type <function name>, %function" 126 // to create a DWARF subprogram entry. 127 fprintf(fp_, ".type %s, %%function\n", name); 128 } else { 129 // Other ELF Format binaries use ".type <function name>, @function" 130 // to create a DWARF subprogram entry. 131 fprintf(fp_, ".type %s, @function\n", name); 132 } 133 fprintf(fp_, ".size %s, %u\n", name, size); 134} 135 136void PlatformEmbeddedFileWriterGeneric::DeclareFunctionEnd(const char* name) {} 137 138void PlatformEmbeddedFileWriterGeneric::FilePrologue() {} 139 140void PlatformEmbeddedFileWriterGeneric::DeclareExternalFilename( 141 int fileid, const char* filename) { 142 // Replace any Windows style paths (backslashes) with forward 143 // slashes. 144 std::string fixed_filename(filename); 145 std::replace(fixed_filename.begin(), fixed_filename.end(), '\\', '/'); 146 fprintf(fp_, ".file %d \"%s\"\n", fileid, fixed_filename.c_str()); 147} 148 149void PlatformEmbeddedFileWriterGeneric::FileEpilogue() { 150 // Omitting this section can imply an executable stack, which is usually 151 // a linker warning/error. C++ compilers add these automatically, but 152 // compiling assembly requires the .note.GNU-stack section to be inserted 153 // manually. 154 // Additional documentation: 155 // https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart 156 fprintf(fp_, ".section .note.GNU-stack,\"\",%%progbits\n"); 157} 158 159int PlatformEmbeddedFileWriterGeneric::IndentedDataDirective( 160 DataDirective directive) { 161 return fprintf(fp_, " %s ", DirectiveAsString(directive)); 162} 163 164DataDirective PlatformEmbeddedFileWriterGeneric::ByteChunkDataDirective() 165 const { 166#if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64) || \ 167 defined(V8_TARGET_ARCH_LOONG64) 168 // MIPS and LOONG64 uses a fixed 4 byte instruction set, using .long 169 // to prevent any unnecessary padding. 170 return kLong; 171#else 172 // Other ISAs just listen to the base 173 return PlatformEmbeddedFileWriterBase::ByteChunkDataDirective(); 174#endif 175} 176 177#undef SYMBOL_PREFIX 178 179} // namespace internal 180} // namespace v8 181